From 74271143414037796ca76989c9c895491d553771 Mon Sep 17 00:00:00 2001 From: John Dietz Date: Sun, 17 Aug 2025 14:17:34 -0400 Subject: [PATCH 1/9] adding kafka ui components to catalog implementation --- CLAUDE.md | 105 +++++++++++++++++++++++++++ kafka/components/kafka/kafka-ui.yaml | 64 ++++++++++++++++ 2 files changed, 169 insertions(+) create mode 100644 CLAUDE.md create mode 100644 kafka/components/kafka/kafka-ui.yaml diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..15acfc6 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,105 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Overview + +The GitOps Catalog is a community-driven collection of cloud native applications that can be easily added to the Kubefirst platform. Each application follows a structured format with Argo CD manifests and standardized metadata. + +## Common Development Tasks + +### Validation Commands + +Run these commands before submitting a pull request: + +```bash +# Validate YAML syntax +yamllint -c .yamllint.yml . + +# Check for broken links in markdown files +# (Automated in CI, manual validation recommended) + +# Verify Git commits are signed +git log --show-signature +``` + +### Adding a New Application + +When adding a new application to the catalog, follow this structure: + +1. Create directory: `/` +2. Add App of Apps manifest: `/.yaml` +3. Create components directory: `/components//` +4. Add Argo CD application manifest: `/components//application.yaml` +5. Add logo: `logos/.svg` (or .png/.jpeg) +6. Update `index.yaml` with application metadata + +### Key Files to Update + +- **index.yaml**: Central registry of all applications with metadata (name, displayName, website, imageUrl, description, category) +- **logos/**: Directory containing application logos (32x32 display size) +- **CONTRIBUTING.md**: Detailed instructions for contributors + +## Architecture & Patterns + +### Application Structure + +Each application follows the "App of Apps" pattern: +- Root manifest (`.yaml`) deploys to ArgoCD namespace +- Points to components folder in the GitOps repository +- Components contain the actual application manifests + +### Token Substitution + +Applications use Kubefirst tokens that get replaced at deployment time: +- ``: Kubernetes cluster name +- ``: GitOps repository URL +- ``: Path in the registry +- ``: Target cluster +- ``: ArgoCD project +- ``: Domain for ingress +- Full list in CONTRIBUTING.md + +### Required Annotations + +All Argo CD applications must include: +```yaml +annotations: + kubefirst.konstruct.io/application-name: + kubefirst.konstruct.io/source: catalog-templates +``` + +### Categories + +Applications must belong to one of these categories: +- App management +- Architecture +- CI/CD +- Database +- End user application +- FinOps +- Infrastructure +- Miscellaneous +- Monitoring +- Observability +- Security +- Storage +- Testing + +## Important Conventions + +1. **Commit Signing**: All commits must be signed (enforced by CI) +2. **YAML Linting**: Follow `.yamllint.yml` rules (line-length disabled, truthy check-keys disabled) +3. **Logo Requirements**: SVG preferred, PNG/JPEG accepted, displayed at 32x32 pixels +4. **Character Limits**: displayName (120 chars max), description (200 chars max) +5. **Sync Wave**: Use annotation `argocd.argoproj.io/sync-wave: '100'` for proper ordering + +## CI/CD Workflow + +GitHub Actions validate: +- YAML syntax (yamllint) +- Markdown formatting +- Link validity +- Commit signatures (PRs only) + +No build or deployment steps - this is a catalog of manifests that get deployed by Kubefirst platform. \ No newline at end of file diff --git a/kafka/components/kafka/kafka-ui.yaml b/kafka/components/kafka/kafka-ui.yaml new file mode 100644 index 0000000..327de51 --- /dev/null +++ b/kafka/components/kafka/kafka-ui.yaml @@ -0,0 +1,64 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: kafka-ui + namespace: kafka +spec: + replicas: 1 + selector: + matchLabels: + app: kafka-ui + template: + metadata: + labels: + app: kafka-ui + spec: + containers: + - name: kafka-ui + image: provectuslabs/kafka-ui:latest + ports: + - containerPort: 8080 + env: + - name: KAFKA_CLUSTERS_0_NAME + value: "my-kafka" + - name: KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS + value: "my-kafka:9092" +--- +apiVersion: v1 +kind: Service +metadata: + name: kafka-ui + namespace: kafka +spec: + selector: + app: kafka-ui + ports: + - port: 8080 + targetPort: 8080 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + cert-manager.io/cluster-issuer: letsencrypt-prod + argocd.argoproj.io/sync-wave: '1' + name: kafka-ui + namespace: kafka +spec: + ingressClassName: nginx + rules: + - host: kafka. + http: + paths: + - backend: + service: + name: kafka-ui + port: + number: 8080 + path: / + pathType: Prefix + tls: + - hosts: + - kafka. + secretName: kafka-ui-tls From 637bce3767ae84181c0b412aaf00852cc1c74b0e Mon Sep 17 00:00:00 2001 From: John Dietz Date: Sun, 17 Aug 2025 14:30:43 -0400 Subject: [PATCH 2/9] getting vale out of claude's business --- .vale.ini | 3 +++ CLAUDE.md | 4 ++-- kafka/components/kafka/kafka-ui.yaml | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.vale.ini b/.vale.ini index a3f608f..5c752ea 100644 --- a/.vale.ini +++ b/.vale.ini @@ -11,3 +11,6 @@ IgnoredScopes = code BlockIgnores = (?s) *(import.*?\n), \ (?s) *(### gitops\n) TokenIgnores = (?s) *(export.*?\n) + +[CLAUDE.md] +IgnoredClasses = Custom.* diff --git a/CLAUDE.md b/CLAUDE.md index 15acfc6..abdbe22 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -45,7 +45,7 @@ When adding a new application to the catalog, follow this structure: ### Application Structure Each application follows the "App of Apps" pattern: -- Root manifest (`.yaml`) deploys to ArgoCD namespace +- Root manifest (`.yaml`) deploys to `arcocd` namespace - Points to components folder in the GitOps repository - Components contain the actual application manifests @@ -56,7 +56,7 @@ Applications use Kubefirst tokens that get replaced at deployment time: - ``: GitOps repository URL - ``: Path in the registry - ``: Target cluster -- ``: ArgoCD project +- ``: Argo CD project - ``: Domain for ingress - Full list in CONTRIBUTING.md diff --git a/kafka/components/kafka/kafka-ui.yaml b/kafka/components/kafka/kafka-ui.yaml index 327de51..001e9b4 100644 --- a/kafka/components/kafka/kafka-ui.yaml +++ b/kafka/components/kafka/kafka-ui.yaml @@ -34,8 +34,8 @@ spec: selector: app: kafka-ui ports: - - port: 8080 - targetPort: 8080 + - port: 8080 + targetPort: 8080 --- apiVersion: networking.k8s.io/v1 kind: Ingress From ef56545cd9fe7c5c94fca7faa71905878254a90e Mon Sep 17 00:00:00 2001 From: John Dietz Date: Sun, 17 Aug 2025 14:34:14 -0400 Subject: [PATCH 3/9] lint fixes --- .vale.ini | 2 +- styles/Vocab/base/accept.txt | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.vale.ini b/.vale.ini index 5c752ea..2a6b14f 100644 --- a/.vale.ini +++ b/.vale.ini @@ -13,4 +13,4 @@ BlockIgnores = (?s) *(import.*?\n), \ TokenIgnores = (?s) *(export.*?\n) [CLAUDE.md] -IgnoredClasses = Custom.* +BasedOnStyles = diff --git a/styles/Vocab/base/accept.txt b/styles/Vocab/base/accept.txt index f73398a..bc65920 100644 --- a/styles/Vocab/base/accept.txt +++ b/styles/Vocab/base/accept.txt @@ -77,6 +77,7 @@ teardown todo toolset Traefik +truthy truststore Typesense @@ -93,5 +94,6 @@ walkthrough # X # Y +yamllint # Z From d5782d8584a8bad44c454c4f4e67863d39bee08a Mon Sep 17 00:00:00 2001 From: John Dietz Date: Sun, 17 Aug 2025 14:40:16 -0400 Subject: [PATCH 4/9] removing claude.md from markdownlint --- .markdownlintignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .markdownlintignore diff --git a/.markdownlintignore b/.markdownlintignore new file mode 100644 index 0000000..681311e --- /dev/null +++ b/.markdownlintignore @@ -0,0 +1 @@ +CLAUDE.md \ No newline at end of file From 0d467af850d7c326f34e8b1d159d46ab50038da3 Mon Sep 17 00:00:00 2001 From: John Dietz Date: Sun, 17 Aug 2025 14:43:20 -0400 Subject: [PATCH 5/9] removing claude.md from markdownlint --- .github/workflows/check-markdown.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/check-markdown.yml b/.github/workflows/check-markdown.yml index 3937f5e..7e4d424 100644 --- a/.github/workflows/check-markdown.yml +++ b/.github/workflows/check-markdown.yml @@ -15,4 +15,6 @@ jobs: uses: DavidAnson/markdownlint-cli2-action@v13.0.0 with: config: .markdownlint.json - globs: "**.md" + globs: | + **.md + !CLAUDE.md From d86af82d4fabc138722b3c853b239453825e46e7 Mon Sep 17 00:00:00 2001 From: John Dietz Date: Sun, 17 Aug 2025 16:59:58 -0400 Subject: [PATCH 6/9] adding harbor to the gitops catalog --- harbor/components/harbor/application.yaml | 97 +++++++++++++++++++ harbor/components/harbor/external-secret.yaml | 16 +++ harbor/harbor.yaml | 25 +++++ index.yaml | 11 +++ logos/harbor.svg | 1 + 5 files changed, 150 insertions(+) create mode 100644 harbor/components/harbor/application.yaml create mode 100644 harbor/components/harbor/external-secret.yaml create mode 100644 harbor/harbor.yaml create mode 100644 logos/harbor.svg diff --git a/harbor/components/harbor/application.yaml b/harbor/components/harbor/application.yaml new file mode 100644 index 0000000..cd0528d --- /dev/null +++ b/harbor/components/harbor/application.yaml @@ -0,0 +1,97 @@ +--- +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: -harbor + namespace: argocd + annotations: + kubefirst.konstruct.io/application-name: harbor + kubefirst.konstruct.io/source: catalog-templates + finalizers: + - resources-finalizer.argocd.argoproj.io +spec: + destination: + namespace: harbor + name: + project: + source: + chart: harbor + repoURL: https://helm.goharbor.io + targetRevision: 1.15.1 + helm: + releaseName: harbor + values: | + expose: + type: ingress + tls: + enabled: true + certSource: secret + secret: + secretName: harbor-tls + ingress: + hosts: + core: harbor. + className: nginx + annotations: + cert-manager.io/cluster-issuer: letsencrypt-prod + nginx.ingress.kubernetes.io/ssl-redirect: "true" + nginx.ingress.kubernetes.io/proxy-body-size: "0" + nginx.ingress.kubernetes.io/proxy-read-timeout: "600" + nginx.ingress.kubernetes.io/proxy-send-timeout: "600" + + externalURL: https://harbor. + + harborAdminPassword: "" # Will be set by external secret + existingSecretAdminPassword: harbor-admin-secret + existingSecretAdminPasswordKey: HARBOR_ADMIN_PASSWORD + + persistence: + enabled: true + persistentVolumeClaim: + registry: + storageClass: "" + size: 50Gi + database: + storageClass: "" + size: 5Gi + redis: + storageClass: "" + size: 5Gi + trivy: + storageClass: "" + size: 10Gi + + portal: + replicas: 1 + + core: + replicas: 1 + + registry: + replicas: 1 + + trivy: + enabled: true + gitHubToken: "" + skipUpdate: false + + database: + type: internal + internal: + password: "" # Will be auto-generated + + redis: + type: internal + internal: + password: "" # Will be auto-generated + + metrics: + enabled: true + serviceMonitor: + enabled: false + syncPolicy: + automated: + prune: true + selfHeal: true + syncOptions: + - CreateNamespace=true \ No newline at end of file diff --git a/harbor/components/harbor/external-secret.yaml b/harbor/components/harbor/external-secret.yaml new file mode 100644 index 0000000..75dc045 --- /dev/null +++ b/harbor/components/harbor/external-secret.yaml @@ -0,0 +1,16 @@ +--- +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: -harbor-admin-secret + namespace: harbor +spec: + target: + name: harbor-admin-secret + secretStoreRef: + kind: ClusterSecretStore + name: vault-kv-secret + refreshInterval: 10s + dataFrom: + - extract: + key: /harbor \ No newline at end of file diff --git a/harbor/harbor.yaml b/harbor/harbor.yaml new file mode 100644 index 0000000..3ba857c --- /dev/null +++ b/harbor/harbor.yaml @@ -0,0 +1,25 @@ +--- +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: -harbor-components + namespace: argocd + annotations: + argocd.argoproj.io/sync-wave: '100' + finalizers: + - resources-finalizer.argocd.argoproj.io +spec: + project: default + source: + repoURL: + path: /components/harbor + targetRevision: HEAD + destination: + name: in-cluster + namespace: harbor + syncPolicy: + automated: + prune: true + selfHeal: true + syncOptions: + - CreateNamespace=true \ No newline at end of file diff --git a/index.yaml b/index.yaml index 2ee8e21..2a43be2 100644 --- a/index.yaml +++ b/index.yaml @@ -84,6 +84,17 @@ apps: description: "Turbo-Boost your development project with automation using the grapple solution framework. Instant API and UI module generate in your kubernetes cluster or your development project." category: Architecture + - name: harbor + displayName: Harbor + website: "https://goharbor.io/" + secretKeys: + - name: HARBOR_ADMIN_PASSWORD + label: Harbor admin password + env: HARBOR_ADMIN_PASSWORD + imageUrl: "https://raw.githubusercontent.com/konstructio/gitops-catalog/main/logos/harbor.svg" + description: "Harbor is an open source cloud native registry that stores, signs, and scans container images for vulnerabilities with built-in security policies and RBAC." + category: Infrastructure + - name: kafka displayName: Kafka website: "https://kafka.apache.org/" diff --git a/logos/harbor.svg b/logos/harbor.svg new file mode 100644 index 0000000..9552079 --- /dev/null +++ b/logos/harbor.svg @@ -0,0 +1 @@ +Harbor logo \ No newline at end of file From 3593a574ac269449a7a5e7090a31055e10fac65e Mon Sep 17 00:00:00 2001 From: John Dietz Date: Sun, 17 Aug 2025 17:11:49 -0400 Subject: [PATCH 7/9] harbor lint fixes --- harbor/components/harbor/application.yaml | 12 +----------- harbor/components/harbor/external-secret.yaml | 2 +- harbor/harbor.yaml | 2 +- 3 files changed, 3 insertions(+), 13 deletions(-) diff --git a/harbor/components/harbor/application.yaml b/harbor/components/harbor/application.yaml index cd0528d..b53309a 100644 --- a/harbor/components/harbor/application.yaml +++ b/harbor/components/harbor/application.yaml @@ -38,13 +38,10 @@ spec: nginx.ingress.kubernetes.io/proxy-body-size: "0" nginx.ingress.kubernetes.io/proxy-read-timeout: "600" nginx.ingress.kubernetes.io/proxy-send-timeout: "600" - externalURL: https://harbor. - harborAdminPassword: "" # Will be set by external secret existingSecretAdminPassword: harbor-admin-secret existingSecretAdminPasswordKey: HARBOR_ADMIN_PASSWORD - persistence: enabled: true persistentVolumeClaim: @@ -60,31 +57,24 @@ spec: trivy: storageClass: "" size: 10Gi - portal: replicas: 1 - core: replicas: 1 - registry: replicas: 1 - trivy: enabled: true gitHubToken: "" skipUpdate: false - database: type: internal internal: password: "" # Will be auto-generated - redis: type: internal internal: password: "" # Will be auto-generated - metrics: enabled: true serviceMonitor: @@ -94,4 +84,4 @@ spec: prune: true selfHeal: true syncOptions: - - CreateNamespace=true \ No newline at end of file + - CreateNamespace=true diff --git a/harbor/components/harbor/external-secret.yaml b/harbor/components/harbor/external-secret.yaml index 75dc045..248fc2c 100644 --- a/harbor/components/harbor/external-secret.yaml +++ b/harbor/components/harbor/external-secret.yaml @@ -13,4 +13,4 @@ spec: refreshInterval: 10s dataFrom: - extract: - key: /harbor \ No newline at end of file + key: /harbor diff --git a/harbor/harbor.yaml b/harbor/harbor.yaml index 3ba857c..c213b61 100644 --- a/harbor/harbor.yaml +++ b/harbor/harbor.yaml @@ -22,4 +22,4 @@ spec: prune: true selfHeal: true syncOptions: - - CreateNamespace=true \ No newline at end of file + - CreateNamespace=true From 909844ec562265b2c62c8a0255a83914c269b822 Mon Sep 17 00:00:00 2001 From: John Dietz Date: Mon, 18 Aug 2025 10:15:17 -0400 Subject: [PATCH 8/9] adjustments to harbor configuration set --- harbor/components/harbor/application.yaml | 26 ++++++++++++-- harbor/components/harbor/external-secret.yaml | 36 +++++++++++++++++++ index.yaml | 6 ++++ 3 files changed, 65 insertions(+), 3 deletions(-) diff --git a/harbor/components/harbor/application.yaml b/harbor/components/harbor/application.yaml index b53309a..f31b890 100644 --- a/harbor/components/harbor/application.yaml +++ b/harbor/components/harbor/application.yaml @@ -39,7 +39,9 @@ spec: nginx.ingress.kubernetes.io/proxy-read-timeout: "600" nginx.ingress.kubernetes.io/proxy-send-timeout: "600" externalURL: https://harbor. - harborAdminPassword: "" # Will be set by external secret + + harborAdminPassword: "" # Don't set this when using existingSecretAdminPassword + secretKey: harbor-admin existingSecretAdminPassword: harbor-admin-secret existingSecretAdminPasswordKey: HARBOR_ADMIN_PASSWORD persistence: @@ -63,6 +65,10 @@ spec: replicas: 1 registry: replicas: 1 + + jobservice: + replicas: 1 + trivy: enabled: true gitHubToken: "" @@ -70,11 +76,25 @@ spec: database: type: internal internal: - password: "" # Will be auto-generated + # Password from external secret + existingSecret: harbor-database-secret + existingSecretPasswordKey: POSTGRES_PASSWORD + redis: type: internal internal: - password: "" # Will be auto-generated + # Password from external secret + existingSecret: harbor-redis-secret + existingSecretPasswordKey: REDIS_PASSWORD + + # Disable internal TLS to avoid the SSL directory errors + internalTLS: + enabled: false + + # Core secret for internal components + core: + secret: "" # Let Harbor generate this + secretName: harbor-core metrics: enabled: true serviceMonitor: diff --git a/harbor/components/harbor/external-secret.yaml b/harbor/components/harbor/external-secret.yaml index 248fc2c..6331ff9 100644 --- a/harbor/components/harbor/external-secret.yaml +++ b/harbor/components/harbor/external-secret.yaml @@ -14,3 +14,39 @@ spec: dataFrom: - extract: key: /harbor +--- +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: -harbor-database-secret + namespace: harbor +spec: + target: + name: harbor-database-secret + secretStoreRef: + kind: ClusterSecretStore + name: vault-kv-secret + refreshInterval: 10s + data: + - secretKey: POSTGRES_PASSWORD + remoteRef: + key: /harbor + property: POSTGRES_PASSWORD +--- +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: -harbor-redis-secret + namespace: harbor +spec: + target: + name: harbor-redis-secret + secretStoreRef: + kind: ClusterSecretStore + name: vault-kv-secret + refreshInterval: 10s + data: + - secretKey: REDIS_PASSWORD + remoteRef: + key: /harbor + property: REDIS_PASSWORD diff --git a/index.yaml b/index.yaml index 2a43be2..3560e7e 100644 --- a/index.yaml +++ b/index.yaml @@ -91,6 +91,12 @@ apps: - name: HARBOR_ADMIN_PASSWORD label: Harbor admin password env: HARBOR_ADMIN_PASSWORD + - name: POSTGRES_PASSWORD + label: Harbor database password + env: POSTGRES_PASSWORD + - name: REDIS_PASSWORD + label: Harbor Redis password + env: REDIS_PASSWORD imageUrl: "https://raw.githubusercontent.com/konstructio/gitops-catalog/main/logos/harbor.svg" description: "Harbor is an open source cloud native registry that stores, signs, and scans container images for vulnerabilities with built-in security policies and RBAC." category: Infrastructure From efcdb6b4195a00d58d63ec7ea3ead42f88537e1c Mon Sep 17 00:00:00 2001 From: John Dietz Date: Mon, 18 Aug 2025 13:04:13 -0400 Subject: [PATCH 9/9] Apply suggestions from code review --- harbor/components/harbor/application.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/harbor/components/harbor/application.yaml b/harbor/components/harbor/application.yaml index d89f267..0a7df90 100644 --- a/harbor/components/harbor/application.yaml +++ b/harbor/components/harbor/application.yaml @@ -85,7 +85,6 @@ spec: # Disable internal TLS to avoid the SSL directory errors internalTLS: enabled: false - # Core secret for internal components core: secret: "" # Let Harbor generate this