From 1ba8752fbfb9d9da709c02398516d2807883b7c6 Mon Sep 17 00:00:00 2001 From: Philipp Markiewka Date: Tue, 21 Oct 2025 14:05:30 +0200 Subject: [PATCH 1/6] feat(content): laod example-apps via content-loader functionality - Move example-app definitions from `argocd/example-apps` and `applications/` into `examples/example-apps-via-content-loader` - Adjust Dockerfile to initialize example-apps folder as standalone git repo for content-loader - Update `GitopsPlaygroundCli` to include content examples via `--content.examples` flag - Extend config merging logic (`MapUtils.deepMerge`) to support additional example content source - Update schema, configurator, and tests to handle example-apps path and validation - Clean up redundant templates and adjust paths accordingly This refactor isolates example application definitions into a dedicated content-loader directory, simplifying configuration handling and enabling dynamic content loading via the CLI. --- .dockerignore | 1 + Dockerfile | 27 +- .../argocd/nginx/helm-jenkins/README.md | 6 - .../argocd/nginx/helm-jenkins/index.html | 11 - .../k8s/values-production.ftl.yaml | 12 - .../argocd/nginx/helm-umbrella/README.md | 2 - .../helm/k8s/production/configMap.ftl.yaml | 17 - .../helm/k8s/staging/configMap.ftl.yaml | 17 - .../helm/k8s/values-production.ftl.yaml | 13 - .../helm/k8s/values-staging.ftl.yaml | 13 - argocd/example-apps/README.md | 1 - .../argocd/exercise-nginx-helm.ftl.yaml | 53 --- .../argocd/exercise-petclinic-helm.ftl.yaml | 53 --- argocd/example-apps/argocd/misc.ftl.yaml | 60 --- docs/configuration.schema.json | 111 ------ .../argocd/applications/example-apps.ftl.yaml | 2 +- .../argocd/projects/example-apps.ftl.yaml | 17 +- .../argocd}/example-apps/apps/.gitkeep | 0 .../argocd/example-apps/argocd/misc.ftl.yaml | 24 ++ .../argocd/nginx-helm-jenkins.ftl.yaml | 14 +- .../argocd/nginx-helm-umbrella.ftl.yaml | 6 +- .../argocd/petclinic-helm.ftl.yaml | 14 +- .../argocd/petclinic-plain.ftl.yaml | 14 +- .../argocd}/example-apps/misc/.gitkeep | 0 .../argocd}/helm-umbrella/Chart.yaml | 0 .../argocd/helm-umbrella/README.md | 0 .../argocd}/helm-umbrella/values.ftl.yaml | 10 +- .../nginx-helm-jenkins}/Jenkinsfile.ftl | 10 +- .../argocd/nginx-helm-jenkins/README.md | 0 .../argocd/nginx-helm-jenkins/index.html | 0 .../k8s/production/external-secret.ftl.yaml | 2 + .../k8s/staging/external-secret.ftl.yaml | 2 + .../k8s/values-production.ftl.yaml | 8 +- .../k8s/values-shared.ftl.yaml | 4 +- .../k8s/values-staging.ftl.yaml | 12 + .../argocd/petclinic-helm}/Dockerfile.ftl | 2 +- .../argocd/petclinic-helm}/Jenkinsfile.ftl | 26 +- .../k8s/production/configMap.ftl.yaml | 0 .../k8s/production/secrets/secret.ftl.yaml | 0 .../k8s/production/secrets/secret2.ftl.yaml | 0 .../k8s/staging/configMap.ftl.yaml | 0 .../k8s/staging/secrets/secret.ftl.yaml | 0 .../k8s/staging/secrets/secret2.ftl.yaml | 0 .../k8s/values-production.ftl.yaml | 13 + .../k8s/values-shared.ftl.yaml | 7 +- .../k8s/values-staging.ftl.yaml | 13 + .../argocd/petclinic-plain/Dockerfile.ftl | 13 + .../argocd/petclinic-plain}/Jenkinsfile.ftl | 26 +- .../k8s/production/deployment.ftl.yaml | 0 .../k8s/production}/ingress.ftl.yaml | 6 +- .../k8s/production/service.ftl.yaml | 0 .../k8s/staging/deployment.ftl.yaml | 0 .../k8s/staging}/ingress.ftl.yaml | 6 +- .../k8s/staging/service.ftl.yaml | 0 .../config.yaml | 47 +++ scripts/scm-manager/init-scmm.sh | 44 --- .../gitops/cli/GitopsPlaygroundCli.groovy | 10 +- .../config/ApplicationConfigurator.groovy | 13 - .../com/cloudogu/gitops/config/Config.groovy | 89 ----- .../cloudogu/gitops/features/Jenkins.groovy | 8 - .../gitops/features/ScmManager.groovy | 41 -- .../gitops/features/argocd/ArgoCD.groovy | 103 ------ .../com/cloudogu/gitops/utils/MapUtils.groovy | 23 +- .../gitops/ApplicationConfiguratorTest.groovy | 28 -- .../schema/JsonConfigValidatorTest.groovy | 18 - .../gitops/features/ScmManagerTest.groovy | 17 - .../gitops/features/argocd/ArgoCDTest.groovy | 349 +----------------- src/test/resources/testMainConfig.yaml | 25 -- 68 files changed, 239 insertions(+), 1224 deletions(-) delete mode 100644 applications/argocd/nginx/helm-jenkins/README.md delete mode 100644 applications/argocd/nginx/helm-jenkins/index.html delete mode 100644 applications/argocd/nginx/helm-jenkins/k8s/values-production.ftl.yaml delete mode 100644 applications/argocd/nginx/helm-umbrella/README.md delete mode 100644 applications/argocd/petclinic/helm/k8s/production/configMap.ftl.yaml delete mode 100644 applications/argocd/petclinic/helm/k8s/staging/configMap.ftl.yaml delete mode 100644 applications/argocd/petclinic/helm/k8s/values-production.ftl.yaml delete mode 100644 applications/argocd/petclinic/helm/k8s/values-staging.ftl.yaml delete mode 100644 argocd/example-apps/README.md delete mode 100644 argocd/example-apps/argocd/exercise-nginx-helm.ftl.yaml delete mode 100644 argocd/example-apps/argocd/exercise-petclinic-helm.ftl.yaml delete mode 100644 argocd/example-apps/argocd/misc.ftl.yaml rename {argocd => examples/example-apps-via-content-loader/argocd}/argocd/applications/example-apps.ftl.yaml (82%) rename {argocd => examples/example-apps-via-content-loader/argocd}/argocd/projects/example-apps.ftl.yaml (56%) rename {argocd => examples/example-apps-via-content-loader/argocd}/example-apps/apps/.gitkeep (100%) create mode 100644 examples/example-apps-via-content-loader/argocd/example-apps/argocd/misc.ftl.yaml rename {argocd => examples/example-apps-via-content-loader/argocd}/example-apps/argocd/nginx-helm-jenkins.ftl.yaml (71%) rename {argocd => examples/example-apps-via-content-loader/argocd}/example-apps/argocd/nginx-helm-umbrella.ftl.yaml (71%) rename {argocd => examples/example-apps-via-content-loader/argocd}/example-apps/argocd/petclinic-helm.ftl.yaml (71%) rename {argocd => examples/example-apps-via-content-loader/argocd}/example-apps/argocd/petclinic-plain.ftl.yaml (71%) rename {argocd => examples/example-apps-via-content-loader/argocd}/example-apps/misc/.gitkeep (100%) rename {applications/argocd/nginx => examples/example-apps-via-content-loader/argocd}/helm-umbrella/Chart.yaml (100%) create mode 100644 examples/example-apps-via-content-loader/argocd/helm-umbrella/README.md rename {applications/argocd/nginx => examples/example-apps-via-content-loader/argocd}/helm-umbrella/values.ftl.yaml (67%) rename {applications/argocd/nginx/helm-jenkins => examples/example-apps-via-content-loader/argocd/nginx-helm-jenkins}/Jenkinsfile.ftl (90%) create mode 100644 examples/example-apps-via-content-loader/argocd/nginx-helm-jenkins/README.md create mode 100644 examples/example-apps-via-content-loader/argocd/nginx-helm-jenkins/index.html rename applications/argocd/nginx/helm-jenkins/k8s/production/external-secret.yaml => examples/example-apps-via-content-loader/argocd/nginx-helm-jenkins/k8s/production/external-secret.ftl.yaml (90%) rename applications/argocd/nginx/helm-jenkins/k8s/staging/external-secret.yaml => examples/example-apps-via-content-loader/argocd/nginx-helm-jenkins/k8s/staging/external-secret.ftl.yaml (90%) rename applications/argocd/nginx/helm-jenkins/k8s/values-staging.ftl.yaml => examples/example-apps-via-content-loader/argocd/nginx-helm-jenkins/k8s/values-production.ftl.yaml (51%) rename {applications/argocd/nginx/helm-jenkins => examples/example-apps-via-content-loader/argocd/nginx-helm-jenkins}/k8s/values-shared.ftl.yaml (89%) create mode 100644 examples/example-apps-via-content-loader/argocd/nginx-helm-jenkins/k8s/values-staging.ftl.yaml rename {applications/argocd/petclinic => examples/example-apps-via-content-loader/argocd/petclinic-helm}/Dockerfile.ftl (87%) rename {applications/argocd/petclinic/helm => examples/example-apps-via-content-loader/argocd/petclinic-helm}/Jenkinsfile.ftl (86%) create mode 100644 examples/example-apps-via-content-loader/argocd/petclinic-helm/k8s/production/configMap.ftl.yaml rename {applications/argocd/petclinic/helm => examples/example-apps-via-content-loader/argocd/petclinic-helm}/k8s/production/secrets/secret.ftl.yaml (100%) rename {applications/argocd/petclinic/helm => examples/example-apps-via-content-loader/argocd/petclinic-helm}/k8s/production/secrets/secret2.ftl.yaml (100%) create mode 100644 examples/example-apps-via-content-loader/argocd/petclinic-helm/k8s/staging/configMap.ftl.yaml rename {applications/argocd/petclinic/helm => examples/example-apps-via-content-loader/argocd/petclinic-helm}/k8s/staging/secrets/secret.ftl.yaml (100%) rename {applications/argocd/petclinic/helm => examples/example-apps-via-content-loader/argocd/petclinic-helm}/k8s/staging/secrets/secret2.ftl.yaml (100%) create mode 100644 examples/example-apps-via-content-loader/argocd/petclinic-helm/k8s/values-production.ftl.yaml rename {applications/argocd/petclinic/helm => examples/example-apps-via-content-loader/argocd/petclinic-helm}/k8s/values-shared.ftl.yaml (77%) create mode 100644 examples/example-apps-via-content-loader/argocd/petclinic-helm/k8s/values-staging.ftl.yaml create mode 100644 examples/example-apps-via-content-loader/argocd/petclinic-plain/Dockerfile.ftl rename {applications/argocd/petclinic/plain-k8s => examples/example-apps-via-content-loader/argocd/petclinic-plain}/Jenkinsfile.ftl (90%) rename {applications/argocd/petclinic/plain-k8s => examples/example-apps-via-content-loader/argocd/petclinic-plain}/k8s/production/deployment.ftl.yaml (100%) rename {applications/argocd/petclinic/plain-k8s/k8s/staging => examples/example-apps-via-content-loader/argocd/petclinic-plain/k8s/production}/ingress.ftl.yaml (71%) rename {applications/argocd/petclinic/plain-k8s => examples/example-apps-via-content-loader/argocd/petclinic-plain}/k8s/production/service.ftl.yaml (100%) rename {applications/argocd/petclinic/plain-k8s => examples/example-apps-via-content-loader/argocd/petclinic-plain}/k8s/staging/deployment.ftl.yaml (100%) rename {applications/argocd/petclinic/plain-k8s/k8s/production => examples/example-apps-via-content-loader/argocd/petclinic-plain/k8s/staging}/ingress.ftl.yaml (63%) rename {applications/argocd/petclinic/plain-k8s => examples/example-apps-via-content-loader/argocd/petclinic-plain}/k8s/staging/service.ftl.yaml (100%) create mode 100644 examples/example-apps-via-content-loader/config.yaml diff --git a/.dockerignore b/.dockerignore index fc4449634..1e5cd1d7f 100644 --- a/.dockerignore +++ b/.dockerignore @@ -3,6 +3,7 @@ # Allowlist !applications/ +!examples/ !exercises/ !argocd/ !docker-registry/ diff --git a/Dockerfile b/Dockerfile index 6f4ef117b..854bc784e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -218,7 +218,8 @@ ENV HOME=/home \ GITOPS_BUILD_LIB_REPO=/gitops/repos/gitops-build-lib.git \ CES_BUILD_LIB_REPO=/gitops/repos/ces-build-lib.git \ JENKINS_PLUGIN_FOLDER=/gitops/jenkins-plugins/ \ - LOCAL_HELM_CHART_FOLDER=/gitops/charts/ + LOCAL_HELM_CHART_FOLDER=/gitops/charts/ \ + EXAMPLE_APPS_CONTENT_REPO=/app/examples/example-apps-via-content-loader WORKDIR /app @@ -232,10 +233,30 @@ RUN apk update --no-cache && apk upgrade --no-cache && \ git \ unzip -USER 1000:0 - COPY --from=downloader /dist / +# Set example apps config to use the repos from the image +RUN sed -i \ + -e "s|url: https://github.com/cloudogu/gitops-build-lib|url: 'file://$GITOPS_BUILD_LIB_REPO'|g" \ + -e "s|url: https://github.com/cloudogu/ces-build-lib|url: 'file://$CES_BUILD_LIB_REPO'|g" \ + -e "s|url: https://github.com/cloudogu/spring-boot-helm-chart|url: 'file://$SPRING_BOOT_HELM_CHART_REPO'|g" \ + -e "s|url: https://github.com/cloudogu/spring-petclinic|url: 'file://$SPRING_PETCLINIC_REPO'|g" \ + -e "s|url: https://github.com/cloudogu/gitops-playground|url: 'file://$EXAMPLE_APPS_CONTENT_REPO'|g" \ + -e "/^[[:space:]]*path: examples\/example-apps-via-content-loader\//d" \ + /app/examples/example-apps-via-content-loader/config.yaml + +# Initialize example apps folder with git, so we can use it with content-loader +# we need safe.directory setting because of: fatal: detected dubious ownership in repository at '/app/examples/example-apps-via-content-loader' +RUN git -C /app/examples/example-apps-via-content-loader init -b main && \ + git -C /app/examples/example-apps-via-content-loader config user.email "noreply@example.com" && \ + git -C /app/examples/example-apps-via-content-loader config user.name "Container" && \ + git -C /app/examples/example-apps-via-content-loader add -A && \ + git -C /app/examples/example-apps-via-content-loader commit -m "initial commit" && \ + git config --global --add safe.directory /app/examples/example-apps-via-content-loader + + +USER 1000:0 + ARG VCS_REF ARG BUILD_DATE LABEL org.opencontainers.image.title="gitops-playground" \ diff --git a/applications/argocd/nginx/helm-jenkins/README.md b/applications/argocd/nginx/helm-jenkins/README.md deleted file mode 100644 index 026c5205d..000000000 --- a/applications/argocd/nginx/helm-jenkins/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# nginx-helm-jenkins - -3rd Party app (NGINX) with Helm, templated in Jenkins using the gitops-build-lib. - -When vault is enabled, this example also integrates an external secret that is managed in Vault. -You can see this secret when visiting `/secret`. diff --git a/applications/argocd/nginx/helm-jenkins/index.html b/applications/argocd/nginx/helm-jenkins/index.html deleted file mode 100644 index d4ceee9d1..000000000 --- a/applications/argocd/nginx/helm-jenkins/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - cloudogu/gitops-playground - - -

Hello cloudogu gitops playground!

