build source
This commit is contained in:
commit
ee1fec43ed
4171 changed files with 1351288 additions and 0 deletions
369
internal/k8s/forgejo_test.go
Normal file
369
internal/k8s/forgejo_test.go
Normal file
|
|
@ -0,0 +1,369 @@
|
|||
package k8s
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/yaml"
|
||||
)
|
||||
|
||||
func toInt64(v interface{}) int64 {
|
||||
switch n := v.(type) {
|
||||
case int64:
|
||||
return n
|
||||
case float64:
|
||||
return int64(n)
|
||||
case int:
|
||||
return int64(n)
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func forgejoYAMLPath() string {
|
||||
_, thisFile, _, _ := runtime.Caller(0)
|
||||
return filepath.Join(filepath.Dir(thisFile), "..", "..", "..", "..", "k8s", "dev-infra", "forgejo.yaml")
|
||||
}
|
||||
|
||||
func readForgejoDocuments(t *testing.T) []map[string]interface{} {
|
||||
t.Helper()
|
||||
data, err := os.ReadFile(forgejoYAMLPath())
|
||||
if err != nil {
|
||||
t.Fatalf("reading forgejo.yaml: %v", err)
|
||||
}
|
||||
|
||||
var docs []map[string]interface{}
|
||||
parts := strings.Split(string(data), "\n---")
|
||||
for _, part := range parts {
|
||||
trimmed := strings.TrimSpace(part)
|
||||
if trimmed == "" {
|
||||
continue
|
||||
}
|
||||
// Strip leading comment lines (file-level comments before first doc)
|
||||
lines := strings.Split(trimmed, "\n")
|
||||
var contentLines []string
|
||||
for _, line := range lines {
|
||||
stripped := strings.TrimSpace(line)
|
||||
if len(contentLines) == 0 && (stripped == "" || strings.HasPrefix(stripped, "#")) {
|
||||
continue
|
||||
}
|
||||
contentLines = append(contentLines, line)
|
||||
}
|
||||
content := strings.Join(contentLines, "\n")
|
||||
if content == "" {
|
||||
continue
|
||||
}
|
||||
var doc map[string]interface{}
|
||||
if err := yaml.NewYAMLOrJSONDecoder(strings.NewReader(content), 4096).Decode(&doc); err != nil {
|
||||
t.Fatalf("decoding YAML document: %v\n---\n%s", err, content[:min(200, len(content))])
|
||||
}
|
||||
docs = append(docs, doc)
|
||||
}
|
||||
return docs
|
||||
}
|
||||
|
||||
func findDoc(docs []map[string]interface{}, kind, name string) map[string]interface{} {
|
||||
for _, doc := range docs {
|
||||
if doc["kind"] == kind {
|
||||
meta, ok := doc["metadata"].(map[string]interface{})
|
||||
if ok && meta["name"] == name {
|
||||
return doc
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestForgejoYAMLExists(t *testing.T) {
|
||||
path := forgejoYAMLPath()
|
||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||
t.Fatalf("forgejo.yaml does not exist at %s", path)
|
||||
}
|
||||
}
|
||||
|
||||
func TestForgejoYAMLDocumentCount(t *testing.T) {
|
||||
docs := readForgejoDocuments(t)
|
||||
// Expected: Secret (admin), ConfigMap, PVC, Deployment, Service, IngressRoute, Middleware (basic-auth), Secret (htpasswd), Middleware (trailing-slash)
|
||||
if len(docs) < 9 {
|
||||
kinds := make([]string, len(docs))
|
||||
for i, d := range docs {
|
||||
kinds[i] = d["kind"].(string)
|
||||
}
|
||||
t.Errorf("expected at least 9 YAML documents, got %d: %v", len(docs), kinds)
|
||||
}
|
||||
}
|
||||
|
||||
func TestForgejoAdminSecret(t *testing.T) {
|
||||
docs := readForgejoDocuments(t)
|
||||
doc := findDoc(docs, "Secret", "forgejo-admin-secret")
|
||||
if doc == nil {
|
||||
t.Fatal("missing forgejo-admin-secret Secret")
|
||||
}
|
||||
meta := doc["metadata"].(map[string]interface{})
|
||||
if meta["namespace"] != "dev-infra" {
|
||||
t.Errorf("expected namespace dev-infra, got %v", meta["namespace"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestForgejoConfigMap(t *testing.T) {
|
||||
docs := readForgejoDocuments(t)
|
||||
doc := findDoc(docs, "ConfigMap", "forgejo-config")
|
||||
if doc == nil {
|
||||
t.Fatal("missing forgejo-config ConfigMap")
|
||||
}
|
||||
|
||||
meta := doc["metadata"].(map[string]interface{})
|
||||
if meta["namespace"] != "dev-infra" {
|
||||
t.Errorf("expected namespace dev-infra, got %v", meta["namespace"])
|
||||
}
|
||||
|
||||
data := doc["data"].(map[string]interface{})
|
||||
appIni, ok := data["app.ini"].(string)
|
||||
if !ok {
|
||||
t.Fatal("missing app.ini in ConfigMap data")
|
||||
}
|
||||
|
||||
requiredSettings := []string{
|
||||
"ROOT_URL = https://spinoff.dev/forgejo/",
|
||||
"HTTP_PORT = 3000",
|
||||
"DB_TYPE = sqlite3",
|
||||
"ENABLED = true",
|
||||
"DISABLE_REGISTRATION = true",
|
||||
"OFFLINE_MODE = true",
|
||||
"DEFAULT_BRANCH = main",
|
||||
}
|
||||
for _, s := range requiredSettings {
|
||||
if !strings.Contains(appIni, s) {
|
||||
t.Errorf("app.ini missing required setting: %s", s)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestForgejoPVC(t *testing.T) {
|
||||
docs := readForgejoDocuments(t)
|
||||
doc := findDoc(docs, "PersistentVolumeClaim", "forgejo-storage")
|
||||
if doc == nil {
|
||||
t.Fatal("missing forgejo-storage PVC")
|
||||
}
|
||||
|
||||
meta := doc["metadata"].(map[string]interface{})
|
||||
if meta["namespace"] != "dev-infra" {
|
||||
t.Errorf("expected namespace dev-infra, got %v", meta["namespace"])
|
||||
}
|
||||
|
||||
spec := doc["spec"].(map[string]interface{})
|
||||
storageClass, ok := spec["storageClassName"].(string)
|
||||
if !ok || storageClass != "longhorn" {
|
||||
t.Errorf("expected storageClassName longhorn, got %v", storageClass)
|
||||
}
|
||||
|
||||
resources := spec["resources"].(map[string]interface{})
|
||||
requests := resources["requests"].(map[string]interface{})
|
||||
if requests["storage"] != "5Gi" {
|
||||
t.Errorf("expected 5Gi storage, got %v", requests["storage"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestForgejoDeployment(t *testing.T) {
|
||||
docs := readForgejoDocuments(t)
|
||||
doc := findDoc(docs, "Deployment", "forgejo")
|
||||
if doc == nil {
|
||||
t.Fatal("missing forgejo Deployment")
|
||||
}
|
||||
|
||||
meta := doc["metadata"].(map[string]interface{})
|
||||
if meta["namespace"] != "dev-infra" {
|
||||
t.Errorf("expected namespace dev-infra, got %v", meta["namespace"])
|
||||
}
|
||||
|
||||
labels := meta["labels"].(map[string]interface{})
|
||||
if labels["app"] != "forgejo" {
|
||||
t.Errorf("expected label app=forgejo, got %v", labels["app"])
|
||||
}
|
||||
|
||||
spec := doc["spec"].(map[string]interface{})
|
||||
|
||||
strategy := spec["strategy"].(map[string]interface{})
|
||||
if strategy["type"] != "Recreate" {
|
||||
t.Errorf("expected Recreate strategy, got %v", strategy["type"])
|
||||
}
|
||||
|
||||
template := spec["template"].(map[string]interface{})
|
||||
podSpec := template["spec"].(map[string]interface{})
|
||||
|
||||
t.Run("init_containers", func(t *testing.T) {
|
||||
initContainers, ok := podSpec["initContainers"].([]interface{})
|
||||
if !ok || len(initContainers) < 2 {
|
||||
t.Fatal("expected at least 2 init containers (setup-config and create-admin)")
|
||||
}
|
||||
setupC := initContainers[0].(map[string]interface{})
|
||||
if setupC["name"] != "setup-config" {
|
||||
t.Errorf("expected first init container name setup-config, got %v", setupC["name"])
|
||||
}
|
||||
initC := initContainers[1].(map[string]interface{})
|
||||
if initC["name"] != "create-admin" {
|
||||
t.Errorf("expected second init container name create-admin, got %v", initC["name"])
|
||||
}
|
||||
image, _ := initC["image"].(string)
|
||||
if !strings.HasPrefix(image, "codeberg.org/forgejo/forgejo:") {
|
||||
t.Errorf("expected forgejo image, got %v", image)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("containers", func(t *testing.T) {
|
||||
containers := podSpec["containers"].([]interface{})
|
||||
if len(containers) != 2 {
|
||||
t.Fatalf("expected 2 containers (forgejo + ipip-sidecar), got %d", len(containers))
|
||||
}
|
||||
|
||||
forgejo := containers[0].(map[string]interface{})
|
||||
if forgejo["name"] != "forgejo" {
|
||||
t.Errorf("expected container name forgejo, got %v", forgejo["name"])
|
||||
}
|
||||
image, _ := forgejo["image"].(string)
|
||||
if !strings.HasPrefix(image, "codeberg.org/forgejo/forgejo:") {
|
||||
t.Errorf("expected forgejo image, got %v", image)
|
||||
}
|
||||
|
||||
ports := forgejo["ports"].([]interface{})
|
||||
if len(ports) != 1 {
|
||||
t.Errorf("expected 1 port, got %d", len(ports))
|
||||
}
|
||||
port := ports[0].(map[string]interface{})
|
||||
containerPort := toInt64(port["containerPort"])
|
||||
if containerPort != 3000 {
|
||||
t.Errorf("expected port 3000, got %v", port["containerPort"])
|
||||
}
|
||||
|
||||
ipip := containers[1].(map[string]interface{})
|
||||
if ipip["name"] != "ipip-sidecar" {
|
||||
t.Errorf("expected container name ipip-sidecar, got %v", ipip["name"])
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("volumes", func(t *testing.T) {
|
||||
volumes := podSpec["volumes"].([]interface{})
|
||||
if len(volumes) < 2 {
|
||||
t.Fatalf("expected at least 2 volumes (storage + config), got %d", len(volumes))
|
||||
}
|
||||
volumeNames := make(map[string]bool)
|
||||
for _, v := range volumes {
|
||||
vol := v.(map[string]interface{})
|
||||
volumeNames[vol["name"].(string)] = true
|
||||
}
|
||||
if !volumeNames["storage"] {
|
||||
t.Error("missing storage volume")
|
||||
}
|
||||
if !volumeNames["config"] {
|
||||
t.Error("missing config volume")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestForgejoService(t *testing.T) {
|
||||
docs := readForgejoDocuments(t)
|
||||
doc := findDoc(docs, "Service", "forgejo")
|
||||
if doc == nil {
|
||||
t.Fatal("missing forgejo Service")
|
||||
}
|
||||
|
||||
meta := doc["metadata"].(map[string]interface{})
|
||||
if meta["namespace"] != "dev-infra" {
|
||||
t.Errorf("expected namespace dev-infra, got %v", meta["namespace"])
|
||||
}
|
||||
|
||||
spec := doc["spec"].(map[string]interface{})
|
||||
if spec["type"] != "ClusterIP" {
|
||||
t.Errorf("expected ClusterIP, got %v", spec["type"])
|
||||
}
|
||||
|
||||
ports := spec["ports"].([]interface{})
|
||||
if len(ports) != 1 {
|
||||
t.Fatalf("expected 1 port, got %d", len(ports))
|
||||
}
|
||||
port := ports[0].(map[string]interface{})
|
||||
portNum := toInt64(port["port"])
|
||||
if portNum != 3000 {
|
||||
t.Errorf("expected port 3000, got %v", port["port"])
|
||||
}
|
||||
|
||||
selector := spec["selector"].(map[string]interface{})
|
||||
if selector["app"] != "forgejo" {
|
||||
t.Errorf("expected selector app=forgejo, got %v", selector["app"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestForgejoIngressRoute(t *testing.T) {
|
||||
docs := readForgejoDocuments(t)
|
||||
doc := findDoc(docs, "IngressRoute", "forgejo-ingress")
|
||||
if doc == nil {
|
||||
t.Fatal("missing forgejo-ingress IngressRoute")
|
||||
}
|
||||
|
||||
meta := doc["metadata"].(map[string]interface{})
|
||||
if meta["namespace"] != "dev-infra" {
|
||||
t.Errorf("expected namespace dev-infra, got %v", meta["namespace"])
|
||||
}
|
||||
|
||||
spec := doc["spec"].(map[string]interface{})
|
||||
entryPoints := spec["entryPoints"].([]interface{})
|
||||
if len(entryPoints) != 2 {
|
||||
t.Errorf("expected 2 entryPoints (web, websecure), got %d", len(entryPoints))
|
||||
}
|
||||
|
||||
routes := spec["routes"].([]interface{})
|
||||
if len(routes) < 2 {
|
||||
t.Fatalf("expected at least 2 routes (main + trailing-slash redirect), got %d", len(routes))
|
||||
}
|
||||
|
||||
mainRoute := routes[0].(map[string]interface{})
|
||||
matchRule, _ := mainRoute["match"].(string)
|
||||
if !strings.Contains(matchRule, "PathPrefix(`/forgejo/`)") {
|
||||
t.Errorf("expected PathPrefix /forgejo/ in main route, got %v", matchRule)
|
||||
}
|
||||
|
||||
middlewares := mainRoute["middlewares"].([]interface{})
|
||||
if len(middlewares) < 1 {
|
||||
t.Fatal("expected at least 1 middleware on main route")
|
||||
}
|
||||
mw := middlewares[0].(map[string]interface{})
|
||||
if mw["name"] != "forgejo-basic-auth" {
|
||||
t.Errorf("expected forgejo-basic-auth middleware, got %v", mw["name"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestForgejoBasicAuthMiddleware(t *testing.T) {
|
||||
docs := readForgejoDocuments(t)
|
||||
doc := findDoc(docs, "Middleware", "forgejo-basic-auth")
|
||||
if doc == nil {
|
||||
t.Fatal("missing forgejo-basic-auth Middleware")
|
||||
}
|
||||
|
||||
meta := doc["metadata"].(map[string]interface{})
|
||||
if meta["namespace"] != "dev-infra" {
|
||||
t.Errorf("expected namespace dev-infra, got %v", meta["namespace"])
|
||||
}
|
||||
|
||||
spec := doc["spec"].(map[string]interface{})
|
||||
basicAuth := spec["basicAuth"].(map[string]interface{})
|
||||
if basicAuth["secret"] != "forgejo-basic-auth-secret" {
|
||||
t.Errorf("expected secret forgejo-basic-auth-secret, got %v", basicAuth["secret"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestForgejoTrailingSlashMiddleware(t *testing.T) {
|
||||
docs := readForgejoDocuments(t)
|
||||
doc := findDoc(docs, "Middleware", "forgejo-add-trailing-slash")
|
||||
if doc == nil {
|
||||
t.Fatal("missing forgejo-add-trailing-slash Middleware")
|
||||
}
|
||||
|
||||
spec := doc["spec"].(map[string]interface{})
|
||||
redirect := spec["redirectRegex"].(map[string]interface{})
|
||||
if redirect["permanent"] != true {
|
||||
t.Error("expected permanent redirect")
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue