diff --git a/.github/workflows/ocm.yaml b/.github/workflows/ocm.yaml index 2c4c6ff..15ffea3 100644 --- a/.github/workflows/ocm.yaml +++ b/.github/workflows/ocm.yaml @@ -1,13 +1,6 @@ name: OCM on: - pull_request: - branches: [showroom] - paths: - - "showroom/ocm/**" - - ".github/workflows/ocm.yaml" - - "charts/**" - - "ocm/**" workflow_dispatch: inputs: oci_registry: @@ -28,10 +21,9 @@ concurrency: jobs: ocm: - if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository runs-on: ubuntu-latest permissions: - contents: read + contents: write packages: write env: OCI_REGISTRY_INPUT: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.oci_registry || '' }} @@ -142,3 +134,49 @@ jobs: fi echo "Pushing OCM transport archive to ${OCI_REGISTRY}" env -u GITHUB_TOKEN ocm transfer ctf ./ocm/transport.ctf "OCIRegistry::${OCI_REGISTRY}" + + - name: Sync tier manifests from OCM descriptors + id: sync_tier_images + if: github.event_name != 'pull_request' + shell: bash + run: | + set -euxo pipefail + SIGNING_IMAGE="$(yq -r '.components[0].resources[] | select(.name == "image") | .access.imageReference' showroom/ocm/collector-contrib-signing.yaml)" + VERIFY_IMAGE="$(yq -r '.components[0].resources[] | select(.name == "image") | .access.imageReference' showroom/ocm/collector-contrib-verify.yaml)" + test -n "${SIGNING_IMAGE}" + test -n "${VERIFY_IMAGE}" + yq -i '(. | select(.kind == "Deployment") | .spec.template.spec.containers[] | select(.name == "otel-collector") | .image) = strenv(SIGNING_IMAGE)' showroom/kubectl/tier-1.yaml + yq -i '(. | select(.kind == "DaemonSet") | .spec.template.spec.containers[] | select(.name == "otel-collector") | .image) = strenv(VERIFY_IMAGE)' showroom/kubectl/tier-2.yaml + if git diff --quiet -- showroom/kubectl/tier-1.yaml showroom/kubectl/tier-2.yaml; then + echo "changed=false" >> "${GITHUB_OUTPUT}" + exit 0 + fi + echo "changed=true" >> "${GITHUB_OUTPUT}" + + - name: Create PR for synced tier manifests + if: github.event_name != 'pull_request' && steps.sync_tier_images.outputs.changed == 'true' + uses: peter-evans/create-pull-request@v7 + with: + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: "chore(showroom): sync tier collector images from OCM descriptors" + author: "gitops-bot " + committer: "gitops-bot " + branch: "ci/ocm-sync-tier-images" + delete-branch: true + title: "chore(showroom): sync tier collector images from OCM descriptors" + body: | + This PR was auto-generated by the OCM workflow. + + It syncs collector images in: + - `showroom/kubectl/tier-1.yaml` + - `showroom/kubectl/tier-2.yaml` + + Source of truth: + - `showroom/ocm/collector-contrib-signing.yaml` + - `showroom/ocm/collector-contrib-verify.yaml` + add-paths: | + showroom/kubectl/tier-1.yaml + showroom/kubectl/tier-2.yaml + labels: | + automation + ocm diff --git a/showroom/flux/tier-1-tier-2/kustomization.yaml b/showroom/flux/tier-1-tier-2/kustomization.yaml new file mode 100644 index 0000000..c71f974 --- /dev/null +++ b/showroom/flux/tier-1-tier-2/kustomization.yaml @@ -0,0 +1,5 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - ../../kubectl/tier-1.yaml + - ../../kubectl/tier-2.yaml diff --git a/showroom/kubectl/flux-tier-1-tier-2.yaml b/showroom/kubectl/flux-tier-1-tier-2.yaml new file mode 100644 index 0000000..59f62b4 --- /dev/null +++ b/showroom/kubectl/flux-tier-1-tier-2.yaml @@ -0,0 +1,26 @@ +# spec.ref.branch is the Git default in-repo; task showroom flux:install patches it to FLUX_GIT_BRANCH (CLI, .env, or CI). +apiVersion: source.toolkit.fluxcd.io/v1 +kind: GitRepository +metadata: + name: showroom-tier-sync + namespace: flux-system +spec: + interval: 1m + url: https://github.com/apeirora/audit-log-poc-for-otel.git + ref: + branch: showroom +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: showroom-tier-1-tier-2 + namespace: flux-system +spec: + interval: 1m + prune: true + wait: true + timeout: 3m + sourceRef: + kind: GitRepository + name: showroom-tier-sync + path: ./showroom/flux/tier-1-tier-2 diff --git a/showroom/kubectl/tier-1.yaml b/showroom/kubectl/tier-1.yaml index 0d0bfe7..76ef0c8 100644 --- a/showroom/kubectl/tier-1.yaml +++ b/showroom/kubectl/tier-1.yaml @@ -11,6 +11,7 @@ apiVersion: v1 kind: ConfigMap metadata: name: dice-java-otelcol-config + namespace: tier-1 data: config.yaml: | extensions: @@ -74,11 +75,13 @@ apiVersion: v1 kind: ServiceAccount metadata: name: dice-java-cert-sync + namespace: tier-1 --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: dice-java-cert-sync + namespace: tier-1 rules: - apiGroups: [""] resources: ["secrets"] @@ -88,6 +91,7 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: dice-java-cert-sync + namespace: tier-1 subjects: - kind: ServiceAccount name: dice-java-cert-sync @@ -100,6 +104,7 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: otelcol-agent-secret-reader + namespace: tier-1 rules: - apiGroups: [""] resources: ["secrets"] @@ -110,6 +115,7 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: otelcol-agent-secret-reader + namespace: tier-1 subjects: - kind: ServiceAccount name: otelcol-agent @@ -123,6 +129,7 @@ apiVersion: apps/v1 kind: Deployment metadata: name: dice-java + namespace: tier-1 labels: app: dice-java spec: @@ -252,6 +259,7 @@ apiVersion: v1 kind: Service metadata: name: dice-java + namespace: tier-1 labels: app: dice-java spec: diff --git a/showroom/kubectl/tier-2.yaml b/showroom/kubectl/tier-2.yaml index 324f70c..aeb02a3 100644 --- a/showroom/kubectl/tier-2.yaml +++ b/showroom/kubectl/tier-2.yaml @@ -7,12 +7,14 @@ apiVersion: v1 kind: ServiceAccount metadata: name: otelcol-agent + namespace: tier-2 --- # ConfigMap containing the OTel Collector Agent configuration apiVersion: v1 kind: ConfigMap metadata: name: otelcol-agent-config + namespace: tier-2 data: config.yaml: | extensions: @@ -122,6 +124,7 @@ apiVersion: apps/v1 kind: DaemonSet metadata: name: otelcol-agent + namespace: tier-2 labels: app: otelcol-agent component: otel-collector @@ -268,6 +271,7 @@ apiVersion: v1 kind: Service metadata: name: otelcol-agent + namespace: tier-2 labels: app: otelcol-agent component: otel-collector @@ -291,6 +295,7 @@ apiVersion: v1 kind: Service metadata: name: otelcol-agent-metrics + namespace: tier-2 labels: app: otelcol-agent component: otel-collector diff --git a/showroom/taskfile.yaml b/showroom/taskfile.yaml index 6a44fd2..1948142 100644 --- a/showroom/taskfile.yaml +++ b/showroom/taskfile.yaml @@ -34,6 +34,12 @@ includes: desc: OCM tasks. taskfile: ./tasks/ocm.yaml + flux: + desc: Flux GitOps tasks for tier-1 and tier-2. + taskfile: ./tasks/flux.yaml + vars: + FLUX_GIT_BRANCH: '{{ .FLUX_GIT_BRANCH | default "showroom" }}' + dice: desc: Install and manage the sample application (dice-java). taskfile: ./tasks/tier-1.yaml @@ -65,6 +71,15 @@ tasks: - task: otelcol-agent:install - task: dice:install + deploy-gitops: + desc: Install setup and let Flux reconcile tier-1 and tier-2 from git (Git ref.branch = FLUX_GIT_BRANCH, default showroom; use your PR branch for GitOps against a PR). + cmds: + - task: garden:set-kubeconfig + - task: cluster:install + - task: secrets:apply + - task: monitoring:install + - task: flux:install + clean: desc: Uninstall the complete setup, client applications (tier-1), OTel Collector agent (tier-2) and monitoring stack (tier-3) deps: diff --git a/showroom/tasks/flux.yaml b/showroom/tasks/flux.yaml new file mode 100644 index 0000000..cd10529 --- /dev/null +++ b/showroom/tasks/flux.yaml @@ -0,0 +1,82 @@ +version: "3" + +description: Taskfile for Flux reconciliation of tier-1 and tier-2. + +vars: + FLUX_GIT_BRANCH: '{{ default "showroom" (env "FLUX_GIT_BRANCH") }}' + +includes: + tools: + taskfile: ./tools.yaml + internal: true + cluster: + taskfile: ./cluster.yaml + internal: true + +tasks: + install: + desc: Install Flux GitRepository and Kustomization for tier-1 and tier-2. Set FLUX_GIT_BRANCH to your PR branch (or GITHUB_HEAD_REF in CI); defaults to showroom. Kustomize path stays showroom/flux/tier-1-tier-2. + deps: + - task: tools:install-kubectl + - task: cluster:install + requires: + vars: [KUBECTL_CMD] + preconditions: + - sh: "{{ .KUBECTL_CMD }} cluster-info >/dev/null 2>&1" + msg: "Please ensure that you have a k8s-cluster running. Try:\ttask garden:set-kubeconfig" + - sh: "{{ .KUBECTL_CMD }} get crd gitrepositories.source.toolkit.fluxcd.io >/dev/null 2>&1" + msg: "Flux CRDs are not installed. Install Flux first and retry." + cmds: + - 'echo "Flux GitRepository ref.branch={{ .FLUX_GIT_BRANCH }}"' + - "{{ .KUBECTL_CMD }} apply -f kubectl/flux-tier-1-tier-2.yaml" + - '{{ .KUBECTL_CMD }} -n flux-system patch gitrepository showroom-tier-sync --type merge -p "{\"spec\":{\"ref\":{\"branch\":\"{{ .FLUX_GIT_BRANCH }}\"}}}"' + - "{{ .KUBECTL_CMD }} -n flux-system wait --for=condition=Ready gitrepository/showroom-tier-sync --timeout=180s" + - "{{ .KUBECTL_CMD }} -n flux-system wait --for=condition=Ready kustomization/showroom-tier-1-tier-2 --timeout=180s" + + reconcile-unix: + internal: true + platforms: [linux, darwin] + requires: + vars: [KUBECTL_CMD] + cmds: + - '{{ .KUBECTL_CMD }} -n flux-system annotate --overwrite kustomization/showroom-tier-1-tier-2 reconcile.fluxcd.io/requestedAt="$(date -u +%Y-%m-%dT%H:%M:%SZ)"' + + reconcile-win: + internal: true + platforms: [windows] + requires: + vars: [KUBECTL_CMD] + cmds: + - powershell -NoProfile -Command "& { & '{{ .KUBECTL_CMD }}' -n flux-system annotate --overwrite kustomization/showroom-tier-1-tier-2 ('reconcile.fluxcd.io/requestedAt=' + (Get-Date).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ')) }" + + reconcile: + desc: Trigger immediate Flux reconciliation for tier-1 and tier-2. + deps: + - task: tools:install-kubectl + requires: + vars: [KUBECTL_CMD] + cmds: + - task: reconcile-unix + platforms: [linux, darwin] + - task: reconcile-win + platforms: [windows] + - "{{ .KUBECTL_CMD }} -n flux-system get kustomization showroom-tier-1-tier-2 -o wide" + + status: + desc: Show Flux status for tier-1 and tier-2 sync. + deps: + - task: tools:install-kubectl + requires: + vars: [KUBECTL_CMD] + cmds: + - "{{ .KUBECTL_CMD }} -n flux-system get gitrepository showroom-tier-sync -o wide" + - "{{ .KUBECTL_CMD }} -n flux-system get kustomization showroom-tier-1-tier-2 -o wide" + + uninstall: + desc: Remove Flux GitRepository and Kustomization for tier-1 and tier-2. + deps: + - task: tools:install-kubectl + requires: + vars: [KUBECTL_CMD] + cmds: + - "{{ .KUBECTL_CMD }} delete -f kubectl/flux-tier-1-tier-2.yaml --ignore-not-found" diff --git a/showroom/tasks/secrets.yaml b/showroom/tasks/secrets.yaml new file mode 100644 index 0000000..5c3a28b --- /dev/null +++ b/showroom/tasks/secrets.yaml @@ -0,0 +1,43 @@ +version: "3" + +description: Taskfile for listing, exporting, and applying workload secrets. + +includes: + tools: + taskfile: ./tools.yaml + internal: true + +tasks: + list: + desc: List all secrets in tier-1, tier-2, and tier-3. + deps: + - task: tools:install-kubectl + cmds: + - "kubectl get secrets -n tier-1 -o wide" + - "kubectl get secrets -n tier-2 -o wide" + - "kubectl get secrets -n tier-3 -o wide" + + export: + desc: Export required tier-1 and tier-2 secrets to kubectl/secrets.local.yaml. + deps: + - task: tools:install-kubectl + cmds: + - "kubectl get secret dice-java-openbao-token -n tier-1 -o yaml --show-managed-fields=false > kubectl/secrets.local.yaml" + - "echo --- >> kubectl/secrets.local.yaml" + - "kubectl get secret otel-otlp-client-auth -n tier-1 -o yaml --show-managed-fields=false >> kubectl/secrets.local.yaml" + - "echo --- >> kubectl/secrets.local.yaml" + - "kubectl get secret otel-otlp-ingest-htpasswd -n tier-2 -o yaml --show-managed-fields=false >> kubectl/secrets.local.yaml" + - "echo --- >> kubectl/secrets.local.yaml" + - "kubectl get secret opensearch-credentials -n tier-2 -o yaml --show-managed-fields=false >> kubectl/secrets.local.yaml" + - "echo --- >> kubectl/secrets.local.yaml" + - "kubectl get secret opensearch-ca-cert -n tier-2 -o yaml --show-managed-fields=false >> kubectl/secrets.local.yaml" + + apply: + desc: Apply secrets from local file kubectl/secrets.local.yaml. + deps: + - task: tools:install-kubectl + preconditions: + - sh: 'test -f "kubectl/secrets.local.yaml"' + msg: "Missing kubectl/secrets.local.yaml. Run task secrets:export first." + cmds: + - "kubectl apply -f kubectl/secrets.local.yaml"