- - \ No newline at end of file diff --git a/applications/argocd/nginx/helm-jenkins/k8s/values-production.ftl.yaml b/applications/argocd/nginx/helm-jenkins/k8s/values-production.ftl.yaml deleted file mode 100644 index fa9937375..000000000 --- a/applications/argocd/nginx/helm-jenkins/k8s/values-production.ftl.yaml +++ /dev/null @@ -1,12 +0,0 @@ -namespaceOverride: ${config.application.namePrefix}example-apps-production - -<#if config.features.exampleApps.nginx.baseDomain?has_content> -ingress: - enabled: true - pathType: Prefix - <#if config.application.urlSeparatorHyphen> - hostname: production-nginx-helm-${config.features.exampleApps.nginx.baseDomain} - <#else> - hostname: production.nginx-helm.${config.features.exampleApps.nginx.baseDomain} - - diff --git a/applications/argocd/nginx/helm-umbrella/README.md b/applications/argocd/nginx/helm-umbrella/README.md deleted file mode 100644 index b5726758d..000000000 --- a/applications/argocd/nginx/helm-umbrella/README.md +++ /dev/null @@ -1,2 +0,0 @@ -3rd Party app (NGINX) with helm, templated by argo from a separate git repo, using helm's dependency mechanism. -This is an alternative approach to keeping the values.yaml inside the `application`. \ No newline at end of file diff --git a/applications/argocd/petclinic/helm/k8s/production/configMap.ftl.yaml b/applications/argocd/petclinic/helm/k8s/production/configMap.ftl.yaml deleted file mode 100644 index b688fa4c8..000000000 --- a/applications/argocd/petclinic/helm/k8s/production/configMap.ftl.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: configmap-sample -data: - # property-like keys; each key maps to a simple value - player_initial_lives: "3" - ui_properties_file_name: "user-interface.properties" - - # file-like keys - game.properties: | - enemy.types=aliens,monsters - player.maximum-lives=5 - user-interface.properties: | - color.good=purple - color.bad=yellow - allow.textmode=true diff --git a/applications/argocd/petclinic/helm/k8s/staging/configMap.ftl.yaml b/applications/argocd/petclinic/helm/k8s/staging/configMap.ftl.yaml deleted file mode 100644 index b688fa4c8..000000000 --- a/applications/argocd/petclinic/helm/k8s/staging/configMap.ftl.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: configmap-sample -data: - # property-like keys; each key maps to a simple value - player_initial_lives: "3" - ui_properties_file_name: "user-interface.properties" - - # file-like keys - game.properties: | - enemy.types=aliens,monsters - player.maximum-lives=5 - user-interface.properties: | - color.good=purple - color.bad=yellow - allow.textmode=true diff --git a/applications/argocd/petclinic/helm/k8s/values-production.ftl.yaml b/applications/argocd/petclinic/helm/k8s/values-production.ftl.yaml deleted file mode 100644 index b7528242d..000000000 --- a/applications/argocd/petclinic/helm/k8s/values-production.ftl.yaml +++ /dev/null @@ -1,13 +0,0 @@ -service: - port: 80 - -<#if config.features.exampleApps.petclinic.baseDomain?has_content> -ingress: - hosts: - <#if config.application.urlSeparatorHyphen> - - host: production-petclinic-helm-${config.features.exampleApps.petclinic.baseDomain} - <#else> - - host: production.petclinic-helm.${config.features.exampleApps.petclinic.baseDomain} - - paths: ['/'] - diff --git a/applications/argocd/petclinic/helm/k8s/values-staging.ftl.yaml b/applications/argocd/petclinic/helm/k8s/values-staging.ftl.yaml deleted file mode 100644 index b0eab58c7..000000000 --- a/applications/argocd/petclinic/helm/k8s/values-staging.ftl.yaml +++ /dev/null @@ -1,13 +0,0 @@ -service: - port: 80 - -<#if config.features.exampleApps.petclinic.baseDomain?has_content> -ingress: - hosts: - <#if config.application.urlSeparatorHyphen> - - host: staging-petclinic-helm-${config.features.exampleApps.petclinic.baseDomain} - <#else> - - host: staging.petclinic-helm.${config.features.exampleApps.petclinic.baseDomain} - - paths: ['/'] - diff --git a/argocd/example-apps/README.md b/argocd/example-apps/README.md deleted file mode 100644 index 143c98de3..000000000 --- a/argocd/example-apps/README.md +++ /dev/null @@ -1 +0,0 @@ -Contains examples of end-user applications \ No newline at end of file diff --git a/argocd/example-apps/argocd/exercise-nginx-helm.ftl.yaml b/argocd/example-apps/argocd/exercise-nginx-helm.ftl.yaml deleted file mode 100644 index 0e665aff3..000000000 --- a/argocd/example-apps/argocd/exercise-nginx-helm.ftl.yaml +++ /dev/null @@ -1,53 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: -<#if config.features.argocd.operator> - name: exercise-nginx-helm-staging - namespace: ${config.application.namePrefix}argocd -<#else> - name: exercise-nginx-helm - namespace: ${config.application.namePrefix}example-apps-staging - -spec: - destination: - namespace: ${config.application.namePrefix}example-apps-staging - server: https://kubernetes.default.svc - project: example-apps - source: - path: apps/exercise-nginx-helm/staging - repoURL: ${scmm.repoUrl}argocd/example-apps - targetRevision: main - directory: - recurse: true - syncPolicy: - automated: - prune: true - selfHeal: true - ---- - -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: -<#if config.features.argocd.operator> - name: exercise-nginx-helm-production - namespace: ${config.application.namePrefix}argocd -<#else> - name: exercise-nginx-helm - namespace: ${config.application.namePrefix}example-apps-production - -spec: - destination: - namespace: ${config.application.namePrefix}example-apps-production - server: https://kubernetes.default.svc - project: example-apps - source: - path: apps/exercise-nginx-helm/production - repoURL: ${scmm.repoUrl}argocd/example-apps - targetRevision: main - directory: - recurse: true - syncPolicy: - automated: - prune: true - selfHeal: true \ No newline at end of file diff --git a/argocd/example-apps/argocd/exercise-petclinic-helm.ftl.yaml b/argocd/example-apps/argocd/exercise-petclinic-helm.ftl.yaml deleted file mode 100644 index 12c5985c9..000000000 --- a/argocd/example-apps/argocd/exercise-petclinic-helm.ftl.yaml +++ /dev/null @@ -1,53 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: -<#if config.features.argocd.operator> - name: exercise-petclinic-helm-staging - namespace: ${config.application.namePrefix}argocd -<#else> - name: exercise-petclinic-helm - namespace: ${config.application.namePrefix}example-apps-staging - -spec: - destination: - namespace: ${config.application.namePrefix}example-apps-staging - server: https://kubernetes.default.svc - project: example-apps - source: - path: apps/exercise-spring-petclinic-helm/staging - repoURL: ${scmm.repoUrl}argocd/example-apps - targetRevision: main - directory: - recurse: true - syncPolicy: - automated: - prune: true - selfHeal: true - ---- - -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: -<#if config.features.argocd.operator> - name: exercise-petclinic-helm-production - namespace: ${config.application.namePrefix}argocd -<#else> - name: exercise-petclinic-helm - namespace: ${config.application.namePrefix}example-apps-production - -spec: - destination: - namespace: ${config.application.namePrefix}example-apps-production - server: https://kubernetes.default.svc - project: example-apps - source: - path: apps/exercise-spring-petclinic-helm/production - repoURL: ${scmm.repoUrl}argocd/example-apps - targetRevision: main - directory: - recurse: true - syncPolicy: - automated: - prune: true - selfHeal: true \ No newline at end of file diff --git a/argocd/example-apps/argocd/misc.ftl.yaml b/argocd/example-apps/argocd/misc.ftl.yaml deleted file mode 100644 index e7c99fb77..000000000 --- a/argocd/example-apps/argocd/misc.ftl.yaml +++ /dev/null @@ -1,60 +0,0 @@ -# this misc-Application manages all resources in the misc folder in the gitops repository -# use the misc folder to deploy resources, which are needed for multiple other apps such as ServiceAccounts or shared ConfigMaps -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: -<#if config.features.argocd.operator> - name: misc-example-apps-production - namespace: ${config.application.namePrefix}argocd -<#else> - name: misc - namespace: ${config.application.namePrefix}example-apps-production - -spec: - project: example-apps - destination: - server: https://kubernetes.default.svc - # a namespace must be specified here, because teams are not allowed to deploy cluster-wide. - # You can specify a different namespace in the ressource YAMLs, if you are permitted to deploy in them - namespace: ${config.application.namePrefix}example-apps-production - source: - path: misc/ - repoURL: ${scmm.repoUrl}argocd/example-apps - targetRevision: main - directory: - recurse: true - syncPolicy: - automated: - prune: true - selfHeal: true -<#if config.multiTenant.centralSCMUrl?has_content> ---- -apiVersion: argoproj.io/v1alpha1 -kind: AppProject -metadata: - name: example-apps - namespace: ${config.application.namePrefix}argocd -spec: - description: Contains examples of end-user application - destinations: - - namespace: ${config.application.namePrefix}example-apps-production - server: https://kubernetes.default.svc - - namespace: ${config.application.namePrefix}example-apps-staging - server: https://kubernetes.default.svc - - namespace: ${config.application.namePrefix}argocd - server: https://kubernetes.default.svc - sourceRepos: - - http://scmm.${config.application.namePrefix}scm-manager.svc.cluster.local/scm/repo/${config.application.namePrefix}argocd/example-apps - - http://scmm.${config.application.namePrefix}scm-manager.svc.cluster.local/scm/repo/${config.application.namePrefix}argocd/nginx-helm-umbrella - - sourceNamespaces: - - ${config.application.namePrefix}example-apps-staging - - ${config.application.namePrefix}example-apps-production - - ${config.application.namePrefix}argocd - - namespaceResourceWhitelist: - - group: '*' - kind: '*' - - clusterResourceWhitelist: [] - \ No newline at end of file diff --git a/docs/configuration.schema.json b/docs/configuration.schema.json index 53543e25a..bb4758107 100644 --- a/docs/configuration.schema.json +++ b/docs/configuration.schema.json @@ -1,16 +1,6 @@ { "$schema" : "https://json-schema.org/draft/2020-12/schema", "$defs" : { - "ExampleAppSchema-nullable" : { - "type" : [ "object", "null" ], - "properties" : { - "baseDomain" : { - "type" : [ "string", "null" ], - "description" : "The domain under which a subdomain these applications will be made available" - } - }, - "additionalProperties" : false - }, "HelmConfigWithValues-nullable" : { "type" : [ "object", "null" ], "properties" : { @@ -41,30 +31,6 @@ "additionalProperties" : { "type" : "string" } - }, - "RepositorySchema-nullable" : { - "type" : [ "object", "null" ], - "properties" : { - "url" : { - "type" : [ "string", "null" ], - "description" : "HTTP URL of the repo" - } - }, - "additionalProperties" : false - }, - "RepositorySchemaWithRef-nullable" : { - "type" : [ "object", "null" ], - "properties" : { - "ref" : { - "type" : [ "string", "null" ], - "description" : "Ref of the repo to use, e.g. a tag, commit or branch" - }, - "url" : { - "type" : [ "string", "null" ], - "description" : "HTTP URL of the repo" - } - }, - "additionalProperties" : false } }, "type" : "object", @@ -336,21 +302,6 @@ "additionalProperties" : false, "description" : "Config parameters for the Cert Manager" }, - "exampleApps" : { - "type" : [ "object", "null" ], - "properties" : { - "nginx" : { - "$ref" : "#/$defs/ExampleAppSchema-nullable", - "description" : "Config parameters for the NGINX example apps apps and exercises" - }, - "petclinic" : { - "$ref" : "#/$defs/ExampleAppSchema-nullable", - "description" : "Config parameters for the petclinic example apps apps and exercises" - } - }, - "additionalProperties" : false, - "description" : "Config parameters for the example apps and exercises" - }, "ingressNginx" : { "type" : [ "object", "null" ], "properties" : { @@ -613,45 +564,6 @@ "additionalProperties" : false, "description" : "Config parameters for features or tools" }, - "images" : { - "type" : [ "object", "null" ], - "properties" : { - "helm" : { - "type" : [ "string", "null" ], - "description" : "Sets image for helm" - }, - "helmKubeval" : { - "type" : [ "string", "null" ], - "description" : "Sets image for helmkubeval" - }, - "kubectl" : { - "type" : [ "string", "null" ], - "description" : "Sets image for kubectl" - }, - "kubeval" : { - "type" : [ "string", "null" ], - "description" : "Sets image for kubeval" - }, - "maven" : { - "type" : [ "string", "null" ], - "description" : "Sets image for maven" - }, - "nginx" : { - "type" : [ "string", "null" ], - "description" : "Sets image for nginx used in various applications" - }, - "petclinic" : { - "type" : [ "string", "null" ], - "description" : "Sets image for petclinic used in various applications" - }, - "yamllint" : { - "type" : [ "string", "null" ], - "description" : "Sets image for yamllint" - } - }, - "additionalProperties" : false, - "description" : "Config params for images that do not belong to specific features" - }, "jenkins" : { "type" : [ "object", "null" ], "properties" : { @@ -804,29 +716,6 @@ "additionalProperties" : false, "description" : "Config parameters for Registry" }, - "repositories" : { - "type" : [ "object", "null" ], - "properties" : { - "cesBuildLib" : { - "$ref" : "#/$defs/RepositorySchema-nullable", - "description" : "Repo to pull the ces-build-lib, used in examples and exercises as depedency of the gitops-build-lib" - }, - "gitopsBuildLib" : { - "$ref" : "#/$defs/RepositorySchema-nullable", - "description" : "Repo to pull the gitops-build-lib, used in examples and exercises" - }, - "springBootHelmChart" : { - "$ref" : "#/$defs/RepositorySchemaWithRef-nullable", - "description" : "Repo to pull the generic Spring Boot Helm chart, used in examples and exercises" - }, - "springPetclinic" : { - "$ref" : "#/$defs/RepositorySchemaWithRef-nullable", - "description" : "Repo to pull the Spring Petclinic, used in examples and exercises" - } - }, - "additionalProperties" : false, - "description" : "Config params for repositories used within GOP" - }, "scmm" : { "type" : [ "object", "null" ], "properties" : { diff --git a/argocd/argocd/applications/example-apps.ftl.yaml b/examples/example-apps-via-content-loader/argocd/argocd/applications/example-apps.ftl.yaml similarity index 82% rename from argocd/argocd/applications/example-apps.ftl.yaml rename to examples/example-apps-via-content-loader/argocd/argocd/applications/example-apps.ftl.yaml index 02f9402d3..9d9bdcf1b 100644 --- a/argocd/argocd/applications/example-apps.ftl.yaml +++ b/examples/example-apps-via-content-loader/argocd/argocd/applications/example-apps.ftl.yaml @@ -13,7 +13,7 @@ spec: project: argocd source: path: argocd/ - repoURL: ${scmm.repoUrl}argocd/example-apps<#if config.scmm.provider == "gitlab">.git + repoURL: "http://scmm.${config.application.namePrefix}scm-manager.svc.cluster.local/scm/repo/${config.application.namePrefix}argocd/example-apps" targetRevision: main directory: recurse: true diff --git a/argocd/argocd/projects/example-apps.ftl.yaml b/examples/example-apps-via-content-loader/argocd/argocd/projects/example-apps.ftl.yaml similarity index 56% rename from argocd/argocd/projects/example-apps.ftl.yaml rename to examples/example-apps-via-content-loader/argocd/argocd/projects/example-apps.ftl.yaml index e10024b03..17ce5a9a5 100644 --- a/argocd/argocd/projects/example-apps.ftl.yaml +++ b/examples/example-apps-via-content-loader/argocd/argocd/projects/example-apps.ftl.yaml @@ -4,9 +4,6 @@ metadata: name: example-apps namespace: ${config.application.namePrefix}argocd annotations: -<#if config.features.mail.active?? && config.features.mail.active> - notifications.argoproj.io/subscribe.email: ${config.features.argocd.emailToUser} - spec: description: Contains examples of end-user applications destinations: @@ -15,17 +12,15 @@ spec: - namespace: ${config.application.namePrefix}example-apps-staging server: https://kubernetes.default.svc sourceRepos: - - ${scmm.repoUrl}argocd/example-apps<#if config.scmm.provider == "gitlab">.git - - ${scmm.repoUrl}argocd/nginx-helm-umbrella<#if config.scmm.provider == "gitlab">.git + - http://scmm.${config.application.namePrefix}scm-manager.svc.cluster.local/scm/repo/${config.application.namePrefix}argocd/example-apps + - http://scmm.${config.application.namePrefix}scm-manager.svc.cluster.local/scm/repo/${config.application.namePrefix}argocd/nginx-helm-umbrella # allow to only see application resources from the specified namespace sourceNamespaces: - - '${config.application.namePrefix}example-apps-staging' - - '${config.application.namePrefix}example-apps-production' - <#if config.features.argocd.operator> - - '${config.application.namePrefix}argocd' - + - ${config.application.namePrefix}example-apps-staging + - ${config.application.namePrefix}example-apps-production + - ${config.application.namePrefix}argocd # Allow all namespaced-scoped resources to be created @@ -34,4 +29,4 @@ spec: kind: '*' # Deny all cluster-scoped resources from being created. Least privilege. - clusterResourceWhitelist: \ No newline at end of file + clusterResourceWhitelist: diff --git a/argocd/example-apps/apps/.gitkeep b/examples/example-apps-via-content-loader/argocd/example-apps/apps/.gitkeep similarity index 100% rename from argocd/example-apps/apps/.gitkeep rename to examples/example-apps-via-content-loader/argocd/example-apps/apps/.gitkeep diff --git a/examples/example-apps-via-content-loader/argocd/example-apps/argocd/misc.ftl.yaml b/examples/example-apps-via-content-loader/argocd/example-apps/argocd/misc.ftl.yaml new file mode 100644 index 000000000..370ca5e83 --- /dev/null +++ b/examples/example-apps-via-content-loader/argocd/example-apps/argocd/misc.ftl.yaml @@ -0,0 +1,24 @@ +# this misc-Application manages all resources in the misc folder in the gitops repository +# use the misc folder to deploy resources, which are needed for multiple other apps such as ServiceAccounts or shared ConfigMaps +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: misc-example-apps-production + namespace: ${config.application.namePrefix}argocd +spec: + project: example-apps + destination: + server: https://kubernetes.default.svc + # a namespace must be specified here, because teams are not allowed to deploy cluster-wide. + # You can specify a different namespace in the ressource YAMLs, if you are permitted to deploy in them + namespace: ${config.application.namePrefix}example-apps-production + source: + path: misc/ + repoURL: "http://scmm.${config.application.namePrefix}scm-manager.svc.cluster.local/scm/repo/${config.application.namePrefix}argocd/example-apps" + targetRevision: main + directory: + recurse: true + syncPolicy: + automated: + prune: true + selfHeal: true diff --git a/argocd/example-apps/argocd/nginx-helm-jenkins.ftl.yaml b/examples/example-apps-via-content-loader/argocd/example-apps/argocd/nginx-helm-jenkins.ftl.yaml similarity index 71% rename from argocd/example-apps/argocd/nginx-helm-jenkins.ftl.yaml rename to examples/example-apps-via-content-loader/argocd/example-apps/argocd/nginx-helm-jenkins.ftl.yaml index 782304b9f..37f190a23 100644 --- a/argocd/example-apps/argocd/nginx-helm-jenkins.ftl.yaml +++ b/examples/example-apps-via-content-loader/argocd/example-apps/argocd/nginx-helm-jenkins.ftl.yaml @@ -1,13 +1,8 @@ apiVersion: argoproj.io/v1alpha1 kind: Application metadata: -<#if config.features.argocd.operator> name: nginx-helm-jenkins-staging namespace: ${config.application.namePrefix}argocd -<#else> - name: nginx-helm-jenkins - namespace: ${config.application.namePrefix}example-apps-staging - spec: destination: namespace: ${config.application.namePrefix}example-apps-staging @@ -15,7 +10,7 @@ spec: project: example-apps source: path: apps/nginx-helm-jenkins/staging - repoURL: ${scmm.repoUrl}argocd/example-apps + repoURL: "http://scmm.${config.application.namePrefix}scm-manager.svc.cluster.local/scm/repo/${config.application.namePrefix}argocd/example-apps" targetRevision: main directory: recurse: true @@ -28,13 +23,8 @@ spec: apiVersion: argoproj.io/v1alpha1 kind: Application metadata: -<#if config.features.argocd.operator> name: nginx-helm-jenkins-production namespace: ${config.application.namePrefix}argocd -<#else> - name: nginx-helm-jenkins - namespace: ${config.application.namePrefix}example-apps-production - spec: destination: namespace: ${config.application.namePrefix}example-apps-production @@ -42,7 +32,7 @@ spec: project: example-apps source: path: apps/nginx-helm-jenkins/production - repoURL: ${scmm.repoUrl}argocd/example-apps + repoURL: "http://scmm.${config.application.namePrefix}scm-manager.svc.cluster.local/scm/repo/${config.application.namePrefix}argocd/example-apps" targetRevision: main directory: recurse: true diff --git a/argocd/example-apps/argocd/nginx-helm-umbrella.ftl.yaml b/examples/example-apps-via-content-loader/argocd/example-apps/argocd/nginx-helm-umbrella.ftl.yaml similarity index 71% rename from argocd/example-apps/argocd/nginx-helm-umbrella.ftl.yaml rename to examples/example-apps-via-content-loader/argocd/example-apps/argocd/nginx-helm-umbrella.ftl.yaml index 419f8817e..7e5c1c8bf 100644 --- a/argocd/example-apps/argocd/nginx-helm-umbrella.ftl.yaml +++ b/examples/example-apps-via-content-loader/argocd/example-apps/argocd/nginx-helm-umbrella.ftl.yaml @@ -2,11 +2,7 @@ apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: nginx-helm-umbrella -<#if config.features.argocd.operator> namespace: ${config.application.namePrefix}argocd -<#else> - namespace: ${config.application.namePrefix}example-apps-production - spec: destination: namespace: ${config.application.namePrefix}example-apps-production @@ -14,7 +10,7 @@ spec: project: example-apps source: path: apps/nginx-helm-umbrella - repoURL: ${scmm.repoUrl}argocd/example-apps + repoURL: "http://scmm.${config.application.namePrefix}scm-manager.svc.cluster.local/scm/repo/${config.application.namePrefix}argocd/example-apps" targetRevision: main syncPolicy: automated: diff --git a/argocd/example-apps/argocd/petclinic-helm.ftl.yaml b/examples/example-apps-via-content-loader/argocd/example-apps/argocd/petclinic-helm.ftl.yaml similarity index 71% rename from argocd/example-apps/argocd/petclinic-helm.ftl.yaml rename to examples/example-apps-via-content-loader/argocd/example-apps/argocd/petclinic-helm.ftl.yaml index 37178cae0..6bda7aed9 100644 --- a/argocd/example-apps/argocd/petclinic-helm.ftl.yaml +++ b/examples/example-apps-via-content-loader/argocd/example-apps/argocd/petclinic-helm.ftl.yaml @@ -1,13 +1,8 @@ apiVersion: argoproj.io/v1alpha1 kind: Application metadata: -<#if config.features.argocd.operator> name: petclinic-helm-staging namespace: ${config.application.namePrefix}argocd -<#else> - name: petclinic-helm - namespace: ${config.application.namePrefix}example-apps-staging - spec: destination: namespace: ${config.application.namePrefix}example-apps-staging @@ -15,7 +10,7 @@ spec: project: example-apps source: path: apps/spring-petclinic-helm/staging - repoURL: ${scmm.repoUrl}argocd/example-apps + repoURL: "http://scmm.${config.application.namePrefix}scm-manager.svc.cluster.local/scm/repo/${config.application.namePrefix}argocd/example-apps" targetRevision: main directory: recurse: true @@ -28,13 +23,8 @@ spec: apiVersion: argoproj.io/v1alpha1 kind: Application metadata: -<#if config.features.argocd.operator> name: petclinic-helm-production namespace: ${config.application.namePrefix}argocd -<#else> - name: petclinic-helm - namespace: ${config.application.namePrefix}example-apps-production - spec: destination: namespace: ${config.application.namePrefix}example-apps-production @@ -42,7 +32,7 @@ spec: project: example-apps source: path: apps/spring-petclinic-helm/production - repoURL: ${scmm.repoUrl}argocd/example-apps + repoURL: "http://scmm.${config.application.namePrefix}scm-manager.svc.cluster.local/scm/repo/${config.application.namePrefix}argocd/example-apps" targetRevision: main directory: recurse: true diff --git a/argocd/example-apps/argocd/petclinic-plain.ftl.yaml b/examples/example-apps-via-content-loader/argocd/example-apps/argocd/petclinic-plain.ftl.yaml similarity index 71% rename from argocd/example-apps/argocd/petclinic-plain.ftl.yaml rename to examples/example-apps-via-content-loader/argocd/example-apps/argocd/petclinic-plain.ftl.yaml index 89afcf2b8..e6a1d2b96 100644 --- a/argocd/example-apps/argocd/petclinic-plain.ftl.yaml +++ b/examples/example-apps-via-content-loader/argocd/example-apps/argocd/petclinic-plain.ftl.yaml @@ -1,13 +1,8 @@ apiVersion: argoproj.io/v1alpha1 kind: Application metadata: -<#if config.features.argocd.operator> name: petclinic-plain-staging namespace: ${config.application.namePrefix}argocd -<#else> - name: petclinic-plain - namespace: ${config.application.namePrefix}example-apps-staging - spec: destination: namespace: ${config.application.namePrefix}example-apps-staging @@ -15,7 +10,7 @@ spec: project: example-apps source: path: apps/spring-petclinic-plain/staging - repoURL: ${scmm.repoUrl}argocd/example-apps + repoURL: "http://scmm.${config.application.namePrefix}scm-manager.svc.cluster.local/scm/repo/${config.application.namePrefix}argocd/example-apps" targetRevision: main directory: recurse: true @@ -29,13 +24,8 @@ spec: apiVersion: argoproj.io/v1alpha1 kind: Application metadata: -<#if config.features.argocd.operator> name: petclinic-plain-production namespace: ${config.application.namePrefix}argocd -<#else> - name: petclinic-plain - namespace: ${config.application.namePrefix}example-apps-production - spec: destination: namespace: ${config.application.namePrefix}example-apps-production @@ -43,7 +33,7 @@ spec: project: example-apps source: path: apps/spring-petclinic-plain/production - repoURL: ${scmm.repoUrl}argocd/example-apps + repoURL: "http://scmm.${config.application.namePrefix}scm-manager.svc.cluster.local/scm/repo/${config.application.namePrefix}argocd/example-apps" targetRevision: main directory: recurse: true diff --git a/argocd/example-apps/misc/.gitkeep b/examples/example-apps-via-content-loader/argocd/example-apps/misc/.gitkeep similarity index 100% rename from argocd/example-apps/misc/.gitkeep rename to examples/example-apps-via-content-loader/argocd/example-apps/misc/.gitkeep diff --git a/applications/argocd/nginx/helm-umbrella/Chart.yaml b/examples/example-apps-via-content-loader/argocd/helm-umbrella/Chart.yaml similarity index 100% rename from applications/argocd/nginx/helm-umbrella/Chart.yaml rename to examples/example-apps-via-content-loader/argocd/helm-umbrella/Chart.yaml diff --git a/examples/example-apps-via-content-loader/argocd/helm-umbrella/README.md b/examples/example-apps-via-content-loader/argocd/helm-umbrella/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/applications/argocd/nginx/helm-umbrella/values.ftl.yaml b/examples/example-apps-via-content-loader/argocd/helm-umbrella/values.ftl.yaml similarity index 67% rename from applications/argocd/nginx/helm-umbrella/values.ftl.yaml rename to examples/example-apps-via-content-loader/argocd/helm-umbrella/values.ftl.yaml index 2f456a93d..554b3a5ca 100644 --- a/applications/argocd/nginx/helm-umbrella/values.ftl.yaml +++ b/examples/example-apps-via-content-loader/argocd/helm-umbrella/values.ftl.yaml @@ -1,7 +1,7 @@ <#assign DockerImageParser=statics['com.cloudogu.gitops.utils.DockerImageParser']> nginx: -<#if config.images.nginx?has_content> -<#assign nginxImageObject = DockerImageParser.parse(config.images.nginx)> +<#if config.content.variables.images.nginx?has_content> +<#assign nginxImageObject = DockerImageParser.parse(config.content.variables.images.nginx)> image: registry: ${nginxImageObject.registry} repository: ${nginxImageObject.repository} @@ -31,13 +31,13 @@ nginx: memory: 15Mi -<#if config.features.exampleApps.nginx.baseDomain?has_content> +<#if config.content.variables.nginx.baseDomain?has_content> ingress: enabled: true pathType: Prefix <#if config.application.urlSeparatorHyphen> - hostname: production-nginx-helm-umbrella-${config.features.exampleApps.nginx.baseDomain} + hostname: production-nginx-helm-umbrella-${config.content.variables.nginx.baseDomain} <#else> - hostname: production.nginx-helm-umbrella.${config.features.exampleApps.nginx.baseDomain} + hostname: production.nginx-helm-umbrella.${config.content.variables.nginx.baseDomain} diff --git a/applications/argocd/nginx/helm-jenkins/Jenkinsfile.ftl b/examples/example-apps-via-content-loader/argocd/nginx-helm-jenkins/Jenkinsfile.ftl similarity index 90% rename from applications/argocd/nginx/helm-jenkins/Jenkinsfile.ftl rename to examples/example-apps-via-content-loader/argocd/nginx-helm-jenkins/Jenkinsfile.ftl index 1d798c51c..77c2e73c1 100644 --- a/applications/argocd/nginx/helm-jenkins/Jenkinsfile.ftl +++ b/examples/example-apps-via-content-loader/argocd/nginx-helm-jenkins/Jenkinsfile.ftl @@ -60,11 +60,11 @@ node('docker') { k8sVersion : env.${config.application.namePrefixForEnvVars}K8S_VERSION, buildImages : [ - helm: '${config.images.helm}', - kubectl: '${config.images.kubectl}', - kubeval: '${config.images.kubeval}', - helmKubeval: '${config.images.helmKubeval}', - yamllint: '${config.images.yamllint}' + helm: '${config.content.variables.images.helm}', + kubectl: '${config.content.variables.images.kubectl}', + kubeval: '${config.content.variables.images.kubeval}', + helmKubeval: '${config.content.variables.images.helmKubeval}', + yamllint: '${config.content.variables.images.yamllint}' ], deployments: [ sourcePath: 'k8s', diff --git a/examples/example-apps-via-content-loader/argocd/nginx-helm-jenkins/README.md b/examples/example-apps-via-content-loader/argocd/nginx-helm-jenkins/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/examples/example-apps-via-content-loader/argocd/nginx-helm-jenkins/index.html b/examples/example-apps-via-content-loader/argocd/nginx-helm-jenkins/index.html new file mode 100644 index 000000000..e69de29bb diff --git a/applications/argocd/nginx/helm-jenkins/k8s/production/external-secret.yaml b/examples/example-apps-via-content-loader/argocd/nginx-helm-jenkins/k8s/production/external-secret.ftl.yaml similarity index 90% rename from applications/argocd/nginx/helm-jenkins/k8s/production/external-secret.yaml rename to examples/example-apps-via-content-loader/argocd/nginx-helm-jenkins/k8s/production/external-secret.ftl.yaml index b5fd1dbdc..0ff80392e 100644 --- a/applications/argocd/nginx/helm-jenkins/k8s/production/external-secret.yaml +++ b/examples/example-apps-via-content-loader/argocd/nginx-helm-jenkins/k8s/production/external-secret.ftl.yaml @@ -1,3 +1,4 @@ +<#if config.features.secrets.active> apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: @@ -15,3 +16,4 @@ spec: remoteRef: key: secret/production/nginx-helm-jenkins property: example + diff --git a/applications/argocd/nginx/helm-jenkins/k8s/staging/external-secret.yaml b/examples/example-apps-via-content-loader/argocd/nginx-helm-jenkins/k8s/staging/external-secret.ftl.yaml similarity index 90% rename from applications/argocd/nginx/helm-jenkins/k8s/staging/external-secret.yaml rename to examples/example-apps-via-content-loader/argocd/nginx-helm-jenkins/k8s/staging/external-secret.ftl.yaml index 3a8248f6d..aadef9145 100644 --- a/applications/argocd/nginx/helm-jenkins/k8s/staging/external-secret.yaml +++ b/examples/example-apps-via-content-loader/argocd/nginx-helm-jenkins/k8s/staging/external-secret.ftl.yaml @@ -1,3 +1,4 @@ +<#if config.features.secrets.active> apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: @@ -15,3 +16,4 @@ spec: remoteRef: key: secret/staging/nginx-helm-jenkins property: example + diff --git a/applications/argocd/nginx/helm-jenkins/k8s/values-staging.ftl.yaml b/examples/example-apps-via-content-loader/argocd/nginx-helm-jenkins/k8s/values-production.ftl.yaml similarity index 51% rename from applications/argocd/nginx/helm-jenkins/k8s/values-staging.ftl.yaml rename to examples/example-apps-via-content-loader/argocd/nginx-helm-jenkins/k8s/values-production.ftl.yaml index c7ffd57f3..f4edecb93 100644 --- a/applications/argocd/nginx/helm-jenkins/k8s/values-staging.ftl.yaml +++ b/examples/example-apps-via-content-loader/argocd/nginx-helm-jenkins/k8s/values-production.ftl.yaml @@ -1,12 +1,12 @@ -namespaceOverride: ${config.application.namePrefix}example-apps-staging +namespaceOverride: ${config.application.namePrefix}example-apps-production -<#if config.features.exampleApps.nginx.baseDomain?has_content> +<#if config.content.variables.nginx.baseDomain?has_content> ingress: enabled: true pathType: Prefix <#if config.application.urlSeparatorHyphen> - hostname: staging-nginx-helm-${config.features.exampleApps.nginx.baseDomain} + hostname: production-nginx-helm-${config.content.variables.nginx.baseDomain} <#else> - hostname: staging.nginx-helm.${config.features.exampleApps.nginx.baseDomain} + hostname: production.nginx-helm.${config.content.variables.nginx.baseDomain} diff --git a/applications/argocd/nginx/helm-jenkins/k8s/values-shared.ftl.yaml b/examples/example-apps-via-content-loader/argocd/nginx-helm-jenkins/k8s/values-shared.ftl.yaml similarity index 89% rename from applications/argocd/nginx/helm-jenkins/k8s/values-shared.ftl.yaml rename to examples/example-apps-via-content-loader/argocd/nginx-helm-jenkins/k8s/values-shared.ftl.yaml index 9a0e4d111..f79437c4b 100644 --- a/applications/argocd/nginx/helm-jenkins/k8s/values-shared.ftl.yaml +++ b/examples/example-apps-via-content-loader/argocd/nginx-helm-jenkins/k8s/values-shared.ftl.yaml @@ -1,6 +1,6 @@ <#assign DockerImageParser=statics['com.cloudogu.gitops.utils.DockerImageParser']> -<#if config.images.nginx?has_content> -<#assign nginxImageObject = DockerImageParser.parse(config.images.nginx)> +<#if config.content.variables.images.nginx?has_content> +<#assign nginxImageObject = DockerImageParser.parse(config.content.variables.images.nginx)> image: registry: ${nginxImageObject.registry} repository: ${nginxImageObject.repository} diff --git a/examples/example-apps-via-content-loader/argocd/nginx-helm-jenkins/k8s/values-staging.ftl.yaml b/examples/example-apps-via-content-loader/argocd/nginx-helm-jenkins/k8s/values-staging.ftl.yaml new file mode 100644 index 000000000..9754fb87e --- /dev/null +++ b/examples/example-apps-via-content-loader/argocd/nginx-helm-jenkins/k8s/values-staging.ftl.yaml @@ -0,0 +1,12 @@ +namespaceOverride: ${config.application.namePrefix}example-apps-staging + +<#if config.content.variables.nginx.baseDomain?has_content> +ingress: + enabled: true + pathType: Prefix + <#if config.application.urlSeparatorHyphen> + hostname: staging-nginx-helm-${config.content.variables.nginx.baseDomain} + <#else> + hostname: staging.nginx-helm.${config.content.variables.nginx.baseDomain} + + diff --git a/applications/argocd/petclinic/Dockerfile.ftl b/examples/example-apps-via-content-loader/argocd/petclinic-helm/Dockerfile.ftl similarity index 87% rename from applications/argocd/petclinic/Dockerfile.ftl rename to examples/example-apps-via-content-loader/argocd/petclinic-helm/Dockerfile.ftl index 1c77c830a..4a6fadfd3 100644 --- a/applications/argocd/petclinic/Dockerfile.ftl +++ b/examples/example-apps-via-content-loader/argocd/petclinic-helm/Dockerfile.ftl @@ -1,4 +1,4 @@ -FROM ${baseImage} +FROM ${config.content.variables.images.petclinic} # Set permissions to group 0 for openshift compatibility # See https://docs.openshift.com/container-platform/4.15/openshift_images/create-images.html#use-uid_create-images diff --git a/applications/argocd/petclinic/helm/Jenkinsfile.ftl b/examples/example-apps-via-content-loader/argocd/petclinic-helm/Jenkinsfile.ftl similarity index 86% rename from applications/argocd/petclinic/helm/Jenkinsfile.ftl rename to examples/example-apps-via-content-loader/argocd/petclinic-helm/Jenkinsfile.ftl index c19687e41..878050bee 100644 --- a/applications/argocd/petclinic/helm/Jenkinsfile.ftl +++ b/examples/example-apps-via-content-loader/argocd/petclinic-helm/Jenkinsfile.ftl @@ -40,11 +40,11 @@ properties([ node { -<#if config.images.maven?has_content> +<#if config.content.variables.images.maven?has_content> <#if config.registry.twoRegistries> - mvn = cesBuildLib.MavenInDocker.new(this, '${config.images.maven}', dockerRegistryProxyCredentials) + mvn = cesBuildLib.MavenInDocker.new(this, '${config.content.variables.images.maven}', dockerRegistryProxyCredentials) <#else> - mvn = cesBuildLib.MavenInDocker.new(this, '${config.images.maven}') + mvn = cesBuildLib.MavenInDocker.new(this, '${config.content.variables.images.maven}') <#else> mvn = cesBuildLib.MavenWrapper.new(this) @@ -123,31 +123,31 @@ node { buildImages : [ <#if config.registry.twoRegistries> helm: [ - image: '${config.images.helm}', + image: '${config.content.variables.images.helm}', credentialsId: dockerRegistryProxyCredentials ], kubectl: [ - image: '${config.images.kubectl}', + image: '${config.content.variables.images.kubectl}', credentialsId: dockerRegistryProxyCredentials ], kubeval: [ - image: '${config.images.kubeval}', + image: '${config.content.variables.images.kubeval}', credentialsId: dockerRegistryProxyCredentials ], helmKubeval: [ - image: '${config.images.helmKubeval}', + image: '${config.content.variables.images.helmKubeval}', credentialsId: dockerRegistryProxyCredentials ], yamllint: [ - image: '${config.images.yamllint}', + image: '${config.content.variables.images.yamllint}', credentialsId: dockerRegistryProxyCredentials ] <#else> - helm: '${config.images.helm}', - kubectl: '${config.images.kubectl}', - kubeval: '${config.images.kubeval}', - helmKubeval: '${config.images.helmKubeval}', - yamllint: '${config.images.yamllint}' + helm: '${config.content.variables.images.helm}', + kubectl: '${config.content.variables.images.kubectl}', + kubeval: '${config.content.variables.images.kubeval}', + helmKubeval: '${config.content.variables.images.helmKubeval}', + yamllint: '${config.content.variables.images.yamllint}' ], deployments: [ diff --git a/examples/example-apps-via-content-loader/argocd/petclinic-helm/k8s/production/configMap.ftl.yaml b/examples/example-apps-via-content-loader/argocd/petclinic-helm/k8s/production/configMap.ftl.yaml new file mode 100644 index 000000000..e69de29bb diff --git a/applications/argocd/petclinic/helm/k8s/production/secrets/secret.ftl.yaml b/examples/example-apps-via-content-loader/argocd/petclinic-helm/k8s/production/secrets/secret.ftl.yaml similarity index 100% rename from applications/argocd/petclinic/helm/k8s/production/secrets/secret.ftl.yaml rename to examples/example-apps-via-content-loader/argocd/petclinic-helm/k8s/production/secrets/secret.ftl.yaml diff --git a/applications/argocd/petclinic/helm/k8s/production/secrets/secret2.ftl.yaml b/examples/example-apps-via-content-loader/argocd/petclinic-helm/k8s/production/secrets/secret2.ftl.yaml similarity index 100% rename from applications/argocd/petclinic/helm/k8s/production/secrets/secret2.ftl.yaml rename to examples/example-apps-via-content-loader/argocd/petclinic-helm/k8s/production/secrets/secret2.ftl.yaml diff --git a/examples/example-apps-via-content-loader/argocd/petclinic-helm/k8s/staging/configMap.ftl.yaml b/examples/example-apps-via-content-loader/argocd/petclinic-helm/k8s/staging/configMap.ftl.yaml new file mode 100644 index 000000000..e69de29bb diff --git a/applications/argocd/petclinic/helm/k8s/staging/secrets/secret.ftl.yaml b/examples/example-apps-via-content-loader/argocd/petclinic-helm/k8s/staging/secrets/secret.ftl.yaml similarity index 100% rename from applications/argocd/petclinic/helm/k8s/staging/secrets/secret.ftl.yaml rename to examples/example-apps-via-content-loader/argocd/petclinic-helm/k8s/staging/secrets/secret.ftl.yaml diff --git a/applications/argocd/petclinic/helm/k8s/staging/secrets/secret2.ftl.yaml b/examples/example-apps-via-content-loader/argocd/petclinic-helm/k8s/staging/secrets/secret2.ftl.yaml similarity index 100% rename from applications/argocd/petclinic/helm/k8s/staging/secrets/secret2.ftl.yaml rename to examples/example-apps-via-content-loader/argocd/petclinic-helm/k8s/staging/secrets/secret2.ftl.yaml diff --git a/examples/example-apps-via-content-loader/argocd/petclinic-helm/k8s/values-production.ftl.yaml b/examples/example-apps-via-content-loader/argocd/petclinic-helm/k8s/values-production.ftl.yaml new file mode 100644 index 000000000..fda1b8a91 --- /dev/null +++ b/examples/example-apps-via-content-loader/argocd/petclinic-helm/k8s/values-production.ftl.yaml @@ -0,0 +1,13 @@ +service: + port: 80 + +<#if config.content.variables.petclinic.baseDomain?has_content> +ingress: + hosts: + <#if config.application.urlSeparatorHyphen> + - host: production-petclinic-helm-${config.content.variables.petclinic.baseDomain} + <#else> + - host: production.petclinic-helm.${config.content.variables.petclinic.baseDomain} + + paths: ['/'] + diff --git a/applications/argocd/petclinic/helm/k8s/values-shared.ftl.yaml b/examples/example-apps-via-content-loader/argocd/petclinic-helm/k8s/values-shared.ftl.yaml similarity index 77% rename from applications/argocd/petclinic/helm/k8s/values-shared.ftl.yaml rename to examples/example-apps-via-content-loader/argocd/petclinic-helm/k8s/values-shared.ftl.yaml index 5d88e7297..cee88bed5 100644 --- a/applications/argocd/petclinic/helm/k8s/values-shared.ftl.yaml +++ b/examples/example-apps-via-content-loader/argocd/petclinic-helm/k8s/values-shared.ftl.yaml @@ -6,12 +6,7 @@ service: type: <#if config.application.remote>LoadBalancer<#else>ClusterIP ingress: - enabled: <#if config.features.exampleApps.petclinic.baseDomain?has_content>true<#else>false - -# this is a helm chart dependency -podinfo: - ui: - color: '#456456' + enabled: <#if config.content.variables.petclinic.baseDomain?has_content>true<#else>false <#if config.application.openshift == true> securityContext: diff --git a/examples/example-apps-via-content-loader/argocd/petclinic-helm/k8s/values-staging.ftl.yaml b/examples/example-apps-via-content-loader/argocd/petclinic-helm/k8s/values-staging.ftl.yaml new file mode 100644 index 000000000..68edc532f --- /dev/null +++ b/examples/example-apps-via-content-loader/argocd/petclinic-helm/k8s/values-staging.ftl.yaml @@ -0,0 +1,13 @@ +service: + port: 80 + +<#if config.content.variables.petclinic.baseDomain?has_content> +ingress: + hosts: + <#if config.application.urlSeparatorHyphen> + - host: staging-petclinic-helm-${config.content.variables.petclinic.baseDomain} + <#else> + - host: staging.petclinic-helm.${config.content.variables.petclinic.baseDomain} + + paths: ['/'] + diff --git a/examples/example-apps-via-content-loader/argocd/petclinic-plain/Dockerfile.ftl b/examples/example-apps-via-content-loader/argocd/petclinic-plain/Dockerfile.ftl new file mode 100644 index 000000000..4a6fadfd3 --- /dev/null +++ b/examples/example-apps-via-content-loader/argocd/petclinic-plain/Dockerfile.ftl @@ -0,0 +1,13 @@ +FROM ${config.content.variables.images.petclinic} + +# Set permissions to group 0 for openshift compatibility +# See https://docs.openshift.com/container-platform/4.15/openshift_images/create-images.html#use-uid_create-images +RUN mkdir /app && chown 1000:0 /app \ + && chmod -R g=u /app + +COPY target/*.jar /app/petclinic.jar + +EXPOSE 8080 +USER 1000 + +ENTRYPOINT [ "java", "-server","-jar", "/app/petclinic.jar" ] diff --git a/applications/argocd/petclinic/plain-k8s/Jenkinsfile.ftl b/examples/example-apps-via-content-loader/argocd/petclinic-plain/Jenkinsfile.ftl similarity index 90% rename from applications/argocd/petclinic/plain-k8s/Jenkinsfile.ftl rename to examples/example-apps-via-content-loader/argocd/petclinic-plain/Jenkinsfile.ftl index 5d2c0d357..b02228699 100644 --- a/applications/argocd/petclinic/plain-k8s/Jenkinsfile.ftl +++ b/examples/example-apps-via-content-loader/argocd/petclinic-plain/Jenkinsfile.ftl @@ -33,11 +33,11 @@ node { -<#if config.images.maven?has_content> +<#if config.content.variables.images.maven?has_content> <#if config.registry.twoRegistries> - mvn = cesBuildLib.MavenInDocker.new(this, '${config.images.maven}', dockerRegistryProxyCredentials) + mvn = cesBuildLib.MavenInDocker.new(this, '${config.content.variables.images.maven}', dockerRegistryProxyCredentials) <#else> - mvn = cesBuildLib.MavenInDocker.new(this, '${config.images.maven}') + mvn = cesBuildLib.MavenInDocker.new(this, '${config.content.variables.images.maven}') <#else> mvn = cesBuildLib.MavenWrapper.new(this) @@ -170,31 +170,31 @@ String createSpecificGitOpsConfig() { <#if config.registry.twoRegistries> helm: [ - image: '${config.images.helm}', + image: '${config.content.variables.images.helm}', credentialsId: dockerRegistryProxyCredentials ], kubectl: [ - image: '${config.images.kubectl}', + image: '${config.content.variables.images.kubectl}', credentialsId: dockerRegistryProxyCredentials ], kubeval: [ - image: '${config.images.kubeval}', + image: '${config.content.variables.images.kubeval}', credentialsId: dockerRegistryProxyCredentials ], helmKubeval: [ - image: '${config.images.helmKubeval}', + image: '${config.content.variables.images.helmKubeval}', credentialsId: dockerRegistryProxyCredentials ], yamllint: [ - image: '${config.images.yamllint}', + image: '${config.content.variables.images.yamllint}', credentialsId: dockerRegistryProxyCredentials ] <#else> - helm: '${config.images.helm}', - kubectl: '${config.images.kubectl}', - kubeval: '${config.images.kubeval}', - helmKubeval: '${config.images.helmKubeval}', - yamllint: '${config.images.yamllint}' + helm: '${config.content.variables.images.helm}', + kubectl: '${config.content.variables.images.kubectl}', + kubeval: '${config.content.variables.images.kubeval}', + helmKubeval: '${config.content.variables.images.helmKubeval}', + yamllint: '${config.content.variables.images.yamllint}' <#noparse> ] diff --git a/applications/argocd/petclinic/plain-k8s/k8s/production/deployment.ftl.yaml b/examples/example-apps-via-content-loader/argocd/petclinic-plain/k8s/production/deployment.ftl.yaml similarity index 100% rename from applications/argocd/petclinic/plain-k8s/k8s/production/deployment.ftl.yaml rename to examples/example-apps-via-content-loader/argocd/petclinic-plain/k8s/production/deployment.ftl.yaml diff --git a/applications/argocd/petclinic/plain-k8s/k8s/staging/ingress.ftl.yaml b/examples/example-apps-via-content-loader/argocd/petclinic-plain/k8s/production/ingress.ftl.yaml similarity index 71% rename from applications/argocd/petclinic/plain-k8s/k8s/staging/ingress.ftl.yaml rename to examples/example-apps-via-content-loader/argocd/petclinic-plain/k8s/production/ingress.ftl.yaml index 05e50faf5..bcfb4f8e7 100644 --- a/applications/argocd/petclinic/plain-k8s/k8s/staging/ingress.ftl.yaml +++ b/examples/example-apps-via-content-loader/argocd/petclinic-plain/k8s/production/ingress.ftl.yaml @@ -1,4 +1,4 @@ -<#if config.features.exampleApps.petclinic.baseDomain?has_content> +<#if config.content.variables.petclinic.baseDomain?has_content> apiVersion: networking.k8s.io/v1 kind: Ingress metadata: @@ -8,9 +8,9 @@ metadata: spec: rules: <#if config.application.urlSeparatorHyphen> - - host: staging-petclinic-plain-${config.features.exampleApps.petclinic.baseDomain} + - host: production-petclinic-plain-${config.content.variables.petclinic.baseDomain} <#else> - - host: staging.petclinic-plain.${config.features.exampleApps.petclinic.baseDomain} + - host: production.petclinic-plain.${config.content.variables.petclinic.baseDomain} http: paths: diff --git a/applications/argocd/petclinic/plain-k8s/k8s/production/service.ftl.yaml b/examples/example-apps-via-content-loader/argocd/petclinic-plain/k8s/production/service.ftl.yaml similarity index 100% rename from applications/argocd/petclinic/plain-k8s/k8s/production/service.ftl.yaml rename to examples/example-apps-via-content-loader/argocd/petclinic-plain/k8s/production/service.ftl.yaml diff --git a/applications/argocd/petclinic/plain-k8s/k8s/staging/deployment.ftl.yaml b/examples/example-apps-via-content-loader/argocd/petclinic-plain/k8s/staging/deployment.ftl.yaml similarity index 100% rename from applications/argocd/petclinic/plain-k8s/k8s/staging/deployment.ftl.yaml rename to examples/example-apps-via-content-loader/argocd/petclinic-plain/k8s/staging/deployment.ftl.yaml diff --git a/applications/argocd/petclinic/plain-k8s/k8s/production/ingress.ftl.yaml b/examples/example-apps-via-content-loader/argocd/petclinic-plain/k8s/staging/ingress.ftl.yaml similarity index 63% rename from applications/argocd/petclinic/plain-k8s/k8s/production/ingress.ftl.yaml rename to examples/example-apps-via-content-loader/argocd/petclinic-plain/k8s/staging/ingress.ftl.yaml index 510da81fe..1dda55a55 100644 --- a/applications/argocd/petclinic/plain-k8s/k8s/production/ingress.ftl.yaml +++ b/examples/example-apps-via-content-loader/argocd/petclinic-plain/k8s/staging/ingress.ftl.yaml @@ -1,4 +1,4 @@ -<#if config.features.exampleApps.petclinic.baseDomain?has_content> +<#if config.content.variables.petclinic.baseDomain?has_content> apiVersion: networking.k8s.io/v1 kind: Ingress metadata: @@ -8,9 +8,9 @@ metadata: spec: rules: <#if config.application.urlSeparatorHyphen> - - host: production-petclinic-plain-${config.features.exampleApps.petclinic.baseDomain} + - host: staging-petclinic-plain-${config.content.variables.petclinic.baseDomain} <#else> - - host: production.petclinic-plain.${config.features.exampleApps.petclinic.baseDomain} + - host: staging.petclinic-plain.${config.content.variables.petclinic.baseDomain} http: paths: diff --git a/applications/argocd/petclinic/plain-k8s/k8s/staging/service.ftl.yaml b/examples/example-apps-via-content-loader/argocd/petclinic-plain/k8s/staging/service.ftl.yaml similarity index 100% rename from applications/argocd/petclinic/plain-k8s/k8s/staging/service.ftl.yaml rename to examples/example-apps-via-content-loader/argocd/petclinic-plain/k8s/staging/service.ftl.yaml diff --git a/examples/example-apps-via-content-loader/config.yaml b/examples/example-apps-via-content-loader/config.yaml new file mode 100644 index 000000000..44689aa01 --- /dev/null +++ b/examples/example-apps-via-content-loader/config.yaml @@ -0,0 +1,47 @@ +content: + repos: + - url: https://github.com/cloudogu/gitops-build-lib + target: 3rd-party-dependencies/gitops-build-lib + overwriteMode: RESET + - url: https://github.com/cloudogu/ces-build-lib + target: 3rd-party-dependencies/ces-build-lib + overwriteMode: RESET + - url: https://github.com/cloudogu/spring-boot-helm-chart + target: 3rd-party-dependencies/spring-boot-helm-chart + overwriteMode: RESET + - url: https://github.com/cloudogu/spring-petclinic + target: argocd/petclinic-plain + ref: feature/gitops_ready + targetRef: main + overwriteMode: UPGRADE + createJenkinsJob: true + - url: https://github.com/cloudogu/spring-petclinic + target: argocd/petclinic-helm + ref: feature/gitops_ready + targetRef: main + overwriteMode: UPGRADE + createJenkinsJob: true + - url: https://github.com/cloudogu/gitops-playground + path: examples/example-apps-via-content-loader/ + ref: main + templating: true + type: FOLDER_BASED + overwriteMode: UPGRADE + + namespaces: + - ${config.application.namePrefix}example-apps-production + - ${config.application.namePrefix}example-apps-staging + variables: + petclinic: + baseDomain: "petclinic.localhost" + nginx: + baseDomain: "nginx.localhost" + images: + kubectl: "bitnamilegacy/kubectl:1.29" + helm: "ghcr.io/cloudogu/helm:3.16.4-1" + kubeval: "ghcr.io/cloudogu/helm:3.16.4-1" + helmKubeval: "ghcr.io/cloudogu/helm:3.16.4-1" + yamllint: "cytopia/yamllint:1.25-0.7" + nginx: "" + petclinic: "eclipse-temurin:17-jre-alpine" + maven: "" \ No newline at end of file diff --git a/scripts/scm-manager/init-scmm.sh b/scripts/scm-manager/init-scmm.sh index 7013ef930..a5792caf6 100755 --- a/scripts/scm-manager/init-scmm.sh +++ b/scripts/scm-manager/init-scmm.sh @@ -34,13 +34,6 @@ function initSCMM() { if [[ ${SCM_PROVIDER} == "scm-manager" ]]; then configureScmmManager fi - - if [[ $CONTENT_EXAMPLES == true ]]; then - pushHelmChartRepo "3rd-party-dependencies/spring-boot-helm-chart" - pushHelmChartRepoWithDependency "3rd-party-dependencies/spring-boot-helm-chart-with-dependency" - pushRepoMirror "${GITOPS_BUILD_LIB_REPO}" "3rd-party-dependencies/gitops-build-lib" - pushRepoMirror "${CES_BUILD_LIB_REPO}" "3rd-party-dependencies/ces-build-lib" 'develop' - fi } @@ -199,43 +192,6 @@ function configureScmmManager() { fi fi - if [[ $CONTENT_EXAMPLES == true ]]; then - addRepo "${NAME_PREFIX}argocd" "nginx-helm-jenkins" "3rd Party app (NGINX) with helm, templated in Jenkins (gitops-build-lib)" - setPermission "${NAME_PREFIX}argocd" "nginx-helm-jenkins" "${GITOPS_USERNAME}" "WRITE" - - addRepo "${NAME_PREFIX}argocd" "petclinic-plain" "Java app with plain k8s resources" - setPermission "${NAME_PREFIX}argocd" "petclinic-plain" "${GITOPS_USERNAME}" "WRITE" - - addRepo "${NAME_PREFIX}argocd" "petclinic-helm" "Java app with custom helm chart" - setPermission "${NAME_PREFIX}argocd" "petclinic-helm" "${GITOPS_USERNAME}" "WRITE" - - addRepo "${NAME_PREFIX}argocd" "example-apps" "GitOps repo for examples of end-user applications" - setPermission "${NAME_PREFIX}argocd" "example-apps" "${GITOPS_USERNAME}" "WRITE" - - ### Repos with replicated dependencies - addRepo "3rd-party-dependencies" "spring-boot-helm-chart" - setPermission "3rd-party-dependencies" "spring-boot-helm-chart" "${GITOPS_USERNAME}" "WRITE" - - addRepo "3rd-party-dependencies" "spring-boot-helm-chart-with-dependency" - setPermission "3rd-party-dependencies" "spring-boot-helm-chart-with-dependency" "${GITOPS_USERNAME}" "WRITE" - - addRepo "3rd-party-dependencies" "gitops-build-lib" "Jenkins pipeline shared library for automating deployments via GitOps " - setPermission "3rd-party-dependencies" "gitops-build-lib" "${GITOPS_USERNAME}" "WRITE" - - addRepo "3rd-party-dependencies" "ces-build-lib" "Jenkins pipeline shared library adding features for Maven, Gradle, Docker, SonarQube, Git and others" - setPermission "3rd-party-dependencies" "ces-build-lib" "${GITOPS_USERNAME}" "WRITE" - - ### Exercise Repos - addRepo "${NAME_PREFIX}exercises" "petclinic-helm" - setPermission "${NAME_PREFIX}exercises" "petclinic-helm" "${GITOPS_USERNAME}" "WRITE" - - addRepo "${NAME_PREFIX}exercises" "nginx-validation" - setPermission "${NAME_PREFIX}exercises" "nginx-validation" "${GITOPS_USERNAME}" "WRITE" - - addRepo "${NAME_PREFIX}exercises" "broken-application" - setPermission "${NAME_PREFIX}exercises" "broken-application" "${GITOPS_USERNAME}" "WRITE" - fi - # Install necessary plugins installScmmPlugins diff --git a/src/main/groovy/com/cloudogu/gitops/cli/GitopsPlaygroundCli.groovy b/src/main/groovy/com/cloudogu/gitops/cli/GitopsPlaygroundCli.groovy index 1d55b4695..c8607cbda 100644 --- a/src/main/groovy/com/cloudogu/gitops/cli/GitopsPlaygroundCli.groovy +++ b/src/main/groovy/com/cloudogu/gitops/cli/GitopsPlaygroundCli.groovy @@ -179,9 +179,11 @@ class GitopsPlaygroundCli { String configFilePath = cliParams.application.configFile String configMapName = cliParams.application.configMap + Boolean contentExamples = cliParams.content.examples Map configFile = [:] Map configMap = [:] + Map contentExamplesFile = [:] if (configFilePath) { log.debug("Reading config file ${configFilePath}") @@ -194,8 +196,14 @@ class GitopsPlaygroundCli { configMap = validateConfig(configValues) } + if(contentExamples) { + String contentExamplesConfigPath = "examples/example-apps-via-content-loader/config.yaml" + log.debug("Adding example-apps-via-content-loader configuration from '${contentExamplesConfigPath}'") + contentExamplesFile = validateConfig(new File(contentExamplesConfigPath).text) + } + // Last one takes precedence - def configPrecedence = [configMap, configFile] + def configPrecedence = [configMap, configFile, contentExamplesFile] Map mergedConfigs = [:] configPrecedence.each { deepMerge(it, mergedConfigs) diff --git a/src/main/groovy/com/cloudogu/gitops/config/ApplicationConfigurator.groovy b/src/main/groovy/com/cloudogu/gitops/config/ApplicationConfigurator.groovy index 7d0c54a4a..970a77789 100644 --- a/src/main/groovy/com/cloudogu/gitops/config/ApplicationConfigurator.groovy +++ b/src/main/groovy/com/cloudogu/gitops/config/ApplicationConfigurator.groovy @@ -214,19 +214,6 @@ class ApplicationConfigurator { vault.url = injectSubdomain('vault', baseUrl, urlSeparatorHyphen) log.debug("Setting Vault URL ${vault.url}") } - - if (!newConfig.features.exampleApps.petclinic.baseDomain) { - // This param only requires the host / domain - newConfig.features.exampleApps.petclinic.baseDomain = - new URL(injectSubdomain('petclinic', baseUrl, urlSeparatorHyphen)).host - log.debug("Setting Petclinic URL ${newConfig.features.exampleApps.petclinic.baseDomain}") - } - if (!newConfig.features.exampleApps.nginx.baseDomain) { - // This param only requires the host / domain - newConfig.features.exampleApps.nginx.baseDomain = - new URL(injectSubdomain('nginx', baseUrl, urlSeparatorHyphen)).host - log.debug("Setting Nginx URL ${newConfig.features.exampleApps.nginx.baseDomain}") - } } void setMultiTenantModeConfig(Config newConfig) { diff --git a/src/main/groovy/com/cloudogu/gitops/config/Config.groovy b/src/main/groovy/com/cloudogu/gitops/config/Config.groovy index c6ee41e67..f937a75fa 100644 --- a/src/main/groovy/com/cloudogu/gitops/config/Config.groovy +++ b/src/main/groovy/com/cloudogu/gitops/config/Config.groovy @@ -75,13 +75,6 @@ class Config { @Mixin ApplicationSchema application = new ApplicationSchema() - @JsonPropertyDescription(IMAGES_DESCRIPTION) - @Mixin - ImagesSchema images = new ImagesSchema() - - @JsonPropertyDescription(REPOSITORIES_DESCRIPTION) - RepositoriesSchema repositories = new RepositoriesSchema() - @JsonPropertyDescription(FEATURES_DESCRIPTION) @Mixin FeaturesSchema features = new FeaturesSchema() @@ -491,73 +484,6 @@ class Config { } } - static class ImagesSchema { - @Option(names = ['--kubectl-image'], description = KUBECTL_IMAGE_DESCRIPTION) - @JsonPropertyDescription(KUBECTL_IMAGE_DESCRIPTION) - String kubectl = "bitnamilegacy/kubectl:$K8S_VERSION" - - // cloudogu/helm also contains kubeval and helm kubeval plugin. Using the same image makes builds faster - @Option(names = ['--helm-image'], description = HELM_IMAGE_DESCRIPTION) - @JsonPropertyDescription(HELM_IMAGE_DESCRIPTION) - String helm = HELM_IMAGE - - @Option(names = ['--kubeval-image'], description = KUBEVAL_IMAGE_DESCRIPTION) - @JsonPropertyDescription(KUBEVAL_IMAGE_DESCRIPTION) - String kubeval = HELM_IMAGE - - @Option(names = ['--helmkubeval-image'], description = HELMKUBEVAL_IMAGE_DESCRIPTION) - @JsonPropertyDescription(HELMKUBEVAL_IMAGE_DESCRIPTION) - String helmKubeval = HELM_IMAGE - - @Option(names = ['--yamllint-image'], description = YAMLLINT_IMAGE_DESCRIPTION) - @JsonPropertyDescription(YAMLLINT_IMAGE_DESCRIPTION) - String yamllint = "cytopia/yamllint:1.25-0.7" - - @Option(names = ['--nginx-image'], description = NGINX_IMAGE_DESCRIPTION) - @JsonPropertyDescription(NGINX_IMAGE_DESCRIPTION) - String nginx = '' - - @Option(names = ['--petclinic-image'], description = PETCLINIC_IMAGE_DESCRIPTION) - @JsonPropertyDescription(PETCLINIC_IMAGE_DESCRIPTION) - String petclinic = 'eclipse-temurin:17-jre-alpine' - - @Option(names = ['--maven-image'], description = MAVEN_IMAGE_DESCRIPTION) - @JsonPropertyDescription(MAVEN_IMAGE_DESCRIPTION) - String maven = '' - } - - static class RepositoriesSchema { - @JsonPropertyDescription(SPRING_BOOT_HELM_CHART_DESCRIPTION) - RepositorySchemaWithRef springBootHelmChart = new RepositorySchemaWithRef( - // Take from env or use default because the Dockerfile provides a local copy of the repo - url: System.getenv('SPRING_BOOT_HELM_CHART_REPO') ?: 'https://github.com/cloudogu/spring-boot-helm-chart.git', - ref: '0.4.0' - ) - @JsonPropertyDescription(SPRING_PETCLINIC_DESCRIPTION) - RepositorySchemaWithRef springPetclinic = new RepositorySchemaWithRef( - url: System.getenv('SPRING_PETCLINIC_REPO') ?: 'https://github.com/cloudogu/spring-petclinic.git', - ref: 'b0738b2' - ) - @JsonPropertyDescription(GITOPS_BUILD_LIB_DESCRIPTION) - RepositorySchema gitopsBuildLib = new RepositorySchema( - url: System.getenv('GITOPS_BUILD_LIB_REPO') ?: 'https://github.com/cloudogu/gitops-build-lib.git' - ) - @JsonPropertyDescription(CES_BUILD_LIB_DESCRIPTION) - RepositorySchema cesBuildLib = new RepositorySchema( - url: System.getenv('CES_BUILD_LIB_REPO') ?: 'https://github.com/cloudogu/ces-build-lib.git' - ) - } - - static class RepositorySchema { - @JsonPropertyDescription(REPO_URL_DESCRIPTION) - String url = '' - } - - static class RepositorySchemaWithRef extends RepositorySchema { - @JsonPropertyDescription(REPO_REF_DESCRIPTION) - String ref = '' - } - static class FeaturesSchema { @Mixin @@ -580,9 +506,6 @@ class Config { @JsonPropertyDescription(INGRESS_NGINX_DESCRIPTION) IngressNginxSchema ingressNginx = new IngressNginxSchema() - @JsonPropertyDescription(EXAMPLE_APPS_DESCRIPTION) - ExampleAppsSchema exampleApps = new ExampleAppsSchema() - @Mixin @JsonPropertyDescription(CERTMANAGER_DESCRIPTION) CertManagerSchema certManager = new CertManagerSchema() @@ -836,18 +759,6 @@ class Config { } } - static class ExampleAppsSchema { - @JsonPropertyDescription(PETCLINIC_DESCRIPTION) - ExampleAppSchema petclinic = new ExampleAppSchema() - @JsonPropertyDescription(NGINX_DESCRIPTION) - ExampleAppSchema nginx = new ExampleAppSchema() - - static class ExampleAppSchema { - @JsonPropertyDescription(BASE_DOMAIN_DESCRIPTION) - String baseDomain = '' - } - } - static enum ContentRepoType { FOLDER_BASED, COPY, MIRROR } diff --git a/src/main/groovy/com/cloudogu/gitops/features/Jenkins.groovy b/src/main/groovy/com/cloudogu/gitops/features/Jenkins.groovy index 1fc412ea2..1a21964e5 100644 --- a/src/main/groovy/com/cloudogu/gitops/features/Jenkins.groovy +++ b/src/main/groovy/com/cloudogu/gitops/features/Jenkins.groovy @@ -186,14 +186,6 @@ class Jenkins extends Feature { prometheusConfigurator.enableAuthentication() } - if (config.content.examples) { - - String jobName = "example-apps" - String namespace = "argocd" - createJenkinsjob(namespace, jobName) - - } - } void createJenkinsjob(String namespace, String repoName) { diff --git a/src/main/groovy/com/cloudogu/gitops/features/ScmManager.groovy b/src/main/groovy/com/cloudogu/gitops/features/ScmManager.groovy index 66e52c8a5..68131ff1a 100644 --- a/src/main/groovy/com/cloudogu/gitops/features/ScmManager.groovy +++ b/src/main/groovy/com/cloudogu/gitops/features/ScmManager.groovy @@ -142,15 +142,10 @@ class ScmManager extends Feature { // Used indirectly in utils.sh 😬 REMOTE_CLUSTER : config.application.remote, INSTALL_ARGOCD : config.features.argocd.active, - SPRING_BOOT_HELM_CHART_COMMIT: config.repositories.springBootHelmChart.ref, - SPRING_BOOT_HELM_CHART_REPO : config.repositories.springBootHelmChart.url, - GITOPS_BUILD_LIB_REPO : config.repositories.gitopsBuildLib.url, - CES_BUILD_LIB_REPO : config.repositories.cesBuildLib.url, NAME_PREFIX : config.application.namePrefix, INSECURE : config.application.insecure, SCM_ROOT_PATH : config.scmm.rootPath, SCM_PROVIDER : config.scmm.provider, - CONTENT_EXAMPLES : config.content.examples, SKIP_RESTART : config.scmm.skipRestart, SKIP_PLUGINS : config.scmm.skipPlugins, CENTRAL_SCM_URL : centralSCMUrl, @@ -192,51 +187,15 @@ class ScmManager extends Feature { } argoCDGroup.ifPresent(this.&createArgoCDRepos) - - String dependencysGroupName = '3rd-party-dependencies' - Optional dependencysGroup = getGroup("${mainGroupName}/${dependencysGroupName}") - if (dependencysGroup.isEmpty()) { - def tempGroup = new Group() - .withName(dependencysGroupName) - .withPath(dependencysGroupName.toLowerCase()) - .withParentId(mainSCMGroup.id) - - addGroup(tempGroup) - } - - String exercisesGroupName = 'exercises' - Optional exercisesGroup = getGroup("${mainGroupName}/${exercisesGroupName}") - if (exercisesGroup.isEmpty()) { - def tempGroup = new Group() - .withName(exercisesGroupName) - .withPath(exercisesGroupName.toLowerCase()) - .withParentId(mainSCMGroup.id) - - exercisesGroup = addGroup(tempGroup) - } - - exercisesGroup.ifPresent(this.&createExercisesRepos) - } - - void createExercisesRepos(Group exercisesGroup) { - log.info("Creating GitlabRepos for ${exercisesGroup}") - createRepo("petclinic-helm", "petclinic-helm", exercisesGroup) - createRepo("nginx-validation", "nginx-validation", exercisesGroup) - createRepo("broken-application", "broken-application", exercisesGroup) } void createArgoCDRepos(Group argoCDGroup) { log.info("Creating GitlabRepos for ${argoCDGroup}") createRepo("cluster-resources", "GitOps repo for basic cluster-resources", argoCDGroup) - createRepo("petclinic-helm", "Java app with custom helm chart", argoCDGroup) - createRepo("petclinic-plain", "Java app with plain k8s resources", argoCDGroup) - createRepo("nginx-helm-jenkins", "3rd Party app (NGINX) with helm, templated in Jenkins (gitops-build-lib)", argoCDGroup) createRepo("argocd", "GitOps repo for administration of ArgoCD", argoCDGroup) - createRepo("example-apps", "GitOps repo for examples of end-user applications", argoCDGroup) } - void removeBranchProtection(Project project) { try { this.gitlabApi.getProtectedBranchesApi().unprotectBranch(project.getId(), project.getDefaultBranch()) diff --git a/src/main/groovy/com/cloudogu/gitops/features/argocd/ArgoCD.groovy b/src/main/groovy/com/cloudogu/gitops/features/argocd/ArgoCD.groovy index 826bafb6d..f53559ada 100644 --- a/src/main/groovy/com/cloudogu/gitops/features/argocd/ArgoCD.groovy +++ b/src/main/groovy/com/cloudogu/gitops/features/argocd/ArgoCD.groovy @@ -41,13 +41,7 @@ class ArgoCD extends Feature { protected RepoInitializationAction argocdRepoInitializationAction protected RepoInitializationAction clusterResourcesInitializationAction - protected RepoInitializationAction exampleAppsInitializationAction - protected RepoInitializationAction nginxHelmJenkinsInitializationAction - protected RepoInitializationAction nginxValidationInitializationAction - protected RepoInitializationAction brokenApplicationInitializationAction protected RepoInitializationAction tenantBootstrapInitializationAction - protected File remotePetClinicRepoTmpDir - protected List petClinicInitializationActions = [] protected K8sClient k8sClient protected HelmClient helmClient @@ -82,33 +76,12 @@ class ArgoCD extends Feature { log.debug('Cloning Repositories') - if (config.content.examples) { - def petclinicInitAction = createRepoInitializationAction('applications/argocd/petclinic/plain-k8s', 'argocd/petclinic-plain') - petClinicInitializationActions += petclinicInitAction - gitRepos += petclinicInitAction - - petclinicInitAction = createRepoInitializationAction('applications/argocd/petclinic/helm', 'argocd/petclinic-helm') - petClinicInitializationActions += petclinicInitAction - gitRepos += petclinicInitAction - - petclinicInitAction = createRepoInitializationAction('exercises/petclinic-helm', 'exercises/petclinic-helm') - petClinicInitializationActions += petclinicInitAction - gitRepos += petclinicInitAction - - cloneRemotePetclinicRepo() - } - gitRepos.forEach(repoInitializationAction -> { repoInitializationAction.initLocalRepo() }) prepareGitOpsRepos() - if (config.content.examples) { - prepareApplicationNginxHelmJenkins() - preparePetClinicRepos() - } - gitRepos.forEach(repoInitializationAction -> { repoInitializationAction.repo.commitAndPush('Initial Commit') }) @@ -175,32 +148,6 @@ class ArgoCD extends Feature { gitRepos += tenantBootstrapInitializationAction } - if (config.content.examples) { - exampleAppsInitializationAction = createRepoInitializationAction('argocd/example-apps', 'argocd/example-apps') - gitRepos += exampleAppsInitializationAction - - nginxHelmJenkinsInitializationAction = createRepoInitializationAction('applications/argocd/nginx/helm-jenkins', 'argocd/nginx-helm-jenkins') - gitRepos += nginxHelmJenkinsInitializationAction - - nginxValidationInitializationAction = createRepoInitializationAction('exercises/nginx-validation', 'exercises/nginx-validation') - gitRepos += nginxValidationInitializationAction - - brokenApplicationInitializationAction = createRepoInitializationAction('exercises/broken-application', 'exercises/broken-application') - gitRepos += brokenApplicationInitializationAction - - remotePetClinicRepoTmpDir = File.createTempDir('gitops-playground-petclinic') - } - } - - private void cloneRemotePetclinicRepo() { - log.debug("Cloning petclinic base repo, revision ${config.repositories.springPetclinic.ref}," + - " from ${config.repositories.springPetclinic.url}") - Git git = gitClone() - .setURI(config.repositories.springPetclinic.url) - .setDirectory(remotePetClinicRepoTmpDir) - .call() - git.checkout().setName(config.repositories.springPetclinic.ref).call() - log.debug('Finished cloning petclinic base repo') } /** @@ -229,52 +176,7 @@ class ArgoCD extends Feature { String externalScmmUrl = ScmUrlResolver.externalHost(config) log.debug("Configuring all yaml files in gitops repos to use the external scmm url: ${externalScmmUrl}") replaceFileContentInYamls(new File(clusterResourcesInitializationAction.repo.getAbsoluteLocalRepoTmpDir()), scmmUrlInternal, externalScmmUrl) - - if (config.content.examples) { - replaceFileContentInYamls(new File(exampleAppsInitializationAction.repo.getAbsoluteLocalRepoTmpDir()), scmmUrlInternal, externalScmmUrl) - } - } - if (config.content.examples) { - fileSystemUtils.copyDirectory("${fileSystemUtils.rootDir}/applications/argocd/nginx/helm-umbrella", - Path.of(exampleAppsInitializationAction.repo.getAbsoluteLocalRepoTmpDir(), 'apps/nginx-helm-umbrella/').toString()) - exampleAppsInitializationAction.replaceTemplates() - - //generating the bootstrap application in a app of app pattern for example apps in the /argocd applications folder - if (config.multiTenant.useDedicatedInstance) { - new ArgoApplication( - 'example-apps', - ScmUrlResolver.tenantBaseUrl(config)+'argocd/example-apps', - namespace, - namespace, - 'argocd/', - config.application.getTenantName()) - .generate(tenantBootstrapInitializationAction.repo, 'applications') - } - } - } - - private void prepareApplicationNginxHelmJenkins() { - if (!config.features.secrets.active) { - // External Secrets are not needed in example - FileSystemUtils.deleteFile nginxHelmJenkinsInitializationAction.repo.getAbsoluteLocalRepoTmpDir() + '/k8s/staging/external-secret.yaml' - FileSystemUtils.deleteFile nginxHelmJenkinsInitializationAction.repo.getAbsoluteLocalRepoTmpDir() + '/k8s/production/external-secret.yaml' - } - } - - private void preparePetClinicRepos() { - for (def repoInitAction : petClinicInitializationActions) { - def tmpDir = repoInitAction.repo.getAbsoluteLocalRepoTmpDir() - - log.debug("Copying original petclinic files for petclinic repo: $tmpDir") - fileSystemUtils.copyDirectory(remotePetClinicRepoTmpDir.toString(), tmpDir, new FileSystemUtils.IgnoreDotGitFolderFilter()) - fileSystemUtils.deleteEmptyFiles(Path.of(tmpDir), ~/k8s\/.*\.yaml/) - - new TemplatingEngine().template( - new File("${fileSystemUtils.getRootDir()}/applications/argocd/petclinic/Dockerfile.ftl"), - new File("${tmpDir}/Dockerfile"), - [baseImage: config.images.petclinic as String] - ) } } @@ -499,11 +401,6 @@ class ArgoCD extends Feature { FileSystemUtils.deleteFile argocdRepoInitializationAction.repo.getAbsoluteLocalRepoTmpDir() + '/argocd/templates/allow-namespaces.yaml' } - if (!config.content.examples) { - FileSystemUtils.deleteFile argocdRepoInitializationAction.repo.getAbsoluteLocalRepoTmpDir() + '/applications/example-apps.yaml' - FileSystemUtils.deleteFile argocdRepoInitializationAction.repo.getAbsoluteLocalRepoTmpDir() + '/projects/example-apps.yaml' - } - argocdRepoInitializationAction.repo.commitAndPush("Initial Commit") } diff --git a/src/main/groovy/com/cloudogu/gitops/utils/MapUtils.groovy b/src/main/groovy/com/cloudogu/gitops/utils/MapUtils.groovy index 6e452638b..a3e6a835d 100644 --- a/src/main/groovy/com/cloudogu/gitops/utils/MapUtils.groovy +++ b/src/main/groovy/com/cloudogu/gitops/utils/MapUtils.groovy @@ -5,25 +5,14 @@ class MapUtils { static Map deepMerge(Map src, Map target) { src.each { key, value -> if (value == null) { - // If the value in src is null, set the key in target to null target[key] = null + return + } + def oldVal = target.containsKey(key) ? target[key] : null + if (oldVal instanceof Map && value instanceof Map) { + target[key] = deepMerge((Map) value, (Map) oldVal) } else { - target.merge(key, value) { oldVal, newVal -> - // Case 1: If both values are Maps, perform a deep merge - if (oldVal instanceof Map && newVal instanceof Map) { - return deepMerge(newVal, oldVal) // Recursively merge the maps - } - // Case 2: If newVal is null, set the key to null in target - if (newVal == null) { - return null - } - // Case 3: If oldVal is null, use newVal - if (oldVal == null) { - return newVal - } - // Case 4: Default, return the new value (newVal takes priority) - return newVal - } + target[key] = value } } return target diff --git a/src/test/groovy/com/cloudogu/gitops/ApplicationConfiguratorTest.groovy b/src/test/groovy/com/cloudogu/gitops/ApplicationConfiguratorTest.groovy index e2a603a95..dad5d5ac2 100644 --- a/src/test/groovy/com/cloudogu/gitops/ApplicationConfiguratorTest.groovy +++ b/src/test/groovy/com/cloudogu/gitops/ApplicationConfiguratorTest.groovy @@ -263,26 +263,6 @@ class ApplicationConfiguratorTest { // no exceptions means success } - @Test - void "Certain properties are read from env"() { - withEnvironmentVariable('SPRING_BOOT_HELM_CHART_REPO', 'value1').execute { - def actualConfig = new ApplicationConfigurator(fileSystemUtils).initConfig(new Config()) - assertThat(actualConfig.repositories.springBootHelmChart.url).isEqualTo('value1') - } - withEnvironmentVariable('SPRING_PETCLINIC_REPO', 'value2').execute { - def actualConfig = new ApplicationConfigurator(fileSystemUtils).initConfig(new Config()) - assertThat(actualConfig.repositories.springPetclinic.url).isEqualTo('value2') - } - withEnvironmentVariable('GITOPS_BUILD_LIB_REPO', 'value3').execute { - def actualConfig = new ApplicationConfigurator(fileSystemUtils).initConfig(new Config()) - assertThat(actualConfig.repositories.gitopsBuildLib.url).isEqualTo('value3') - } - withEnvironmentVariable('CES_BUILD_LIB_REPO', 'value4').execute { - def actualConfig = new ApplicationConfigurator(fileSystemUtils).initConfig(new Config()) - assertThat(actualConfig.repositories.cesBuildLib.url).isEqualTo('value4') - } - } - @Test void "base url: evaluates for all tools"() { testConfig.application.baseUrl = 'http://localhost' @@ -298,8 +278,6 @@ class ApplicationConfiguratorTest { assertThat(actualConfig.features.mail.mailhogUrl).isEqualTo("http://mailhog.localhost") assertThat(actualConfig.features.monitoring.grafanaUrl).isEqualTo("http://grafana.localhost") assertThat(actualConfig.features.secrets.vault.url).isEqualTo("http://vault.localhost") - assertThat(actualConfig.features.exampleApps.petclinic.baseDomain).isEqualTo("petclinic.localhost") - assertThat(actualConfig.features.exampleApps.nginx.baseDomain).isEqualTo("nginx.localhost") assertThat(actualConfig.scmm.ingress).isEqualTo("scmm.localhost") assertThat(actualConfig.jenkins.ingress).isEqualTo("jenkins.localhost") } @@ -320,8 +298,6 @@ class ApplicationConfiguratorTest { assertThat(actualConfig.features.mail.mailhogUrl).isEqualTo("http://mailhog-localhost") assertThat(actualConfig.features.monitoring.grafanaUrl).isEqualTo("http://grafana-localhost") assertThat(actualConfig.features.secrets.vault.url).isEqualTo("http://vault-localhost") - assertThat(actualConfig.features.exampleApps.petclinic.baseDomain).isEqualTo("petclinic-localhost") - assertThat(actualConfig.features.exampleApps.nginx.baseDomain).isEqualTo("nginx-localhost") assertThat(actualConfig.scmm.ingress).isEqualTo("scmm-localhost") assertThat(actualConfig.jenkins.ingress).isEqualTo("jenkins-localhost") } @@ -377,8 +353,6 @@ class ApplicationConfiguratorTest { testConfig.features.mail.mailhogUrl = 'mailhog' testConfig.features.monitoring.grafanaUrl = 'grafana' testConfig.features.secrets.vault.url = 'vault' - testConfig.features.exampleApps.petclinic.baseDomain = 'petclinic' - testConfig.features.exampleApps.nginx.baseDomain = 'nginx' def actualConfig = applicationConfigurator.initConfig(testConfig) @@ -386,8 +360,6 @@ class ApplicationConfiguratorTest { assertThat(actualConfig.features.mail.mailhogUrl).isEqualTo("mailhog") assertThat(actualConfig.features.monitoring.grafanaUrl).isEqualTo("grafana") assertThat(actualConfig.features.secrets.vault.url).isEqualTo("vault") - assertThat(actualConfig.features.exampleApps.petclinic.baseDomain).isEqualTo("petclinic") - assertThat(actualConfig.features.exampleApps.nginx.baseDomain).isEqualTo("nginx") } @Test diff --git a/src/test/groovy/com/cloudogu/gitops/config/schema/JsonConfigValidatorTest.groovy b/src/test/groovy/com/cloudogu/gitops/config/schema/JsonConfigValidatorTest.groovy index d1a487525..973f776b2 100644 --- a/src/test/groovy/com/cloudogu/gitops/config/schema/JsonConfigValidatorTest.groovy +++ b/src/test/groovy/com/cloudogu/gitops/config/schema/JsonConfigValidatorTest.groovy @@ -13,28 +13,10 @@ class JsonConfigValidatorTest { static Stream validSchemas() { Stream.Builder ret = Stream.builder() - ret.add(Arguments.of("empty images", [ - images: [:] - ])) - - ret.add(Arguments.of("defined images", [ - images: [ - kubectl: "localhost:30000/kubectl", - helm: "localhost:30000/helm", - yamllint: "localhost:30000/yamllint", - nginx: "localhost:30000/nginx", - ] - ])) - ret.add(Arguments.of("multiple values", [ features: [ argocd: [ url: "http://localhost/argocd" - ], - exampleApps: [ - petclinic: [ - baseDomain: "petclinic.localhost" - ] ] ] ])) diff --git a/src/test/groovy/com/cloudogu/gitops/features/ScmManagerTest.groovy b/src/test/groovy/com/cloudogu/gitops/features/ScmManagerTest.groovy index ae0f49468..08075dc31 100644 --- a/src/test/groovy/com/cloudogu/gitops/features/ScmManagerTest.groovy +++ b/src/test/groovy/com/cloudogu/gitops/features/ScmManagerTest.groovy @@ -45,18 +45,6 @@ class ScmManagerTest { internal: true, url: 'http://jenkins', urlForScmm: 'http://jenkins4scm' - ), - repositories: new Config.RepositoriesSchema( - springBootHelmChart: new Config.RepositorySchemaWithRef( - url: 'springBootHelmChartUrl', - ref: '1.2.3' - ), - gitopsBuildLib: new Config.RepositorySchema( - url: 'gitopsBuildLibUrl' - ), - cesBuildLib: new Config.RepositorySchema( - url: 'cesBuildLibUrl' - ) ) ) CommandExecutorForTest commandExecutor = new CommandExecutorForTest() @@ -106,13 +94,8 @@ class ScmManagerTest { assertThat(env['SCMM_URL_FOR_JENKINS']).isEqualTo('http://scmm4jenkins') assertThat(env['REMOTE_CLUSTER']).isEqualTo('false') assertThat(env['INSTALL_ARGOCD']).isEqualTo('true') - assertThat(env['SPRING_BOOT_HELM_CHART_COMMIT']).isEqualTo('1.2.3') - assertThat(env['SPRING_BOOT_HELM_CHART_REPO']).isEqualTo('springBootHelmChartUrl') - assertThat(env['GITOPS_BUILD_LIB_REPO']).isEqualTo('gitopsBuildLibUrl') - assertThat(env['CES_BUILD_LIB_REPO']).isEqualTo('cesBuildLibUrl') assertThat(env['NAME_PREFIX']).isEqualTo('foo-') assertThat(env['INSECURE']).isEqualTo('false') - assertThat(env['CONTENT_EXAMPLES']).isEqualTo('false') assertThat(env['SKIP_PLUGINS']).isEqualTo('true') assertThat(env['SKIP_RESTART']).isEqualTo('true') } diff --git a/src/test/groovy/com/cloudogu/gitops/features/argocd/ArgoCDTest.groovy b/src/test/groovy/com/cloudogu/gitops/features/argocd/ArgoCDTest.groovy index 4e66d15ce..5305028db 100644 --- a/src/test/groovy/com/cloudogu/gitops/features/argocd/ArgoCDTest.groovy +++ b/src/test/groovy/com/cloudogu/gitops/features/argocd/ArgoCDTest.groovy @@ -31,6 +31,7 @@ class ArgoCDTest { helmKubeval: 'helmKubeval-value', yamllint : 'yamllint-value' ] + Config config = Config.fromMap( application: [ openshift : false, @@ -51,25 +52,13 @@ class ArgoCDTest { internal: true, url : 'https://abc' ], - images: buildImages + [petclinic: 'petclinic-value'], - repositories: [ - springBootHelmChart: [ - url: 'https://github.com/cloudogu/spring-boot-helm-chart.git', - ref: '0.3.0' - ], - springPetclinic : [ - url: 'https://github.com/cloudogu/spring-petclinic.git', - ref: '32c8653' - ], - gitopsBuildLib : [ - url: "https://github.com/cloudogu/gitops-build-lib.git", - ], - cesBuildLib : [ - url: 'https://github.com/cloudogu/ces-build-lib.git', - ] - ], content: [ - examples: true + examples: true, + variables: [ + images: [ + buildImages + [petclinic: 'petclinic-value'] + ] + ] ], features: [ argocd : [ @@ -106,10 +95,6 @@ class ArgoCDTest { ScmmRepo argocdRepo String actualHelmValuesFile ScmmRepo clusterResourcesRepo - ScmmRepo exampleAppsRepo - ScmmRepo nginxHelmJenkinsRepo - ScmmRepo nginxValidationRepo - ScmmRepo brokenApplicationRepo ScmmRepo tenantBootstrap List petClinicRepos = [] CloneCommand gitCloneMock = mock(CloneCommand.class, RETURNS_DEEP_STUBS) @@ -185,21 +170,6 @@ class ArgoCDTest { assertThat(argocdYaml['spec']['source']['directory']).isNull() assertThat(argocdYaml['spec']['source']['path']).isEqualTo('argocd/') // The other application files should be validated here as well! - - // Content examples - assertThat(Path.of(argocdRepo.getAbsoluteLocalRepoTmpDir(), 'projects/example-apps.yaml')).exists() - assertThat(Path.of(argocdRepo.getAbsoluteLocalRepoTmpDir(), 'applications/example-apps.yaml')).exists() - } - - @Test - void 'Disables example content'() { - config.content.examples = false - - def argocd = createArgoCD() - argocd.install() - - assertThat(Path.of(argocdRepo.getAbsoluteLocalRepoTmpDir(), 'projects/example-apps.yaml')).doesNotExist() - assertThat(Path.of(argocdRepo.getAbsoluteLocalRepoTmpDir(), 'applications/example-apps.yaml')).doesNotExist() } @Test @@ -301,13 +271,11 @@ class ArgoCDTest { def clusterRessourcesYaml = new YamlSlurper().parse(Path.of argocdRepo.getAbsoluteLocalRepoTmpDir(), 'projects/cluster-resources.yaml') def argocdYaml = new YamlSlurper().parse(Path.of argocdRepo.getAbsoluteLocalRepoTmpDir(), 'applications/argocd.yaml') def defaultYaml = new YamlSlurper().parse(Path.of argocdRepo.getAbsoluteLocalRepoTmpDir(), 'projects/default.yaml') - def exampleAppsYaml = new YamlSlurper().parse(Path.of argocdRepo.getAbsoluteLocalRepoTmpDir(), 'projects/example-apps.yaml') assertThat(new YamlSlurper().parseText(valuesYaml['argo-cd']['notifications']['notifiers']['service.email'] as String)['from']).isEqualTo("argocd@example.com") assertThat(clusterRessourcesYaml['metadata']['annotations']['notifications.argoproj.io/subscribe.email']).isEqualTo('argocd@example.com') assertThat(argocdYaml['metadata']['annotations']['notifications.argoproj.io/subscribe.on-sync-status-unknown.email']).isEqualTo('argocd@example.com') assertThat(defaultYaml['metadata']['annotations']['notifications.argoproj.io/subscribe.email']).isEqualTo('argocd@example.com') - assertThat(exampleAppsYaml['metadata']['annotations']['notifications.argoproj.io/subscribe.email']).isEqualTo('app-team@example.com') } @Test @@ -319,13 +287,11 @@ class ArgoCDTest { def clusterRessourcesYaml = new YamlSlurper().parse(Path.of argocdRepo.getAbsoluteLocalRepoTmpDir(), 'projects/cluster-resources.yaml') def argocdYaml = new YamlSlurper().parse(Path.of argocdRepo.getAbsoluteLocalRepoTmpDir(), 'applications/argocd.yaml') def defaultYaml = new YamlSlurper().parse(Path.of argocdRepo.getAbsoluteLocalRepoTmpDir(), 'projects/default.yaml') - def exampleAppsYaml = new YamlSlurper().parse(Path.of argocdRepo.getAbsoluteLocalRepoTmpDir(), 'projects/example-apps.yaml') assertThat(new YamlSlurper().parseText(valuesYaml['argo-cd']['notifications']['notifiers']['service.email'] as String)['from']).isEqualTo("argocd@example.org") assertThat(clusterRessourcesYaml['metadata']['annotations']['notifications.argoproj.io/subscribe.email']).isEqualTo('infra@example.org') assertThat(argocdYaml['metadata']['annotations']['notifications.argoproj.io/subscribe.on-sync-status-unknown.email']).isEqualTo('infra@example.org') assertThat(defaultYaml['metadata']['annotations']['notifications.argoproj.io/subscribe.email']).isEqualTo('infra@example.org') - assertThat(exampleAppsYaml['metadata']['annotations']['notifications.argoproj.io/subscribe.email']).isEqualTo('app-team@example.org') } @Test @@ -405,33 +371,6 @@ class ArgoCDTest { assertThat(new YamlSlurper().parseText(valuesYaml['argo-cd']['notifications']['notifiers']['service.email'] as String)) doesNotHaveToString('password') } - @Test - void 'When vault enabled: Pushes external secret, and mounts into example app'() { - createArgoCD().install() - def valuesYaml = new YamlSlurper().parse(Path.of nginxHelmJenkinsRepo.getAbsoluteLocalRepoTmpDir(), 'k8s/values-shared.yaml') - - assertThat((valuesYaml['extraVolumeMounts'] as List)).hasSize(2) - assertThat((valuesYaml['extraVolumes'] as List)).hasSize(2) - - assertThat(new File(nginxHelmJenkinsRepo.getAbsoluteLocalRepoTmpDir() + "/k8s/staging/external-secret.yaml")).exists() - assertThat(new File(nginxHelmJenkinsRepo.getAbsoluteLocalRepoTmpDir() + "/k8s/production/external-secret.yaml")).exists() - assertThat(new File(clusterResourcesRepo.getAbsoluteLocalRepoTmpDir() + "/misc/secrets")).exists() - } - - @Test - void 'When vault disabled: Does not push ExternalSecret and not mount into example app'() { - config.features.secrets.active = false - createArgoCD().install() - def valuesYaml = new YamlSlurper().parse(Path.of nginxHelmJenkinsRepo.getAbsoluteLocalRepoTmpDir(), 'k8s/values-shared.yaml') - assertThat((valuesYaml['extraVolumeMounts'] as List)).hasSize(1) - assertThat((valuesYaml['extraVolumes'] as List)).hasSize(1) - assertThat((valuesYaml['extraVolumeMounts'] as List)[0]['name']).isEqualTo('index') - assertThat((valuesYaml['extraVolumes'] as List)[0]['name']).isEqualTo('index') - - assertThat(new File(nginxHelmJenkinsRepo.getAbsoluteLocalRepoTmpDir() + "/k8s/staging/external-secret.yaml")).doesNotExist() - assertThat(new File(nginxHelmJenkinsRepo.getAbsoluteLocalRepoTmpDir() + "/k8s/production/external-secret.yaml")).doesNotExist() - } - @Test void 'When vault disabled: Does not push path "secrets" to cluster resources'() { config.features.secrets.active = false @@ -439,70 +378,6 @@ class ArgoCDTest { assertThat(new File(clusterResourcesRepo.getAbsoluteLocalRepoTmpDir() + "/misc/secrets")).doesNotExist() } - @Test - void 'Pushes example repos for local'() { - config.application.remote = false - def argocd = createArgoCD() - - def setUriMock = mock(CloneCommand.class, RETURNS_DEEP_STUBS) - def checkoutMock = mock(CheckoutCommand.class, RETURNS_DEEP_STUBS) - when(gitCloneMock.setURI(anyString())).thenReturn(setUriMock) - when(setUriMock.setDirectory(any(File.class)).call().checkout()).thenReturn(checkoutMock) - - argocd.install() - def valuesYaml = parseActualYaml(new File(nginxHelmJenkinsRepo.getAbsoluteLocalRepoTmpDir()), 'k8s/values-shared.yaml') - assertThat(valuesYaml['service']['type']).isEqualTo('ClusterIP') - assertThat(parseActualYaml(new File(nginxHelmJenkinsRepo.getAbsoluteLocalRepoTmpDir()), 'k8s/values-production.yaml')).doesNotContainKey('ingress') - assertThat(parseActualYaml(new File(nginxHelmJenkinsRepo.getAbsoluteLocalRepoTmpDir()), 'k8s/values-staging.yaml')).doesNotContainKey('ingress') - assertThat(valuesYaml).doesNotContainKey('resources') - - valuesYaml = parseActualYaml(new File(exampleAppsRepo.getAbsoluteLocalRepoTmpDir()), 'apps/nginx-helm-umbrella/values.yaml') - assertThat(valuesYaml['nginx']['service']['type']).isEqualTo('ClusterIP') - assertThat(valuesYaml['nginx'] as Map).doesNotContainKey('ingress') - assertThat(valuesYaml['nginx'] as Map).doesNotContainKey('resources') - - assertThat((parseActualYaml(brokenApplicationRepo.absoluteLocalRepoTmpDir + '/broken-application.yaml')[1]['spec']['type'])) - .isEqualTo('ClusterIP') - assertThat((parseActualYaml(brokenApplicationRepo.absoluteLocalRepoTmpDir + '/broken-application.yaml')[0]['spec']['template']['spec']['containers'] as List)[0]['resources']) - .isNull() - - assertThat(new File(nginxValidationRepo.absoluteLocalRepoTmpDir, '/k8s/values-shared.yaml').text).doesNotContain('resources:') - - // Assert Petclinic repo cloned - verify(gitCloneMock).setURI('https://github.com/cloudogu/spring-petclinic.git') - verify(setUriMock).setDirectory(argocd.remotePetClinicRepoTmpDir) - verify(checkoutMock).setName('32c8653') - - assertPetClinicRepos('ClusterIP', 'LoadBalancer', '') - } - - @Test - void 'Pushes example repos for remote'() { - config.application.remote = true - config.features.exampleApps.petclinic.baseDomain = 'petclinic.local' - config.features.exampleApps.nginx.baseDomain = 'nginx.local' - - createArgoCD().install() - - assertThat(parseActualYaml(new File(nginxHelmJenkinsRepo.getAbsoluteLocalRepoTmpDir()), 'k8s/values-shared.yaml').toString()) - .doesNotContain('ClusterIP') - assertThat(parseActualYaml(new File(nginxHelmJenkinsRepo.getAbsoluteLocalRepoTmpDir()), 'k8s/values-production.yaml')['ingress']['hostname']).isEqualTo('production.nginx-helm.nginx.local') - assertThat(parseActualYaml(new File(nginxHelmJenkinsRepo.getAbsoluteLocalRepoTmpDir()), 'k8s/values-staging.yaml')['ingress']['hostname']).isEqualTo('staging.nginx-helm.nginx.local') - - assertThat(parseActualYaml(new File(exampleAppsRepo.getAbsoluteLocalRepoTmpDir()), 'apps/nginx-helm-umbrella/values.yaml').toString()) - .doesNotContain('ClusterIP') - - def valuesYaml = parseActualYaml(new File(exampleAppsRepo.getAbsoluteLocalRepoTmpDir()), 'apps/nginx-helm-umbrella/values.yaml') - assertThat(valuesYaml['nginx']['ingress']['hostname'] as String).isEqualTo('production.nginx-helm-umbrella.nginx.local') - - assertThat((parseActualYaml(brokenApplicationRepo.absoluteLocalRepoTmpDir + '/broken-application.yaml')[2]['spec']['rules'] as List)[0]['host']) - .isEqualTo('broken-application.nginx.local') - assertThat((parseActualYaml(brokenApplicationRepo.absoluteLocalRepoTmpDir + '/broken-application.yaml')[1]['spec']['type'])) - .isEqualTo('LoadBalancer') - - assertPetClinicRepos('LoadBalancer', 'ClusterIP', 'petclinic.local') - } - @Test void 'Prepares repos for air-gapped mode'() { config.features.monitoring.active = false @@ -542,52 +417,12 @@ class ArgoCDTest { k8sCommands.assertExecuted("kubectl apply -f https://raw.githubusercontent.com/prometheus-community/helm-charts/kube-prometheus-stack-42.0.3/charts/kube-prometheus-stack/charts/crds/crds/crd-servicemonitors.yaml") } - @Test - void 'If urlSeparatorHyphen is set, ensure that hostnames are build correctly '() { - config.application.remote = true - config.features.exampleApps.petclinic.baseDomain = 'petclinic-local' - config.features.exampleApps.nginx.baseDomain = 'nginx-local' - config.application.urlSeparatorHyphen = true - - createArgoCD().install() - - def valuesYaml = parseActualYaml(new File(exampleAppsRepo.getAbsoluteLocalRepoTmpDir()), 'apps/nginx-helm-umbrella/values.yaml') - assertThat(valuesYaml['nginx']['ingress']['hostname'] as String).isEqualTo('production-nginx-helm-umbrella-nginx-local') - - assertThat(parseActualYaml(new File(nginxHelmJenkinsRepo.getAbsoluteLocalRepoTmpDir()), 'k8s/values-production.yaml')['ingress']['hostname']).isEqualTo('production-nginx-helm-nginx-local') - assertThat(parseActualYaml(new File(nginxHelmJenkinsRepo.getAbsoluteLocalRepoTmpDir()), 'k8s/values-staging.yaml')['ingress']['hostname']).isEqualTo('staging-nginx-helm-nginx-local') - - assertThat((parseActualYaml(brokenApplicationRepo.absoluteLocalRepoTmpDir + '/broken-application.yaml')[2]['spec']['rules'] as List)[0]['host']) - .isEqualTo('broken-application-nginx-local') - - assertPetClinicRepos('LoadBalancer', 'ClusterIP', 'petclinic-local') - } - - @Test - void 'If urlSeparatorHyphen is NOT set, ensure that hostnames are build correctly '() { - config.application.remote = true - config.features.exampleApps.petclinic.baseDomain = 'petclinic.local' - config.features.exampleApps.nginx.baseDomain = 'nginx.local' - config.application.urlSeparatorHyphen = false - - createArgoCD().install() - - def valuesYaml = parseActualYaml(new File(exampleAppsRepo.getAbsoluteLocalRepoTmpDir()), 'apps/nginx-helm-umbrella/values.yaml') - assertThat(valuesYaml['nginx']['ingress']['hostname'] as String).isEqualTo('production.nginx-helm-umbrella.nginx.local') - - assertThat(parseActualYaml(new File(nginxHelmJenkinsRepo.getAbsoluteLocalRepoTmpDir()), 'k8s/values-production.yaml')['ingress']['hostname']).isEqualTo('production.nginx-helm.nginx.local') - assertThat(parseActualYaml(new File(nginxHelmJenkinsRepo.getAbsoluteLocalRepoTmpDir()), 'k8s/values-staging.yaml')['ingress']['hostname']).isEqualTo('staging.nginx-helm.nginx.local') - assertPetClinicRepos('LoadBalancer', 'ClusterIP', 'petclinic.local') - } - @Test void 'For internal SCMM: Use service address in gitops repos'() { def argocd = createArgoCD() argocd.install() List filesWithInternalSCMM = findFilesContaining(new File(clusterResourcesRepo.getAbsoluteLocalRepoTmpDir()), argocd.scmmUrlInternal) assertThat(filesWithInternalSCMM).isNotEmpty() - filesWithInternalSCMM = findFilesContaining(new File(exampleAppsRepo.getAbsoluteLocalRepoTmpDir()), argocd.scmmUrlInternal) - assertThat(filesWithInternalSCMM).isNotEmpty() } @Test @@ -597,13 +432,9 @@ class ArgoCDTest { argocd.install() List filesWithInternalSCMM = findFilesContaining(new File(clusterResourcesRepo.getAbsoluteLocalRepoTmpDir()), argocd.scmmUrlInternal) assertThat(filesWithInternalSCMM).isEmpty() - filesWithInternalSCMM = findFilesContaining(new File(exampleAppsRepo.getAbsoluteLocalRepoTmpDir()), argocd.scmmUrlInternal) - assertThat(filesWithInternalSCMM).isEmpty() List filesWithExternalSCMM = findFilesContaining(new File(clusterResourcesRepo.getAbsoluteLocalRepoTmpDir()), "https://abc") assertThat(filesWithExternalSCMM).isNotEmpty() - filesWithExternalSCMM = findFilesContaining(new File(exampleAppsRepo.getAbsoluteLocalRepoTmpDir()), "https://abc") - assertThat(filesWithExternalSCMM).isNotEmpty() } @Test @@ -612,7 +443,6 @@ class ArgoCDTest { argocd.install() assertArgoCdYamlPrefixes(argocd.scmmUrlInternal, '') - assertJenkinsEnvironmentVariablesPrefixes('') } @Test @@ -620,7 +450,6 @@ class ArgoCDTest { config.registry.twoRegistries = true createArgoCD().install() - assertJenkinsEnvironmentVariablesPrefixes('') assertJenkinsfileRegistryCredentials() } @@ -633,7 +462,6 @@ class ArgoCDTest { argocd.install() assertArgoCdYamlPrefixes(argocd.scmmUrlInternal, 'abc-') - assertJenkinsEnvironmentVariablesPrefixes('ABC_') } @Test @@ -653,60 +481,6 @@ class ArgoCDTest { } } - - @Test - void 'configures custom nginx image'() { - config.images.nginx = 'localhost:5000/nginx/nginx:latest' - createArgoCD().install() - - def image = parseActualYaml(nginxHelmJenkinsRepo.absoluteLocalRepoTmpDir + '/k8s/values-shared.yaml')['image'] - assertThat(image['registry']).isEqualTo('localhost:5000') - assertThat(image['repository']).isEqualTo('nginx/nginx') - assertThat(image['tag']).isEqualTo('latest') - - image = parseActualYaml(new File(exampleAppsRepo.getAbsoluteLocalRepoTmpDir()), 'apps/nginx-helm-umbrella/values.yaml')['nginx']['image'] - assertThat(image['registry']).isEqualTo('localhost:5000') - assertThat(image['repository']).isEqualTo('nginx/nginx') - assertThat(image['tag']).isEqualTo('latest') - - def deployment = parseActualYaml(brokenApplicationRepo.absoluteLocalRepoTmpDir + '/broken-application.yaml')[0] - assertThat(deployment['kind']).as("Did not correctly fetch deployment from broken-application.yaml").isEqualTo("Deploymentz") - assertThat((deployment['spec']['template']['spec']['containers'] as List)[0]['image']).isEqualTo('localhost:5000/nginx/nginx:latest') - - def yamlString = new File(nginxValidationRepo.absoluteLocalRepoTmpDir, '/k8s/values-shared.yaml').text - assertThat(yamlString).startsWith("""image: - registry: localhost:5000 - repository: nginx/nginx - tag: latest -""") - } - - @Test - void 'Sets image pull secrets for nginx'() { - config.registry.createImagePullSecrets = true - config.registry.twoRegistries = true - config.registry.proxyUrl = 'proxy-url' - config.registry.proxyUsername = 'proxy-user' - config.registry.proxyPassword = 'proxy-pw' - - createArgoCD().install() - - assertThat(parseActualYaml(nginxHelmJenkinsRepo.absoluteLocalRepoTmpDir + '/k8s/values-shared.yaml')['global']['imagePullSecrets']) - .isEqualTo(['proxy-registry']) - - assertThat(parseActualYaml(new File(exampleAppsRepo.getAbsoluteLocalRepoTmpDir()), 'apps/nginx-helm-umbrella/values.yaml')['nginx']['global']['imagePullSecrets']) - .isEqualTo(['proxy-registry']) - - def deployment = parseActualYaml(brokenApplicationRepo.absoluteLocalRepoTmpDir + '/broken-application.yaml')[0] - assertThat(deployment['spec']['imagePullSecrets']).isEqualTo([[name: 'proxy-registry']]) - - assertThat(new File(nginxValidationRepo.absoluteLocalRepoTmpDir, '/k8s/values-shared.yaml').text) - .contains("""global: - imagePullSecrets: - - proxy-registry -""") - } - @Test void 'Skips CRDs for argo cd'() { config.application.skipCrds = true @@ -737,55 +511,6 @@ class ArgoCDTest { } } - @Test - void 'use custom maven image'() { - config.images.maven = 'maven:latest' - - createArgoCD().install() - - for (def petclinicRepo : petClinicRepos) { - if (petclinicRepo.scmmRepoTarget.contains('argocd/petclinic-plain')) { - assertThat(new File(petclinicRepo.absoluteLocalRepoTmpDir, 'Jenkinsfile').text).contains('mvn = cesBuildLib.MavenInDocker.new(this, \'maven:latest\')') - } - } - } - - @Test - void 'use maven with proxy registry and credentials'() { - config.images.maven = 'latest' - config.registry.twoRegistries = true - - createArgoCD().install() - - for (def petclinicRepo : petClinicRepos) { - if (petclinicRepo.scmmRepoTarget.contains('argocd/petclinic-plain')) { - assertThat(new File(petclinicRepo.absoluteLocalRepoTmpDir, 'Jenkinsfile').text).contains('mvn = cesBuildLib.MavenInDocker.new(this, \'latest\', dockerRegistryProxyCredentials)') - } - } - - } - - - @Test - void 'Sets pod resource limits and requests'() { - config.application.podResources = true - - createArgoCD().install() - - assertThat(parseActualYaml(new File(nginxHelmJenkinsRepo.getAbsoluteLocalRepoTmpDir()), 'k8s/values-shared.yaml')['resources'] as Map) - .containsKeys('limits', 'requests') - - assertThat(parseActualYaml(new File(exampleAppsRepo.getAbsoluteLocalRepoTmpDir()), 'apps/nginx-helm-umbrella/values.yaml')['nginx']['resources'] as Map) - .containsKeys('limits', 'requests') - - assertThat(new File(nginxValidationRepo.absoluteLocalRepoTmpDir, '/k8s/values-shared.yaml').text).contains('limits:', 'resources:') - - assertThat((parseActualYaml(brokenApplicationRepo.absoluteLocalRepoTmpDir + '/broken-application.yaml')[0]['spec']['template']['spec']['containers'] as List)[0]['resources'] as Map) - .containsKeys('limits', 'requests') - - assertPetClinicRepos('ClusterIP', 'LoadBalancer', '') - } - @Test void 'ArgoCD with active network policies'() { config.application.netpols = true @@ -843,7 +568,7 @@ class ArgoCDTest { } private void assertArgoCdYamlPrefixes(String scmmUrl, String expectedPrefix) { - assertAllYamlFiles(new File(argocdRepo.getAbsoluteLocalRepoTmpDir()), 'projects', 4) { Path file -> + assertAllYamlFiles(new File(argocdRepo.getAbsoluteLocalRepoTmpDir()), 'projects', 3) { Path file -> def yaml = parseActualYaml(file.toString()) List sourceRepos = yaml['spec']['sourceRepos'] as List // Some projects might not have sourceRepos @@ -876,7 +601,7 @@ class ArgoCDTest { } } - assertAllYamlFiles(new File(argocdRepo.getAbsoluteLocalRepoTmpDir()), 'applications', 5) { Path file -> + assertAllYamlFiles(new File(argocdRepo.getAbsoluteLocalRepoTmpDir()), 'applications', 4) { Path file -> def yaml = parseActualYaml(file.toString()) assertThat(yaml['spec']['source']['repoURL'] as String) .as("$file repoURL have name prefix") @@ -891,16 +616,6 @@ class ArgoCDTest { .isEqualTo("${expectedPrefix}argocd".toString()) } - assertAllYamlFiles(new File(exampleAppsRepo.getAbsoluteLocalRepoTmpDir()), 'argocd', 7) { Path it -> - def yaml = parseActualYaml(it.toString()) - List yamlDocuments = yaml instanceof List ? yaml : [yaml] - for (def document in yamlDocuments) { - assertThat(document['spec']['source']['repoURL'] as String) - .as("$it repoURL have name prefix") - .startsWith("${scmmUrl}/repo/${expectedPrefix}argocd") - } - } - assertAllYamlFiles(new File(clusterResourcesRepo.getAbsoluteLocalRepoTmpDir()), 'argocd', 1) { Path it -> def yaml = parseActualYaml(it.toString()) @@ -948,29 +663,6 @@ class ArgoCDTest { assertThat(nFiles).isEqualTo(numberOfFiles) } - private void assertJenkinsEnvironmentVariablesPrefixes(String prefix) { - List defaultRegistryEnvVars = ["env.${prefix}REGISTRY_URL", "env.${prefix}REGISTRY_PATH"] - List twoRegistriesEnvVars = ["env.${prefix}REGISTRY_PROXY_URL"] - - assertThat(new File(nginxHelmJenkinsRepo.absoluteLocalRepoTmpDir, 'Jenkinsfile').text).contains("env.${prefix}K8S_VERSION") - - for (def petclinicRepo : petClinicRepos) { - defaultRegistryEnvVars.each { expectedEnvVar -> - assertThat(new File(petclinicRepo.absoluteLocalRepoTmpDir, 'Jenkinsfile').text).contains(expectedEnvVar) - } - - if (config.registry['twoRegistries']) { - twoRegistriesEnvVars.each { expectedEnvVar -> - assertThat(new File(petclinicRepo.absoluteLocalRepoTmpDir, 'Jenkinsfile').text).contains(expectedEnvVar) - } - } else { - twoRegistriesEnvVars.each { expectedEnvVar -> - assertThat(new File(petclinicRepo.absoluteLocalRepoTmpDir, 'Jenkinsfile').text).doesNotContain(expectedEnvVar) - } - } - } - } - private static List findFilesContaining(File folder, String stringToSearch) { List result = [] folder.eachFileRecurse(FileType.FILES) { @@ -1562,21 +1254,6 @@ class ArgoCDTest { assertThat(miscYaml['metadata']['namespace']).isEqualTo('argocd') } - @Test - void 'generate example-apps bootstrapping application via ArgoApplication when true'() { - setup() - assertThat(new File(tenantBootstrap.getAbsoluteLocalRepoTmpDir() + "/applications/bootstrap.yaml")).exists() - assertThat(new File(tenantBootstrap.getAbsoluteLocalRepoTmpDir() + "/applications/argocd-application-example-apps-testPrefix-argocd.yaml")).exists() - } - - @Test - void 'not generating example-apps bootstrapping application via ArgoApplication when false'() { - config.content.examples = false - setup() - assertThat(new File(tenantBootstrap.getAbsoluteLocalRepoTmpDir() + "/applications/bootstrap.yaml")).exists() - assertThat(new File(tenantBootstrap.getAbsoluteLocalRepoTmpDir() + "/applications/argocd-application-example-apps-testPrefix-argocd.yaml")).doesNotExist() - } - @Test void 'Append namespaces to Argocd argocd-default-cluster-config secrets'() { config.application.namespaces.dedicatedNamespaces = new LinkedHashSet(['dedi-test1', 'dedi-test2', 'dedi-test3']) @@ -1963,14 +1640,6 @@ class ArgoCDTest { if (config.multiTenant.useDedicatedInstance) { tenantBootstrap = tenantBootstrapInitializationAction.repo } - - if (config.content.examples) { - exampleAppsRepo = exampleAppsInitializationAction.repo - nginxHelmJenkinsRepo = nginxHelmJenkinsInitializationAction.repo - nginxValidationRepo = nginxValidationInitializationAction.repo - brokenApplicationRepo = brokenApplicationInitializationAction.repo - petClinicRepos = petClinicInitializationActions.collect { it.repo } - } } @Override diff --git a/src/test/resources/testMainConfig.yaml b/src/test/resources/testMainConfig.yaml index f551dad57..1cca2d514 100644 --- a/src/test/resources/testMainConfig.yaml +++ b/src/test/resources/testMainConfig.yaml @@ -49,26 +49,6 @@ application: skipCrds: false namespaceIsolation: false netpols: false -images: - kubectl: "bitnamilegacy/kubectl:1.29" - helm: "ghcr.io/cloudogu/helm:3.15.4-1" - kubeval: "ghcr.io/cloudogu/helm:3.15.4-1" - helmKubeval: "ghcr.io/cloudogu/helm:3.15.4-1" - yamllint: "cytopia/yamllint:1.25-0.7" - nginx: "" - petclinic: "eclipse-temurin:11-jre-alpine" - maven: "" -repositories: - springBootHelmChart: - url: "/gitops/repos/spring-boot-helm-chart.git" - ref: "0.3.2" - springPetclinic: - url: "/gitops/repos/spring-petclinic.git" - ref: "b0e0d18" - gitopsBuildLib: - url: "/gitops/repos/gitops-build-lib.git" - cesBuildLib: - url: "/gitops/repos/ces-build-lib.git" features: argocd: active: false @@ -128,11 +108,6 @@ features: version: "4.11.3" values: {} image: "" - exampleApps: - petclinic: - baseDomain: "" - nginx: - baseDomain: "" certManager: active: false helm: From 739ca2f78b51df6a721c81ff3df559eee0e98cb7 Mon Sep 17 00:00:00 2001 From: Marco Droll Date: Mon, 27 Oct 2025 15:27:24 +0100 Subject: [PATCH 2/6] - helm-with-dependencies not existing anymore - extract hardcoded references for example-apps in unit test --- .../argocd/petclinic-helm/Jenkinsfile.ftl | 4 +- .../gitops/features/JenkinsTest.groovy | 44 ------------------- 2 files changed, 2 insertions(+), 46 deletions(-) diff --git a/examples/example-apps-via-content-loader/argocd/petclinic-helm/Jenkinsfile.ftl b/examples/example-apps-via-content-loader/argocd/petclinic-helm/Jenkinsfile.ftl index 878050bee..a5cf30a31 100644 --- a/examples/example-apps-via-content-loader/argocd/petclinic-helm/Jenkinsfile.ftl +++ b/examples/example-apps-via-content-loader/argocd/petclinic-helm/Jenkinsfile.ftl @@ -20,8 +20,8 @@ String getCesBuildLibRepo() { configRepositoryPRBaseUrl+"/repo/3rd-party-depende String getCesBuildLibVersion() { '2.5.0' } String getGitOpsBuildLibRepo() { configRepositoryPRBaseUrl+"/repo/3rd-party-dependencies/gitops-build-lib" } String getGitOpsBuildLibVersion() { '0.8.0'} -String getHelmChartRepository() { configRepositoryPRBaseUrl+"/repo/3rd-party-dependencies/spring-boot-helm-chart-with-dependency" } -String getHelmChartVersion() { "1.0.0" } +String getHelmChartRepository() { configRepositoryPRBaseUrl+"/repo/3rd-party-dependencies/spring-boot-helm-chart" } +String getHelmChartVersion() { "0.4.0" } String getMainBranch() { 'main' } cesBuildLib = library(identifier: "ces-build-lib@${cesBuildLibVersion}", diff --git a/src/test/groovy/com/cloudogu/gitops/features/JenkinsTest.groovy b/src/test/groovy/com/cloudogu/gitops/features/JenkinsTest.groovy index 30f6aa070..3f0ac211f 100644 --- a/src/test/groovy/com/cloudogu/gitops/features/JenkinsTest.groovy +++ b/src/test/groovy/com/cloudogu/gitops/features/JenkinsTest.groovy @@ -213,20 +213,6 @@ me:x:1000:''') verify(userManager).createUser('metrics-usr', 'metrics-pw') verify(userManager).grantPermission('metrics-usr', UserManager.Permissions.METRICS_VIEW) - - verify(jobManger).createCredential('my-prefix-example-apps', 'scmm-user', - 'my-prefix-gitops', 'scmm-pw', 'credentials for accessing scm-manager') - - verify(jobManger).startJob('my-prefix-example-apps') - verify(jobManger).createJob('my-prefix-example-apps', 'http://scmm/scm', - "my-prefix-argocd", 'scmm-user') - - verify(jobManger).createCredential('my-prefix-example-apps', 'registry-user', - 'reg-usr', 'reg-pw', 'credentials for accessing the docker-registry for writing images built on jenkins') - verify(jobManger, never()).createCredential(eq('my-prefix-example-apps'), eq('registry-proxy-user'), - anyString(), anyString(), anyString()) - verify(jobManger, never()).createCredential(eq('my-prefix-example-apps'), eq('registry-proxy-user'), - anyString(), anyString(), anyString()) } @Test @@ -279,36 +265,6 @@ me:x:1000:''') createJenkins().install() assertThat(config.jenkins.url).endsWith('192.168.16.2:42') } - - @Test - void 'Handles two registries'() { - config.registry.twoRegistries = true - config.content.examples = true - config.application.namePrefix = 'my-prefix-' - config.application.namePrefixForEnvVars = 'MY_PREFIX_' - - config.registry.url = 'reg-url' - config.registry.path = 'reg-path' - config.registry.username = 'reg-usr' - config.registry.password = 'reg-pw' - config.registry.proxyUrl = 'reg-proxy-url' - config.registry.proxyUsername = 'reg-proxy-usr' - config.registry.proxyPassword = 'reg-proxy-pw' - - createJenkins().install() - - verify(globalPropertyManager).setGlobalProperty('MY_PREFIX_REGISTRY_PROXY_URL', 'reg-proxy-url') - - verify(globalPropertyManager).setGlobalProperty(eq('MY_PREFIX_REGISTRY_URL'), anyString()) - verify(globalPropertyManager).setGlobalProperty(eq('MY_PREFIX_REGISTRY_PATH'), anyString()) - - verify(jobManger).createCredential('my-prefix-example-apps', 'registry-user', - 'reg-usr', 'reg-pw', - 'credentials for accessing the docker-registry for writing images built on jenkins') - verify(jobManger).createCredential('my-prefix-example-apps', 'registry-proxy-user', - 'reg-proxy-usr', 'reg-proxy-pw', - 'credentials for accessing the docker-registry that contains 3rd party or base images') - } @Test void 'Does not create create job credentials when argo cd is deactivated'() { From 019d248874bf30b76ae31212637d126420ecc1b7 Mon Sep 17 00:00:00 2001 From: Marco Droll Date: Mon, 27 Oct 2025 15:59:25 +0100 Subject: [PATCH 3/6] add config.yaml referenced origin feature branch until it get merged back to main for test evaluation --- examples/example-apps-via-content-loader/config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/example-apps-via-content-loader/config.yaml b/examples/example-apps-via-content-loader/config.yaml index 44689aa01..351888eb6 100644 --- a/examples/example-apps-via-content-loader/config.yaml +++ b/examples/example-apps-via-content-loader/config.yaml @@ -23,7 +23,7 @@ content: createJenkinsJob: true - url: https://github.com/cloudogu/gitops-playground path: examples/example-apps-via-content-loader/ - ref: main + ref: feature/extract-example-apps templating: true type: FOLDER_BASED overwriteMode: UPGRADE From 705355f4374be9110241e8f62e81b9ebcb824a3c Mon Sep 17 00:00:00 2001 From: Marco Droll Date: Tue, 28 Oct 2025 16:15:23 +0100 Subject: [PATCH 4/6] re-inserted unit test in its previous components reduced by the SetCredentials verification parts --- .../gitops/features/JenkinsTest.groovy | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/test/groovy/com/cloudogu/gitops/features/JenkinsTest.groovy b/src/test/groovy/com/cloudogu/gitops/features/JenkinsTest.groovy index 3f0ac211f..eae2d2589 100644 --- a/src/test/groovy/com/cloudogu/gitops/features/JenkinsTest.groovy +++ b/src/test/groovy/com/cloudogu/gitops/features/JenkinsTest.groovy @@ -266,6 +266,29 @@ me:x:1000:''') assertThat(config.jenkins.url).endsWith('192.168.16.2:42') } + @Test + void 'Handles two registries'() { + config.registry.twoRegistries = true + config.content.examples = true + config.application.namePrefix = 'my-prefix-' + config.application.namePrefixForEnvVars = 'MY_PREFIX_' + + config.registry.url = 'reg-url' + config.registry.path = 'reg-path' + config.registry.username = 'reg-usr' + config.registry.password = 'reg-pw' + config.registry.proxyUrl = 'reg-proxy-url' + config.registry.proxyUsername = 'reg-proxy-usr' + config.registry.proxyPassword = 'reg-proxy-pw' + + createJenkins().install() + + verify(globalPropertyManager).setGlobalProperty('MY_PREFIX_REGISTRY_PROXY_URL', 'reg-proxy-url') + + verify(globalPropertyManager).setGlobalProperty(eq('MY_PREFIX_REGISTRY_URL'), anyString()) + verify(globalPropertyManager).setGlobalProperty(eq('MY_PREFIX_REGISTRY_PATH'), anyString()) + } + @Test void 'Does not create create job credentials when argo cd is deactivated'() { config.application.namePrefixForEnvVars = 'MY_PREFIX_' From 3b99a126bf60bec0076db0a8b50fd6c72a2401f7 Mon Sep 17 00:00:00 2001 From: Marco Droll Date: Thu, 6 Nov 2025 16:05:20 +0100 Subject: [PATCH 5/6] - Remove exercises - Remove not used constants - Add references for e.g., two registries operation inside the content-loader doc --- docs/content-loader/content-loader.md | 3 + exercises/broken-application/README.md | 11 -- .../broken-application.ftl.yaml | 82 ------------- exercises/nginx-validation/Jenkinsfile.ftl | 107 ----------------- exercises/nginx-validation/README.md | 9 -- .../nginx-validation/config.yamllint.yaml | 10 -- exercises/nginx-validation/index.html | 11 -- .../k8s/values-production.ftl.yaml | 12 -- .../k8s/values-shared.ftl.yaml | 44 ------- .../k8s/values-staging.ftl.yaml | 12 -- exercises/petclinic-helm/Jenkinsfile.ftl | 109 ------------------ exercises/petclinic-helm/README.md | 9 -- .../k8s/values-production.ftl.yaml | 13 --- .../petclinic-helm/k8s/values-shared.ftl.yaml | 27 ----- .../k8s/values-staging.ftl.yaml | 13 --- .../gitops/config/ConfigConstants.groovy | 20 ---- 16 files changed, 3 insertions(+), 489 deletions(-) delete mode 100644 exercises/broken-application/README.md delete mode 100644 exercises/broken-application/broken-application.ftl.yaml delete mode 100644 exercises/nginx-validation/Jenkinsfile.ftl delete mode 100644 exercises/nginx-validation/README.md delete mode 100644 exercises/nginx-validation/config.yamllint.yaml delete mode 100644 exercises/nginx-validation/index.html delete mode 100644 exercises/nginx-validation/k8s/values-production.ftl.yaml delete mode 100644 exercises/nginx-validation/k8s/values-shared.ftl.yaml delete mode 100644 exercises/nginx-validation/k8s/values-staging.ftl.yaml delete mode 100644 exercises/petclinic-helm/Jenkinsfile.ftl delete mode 100644 exercises/petclinic-helm/README.md delete mode 100644 exercises/petclinic-helm/k8s/values-production.ftl.yaml delete mode 100644 exercises/petclinic-helm/k8s/values-shared.ftl.yaml delete mode 100644 exercises/petclinic-helm/k8s/values-staging.ftl.yaml diff --git a/docs/content-loader/content-loader.md b/docs/content-loader/content-loader.md index c49e192fe..fb0ea3709 100644 --- a/docs/content-loader/content-loader.md +++ b/docs/content-loader/content-loader.md @@ -13,6 +13,9 @@ Example for a GOP content repository: This document will use the short for "repo" from here on, for brevity. +In case for two registries or airgapped mode, you have to specify the registry sources via own config.yaml settings +unter the content.variables.images section. + # Table of contents diff --git a/exercises/broken-application/README.md b/exercises/broken-application/README.md deleted file mode 100644 index a840ed786..000000000 --- a/exercises/broken-application/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Exercise: Broken Application - -This application does not run. Can you figure out how to resolve these errors? -Try applying `broken-application.yaml` with `kubectl`: - -```bash -kubectl apply -f broken-application.yaml -``` - -When you resolved all errors, you should be able to access the application. -Look into the service definition on how to access it. diff --git a/exercises/broken-application/broken-application.ftl.yaml b/exercises/broken-application/broken-application.ftl.yaml deleted file mode 100644 index e475c4f9b..000000000 --- a/exercises/broken-application/broken-application.ftl.yaml +++ /dev/null @@ -1,82 +0,0 @@ -<#assign DockerImageParser=statics['com.cloudogu.gitops.utils.DockerImageParser']> -apiVersion: apps/v1 -kind: Deploymentz -metadata: - name: broken-application -spec: - replicas: 1 - selector: - matchLabels: - app: broken-application -<#if config.registry.createImagePullSecrets == true> - imagePullSecrets: - - name: proxy-registry - - template: - metadata: - labels: - app: broken-application - spec: - containers: - - name: broken-application - image: <#if config.images.nginx?has_content> - ${DockerImageParser.parse(config.images.nginx)} - <#else> - bitnamilegacy/nginx:1.25.1 - - ports: - - containerPort: 8080 -<#if config.application.podResources == true> - resources: - limits: - cpu: 100m - memory: 30Mi - requests: - cpu: 30m - memory: 15Mi - - ---- - -apiVersion: v1 -kind: Service -metadata: - name: broken-application - labels: - app: broken-application -spec: - type: <#if config.application.remote>LoadBalancer<#else>ClusterIP - ports: - - name: http - port: 80 - targetPort: 8080 - selector: - app: broken-application - -<#if config.features.exampleApps.nginx.baseDomain?has_content> ---- - -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: broken-application - labels: - app: broken-application -spec: - rules: - <#if config.application.urlSeparatorHyphen> - - host: broken-application-${config.features.exampleApps.nginx.baseDomain} - <#else> - - host: broken-application.${config.features.exampleApps.nginx.baseDomain} - - http: - paths: - - backend: - service: - name: broken-application - port: - name: http - path: / - pathType: Prefix - - diff --git a/exercises/nginx-validation/Jenkinsfile.ftl b/exercises/nginx-validation/Jenkinsfile.ftl deleted file mode 100644 index dcebcf1b5..000000000 --- a/exercises/nginx-validation/Jenkinsfile.ftl +++ /dev/null @@ -1,107 +0,0 @@ -#!groovy - -String getApplication() { "exercise-nginx-helm" } -String getScmManagerCredentials() { 'scmm-user' } -String getConfigRepositoryPRBaseUrl() { env.SCMM_URL } -String getConfigRepositoryPRRepo() { '${config.application.namePrefix}argocd/example-apps' } -<#noparse> -String getCesBuildLibRepo() { "${env.SCMM_URL}/repo/3rd-party-dependencies/ces-build-lib/" } -String getCesBuildLibVersion() { '2.5.0' } -String getGitOpsBuildLibRepo() { "${env.SCMM_URL}/repo/3rd-party-dependencies/gitops-build-lib" } -String getGitOpsBuildLibVersion() { '0.8.0'} -String getHelmChartRepository() { "https://raw.githubusercontent.com/bitnami/charts/archive-full-index/bitnami" } -String getHelmChartName() { "nginx" } -String getHelmChartVersion() { "13.2.21" } -String getMainBranch() { 'main' } - -cesBuildLib = library(identifier: "ces-build-lib@${cesBuildLibVersion}", - retriever: modernSCM([$class: 'GitSCMSource', remote: cesBuildLibRepo, credentialsId: scmManagerCredentials]) -).com.cloudogu.ces.cesbuildlib - -gitOpsBuildLib = library(identifier: "gitops-build-lib@${gitOpsBuildLibVersion}", - retriever: modernSCM([$class: 'GitSCMSource', remote: gitOpsBuildLibRepo, credentialsId: scmManagerCredentials]) -).com.cloudogu.gitops.gitopsbuildlib - -properties([ - // Keep only the last 10 build to preserve space - disableConcurrentBuilds() -]) - -node('docker') { - - def git = cesBuildLib.Git.new(this) - - catchError { - - stage('Checkout') { - checkout scm - git.clean('') - } - - stage('Deploy') { - if (env.BRANCH_NAME in [mainBranch]) { - def gitopsConfig = [ - scm : [ - provider : 'SCMManager', - credentialsId: scmManagerCredentials, - baseUrl : configRepositoryPRBaseUrl, - repositoryUrl : configRepositoryPRRepo, - ], - cesBuildLibRepo: cesBuildLibRepo, - cesBuildLibVersion: cesBuildLibVersion, - cesBuildLibCredentialsId: scmManagerCredentials, - application: application, - mainBranch: mainBranch, - gitopsTool: 'ARGO', - folderStructureStrategy: 'ENV_PER_APP', - - k8sVersion : env.${config.application.namePrefixForEnvVars}K8S_VERSION, - buildImages : [ - helm: '${config.images.helm}', - kubectl: '${config.images.kubectl}', - kubeval: '${config.images.kubeval}', - helmKubeval: '${config.images.helmKubeval}', - yamllint: '${config.images.yamllint}' - ], - deployments: [ - sourcePath: 'k8s', - destinationRootPath: 'apps', - helm : [ - repoType : 'HELM', - repoUrl : helmChartRepository, - chartName: helmChartName, - version : helmChartVersion, - ] - ], - stages: [ - staging: [ - namespace: '${config.application.namePrefix}example-apps-staging', - deployDirectly: true - ], - production: [ - namespace: '${config.application.namePrefix}example-apps-production', - deployDirectly: false - ], - ], -<#noparse> - fileConfigmaps: [ - [ - name : "exercise-index-nginx", - sourceFilePath : "../index.html", - stage: ["staging", "production"] - ] - ] - ] - - deployViaGitops(gitopsConfig) - } else { - echo 'Skipping deploy, because build not successful or not on main branch' - - } - } - } -} - -def cesBuildLib -def gitOpsBuildLib - diff --git a/exercises/nginx-validation/README.md b/exercises/nginx-validation/README.md deleted file mode 100644 index 3b8f5252c..000000000 --- a/exercises/nginx-validation/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# Exercise: Resource validation using `gitops-build-lib` - -This repository contains an exercise on the validation utils provided by our `gitops-build-lib`. We've prepared some -broken yaml-resources for this nginx-pipeline. Your task is to eliminate all the bugs and let the `jenkins` deploy it. -Jenkins will provide you guidance using its logs. The validators will spot all the bugs for you, all you have to do is check the -logs and fix the bugs. - -The first step you have to take is to copy this repository under the namespace `argocd` in order for `jenkins` to pick it up. -You can use the export and import functions in SCM-Manager. You can export in "Settings" and import by clicking "Add Repository" diff --git a/exercises/nginx-validation/config.yamllint.yaml b/exercises/nginx-validation/config.yamllint.yaml deleted file mode 100644 index 182f60118..000000000 --- a/exercises/nginx-validation/config.yamllint.yaml +++ /dev/null @@ -1,10 +0,0 @@ ---- -extends: default - -rules: - document-start: - present: false - indentation: - spaces: consistent - indent-sequences: consistent - check-multi-line-strings: false \ No newline at end of file diff --git a/exercises/nginx-validation/index.html b/exercises/nginx-validation/index.html deleted file mode 100644 index 16a5df40d..000000000 --- a/exercises/nginx-validation/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - nginx - validation - - -

