diff options
| -rw-r--r-- | cmd/main.go | 16 | ||||
| -rw-r--r-- | internal/admin/middleware.go | 8 | ||||
| -rw-r--r-- | internal/admin/middleware_test.go | 5 | ||||
| -rw-r--r-- | internal/admin/model.go | 20 | ||||
| -rw-r--r-- | justfile | 5 | ||||
| -rw-r--r-- | manifests/base/cm.yaml | 25 | ||||
| -rw-r--r-- | manifests/base/deploy.yaml | 57 | ||||
| -rw-r--r-- | manifests/base/kustomization.yaml | 14 | ||||
| -rw-r--r-- | manifests/base/pvc.yaml | 14 | ||||
| -rw-r--r-- | manifests/base/svc.yaml | 12 | ||||
| -rw-r--r-- | manifests/cgit/cgit-cm.yaml | 39 | ||||
| -rw-r--r-- | manifests/cgit/cgit-deploy.yaml | 50 | ||||
| -rw-r--r-- | manifests/cgit/cgit-ing.yaml | 27 | ||||
| -rw-r--r-- | manifests/cgit/cgit-sa.yaml | 4 | ||||
| -rw-r--r-- | manifests/cgit/cgit-svc.yaml | 14 | ||||
| -rw-r--r-- | manifests/cgit/kustomization.yaml | 25 | ||||
| -rw-r--r-- | manifests/deploy.yaml | 46 | ||||
| -rw-r--r-- | manifests/local/kustomization.yaml | 15 | ||||
| -rw-r--r-- | manifests/svc.yaml | 20 |
19 files changed, 397 insertions, 19 deletions
diff --git a/cmd/main.go b/cmd/main.go index eaf2450..755a005 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -17,6 +17,7 @@ var ( reposDir string mgmtRepo bool backendCommand string + loggingLevel string addr string modelPath string policyPath string @@ -25,8 +26,22 @@ var ( newToken bool ) +var ( + logLevels = map[string]slog.Level{ + "DEBUG": slog.LevelDebug, + "INFO": slog.LevelInfo, + "ERROR": slog.LevelError, + } +) + func main() { flag.Parse() + level, ok := logLevels[loggingLevel] + if !ok { + slog.Error("log levels are DEBUG, INFO, ERROR", "found", loggingLevel) + os.Exit(1) + } + slog.SetLogLoggerLevel(level) if newToken { token, hash, err := authz.GenerateNewToken() if err != nil { @@ -67,6 +82,7 @@ func main() { func init() { flag.StringVar(&backendCommand, "c", "git http-backend", "CGI binary to execute") + flag.StringVar(&loggingLevel, "e", "INFO", "set log level") flag.StringVar(&addr, "l", ":8080", "Address/port to listen on") flag.StringVar(&modelPath, "m", "./auth_model.ini", "casbin authentication model") flag.StringVar(&policyPath, "p", "./policy.csv", "casbin auth policy") diff --git a/internal/admin/middleware.go b/internal/admin/middleware.go index 0dcf558..90560fa 100644 --- a/internal/admin/middleware.go +++ b/internal/admin/middleware.go @@ -1,17 +1,19 @@ package admin import ( - "fmt" + "log/slog" "net/http" ) // Hooks middleware to handle requests to the admin repo. func Hooks(adminSvc *Servicer, next http.Handler) http.Handler { - repoUpdatePath := fmt.Sprintf("/%s/git-receive-pack", mgmtRepoName) + repoUpdatePath := "/mgmt/git-receive-pack" return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { next.ServeHTTP(rw, req) + slog.Debug("hooks middleware", "url", req.URL.Path) if req.URL.Path == repoUpdatePath && req.Method == http.MethodPost { - adminSvc.Reload() + slog.Debug("hook firing reload") + go adminSvc.Reload() } }) } diff --git a/internal/admin/middleware_test.go b/internal/admin/middleware_test.go index a50d02d..ffc2e2c 100644 --- a/internal/admin/middleware_test.go +++ b/internal/admin/middleware_test.go @@ -8,6 +8,7 @@ import ( "os" "path/filepath" "testing" + "time" "github.com/go-git/go-billy/v5/util" "github.com/go-git/go-git/v5" @@ -88,13 +89,15 @@ func TestHooks(t *testing.T) { if err != nil { t.Fatal("couldn't commit file", err) } - req := httptest.NewRequest(http.MethodPost, "http://localhost:3456/mgmt.git/git-receive-pack", bytes.NewBuffer([]byte("stuff"))) + req := httptest.NewRequest(http.MethodPost, "http://localhost:3456/mgmt/git-receive-pack", bytes.NewBuffer([]byte("stuff"))) recorder := httptest.NewRecorder() adminHandler := Hooks(adminService, junkTestHandler()) adminHandler.ServeHTTP(recorder, req) result := recorder.Result() defer result.Body.Close() found := false + // wait for bg job to complete + time.Sleep(1 * time.Second) for _, v := range adminService.Conf.Repos { if v.Name == newTestConfigRepo.Name { found = true diff --git a/internal/admin/model.go b/internal/admin/model.go index 079496e..a797bbd 100644 --- a/internal/admin/model.go +++ b/internal/admin/model.go @@ -99,6 +99,7 @@ type ServerRepos struct { func loadConfigFromGit(baseDir, filePath string) ([]byte, error) { mgmtPath := filepath.Join(baseDir, mgmtRepoName) + slog.Info("loading server config", "configPath", mgmtPath) _, err := os.Stat(mgmtPath) if errors.Is(err, os.ErrNotExist) { return []byte(""), ErrMgmtRepoNotFound @@ -115,15 +116,6 @@ func loadConfigFromGit(baseDir, filePath string) ([]byte, error) { if err != nil { return []byte(""), fmt.Errorf("couldn't clone mgmt repo %s %w", repoURI, err) } - files, err := fs.ReadDir("/") - if err != nil { - log.Fatal(err) - } - for _, file := range files { - fmt.Println(file) - - } - file, err := fs.Open(filePath) if err != nil { return []byte(""), fmt.Errorf("couldn't open file in repo %w", err) @@ -204,10 +196,15 @@ func (s *ServerRepos) ServerPolicies() [][]string { // ConfigureRepos run reconciler for all repos func (s *ServerRepos) ConfigureRepos() error { + slog.Info("configuring repos", "toBeConfigured", len(s.Repos)) + var errs []error for _, repo := range s.Repos { - return repo.ReconcileRepo(s.basePath) + if err := repo.ReconcileRepo(s.basePath); err != nil { + slog.Error("error reconcile", "repo", repo.Name, "err", err) + errs = append(errs, err) + } } - return nil + return errors.Join(errs...) } func readOnlyPaths(role, repoName string) [][]string { @@ -250,6 +247,7 @@ func (r *GitRepo) CasbinPolicies() [][]string { func (r *GitRepo) ReconcileRepo(basePath string) error { // if exist -> continue repoBase := filepath.Join(basePath, fmt.Sprintf("%s.git", r.Name)) + slog.Info("reconciling repo", "repoPath", repoBase) _, err := os.Stat(repoBase) if errors.Is(err, fs.ErrNotExist) { // if no exist -> init bare @@ -34,10 +34,7 @@ test: go tool cover -func={{ TEMPDIR }}/testcover.out debug-run: - dlv debug cmd/main.go -- -s {{justfile_directory()}}/gitserver.yaml -r $(mktemp -d) -t tokens.csv -p policy.csv -m auth_model.ini -a - -debug-test pkg: - dlv test {{pkg}} -- -test.v + dlv debug cmd/main.go -- -s {{justfile_directory()}}/gitserver.yaml -r {{ TEMPDIR }} -t tokens.csv -p policy.csv -m auth_model.ini -a local-push: (push "localhost:5000") @echo "build and push to local dir" diff --git a/manifests/base/cm.yaml b/manifests/base/cm.yaml new file mode 100644 index 0000000..18423be --- /dev/null +++ b/manifests/base/cm.yaml @@ -0,0 +1,25 @@ +apiVersion: v1 +data: + policy.csv: | + g, role:admin, role:maintainers + g, uid:admin, role:admin + g, uid:grumps, role:maintainers + g, aid:argo, role:bots + auth_model.ini: | + [request_definition] + r = sub, obj, act + + [policy_definition] + p = sub, obj, act + + [role_definition] + g = _, _ + + [policy_effect] + e = some(where (p.eft == allow)) + + [matchers] + m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act +kind: ConfigMap +metadata: + name: go-git-policy diff --git a/manifests/base/deploy.yaml b/manifests/base/deploy.yaml new file mode 100644 index 0000000..f7ad0bf --- /dev/null +++ b/manifests/base/deploy.yaml @@ -0,0 +1,57 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + deployment.kubernetes.io/revision: "3" + labels: + app: go-git-server + name: go-git-server + namespace: default +spec: + progressDeadlineSeconds: 600 + replicas: 1 + revisionHistoryLimit: 10 + selector: + matchLabels: + app: go-git-server + strategy: + rollingUpdate: + maxSurge: 25% + maxUnavailable: 25% + type: RollingUpdate + template: + metadata: + creationTimestamp: null + labels: + app: go-git-server + spec: + containers: + - image: go-git-registry:5000/go-git-server:latest + imagePullPolicy: Always + name: go-git-server + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /tokens + name: go-git-server-tokens + readOnly: true + - mountPath: /opt/repos + name: go-git-storage + - mountPath: /opt/app/etc + name: go-git-policy + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + terminationGracePeriodSeconds: 30 + volumes: + - configMap: + defaultMode: 420 + name: go-git-policy + name: go-git-policy + - name: go-git-storage + persistentVolumeClaim: + claimName: go-git-storage + - name: go-git-server-tokens + secret: + defaultMode: 420 + secretName: go-git-server diff --git a/manifests/base/kustomization.yaml b/manifests/base/kustomization.yaml new file mode 100644 index 0000000..952446b --- /dev/null +++ b/manifests/base/kustomization.yaml @@ -0,0 +1,14 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +metadata: + name: go-git-server + +commonLabels: + app: go-git-server + +resources: +- cm.yaml +- svc.yaml +- pvc.yaml +- deploy.yaml + diff --git a/manifests/base/pvc.yaml b/manifests/base/pvc.yaml new file mode 100644 index 0000000..1a47dc5 --- /dev/null +++ b/manifests/base/pvc.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: go-git-storage + annotations: + volumeType: local +spec: + accessModes: + - ReadWriteOnce + storageClassName: local-path + resources: + requests: + storage: 512Mi + diff --git a/manifests/base/svc.yaml b/manifests/base/svc.yaml new file mode 100644 index 0000000..7305255 --- /dev/null +++ b/manifests/base/svc.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + app: go-git-server + name: go-git-server +spec: + ports: + - name: http + port: 8080 + selector: + app: go-git-server diff --git a/manifests/cgit/cgit-cm.yaml b/manifests/cgit/cgit-cm.yaml new file mode 100644 index 0000000..e01a6b5 --- /dev/null +++ b/manifests/cgit/cgit-cm.yaml @@ -0,0 +1,39 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: cgitrc +data: + cgitrc: | + # cgit config + # see cgitrc(5) for details + root-title=git.ofmax.li + root-desc=grumpy software + + readme=:README.md + + about-filter=/usr/lib/cgit/filters/about-formatting.sh + source-filter=/usr/lib/cgit/filters/syntax-highlighting.py + + enable-index-links=1 + enable-log-filecount=1 + enable-commit-graph=1 + enable-index-owner=1 + enable-http-clone=0 + enable-git-config=1 + enable-commit-graph=1 + enable-follow-links=1 + snapshots=tar.gz + css=/cgit.css + logo=/cgit.png + virtual-root=/ + robots=nofollow + remove-suffix=1 + + mimetype.html=text/html + mimetype.jpg=image/jpeg + mimetype.jpeg=image/jpeg + mimetype.pdf=application/pdf + mimetype.png=image/png + + strict-export=git-web-export-ok + scan-path=/opt/repos diff --git a/manifests/cgit/cgit-deploy.yaml b/manifests/cgit/cgit-deploy.yaml new file mode 100644 index 0000000..cfbdeb8 --- /dev/null +++ b/manifests/cgit/cgit-deploy.yaml @@ -0,0 +1,50 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: cgit +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/instance: cgit + app.kubernetes.io/name: cgit + template: + metadata: + labels: + app.kubernetes.io/instance: cgit + app.kubernetes.io/name: cgit + spec: + containers: + - env: + - name: CGIT_HOSTNAME + value: git.localhost + - name: CGIT_PORT + value: "8080" + - name: CGIT_CONFIG + value: /opt/etc/cgitrc + image: registry.gitlab.com/grumps/grumpy-containers/cgit:v0.0.5 + imagePullPolicy: Always + name: cgit + ports: + - containerPort: 8080 + name: http + protocol: TCP + volumeMounts: + - mountPath: /opt/repos + name: go-git-storage + readOnly: false + - mountPath: /opt/etc + name: cgitrc + readOnly: true + imagePullSecrets: + - name: regcred + serviceAccountName: cgit + volumes: + - name: go-git-storage + persistentVolumeClaim: + claimName: go-git-storage + - name: cgitrc + configMap: + defaultMode: 420 + name: cgitrc + diff --git a/manifests/cgit/cgit-ing.yaml b/manifests/cgit/cgit-ing.yaml new file mode 100644 index 0000000..e331bfc --- /dev/null +++ b/manifests/cgit/cgit-ing.yaml @@ -0,0 +1,27 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + certmanager.k8s.io/cluseterissuer: letsencrypt-prod + ingress.kubernetes.io/ssl-redirect: "true" + kubernetes.io/ingress.class: traefik + traefik.ingress.kubernetes.io/frontend-entry-points: http,https + traefik.ingress.kubernetes.io/redirect-entry-point: https + traefik.ingress.kubernetes.io/redirect-permanent: "true" + name: cgit +spec: + rules: + - host: git.ofmax.li + http: + paths: + - backend: + service: + name: cgit + port: + number: 8080 + pathType: Prefix + path: / + tls: + - hosts: + - git.ofmax.li + secretName: git-ofmax-li-sec diff --git a/manifests/cgit/cgit-sa.yaml b/manifests/cgit/cgit-sa.yaml new file mode 100644 index 0000000..43f5e65 --- /dev/null +++ b/manifests/cgit/cgit-sa.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: cgit diff --git a/manifests/cgit/cgit-svc.yaml b/manifests/cgit/cgit-svc.yaml new file mode 100644 index 0000000..9165c59 --- /dev/null +++ b/manifests/cgit/cgit-svc.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: cgit +spec: + ports: + - name: http + port: 8080 + protocol: TCP + targetPort: http + selector: + app.kubernetes.io/instance: cgit + app.kubernetes.io/name: cgit + type: ClusterIP diff --git a/manifests/cgit/kustomization.yaml b/manifests/cgit/kustomization.yaml new file mode 100644 index 0000000..9a8a4af --- /dev/null +++ b/manifests/cgit/kustomization.yaml @@ -0,0 +1,25 @@ +# Labels to add to all resources and selectors. +commonLabels: + app.kubernetes.io/instance: cgit + app.kubernetes.io/name: cgit + app.kubernetes.io/version: "1.0" + helm.sh/chart: cgit-0.1.0 + +# Images modify the tags for images without +# creating patches. +images: +- name: registry.gitlab.com/grumps/grumpy-containers/cgit + newTag: latest + +# Value of this field is prepended to the +# names of all resources +namePrefix: cgit + +# List of resource files that kustomize reads, modifies +# and emits as a YAML string +resources: +- cgit-deploy.yaml +- cgit-ing.yaml +- cgit-sa.yaml +- cgit-svc.yaml +- cgit-cm.yaml diff --git a/manifests/deploy.yaml b/manifests/deploy.yaml new file mode 100644 index 0000000..f80592d --- /dev/null +++ b/manifests/deploy.yaml @@ -0,0 +1,46 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + deployment.kubernetes.io/revision: "7" + labels: + app: go-git-server + name: go-git-server + namespace: default +spec: + progressDeadlineSeconds: 600 + replicas: 1 + revisionHistoryLimit: 10 + selector: + matchLabels: + app: go-git-server + strategy: + rollingUpdate: + maxSurge: 25% + maxUnavailable: 25% + type: RollingUpdate + template: + metadata: + creationTimestamp: null + labels: + app: go-git-server + spec: + containers: + - image: public.ecr.aws/s0f9o2k5/go-git-server:latest + imagePullPolicy: Always + name: go-git-server + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /tokens + name: go-git-server-tokens + readOnly: true + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + terminationGracePeriodSeconds: 30 + volumes: + - name: go-git-server-tokens + secret: + defaultMode: 420 + secretName: go-git-server diff --git a/manifests/local/kustomization.yaml b/manifests/local/kustomization.yaml new file mode 100644 index 0000000..df15211 --- /dev/null +++ b/manifests/local/kustomization.yaml @@ -0,0 +1,15 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +metadata: + name: go-git-server-local + +commonLabels: + app: go-git-server + +resources: +- ../base + +images: +- name: public.ecr.aws/s0f9o2k5/go-git-server + newName: go-git-registry:5000/go-git-server + diff --git a/manifests/svc.yaml b/manifests/svc.yaml new file mode 100644 index 0000000..0f1e1a2 --- /dev/null +++ b/manifests/svc.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + app: go-git-server + name: go-git-server + namespace: default +spec: + clusterIP: 10.43.87.231 + clusterIPs: + - 10.43.87.231 + internalTrafficPolicy: Cluster + ipFamilies: + - IPv4 + ipFamilyPolicy: SingleStack + ports: + - name: 8080-8080 + port: 8080 + selector: + app: go-git-server |