yEAH - you fixed me and successfully overcame the validation errors!

- - \ No newline at end of file diff --git a/exercises/nginx-validation/k8s/values-production.ftl.yaml b/exercises/nginx-validation/k8s/values-production.ftl.yaml deleted file mode 100644 index 1970de912..000000000 --- a/exercises/nginx-validation/k8s/values-production.ftl.yaml +++ /dev/null @@ -1,12 +0,0 @@ -namespaceOverride: ${config.application.namePrefix}example-apps-production - -<#if config.features.exampleApps.nginx.baseDomain?has_content> -ingress: - enabled: true - pathType: Prefix - <#if config.application.urlSeparatorHyphen> - hostname: production-exercise-nginx-helm-${config.features.exampleApps.nginx.baseDomain} - <#else> - hostname: production.exercise-nginx-helm.${config.features.exampleApps.nginx.baseDomain} - - diff --git a/exercises/nginx-validation/k8s/values-shared.ftl.yaml b/exercises/nginx-validation/k8s/values-shared.ftl.yaml deleted file mode 100644 index 8888c5658..000000000 --- a/exercises/nginx-validation/k8s/values-shared.ftl.yaml +++ /dev/null @@ -1,44 +0,0 @@ -<#assign DockerImageParser=statics['com.cloudogu.gitops.utils.DockerImageParser']> -<#if config.images.nginx?has_content> -<#assign nginxImageObject = DockerImageParser.parse(config.images.nginx)> -image: - registry: ${nginxImageObject.registry} - repository: ${nginxImageObject.repository} - tag: ${nginxImageObject.tag} -<#else> -image: - repository: bitnamilegacy/nginx - - -<#if config.registry.createImagePullSecrets == true> -global: - imagePullSecrets: - - proxy-registry - -service: - ports: - http: 80 - -staticSiteConfigmap: exercise-index-nginx - -extraEnvVars: - - name: LOG_LEVEL - value: debug -serverBlock: |- - server { - listen 0.0.0.0:8080; - location /hi { - return 200 "hello!"; - } - } - -<#if config.application.podResources == true> -resources: - limits: - cpu: 100m - memory: 30Mi - requests: - cpu: 30m - memory: 15Mi - - \ No newline at end of file diff --git a/exercises/nginx-validation/k8s/values-staging.ftl.yaml b/exercises/nginx-validation/k8s/values-staging.ftl.yaml deleted file mode 100644 index ffc331d6a..000000000 --- a/exercises/nginx-validation/k8s/values-staging.ftl.yaml +++ /dev/null @@ -1,12 +0,0 @@ -namespaceOverride: ${config.application.namePrefix}example-apps-staging - -<#if config.features.exampleApps.nginx.baseDomain?has_content> -ingress: - enabled: true - pathType: Prefix - <#if config.application.urlSeparatorHyphen> - hostname: staging-exercise-nginx-helm-${config.features.exampleApps.nginx.baseDomain} - <#else> - hostname: staging.exercise-nginx-helm.${config.features.exampleApps.nginx.baseDomain} - - diff --git a/exercises/petclinic-helm/Jenkinsfile.ftl b/exercises/petclinic-helm/Jenkinsfile.ftl deleted file mode 100644 index ea1102474..000000000 --- a/exercises/petclinic-helm/Jenkinsfile.ftl +++ /dev/null @@ -1,109 +0,0 @@ -#!groovy - -String getApplication() { "exercise-spring-petclinic-helm" } -String getScmManagerCredentials() { 'scmm-user' } -String getConfigRepositoryPRBaseUrl() { env.SCMM_URL } -String getConfigRepositoryPRRepo() { '${config.application.namePrefix}argocd/example-apps' } - -String getDockerRegistryBaseUrl() { env.${config.application.namePrefixForEnvVars}REGISTRY_URL } -String getDockerRegistryPath() { env.${config.application.namePrefixForEnvVars}REGISTRY_PATH } -String getDockerRegistryCredentials() { 'registry-user' } - -<#if config.registry.twoRegistries> -String getDockerRegistryProxyCredentials() { 'registry-proxy-user' } -String getDockerRegistryProxyBaseUrl() { env.${config.application.namePrefixForEnvVars}REGISTRY_PROXY_URL } - -<#noparse> -String getCesBuildLibRepo() { "${env.SCMM_URL}/repo/3rd-party-dependencies/ces-build-lib/" } -String getCesBuildLibVersion() { '2.5.0' } -String getHelmChartRepository() { "${env.SCMM_URL}/repo/3rd-party-dependencies/spring-boot-helm-chart-with-dependency" } -String getHelmChartVersion() { "1.0.0" } -String getMainBranch() { 'main' } - -cesBuildLib = library(identifier: "ces-build-lib@${cesBuildLibVersion}", - retriever: modernSCM([$class: 'GitSCMSource', remote: cesBuildLibRepo, credentialsId: scmManagerCredentials]) -).com.cloudogu.ces.cesbuildlib - -properties([ - // Don't run concurrent builds, because the ITs use the same port causing random failures on concurrent builds. - disableConcurrentBuilds() -]) - -node { - - mvn = cesBuildLib.MavenWrapper.new(this) - -<#if config.jenkins.mavenCentralMirror?has_content> - mvn.useMirrors([name: 'maven-central-mirror', mirrorOf: 'central', url: env.${config.application.namePrefixForEnvVars}MAVEN_CENTRAL_MIRROR]) - -<#noparse> - - - catchError { - - stage('Checkout') { - checkout scm - } - - stage('Build') { - mvn 'clean package -DskipTests -Dcheckstyle.skip' - archiveArtifacts artifacts: '**/target/*.jar' - } - - stage('Test') { - mvn "test -Dmaven.test.failure.ignore=true -Dcheckstyle.skip" - } - - String imageName = "" - stage('Docker') { - String imageTag = createImageTag() - -<#noparse> - String pathPrefix = !dockerRegistryPath?.trim() ? "" : "${dockerRegistryPath}/" - imageName = "${dockerRegistryBaseUrl}/${pathPrefix}${application}:${imageTag}" - -<#if config.registry.twoRegistries> -<#noparse> - docker.withRegistry("https://${dockerRegistryProxyBaseUrl}", dockerRegistryProxyCredentials) { - image = docker.build(imageName, '.') - } - -<#else> -<#noparse> - image = docker.build(imageName, '.') - - -<#noparse> - if (isBuildSuccessful()) { - docker.withRegistry("https://${dockerRegistryBaseUrl}", dockerRegistryCredentials) { - image.push() - } - } else { - echo 'Skipping docker push, because build not successful' - } - } - - stage('Deploy') { - echo 'Use our gitops-build-lib to deploy this application via helm!' - } - } - - // Archive Unit and integration test results, if any - junit allowEmptyResults: true, testResults: '**/target/failsafe-reports/TEST-*.xml,**/target/surefire-reports/TEST-*.xml' -} - - -String createImageTag() { - def git = cesBuildLib.Git.new(this) - String branch = git.simpleBranchName - String branchSuffix = "" - - if (!"develop".equals(branch)) { - branchSuffix = "-${branch}" - } - - return "${new Date().format('yyyyMMddHHmm')}-${git.commitHashShort}${branchSuffix}" -} - -def cesBuildLib - diff --git a/exercises/petclinic-helm/README.md b/exercises/petclinic-helm/README.md deleted file mode 100644 index 8d0b6388d..000000000 --- a/exercises/petclinic-helm/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# Exercise: Deployment from helm application - -This repository contains an exercise on how to use our `gitops-build-lib` to create k8s resources and deploy an application. -The `Jenkinsfile` contains stages on build, tests and building an image but is missing the deploy stage. -Your task is to add the deploy-stage creating, verifying and deploying resources to the cluster using our `gitops-build-lib`. -You can use our documentation on the `gitops-build-lib` to solve it - you can find hints (or the whole solution) in the `argocd/petclinic-helm` repository. - -The first step you have to take is to copy this repository under the namespace `argocd` in order for `jenkins` to pick it up. -You can use the export and import functions in SCM-Manager. You can export in "Settings" and import by clicking "Add Repository" diff --git a/exercises/petclinic-helm/k8s/values-production.ftl.yaml b/exercises/petclinic-helm/k8s/values-production.ftl.yaml deleted file mode 100644 index 5d007d2a8..000000000 --- a/exercises/petclinic-helm/k8s/values-production.ftl.yaml +++ /dev/null @@ -1,13 +0,0 @@ -service: - port: 80 - -<#if config.features.exampleApps.petclinic.baseDomain?has_content> -ingress: - hosts: - <#if config.application.urlSeparatorHyphen> - - host: production-exercise-petclinic-helm-${config.features.exampleApps.petclinic.baseDomain} - <#else> - - host: production.exercise-petclinic-helm.${config.features.exampleApps.petclinic.baseDomain} - - paths: ['/'] - diff --git a/exercises/petclinic-helm/k8s/values-shared.ftl.yaml b/exercises/petclinic-helm/k8s/values-shared.ftl.yaml deleted file mode 100644 index 3514effac..000000000 --- a/exercises/petclinic-helm/k8s/values-shared.ftl.yaml +++ /dev/null @@ -1,27 +0,0 @@ -extraEnv: | - - name: TZ - value: Europe/Berlin -service: - type: <#if config.application.remote>LoadBalancer<#else>ClusterIP - -ingress: - enabled: <#if config.features.exampleApps.petclinic.baseDomain?has_content>true<#else>false - -# this is a helm chart dependency -podinfo: - ui: - color: '#456456' - -<#if config.application.podResources == true> -resources: - limits: - cpu: '1' - memory: 1Gi - requests: - cpu: 300m - memory: 650Mi -<#else> -<#-- Explicitly set to null, because the chart sets memory by default - https://github.com/cloudogu/spring-boot-helm-chart/blob/0.3.2/values.yaml#L40 --> -resources: null - \ No newline at end of file diff --git a/exercises/petclinic-helm/k8s/values-staging.ftl.yaml b/exercises/petclinic-helm/k8s/values-staging.ftl.yaml deleted file mode 100644 index 0f4ae6d67..000000000 --- a/exercises/petclinic-helm/k8s/values-staging.ftl.yaml +++ /dev/null @@ -1,13 +0,0 @@ -service: - port: 80 - -<#if config.features.exampleApps.petclinic.baseDomain?has_content> -ingress: - hosts: - <#if config.application.urlSeparatorHyphen> - - host: staging-exercise-petclinic-helm-${config.features.exampleApps.petclinic.baseDomain} - <#else> - - host: staging.exercise-petclinic-helm.${config.features.exampleApps.petclinic.baseDomain} - - paths: ['/'] - diff --git a/src/main/groovy/com/cloudogu/gitops/config/ConfigConstants.groovy b/src/main/groovy/com/cloudogu/gitops/config/ConfigConstants.groovy index a9a1acdde..a008a18da 100644 --- a/src/main/groovy/com/cloudogu/gitops/config/ConfigConstants.groovy +++ b/src/main/groovy/com/cloudogu/gitops/config/ConfigConstants.groovy @@ -85,14 +85,6 @@ interface ConfigConstants { // group tool configuration String APPLICATION_DESCRIPTION = 'Application configuration parameter for GOP' - String IMAGES_DESCRIPTION = 'Config params for images that do not belong to specific features' - String REPOSITORIES_DESCRIPTION = 'Config params for repositories used within GOP' - String KUBECTL_IMAGE_DESCRIPTION = 'Sets image for kubectl' - String HELM_IMAGE_DESCRIPTION = 'Sets image for helm' - String KUBEVAL_IMAGE_DESCRIPTION = 'Sets image for kubeval' - String HELMKUBEVAL_IMAGE_DESCRIPTION = 'Sets image for helmkubeval' - String YAMLLINT_IMAGE_DESCRIPTION = 'Sets image for yamllint' - String MAVEN_IMAGE_DESCRIPTION = 'Sets image for maven' String GRAFANA_IMAGE_DESCRIPTION = 'Sets image for grafana' String GRAFANA_SIDECAR_IMAGE_DESCRIPTION = 'Sets image for grafana\'s sidecar' String PROMETHEUS_IMAGE_DESCRIPTION = 'Sets image for prometheus' @@ -102,19 +94,11 @@ interface ConfigConstants { String EXTERNAL_SECRETS_CERT_CONTROLLER_IMAGE_DESCRIPTION = 'Sets image for external secrets operator\'s controller' String EXTERNAL_SECRETS_WEBHOOK_IMAGE_DESCRIPTION = 'Sets image for external secrets operator\'s webhook' String VAULT_IMAGE_DESCRIPTION = 'Sets image for vault' - String NGINX_IMAGE_DESCRIPTION = 'Sets image for nginx used in various applications' - String PETCLINIC_IMAGE_DESCRIPTION = 'Sets image for petclinic used in various applications' String BASE_URL_DESCRIPTION = 'the external base url (TLD) for all tools, e.g. https://example.com or http://localhost:8080. The individual -url params for argocd, grafana, vault and mailhog take precedence.' String URL_SEPARATOR_HYPHEN_DESCRIPTION = 'Use hyphens instead of dots to separate application name from base-url' String SKIP_CRDS_DESCRIPTION = 'Skip installation of CRDs. This requires prior installation of CRDs' String NAMESPACE_ISOLATION_DESCRIPTION = 'Configure tools to explicitly work with the given namespaces only, and not cluster-wide. This way GOP can be installed without having cluster-admin permissions.' String MIRROR_REPOS_DESCRIPTION = 'Changes the sources of deployed tools so they are not pulled from the internet, but are pulled from git and work in air-gapped environments.' - String SPRING_BOOT_HELM_CHART_DESCRIPTION = 'Repo to pull the generic Spring Boot Helm chart, used in examples and exercises' - String SPRING_PETCLINIC_DESCRIPTION = 'Repo to pull the Spring Petclinic, used in examples and exercises' - String GITOPS_BUILD_LIB_DESCRIPTION = 'Repo to pull the gitops-build-lib, used in examples and exercises' - String CES_BUILD_LIB_DESCRIPTION = 'Repo to pull the ces-build-lib, used in examples and exercises as depedency of the gitops-build-lib' - String REPO_URL_DESCRIPTION = 'HTTP URL of the repo' - String REPO_REF_DESCRIPTION = 'Ref of the repo to use, e.g. a tag, commit or branch' String NETPOLS_DESCRIPTION = 'Sets Network Policies' String OPENSHIFT_DESCRIPTION = 'When set, openshift specific resources and configurations are applied' @@ -169,10 +153,6 @@ interface ConfigConstants { String ARGOCD_RESOURCE_INCLUSIONS_CLUSTER = 'Internal Kubernetes API Server URL https://IP:PORT (kubernetes.default.svc). Needed in argocd-operator resourceInclusions. Use this parameter if argocd.operator=true and NOT running inside a Pod (remote mode). Full URL needed, for example: https://100.125.0.1:443' String ARGOCD_CUSTOM_NAMESPACE_DESCRIPTION= 'Defines the kubernetes namespace for ArgoCD' // group example apps - String EXAMPLE_APPS_DESCRIPTION = 'Config parameters for the example apps and exercises' - String BASE_DOMAIN_DESCRIPTION = 'The domain under which a subdomain these applications will be made available' - String PETCLINIC_DESCRIPTION = 'Config parameters for the petclinic example apps apps and exercises' - String NGINX_DESCRIPTION = 'Config parameters for the NGINX example apps apps and exercises' // group ingress-class String INGRESS_NGINX_DESCRIPTION = 'Config parameters for the NGINX Ingress Controller' From eb9a3e52a1705037cc7cff3358518b4426fe54c8 Mon Sep 17 00:00:00 2001 From: Marco Droll Date: Fri, 7 Nov 2025 11:58:18 +0100 Subject: [PATCH 6/6] - Remove SCMM exercises and example app destroy handler entries --- .../cloudogu/gitops/destroy/ScmmDestructionHandler.groovy | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/main/groovy/com/cloudogu/gitops/destroy/ScmmDestructionHandler.groovy b/src/main/groovy/com/cloudogu/gitops/destroy/ScmmDestructionHandler.groovy index 6c34b5f83..2960a838c 100644 --- a/src/main/groovy/com/cloudogu/gitops/destroy/ScmmDestructionHandler.groovy +++ b/src/main/groovy/com/cloudogu/gitops/destroy/ScmmDestructionHandler.groovy @@ -25,12 +25,6 @@ class ScmmDestructionHandler implements DestructionHandler { deleteRepository("argocd", "argocd") deleteRepository("argocd", "cluster-resources") deleteRepository("argocd", "example-apps") - deleteRepository("argocd", "nginx-helm-jenkins") - deleteRepository("argocd", "petclinic-plain") - deleteRepository("argocd", "petclinic-helm") - deleteRepository("exercises", "broken-application") - deleteRepository("exercises", "nginx-validation") - deleteRepository("exercises", "petclinic-helm") deleteRepository("3rd-party-dependencies", "ces-build-lib", false) deleteRepository("3rd-party-dependencies", "gitops-build-lib", false) deleteRepository("3rd-party-dependencies", "spring-boot-helm-chart", false)