├── .gitignore ├── charts └── atlantis │ ├── templates │ ├── extra-manifests.yaml │ ├── extra-secret-manifests.yaml │ ├── configmap-config.yaml │ ├── configmap-repo-config.yaml │ ├── configmap-init-config.yaml │ ├── tests │ │ ├── test-atlantis-configmap.yaml │ │ └── test-atlantis-pod.yaml │ ├── configmap-gitconfig-init.yaml │ ├── serviceaccount.yaml │ ├── secret-api.yaml │ ├── secret-netrc.yaml │ ├── secret-gitconfig.yaml │ ├── secret-redis.yaml │ ├── rolebinding.yaml │ ├── role.yaml │ ├── secret-service-account.yaml │ ├── secret-basic-auth.yaml │ ├── secret-aws.yaml │ ├── pvc.yaml │ ├── podmonitor.yaml │ ├── service.yaml │ ├── NOTES.txt │ ├── servicemonitor.yaml │ ├── secret-webhook.yaml │ ├── ingress.yaml │ ├── webhook-ingress.yaml │ ├── _helpers.tpl │ └── statefulset.yaml │ ├── OWNERS │ ├── ci │ ├── ci-init-config-values.yaml │ └── ci-values.yaml │ ├── .helmignore │ ├── Chart.yaml │ ├── test-values.yaml │ ├── tests │ ├── secret-api_test.yaml │ ├── configmap-gitconfig-init_test.yaml │ ├── secret-basic-auth_test.yaml │ ├── pvc_test.yaml │ ├── secret-gitconfig_test.yaml │ ├── secret-netrc_test.yaml │ ├── misc_test.yaml │ ├── secret-service-account_test.yaml │ ├── secret-aws_test.yaml │ ├── podmonitor.yaml │ ├── service_test.yaml │ ├── secret-webhook_test.yaml │ └── statefulset_test.yaml │ ├── README.md.gotmpl │ ├── values.yaml │ └── README.md ├── .github ├── linters │ ├── .jscpd.json │ └── .markdown-lint.yml ├── renovate.json5 ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── linter.yaml │ ├── stale.yml │ ├── release.yaml │ └── lint-test.yaml ├── ct.yaml ├── CODEOWNERS ├── Makefile ├── README.md └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | # IDE or Editor-specific 2 | .idea/ 3 | .vscode/ 4 | -------------------------------------------------------------------------------- /charts/atlantis/templates/extra-manifests.yaml: -------------------------------------------------------------------------------- 1 | {{- range .Values.extraManifests }} 2 | --- 3 | {{ tpl (toYaml .) $ }} 4 | {{- end }} -------------------------------------------------------------------------------- /charts/atlantis/templates/extra-secret-manifests.yaml: -------------------------------------------------------------------------------- 1 | {{- range .Values.extraSecretManifests }} 2 | --- 3 | {{ tpl (toYaml .) $ }} 4 | {{- end }} 5 | -------------------------------------------------------------------------------- /.github/linters/.jscpd.json: -------------------------------------------------------------------------------- 1 | { 2 | "ignore": [ 3 | "**/charts/atlantis/templates/**", 4 | "**/charts/atlantis/tests/**" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /ct.yaml: -------------------------------------------------------------------------------- 1 | # See https://github.com/helm/chart-testing#configuration 2 | remote: origin 3 | target-branch: main 4 | chart-dirs: 5 | - charts 6 | helm-extra-args: --timeout 600s 7 | additional-commands: 8 | - helm unittest {{ .Path }} 9 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners 2 | # These owners will be the default owners for everything in the repo. 3 | * @runatlantis/helm-contributors 4 | -------------------------------------------------------------------------------- /charts/atlantis/OWNERS: -------------------------------------------------------------------------------- 1 | approvers: 2 | - jkodroff 3 | - callmeradical 4 | - lkysow 5 | - jeff-knurek 6 | - sstarcher 7 | - anubhavmishra 8 | reviewers: 9 | - jkodroff 10 | - callmeradical 11 | - lkysow 12 | - jeff-knurek 13 | - sstarcher 14 | - anubhavmishra 15 | -------------------------------------------------------------------------------- /charts/atlantis/ci/ci-init-config-values.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | github: 3 | user: foo 4 | token: bar 5 | secret: baz 6 | 7 | service: 8 | type: ClusterIP 9 | 10 | ingress: 11 | enabled: true 12 | ingressClassName: nginx 13 | host: atlantis.localdev.me 14 | path: / 15 | webhook_ingress: 16 | enabled: true 17 | ingressClassName: nginx 18 | host: atlantis-webook.localdev.me 19 | path: /events 20 | 21 | initConfig: 22 | enabled: true 23 | -------------------------------------------------------------------------------- /charts/atlantis/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *~ 18 | # Various IDEs 19 | .project 20 | .idea/ 21 | *.tmproj 22 | # CI 23 | ci/ 24 | test-values.yaml 25 | -------------------------------------------------------------------------------- /charts/atlantis/templates/configmap-config.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.config }} 2 | apiVersion: v1 3 | kind: ConfigMap 4 | metadata: 5 | name: {{ template "atlantis.fullname" . }} 6 | namespace: {{ .Release.Namespace }} 7 | labels: 8 | {{- include "atlantis.labels" . | nindent 4 }} 9 | {{- with .Values.extraAnnotations }} 10 | annotations: 11 | {{- toYaml . | nindent 4 }} 12 | {{- end }} 13 | data: 14 | atlantis.yaml: | 15 | {{- .Values.config | nindent 4 }} 16 | {{- end }} 17 | -------------------------------------------------------------------------------- /charts/atlantis/templates/configmap-repo-config.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.repoConfig }} 2 | apiVersion: v1 3 | kind: ConfigMap 4 | metadata: 5 | name: {{ template "atlantis.fullname" . }}-repo-config 6 | namespace: {{ .Release.Namespace }} 7 | labels: 8 | {{- include "atlantis.labels" . | nindent 4 }} 9 | {{- with .Values.extraAnnotations }} 10 | annotations: 11 | {{- toYaml . | nindent 4 }} 12 | {{- end }} 13 | data: 14 | repos.yaml: | 15 | {{- .Values.repoConfig | nindent 4 }} 16 | {{- end }} 17 | -------------------------------------------------------------------------------- /charts/atlantis/ci/ci-values.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | github: 3 | user: foo 4 | token: bar 5 | secret: baz 6 | 7 | service: 8 | type: ClusterIP 9 | 10 | ingress: 11 | enabled: true 12 | ingressClassName: nginx 13 | host: atlantis.localdev.me 14 | path: / 15 | webhook_ingress: 16 | enabled: true 17 | ingressClassName: nginx 18 | host: atlantis-webook.localdev.me 19 | path: /events 20 | 21 | resources: 22 | requests: 23 | memory: 64Mi 24 | cpu: 10m 25 | limits: 26 | memory: 128Mi 27 | cpu: 100m 28 | -------------------------------------------------------------------------------- /charts/atlantis/templates/configmap-init-config.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.initConfig.enabled }} 2 | apiVersion: v1 3 | kind: ConfigMap 4 | metadata: 5 | name: {{ template "atlantis.fullname" . }}-init-config 6 | namespace: {{ .Release.Namespace }} 7 | labels: 8 | {{- include "atlantis.labels" . | nindent 4 }} 9 | {{- with .Values.extraAnnotations }} 10 | annotations: 11 | {{- toYaml . | nindent 4 }} 12 | {{- end }} 13 | data: 14 | init-config.sh: | 15 | {{- .Values.initConfig.script | nindent 4 }} 16 | {{- end }} 17 | -------------------------------------------------------------------------------- /charts/atlantis/templates/tests/test-atlantis-configmap.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.test.enabled -}} 2 | apiVersion: v1 3 | kind: ConfigMap 4 | metadata: 5 | name: {{ template "atlantis.fullname" . }}-tests 6 | namespace: {{ .Release.Namespace }} 7 | data: 8 | tests.bats: |- 9 | setup() { 10 | apk add curl -q 11 | } 12 | @test "Atlantis UI is available" { 13 | ATLANTIS_URL={{ template "atlantis.url" . }} 14 | echo "Trying Atlantis at: $ATLANTIS_URL" 15 | curl -v $ATLANTIS_URL 16 | } 17 | {{- end }} 18 | -------------------------------------------------------------------------------- /charts/atlantis/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | # renovate: datasource=docker depName=ghcr.io/runatlantis/atlantis 3 | appVersion: v0.38.0 4 | description: A Helm chart for Atlantis https://www.runatlantis.io 5 | name: atlantis 6 | version: 5.23.0 7 | keywords: 8 | - terraform 9 | home: https://www.runatlantis.io 10 | icon: https://www.runatlantis.io/hero.png 11 | sources: 12 | - https://github.com/runatlantis/atlantis 13 | maintainers: 14 | - name: lkysow 15 | - name: jamengual 16 | - name: chenrui333 17 | - name: nitrocode 18 | - name: genpage 19 | - name: gmartinez-sisti 20 | -------------------------------------------------------------------------------- /charts/atlantis/templates/configmap-gitconfig-init.yaml: -------------------------------------------------------------------------------- 1 | {{- if not .Values.gitconfigReadOnly }} 2 | apiVersion: v1 3 | kind: ConfigMap 4 | metadata: 5 | name: {{ template "atlantis.fullname" . }}-gitconfig-init 6 | namespace: {{ .Release.Namespace }} 7 | labels: 8 | {{- include "atlantis.labels" . | nindent 4 }} 9 | {{- with .Values.extraAnnotations }} 10 | annotations: 11 | {{- toYaml . | nindent 4 }} 12 | {{- end }} 13 | data: 14 | gitconfig-init.sh: | 15 | #!/bin/sh 16 | set -ex 17 | cp -v /etc/.gitconfig /home/atlantis/.gitconfig 18 | chown -v atlantis /home/atlantis/.gitconfig 19 | {{- end }} 20 | -------------------------------------------------------------------------------- /charts/atlantis/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create }} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ template "atlantis.serviceAccountName" . }} 6 | namespace: {{ .Release.Namespace }} 7 | labels: 8 | {{- include "atlantis.labels" . | nindent 4 }} 9 | {{- if or .Values.serviceAccount.annotations .Values.extraAnnotations }} 10 | annotations: 11 | {{- with .Values.serviceAccount.annotations }} 12 | {{- toYaml . | nindent 4 }} 13 | {{- end }} 14 | {{- with .Values.extraAnnotations }} 15 | {{- toYaml . | nindent 4 }} 16 | {{- end }} 17 | {{- end }} 18 | {{- end }} 19 | -------------------------------------------------------------------------------- /charts/atlantis/templates/secret-api.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.api }} 2 | apiVersion: v1 3 | kind: Secret 4 | metadata: 5 | name: {{ template "atlantis.apiSecretName" . }} 6 | namespace: {{ .Release.Namespace }} 7 | labels: 8 | {{- include "atlantis.labels" . | nindent 4 }} 9 | {{- if or .Values.secret.annotations .Values.extraAnnotations }} 10 | annotations: 11 | {{- with .Values.secret.annotations }} 12 | {{- toYaml . | nindent 4 }} 13 | {{- end }} 14 | {{- with .Values.extraAnnotations }} 15 | {{- toYaml . | nindent 4 }} 16 | {{- end }} 17 | {{- end }} 18 | data: 19 | apisecret: {{ .Values.api.secret | b64enc }} 20 | {{- end }} 21 | -------------------------------------------------------------------------------- /charts/atlantis/templates/secret-netrc.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.netrc }} 2 | apiVersion: v1 3 | kind: Secret 4 | metadata: 5 | name: {{ template "atlantis.fullname" . }}-netrc 6 | namespace: {{ .Release.Namespace }} 7 | labels: 8 | {{- include "atlantis.labels" . | nindent 4 }} 9 | {{- if or .Values.secret.annotations .Values.extraAnnotations }} 10 | annotations: 11 | {{- with .Values.secret.annotations }} 12 | {{- toYaml . | nindent 4 }} 13 | {{- end }} 14 | {{- with .Values.extraAnnotations }} 15 | {{- toYaml . | nindent 4 }} 16 | {{- end }} 17 | {{- end }} 18 | data: 19 | netrc: {{ .Values.netrc | b64enc }} 20 | {{- end }} 21 | -------------------------------------------------------------------------------- /charts/atlantis/templates/secret-gitconfig.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.gitconfig }} 2 | apiVersion: v1 3 | kind: Secret 4 | metadata: 5 | name: {{ template "atlantis.fullname" . }}-gitconfig 6 | namespace: {{ .Release.Namespace }} 7 | labels: 8 | {{- include "atlantis.labels" . | nindent 4 }} 9 | {{- if or .Values.secret.annotations .Values.extraAnnotations }} 10 | annotations: 11 | {{- with .Values.secret.annotations }} 12 | {{- toYaml . | nindent 4 }} 13 | {{- end }} 14 | {{- with .Values.extraAnnotations }} 15 | {{- toYaml . | nindent 4 }} 16 | {{- end }} 17 | {{- end }} 18 | data: 19 | gitconfig: {{ .Values.gitconfig | b64enc }} 20 | {{- end }} 21 | -------------------------------------------------------------------------------- /charts/atlantis/templates/secret-redis.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.redis.password }} 2 | apiVersion: v1 3 | kind: Secret 4 | metadata: 5 | name: {{ template "atlantis.fullname" . }}-redis 6 | namespace: {{ .Release.Namespace }} 7 | labels: 8 | {{- include "atlantis.labels" . | nindent 4 }} 9 | {{- if or .Values.secret.annotations .Values.extraAnnotations }} 10 | annotations: 11 | {{- with .Values.secret.annotations }} 12 | {{- toYaml . | nindent 4 }} 13 | {{- end }} 14 | {{- with .Values.extraAnnotations }} 15 | {{- toYaml . | nindent 4 }} 16 | {{- end }} 17 | {{- end }} 18 | data: 19 | password: {{ .Values.redis.password | b64enc }} 20 | {{- end }} 21 | -------------------------------------------------------------------------------- /charts/atlantis/test-values.yaml: -------------------------------------------------------------------------------- 1 | # In order to Atlantis to start, it must have at least one source control 2 | # provider configured. However, we do not want to define a default in 3 | # values.yaml as this would require all users of this chart who are not using 4 | # GitHub to override the value. 5 | github: 6 | user: foo 7 | token: bar 8 | secret: baz 9 | 10 | service: 11 | annotations: 12 | serviceAnnotation1: value1 13 | serviceAnnotation2: value2 14 | 15 | podTemplate: 16 | annotations: 17 | podTemplateAnnotation1: value3 18 | podTemplateAnnotation2: value4 19 | 20 | statefulSet: 21 | annotations: 22 | statefulSetAnnotation1: value5 23 | statefulSetAnnotation2: value6 -------------------------------------------------------------------------------- /charts/atlantis/templates/rolebinding.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.enableKubernetesBackend }} 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: RoleBinding 4 | metadata: 5 | name: {{ template "atlantis.fullname" . }} 6 | namespace: {{ .Release.Namespace }} 7 | labels: 8 | {{- include "atlantis.labels" . | nindent 4 }} 9 | {{- with .Values.extraAnnotations }} 10 | annotations: 11 | {{- toYaml . | nindent 4 }} 12 | {{- end }} 13 | subjects: 14 | - kind: ServiceAccount 15 | name: {{ template "atlantis.serviceAccountName" . }} 16 | namespace: {{ .Release.Namespace }} 17 | roleRef: 18 | apiGroup: rbac.authorization.k8s.io 19 | kind: Role 20 | name: {{ template "atlantis.fullname" . }} 21 | {{- end }} 22 | -------------------------------------------------------------------------------- /charts/atlantis/templates/role.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.enableKubernetesBackend }} 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | name: {{ template "atlantis.fullname" . }} 6 | namespace: {{ .Release.Namespace }} 7 | labels: 8 | {{- include "atlantis.labels" . | nindent 4 }} 9 | {{- with .Values.extraAnnotations }} 10 | annotations: 11 | {{- toYaml . | nindent 4 }} 12 | {{- end }} 13 | rules: 14 | - apiGroups: 15 | - coordination.k8s.io 16 | resources: 17 | - leases 18 | verbs: 19 | - get 20 | - create 21 | - update 22 | - delete 23 | - apiGroups: 24 | - "" 25 | resources: 26 | - secrets 27 | verbs: ['*'] 28 | {{- end }} 29 | -------------------------------------------------------------------------------- /charts/atlantis/templates/secret-service-account.yaml: -------------------------------------------------------------------------------- 1 | {{- range $name, $secret := .Values.serviceAccountSecrets }} 2 | --- 3 | apiVersion: v1 4 | kind: Secret 5 | metadata: 6 | name: {{ $name }} 7 | namespace: {{ $.Release.Namespace }} 8 | labels: 9 | component: service-account-secret 10 | {{- include "atlantis.labels" $ | nindent 4 }} 11 | {{- if or $.Values.secret.annotations $.Values.extraAnnotations }} 12 | annotations: 13 | {{- with $.Values.secret.annotations }} 14 | {{- toYaml . | nindent 4 }} 15 | {{- end }} 16 | {{- with $.Values.extraAnnotations }} 17 | {{- toYaml . | nindent 4 }} 18 | {{- end }} 19 | {{- end }} 20 | data: 21 | service-account.json: {{ $secret }} 22 | {{- end }} 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .DEFAULT_GOAL := help 2 | 3 | .PHONY: help 4 | help: ## List targets & descriptions 5 | @cat Makefile* | grep -E '^[a-zA-Z\/_-]+:.*?## .*$$' | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' 6 | 7 | .PHONY: docs 8 | docs: ## Build helm chart documentation 9 | @docker pull jnorwood/helm-docs:latest 10 | @docker run --rm --volume "$$(pwd):/helm-docs" -u $$(id -u) jnorwood/helm-docs:latest 11 | 12 | .PHONY: unit-test-install 13 | unit-test-install: 14 | @helm plugin list | grep unittest || helm plugin install --version v1.0.3 https://github.com/helm-unittest/helm-unittest 15 | 16 | .PHONY: unit-test-run-atlantis 17 | unit-test-run-atlantis: unit-test-install ## Run unit tests for Atlantis 18 | @helm unittest ./charts/atlantis 19 | -------------------------------------------------------------------------------- /.github/renovate.json5: -------------------------------------------------------------------------------- 1 | { 2 | $schema: "https://docs.renovatebot.com/renovate-schema.json", 3 | extends: [ 4 | "config:base", 5 | "schedule:daily", 6 | ], 7 | commitMessageSuffix: " in {{packageFile}}", 8 | dependencyDashboardAutoclose: true, 9 | automerge: false, 10 | platformAutomerge: false, 11 | labels: ["dependencies"], 12 | vulnerabilityAlerts: { 13 | enabled: true, 14 | labels: [ 15 | "security", 16 | ], 17 | }, 18 | customManagers: [ 19 | { 20 | customType: "regex", 21 | fileMatch: ["\\.yaml$"], 22 | matchStrings: [ 23 | "# renovate: datasource=(?.+?) depName=(?.+?)( packageName=(?.+))?\\s.+: [\"']?(?.+?)[\"']?\\s", 24 | ], 25 | }, 26 | ], 27 | } 28 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## what 2 | 3 | 7 | 8 | 9 | ## why 10 | 11 | 16 | 17 | ## tests 18 | 19 | 22 | 23 | ## references 24 | 25 | 29 | 30 | -------------------------------------------------------------------------------- /charts/atlantis/templates/secret-basic-auth.yaml: -------------------------------------------------------------------------------- 1 | {{- if and (not .Values.basicAuthSecretName) .Values.basicAuth.username .Values.basicAuth.password }} 2 | apiVersion: v1 3 | kind: Secret 4 | metadata: 5 | name: {{ template "atlantis.fullname" . }}-basic-auth 6 | namespace: {{ .Release.Namespace }} 7 | labels: 8 | {{- include "atlantis.labels" . | nindent 4 }} 9 | {{- if or .Values.secret.annotations .Values.extraAnnotations }} 10 | annotations: 11 | {{- with .Values.secret.annotations }} 12 | {{- toYaml . | nindent 4 }} 13 | {{- end }} 14 | {{- with .Values.extraAnnotations }} 15 | {{- toYaml . | nindent 4 }} 16 | {{- end }} 17 | {{- end }} 18 | data: 19 | username: {{ .Values.basicAuth.username | b64enc }} 20 | password: {{ .Values.basicAuth.password | b64enc }} 21 | {{- end }} 22 | -------------------------------------------------------------------------------- /charts/atlantis/templates/tests/test-atlantis-pod.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.test.enabled -}} 2 | apiVersion: v1 3 | kind: Pod 4 | metadata: 5 | name: "{{ .Release.Name }}-ui-test" 6 | namespace: {{ .Release.Namespace }} 7 | annotations: 8 | helm.sh/hook: test 9 | {{- with .Values.test.annotations }} 10 | {{- . | toYaml | nindent 4 }} 11 | {{- end }} 12 | spec: 13 | containers: 14 | - name: {{ .Release.Name }}-ui-test 15 | image: {{ .Values.test.image }}:{{ .Values.test.imageTag }} 16 | command: ["/usr/local/bin/bats", "/tests/"] 17 | volumeMounts: 18 | - mountPath: /tests 19 | name: tests 20 | readOnly: true 21 | volumes: 22 | - name: tests 23 | configMap: 24 | name: {{ template "atlantis.fullname" . }}-tests 25 | restartPolicy: Never 26 | {{- end }} 27 | -------------------------------------------------------------------------------- /charts/atlantis/templates/secret-aws.yaml: -------------------------------------------------------------------------------- 1 | {{- if or .Values.aws.credentials .Values.aws.config }} 2 | apiVersion: v1 3 | kind: Secret 4 | metadata: 5 | name: {{ template "atlantis.fullname" . }}-aws 6 | namespace: {{ .Release.Namespace }} 7 | labels: 8 | {{- include "atlantis.labels" . | nindent 4 }} 9 | {{- if or .Values.secret.annotations .Values.extraAnnotations }} 10 | annotations: 11 | {{- with .Values.secret.annotations }} 12 | {{- toYaml . | nindent 4 }} 13 | {{- end }} 14 | {{- with .Values.extraAnnotations }} 15 | {{- toYaml . | nindent 4 }} 16 | {{- end }} 17 | {{- end }} 18 | data: 19 | {{- if .Values.aws.credentials }} 20 | credentials: {{ .Values.aws.credentials | b64enc }} 21 | {{- end }} 22 | {{- if .Values.aws.config }} 23 | config: {{ .Values.aws.config | b64enc }} 24 | {{- end }} 25 | {{- end }} 26 | -------------------------------------------------------------------------------- /charts/atlantis/templates/pvc.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.volumeClaim.enabled ( not .Values.dataStorage ) }} 2 | apiVersion: v1 3 | kind: PersistentVolumeClaim 4 | metadata: 5 | name: {{ template "atlantis.fullname" . }}-data 6 | namespace: {{ .Release.Namespace }} 7 | labels: 8 | {{- include "atlantis.labels" . | nindent 4 }} 9 | {{- with .Values.extraAnnotations }} 10 | annotations: 11 | {{- toYaml . | nindent 4 }} 12 | {{- end }} 13 | spec: 14 | accessModes: {{ .Values.volumeClaim.accessModes| toYaml | nindent 2 }} 15 | resources: 16 | requests: 17 | # The biggest thing Atlantis stores is the Git repo when it checks it out. 18 | # It deletes the repo after the pull request is merged. 19 | storage: {{ .Values.volumeClaim.dataStorage }} 20 | {{- if .Values.volumeClaim.storageClassName }} 21 | storageClassName: {{ .Values.volumeClaim.storageClassName }} 22 | {{- end }} 23 | {{- end }} 24 | -------------------------------------------------------------------------------- /charts/atlantis/tests/secret-api_test.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | suite: test secret-api for api secret 3 | templates: 4 | - secret-api.yaml 5 | release: 6 | name: my-release 7 | tests: 8 | - it: default values 9 | asserts: 10 | - hasDocuments: 11 | count: 0 12 | - it: apiSecretName 13 | set: 14 | apiSecretName: 'atlantis-api' 15 | asserts: 16 | - hasDocuments: 17 | count: 0 18 | - it: apiSecret 19 | set: 20 | api.secret: 'spongebob' 21 | commonLabels: 22 | team: "infra" 23 | asserts: 24 | - hasDocuments: 25 | count: 1 26 | - isKind: 27 | of: Secret 28 | - isAPIVersion: 29 | of: v1 30 | - equal: 31 | path: metadata.name 32 | value: my-release-atlantis-api 33 | - equal: 34 | path: data["apisecret"] 35 | value: c3BvbmdlYm9i 36 | - equal: 37 | path: metadata.labels.team 38 | value: infra 39 | -------------------------------------------------------------------------------- /.github/workflows/linter.yaml: -------------------------------------------------------------------------------- 1 | name: Lint Code Base 2 | 3 | # Documentation: 4 | # https://help.github.com/en/articles/workflow-syntax-for-github-actions 5 | 6 | on: 7 | pull_request: 8 | 9 | permissions: read-all 10 | 11 | jobs: 12 | build: 13 | name: Lint Code Base 14 | runs-on: ubuntu-latest 15 | permissions: 16 | statuses: write 17 | steps: 18 | - name: Checkout Code 19 | uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 20 | with: 21 | fetch-depth: 0 22 | 23 | - name: Lint Code Base 24 | uses: github/super-linter@b807e99ddd37e444d189cfd2c2ca1274d8ae8ef1 # v7 25 | env: 26 | VALIDATE_ALL_CODEBASE: false 27 | VALIDATE_YAML: false 28 | VALIDATE_KUBERNETES_KUBEVAL: false 29 | VALIDATE_CHECKOV: false 30 | DEFAULT_BRANCH: main 31 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 32 | VALIDATE_GITLEAKS: false 33 | FILTER_REGEX_EXCLUDE: .github/.* 34 | -------------------------------------------------------------------------------- /.github/linters/.markdown-lint.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ########################### 3 | ########################### 4 | ## Markdown Linter rules ## 5 | ########################### 6 | ########################### 7 | 8 | # Linter rules doc: 9 | # - https://github.com/DavidAnson/markdownlint 10 | # 11 | # Note: 12 | # To comment out a single error: 13 | # 14 | # any violations you want 15 | # 16 | # 17 | 18 | ############### 19 | # Rules by id # 20 | ############### 21 | MD004: false # Unordered list style 22 | MD007: 23 | indent: 2 # Unordered list indentation 24 | MD013: null 25 | MD026: 26 | punctuation: ".,;:!。,;:" # List of not allowed 27 | MD029: false # Ordered list item prefix 28 | MD033: false # Allow inline HTML 29 | MD036: false # Emphasis used instead of a heading 30 | 31 | ################# 32 | # Rules by tags # 33 | ################# 34 | blank_lines: false # Error on blank lines 35 | 36 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: Close Stale PRs 2 | on: 3 | schedule: 4 | - cron: '30 1 * * *' 5 | 6 | permissions: read-all 7 | 8 | jobs: 9 | stale: 10 | runs-on: ubuntu-latest 11 | permissions: 12 | issues: write 13 | pull-requests: write 14 | steps: 15 | - uses: actions/stale@997185467fa4f803885201cee163a9f38240193d # v10 16 | with: 17 | stale-pr-message: 'This issue is stale because it has been open for 1 month with no activity. Remove stale label or comment or this will be closed in 1 month.' 18 | stale-issue-message: This issue is stale because it has been open for 1 month with no activity. Remove stale label or comment or this will be closed in 1 month.' 19 | remove-stale-when-updated: true 20 | exempt-pr-labels: "never-stale" 21 | exempt-issue-labels: "never-stale" 22 | # 1 month 23 | days-before-stale: 31 24 | # 1 month 25 | days-before-close: 31 26 | only-labels: 'waiting-on-response' 27 | -------------------------------------------------------------------------------- /charts/atlantis/tests/configmap-gitconfig-init_test.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | suite: test configmap-gitconfig-init for gitconfig 3 | templates: 4 | - configmap-gitconfig-init.yaml 5 | release: 6 | name: my-release 7 | tests: 8 | - it: default values 9 | template: configmap-gitconfig-init.yaml 10 | asserts: 11 | - hasDocuments: 12 | count: 0 13 | - it: gitconfig-read-write 14 | template: configmap-gitconfig-init.yaml 15 | set: 16 | gitconfigReadOnly: false 17 | commonLabels: 18 | team: "infra" 19 | asserts: 20 | - hasDocuments: 21 | count: 1 22 | - isKind: 23 | of: ConfigMap 24 | - isAPIVersion: 25 | of: v1 26 | - equal: 27 | path: metadata.name 28 | value: my-release-atlantis-gitconfig-init 29 | - equal: 30 | path: data["gitconfig-init.sh"] 31 | value: | 32 | #!/bin/sh 33 | set -ex 34 | cp -v /etc/.gitconfig /home/atlantis/.gitconfig 35 | chown -v atlantis /home/atlantis/.gitconfig 36 | -------------------------------------------------------------------------------- /charts/atlantis/templates/podmonitor.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.podMonitor.enabled }} 2 | apiVersion: monitoring.googleapis.com/v1 3 | kind: PodMonitoring 4 | metadata: 5 | name: {{ template "atlantis.fullname" . }} 6 | namespace: {{ .Release.Namespace }} 7 | labels: 8 | {{- include "atlantis.labels" . | nindent 4 }} 9 | {{- if or .Values.service.annotations .Values.extraAnnotations }} 10 | annotations: 11 | {{- with .Values.service.annotations }} 12 | {{- toYaml . | nindent 4 }} 13 | {{- end }} 14 | {{- with .Values.extraAnnotations }} 15 | {{- toYaml . | nindent 4 }} 16 | {{- end }} 17 | {{- end }} 18 | spec: 19 | selector: 20 | matchLabels: 21 | app: {{ template "atlantis.name" . }} 22 | release: {{ .Release.Name }} 23 | {{- if .Values.podTemplate.labels }} 24 | {{- toYaml .Values.podTemplate.labels | nindent 6 }} 25 | {{- end }} 26 | endpoints: 27 | - port: atlantis 28 | {{- with .Values.podMonitor }} 29 | interval: {{ .interval }} 30 | {{- with .metricRelabeling }} 31 | metricRelabeling: 32 | {{- toYaml . | nindent 4 }} 33 | {{- end }} 34 | {{- end }} 35 | {{- end }} 36 | -------------------------------------------------------------------------------- /charts/atlantis/tests/secret-basic-auth_test.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | suite: test secret-basic-auth for git basic-auth secret 3 | templates: 4 | - secret-basic-auth.yaml 5 | release: 6 | name: my-release 7 | tests: 8 | - it: default values 9 | asserts: 10 | - hasDocuments: 11 | count: 0 12 | - it: basicAuthSecretName 13 | set: 14 | basicAuthSecretName: "atlantis-basic-auth" 15 | asserts: 16 | - hasDocuments: 17 | count: 0 18 | - it: basicAuth 19 | set: 20 | basicAuth: 21 | username: "atlantis" 22 | password: "forever" 23 | commonLabels: 24 | team: "infra" 25 | asserts: 26 | - hasDocuments: 27 | count: 1 28 | - isKind: 29 | of: Secret 30 | - isAPIVersion: 31 | of: v1 32 | - equal: 33 | path: metadata.name 34 | value: my-release-atlantis-basic-auth 35 | - equal: 36 | path: data["username"] 37 | value: YXRsYW50aXM= 38 | - equal: 39 | path: data["password"] 40 | value: Zm9yZXZlcg== 41 | - equal: 42 | path: metadata.labels.team 43 | value: infra 44 | 45 | -------------------------------------------------------------------------------- /charts/atlantis/tests/pvc_test.yaml: -------------------------------------------------------------------------------- 1 | suite: test pvc 2 | templates: 3 | - pvc.yaml 4 | chart: 5 | appVersion: test-appVersion 6 | release: 7 | name: my-release 8 | tests: 9 | - it: pvc 10 | template: pvc.yaml 11 | asserts: 12 | - isKind: 13 | of: PersistentVolumeClaim 14 | - equal: 15 | path: apiVersion 16 | value: v1 17 | - equal: 18 | path: metadata.name 19 | value: my-release-atlantis-data 20 | - equal: 21 | path: spec.accessModes 22 | value: 23 | - ReadWriteOnce 24 | - equal: 25 | path: spec.resources.requests.storage 26 | value: 5Gi 27 | - it: accessModes 28 | template: pvc.yaml 29 | set: 30 | volumeClaim: 31 | accessModes: 32 | - ReadWriteMany 33 | asserts: 34 | - equal: 35 | path: spec.accessModes 36 | value: 37 | - ReadWriteMany 38 | - it: storage requests 39 | template: pvc.yaml 40 | set: 41 | volumeClaim: 42 | dataStorage: 10Gi 43 | asserts: 44 | - equal: 45 | path: spec.resources.requests.storage 46 | value: 10Gi 47 | -------------------------------------------------------------------------------- /charts/atlantis/tests/secret-gitconfig_test.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | suite: test secret-gitconfig for gitconfig 3 | templates: 4 | - secret-gitconfig.yaml 5 | release: 6 | name: my-release 7 | tests: 8 | - it: default values 9 | template: secret-gitconfig.yaml 10 | asserts: 11 | - hasDocuments: 12 | count: 0 13 | - it: gitconfigSecretName 14 | template: secret-gitconfig.yaml 15 | set: 16 | gitconfigSecretName: 'atlantis-gitconfig' 17 | asserts: 18 | - hasDocuments: 19 | count: 0 20 | - it: gitconfig 21 | template: secret-gitconfig.yaml 22 | set: 23 | gitconfig: | 24 | [url "https://YOUR_GH_TOKEN@github.com"] 25 | insteadOf = https://github.com 26 | commonLabels: 27 | team: "infra" 28 | asserts: 29 | - hasDocuments: 30 | count: 1 31 | - isKind: 32 | of: Secret 33 | - isAPIVersion: 34 | of: v1 35 | - equal: 36 | path: metadata.name 37 | value: my-release-atlantis-gitconfig 38 | - equal: 39 | path: data["gitconfig"] 40 | value: W3VybCAiaHR0cHM6Ly9ZT1VSX0dIX1RPS0VOQGdpdGh1Yi5jb20iXQppbnN0ZWFkT2YgPSBodHRwczovL2dpdGh1Yi5jb20K 41 | - equal: 42 | path: metadata.labels.team 43 | value: infra 44 | 45 | 46 | -------------------------------------------------------------------------------- /charts/atlantis/tests/secret-netrc_test.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | suite: test secret-netrc for netrc 3 | templates: 4 | - secret-netrc.yaml 5 | release: 6 | name: my-release 7 | tests: 8 | - it: default values 9 | asserts: 10 | - hasDocuments: 11 | count: 0 12 | - it: netrcSecretName 13 | set: 14 | netrcSecretName: 'atlantis-netrc' 15 | asserts: 16 | - hasDocuments: 17 | count: 0 18 | - it: netrc 19 | set: 20 | netrc: | 21 | machine artifactory.myapp.com login YOUR_USERNAME password YOUR_PASSWORD 22 | machine bitbucket.myapp.com login YOUR_USERNAME password YOUR_PASSWORD 23 | commonLabels: 24 | team: "infra" 25 | asserts: 26 | - hasDocuments: 27 | count: 1 28 | - isKind: 29 | of: Secret 30 | - isAPIVersion: 31 | of: v1 32 | - equal: 33 | path: metadata.name 34 | value: my-release-atlantis-netrc 35 | - equal: 36 | path: data["netrc"] 37 | value: bWFjaGluZSBhcnRpZmFjdG9yeS5teWFwcC5jb20gbG9naW4gWU9VUl9VU0VSTkFNRSBwYXNzd29yZCBZT1VSX1BBU1NXT1JECm1hY2hpbmUgYml0YnVja2V0Lm15YXBwLmNvbSBsb2dpbiBZT1VSX1VTRVJOQU1FIHBhc3N3b3JkIFlPVVJfUEFTU1dPUkQK 38 | - equal: 39 | path: metadata.labels.team 40 | value: infra 41 | 42 | 43 | -------------------------------------------------------------------------------- /charts/atlantis/tests/misc_test.yaml: -------------------------------------------------------------------------------- 1 | suite: test miscellaneous cases 2 | templates: 3 | - "*.yaml" 4 | chart: 5 | appVersion: test-appVersion 6 | release: 7 | name: my-release 8 | namespace: my-namespace 9 | tests: 10 | - it: ensure namespaces are specified in all resources 11 | set: 12 | config: dummy 13 | gitconfigReadOnly: false 14 | gitconfig: dummy 15 | initConfig: 16 | enabled: true 17 | repoConfig: dummy 18 | podMonitor: 19 | enabled: true 20 | servicemonitor: 21 | enabled: true 22 | enableKubernetesBackend: true 23 | api: 24 | secret: dummy 25 | aws: 26 | config: dummy 27 | basicAuth: 28 | username: dummy 29 | password: dummy 30 | netrc: dummy 31 | redis: 32 | password: dummy 33 | serviceAccountSecrets: 34 | credentials: dummy 35 | webhook_ingress: 36 | enabled: true 37 | extraManifests: 38 | - apiVersion: v1 39 | kind: Pod 40 | metadata: 41 | name: dummy-manifest 42 | namespace: my-namespace 43 | extraSecretManifests: 44 | - apiVersion: v1 45 | kind: Pod 46 | metadata: 47 | name: dummy-secret 48 | namespace: my-namespace 49 | 50 | asserts: 51 | - equal: 52 | path: metadata.namespace 53 | value: my-namespace 54 | -------------------------------------------------------------------------------- /charts/atlantis/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ template "atlantis.fullname" . }} 5 | namespace: {{ .Release.Namespace }} 6 | labels: 7 | {{- include "atlantis.labels" . | nindent 4 }} 8 | {{- if or .Values.service.annotations .Values.extraAnnotations }} 9 | annotations: 10 | {{- with .Values.service.annotations }} 11 | {{- toYaml . | nindent 4 }} 12 | {{- end }} 13 | {{- with .Values.extraAnnotations }} 14 | {{- toYaml . | nindent 4 }} 15 | {{- end }} 16 | {{- end }} 17 | spec: 18 | {{- if .Values.service.loadBalancerSourceRanges }} 19 | loadBalancerSourceRanges: 20 | {{- toYaml .Values.service.loadBalancerSourceRanges | nindent 4 }} 21 | {{- end }} 22 | {{- if .Values.service.loadBalancerIP }} 23 | loadBalancerIP: {{ .Values.service.loadBalancerIP }} 24 | {{- end }} 25 | {{- if .Values.service.externalTrafficPolicy }} 26 | externalTrafficPolicy: {{ .Values.service.externalTrafficPolicy }} 27 | {{- end }} 28 | type: {{ .Values.service.type }} 29 | ports: 30 | - port: {{ .Values.service.port }} 31 | targetPort: {{ .Values.service.targetPort }} 32 | {{- if .Values.service.nodePort }} 33 | nodePort: {{ .Values.service.nodePort }} 34 | {{- end }} 35 | protocol: TCP 36 | name: {{ .Values.service.portName }} 37 | selector: 38 | app: {{ template "atlantis.name" . }} 39 | release: {{ .Release.Name }} 40 | -------------------------------------------------------------------------------- /charts/atlantis/tests/secret-service-account_test.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | suite: test secret-service-account for serviceAccountSecrets 3 | templates: 4 | - secret-service-account.yaml 5 | release: 6 | name: my-release 7 | tests: 8 | - it: default values 9 | template: secret-service-account.yaml 10 | asserts: 11 | - hasDocuments: 12 | count: 0 13 | - it: serviceAccountSecrets 14 | template: secret-service-account.yaml 15 | set: 16 | serviceAccountSecrets: 17 | credentials: VG9ueSBTb3ByYW5v 18 | credentials-staging: Q2FybWVsYSBTb3ByYW5v 19 | commonLabels: 20 | team: infra 21 | asserts: 22 | - hasDocuments: 23 | count: 2 24 | - isKind: 25 | of: Secret 26 | - isAPIVersion: 27 | of: v1 28 | - equal: 29 | path: metadata.labels.component 30 | value: service-account-secret 31 | - documentIndex: 0 32 | equal: 33 | path: data["service-account.json"] 34 | value: VG9ueSBTb3ByYW5v 35 | - documentIndex: 0 36 | equal: 37 | path: metadata.name 38 | value: credentials 39 | - documentIndex: 0 40 | equal: 41 | path: metadata.labels.team 42 | value: infra 43 | - documentIndex: 1 44 | equal: 45 | path: data["service-account.json"] 46 | value: Q2FybWVsYSBTb3ByYW5v 47 | - documentIndex: 1 48 | equal: 49 | path: metadata.name 50 | value: credentials-staging 51 | - documentIndex: 1 52 | equal: 53 | path: metadata.labels.team 54 | value: infra 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /charts/atlantis/tests/secret-aws_test.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | suite: test secret-aws for aws 3 | templates: 4 | - secret-aws.yaml 5 | release: 6 | name: my-release 7 | tests: 8 | - it: default values 9 | asserts: 10 | - hasDocuments: 11 | count: 0 12 | - it: awsSecretName 13 | set: 14 | awsSecretName: 'atlantis-aws' 15 | asserts: 16 | - hasDocuments: 17 | count: 0 18 | - it: aws 19 | set: 20 | aws: 21 | credentials: | 22 | [default] 23 | aws_access_key_id=YOUR_ACCESS_KEY_ID 24 | aws_secret_access_key=YOUR_SECRET_ACCESS_KEY 25 | region=us-east-1 26 | config: | 27 | [profile a_role_to_assume] 28 | role_arn = arn:aws:iam::123456789:role/service-role/roleToAssume 29 | source_profile = default 30 | commonLabels: 31 | team: "infra" 32 | asserts: 33 | - hasDocuments: 34 | count: 1 35 | - isKind: 36 | of: Secret 37 | - isAPIVersion: 38 | of: v1 39 | - equal: 40 | path: metadata.name 41 | value: my-release-atlantis-aws 42 | - equal: 43 | path: data["config"] 44 | value: W3Byb2ZpbGUgYV9yb2xlX3RvX2Fzc3VtZV0Kcm9sZV9hcm4gPSBhcm46YXdzOmlhbTo6MTIzNDU2Nzg5OnJvbGUvc2VydmljZS1yb2xlL3JvbGVUb0Fzc3VtZQpzb3VyY2VfcHJvZmlsZSA9IGRlZmF1bHQK 45 | - equal: 46 | path: data["credentials"] 47 | value: W2RlZmF1bHRdCmF3c19hY2Nlc3Nfa2V5X2lkPVlPVVJfQUNDRVNTX0tFWV9JRAphd3Nfc2VjcmV0X2FjY2Vzc19rZXk9WU9VUl9TRUNSRVRfQUNDRVNTX0tFWQpyZWdpb249dXMtZWFzdC0xCg== 48 | - equal: 49 | path: metadata.labels.team 50 | value: infra 51 | 52 | 53 | -------------------------------------------------------------------------------- /charts/atlantis/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | 1. Get the application URL by running these commands: 2 | {{- if .Values.ingress.enabled }} 3 | {{- range .Values.ingress.hosts }} 4 | http{{ if $.Values.ingress.tls }}s{{ end }}://{{ . }}{{ $.Values.ingress.path }} 5 | {{- end }} 6 | {{- else if contains "NodePort" .Values.service.type }} 7 | export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "atlantis.fullname" . }}) 8 | export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") 9 | echo http://$NODE_IP:$NODE_PORT 10 | {{- else if contains "LoadBalancer" .Values.service.type }} 11 | NOTE: It may take a few minutes for the LoadBalancer IP to be available. 12 | You can watch the status of by running 'kubectl get svc -w {{ template "atlantis.fullname" . }}' 13 | export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "atlantis.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') 14 | echo http://$SERVICE_IP:{{ .Values.service.port }} 15 | {{- else if contains "ClusterIP" .Values.service.type }} 16 | export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "atlantis.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") 17 | echo "Visit http://127.0.0.1:8080 to use your application" 18 | kubectl port-forward $POD_NAME 8080:80 19 | {{- end }} 20 | 2. Atlantis will not start successfully unless at least one of the following sets of credentials are specified (see values.yaml for detailed usage): 21 | - github 22 | - githubApp 23 | - gitea 24 | - gitlab 25 | - bitbucket -------------------------------------------------------------------------------- /charts/atlantis/templates/servicemonitor.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.servicemonitor.enabled }} 2 | apiVersion: monitoring.coreos.com/v1 3 | kind: ServiceMonitor 4 | metadata: 5 | name: {{ template "atlantis.fullname" . }} 6 | namespace: {{ .Release.Namespace }} 7 | labels: 8 | {{- include "atlantis.labels" . | nindent 4 }} 9 | {{- with .Values.servicemonitor.additionalLabels }} 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | {{- if or .Values.service.annotations .Values.extraAnnotations }} 13 | annotations: 14 | {{- with .Values.service.annotations }} 15 | {{- toYaml . | nindent 4 }} 16 | {{- end }} 17 | {{- with .Values.extraAnnotations }} 18 | {{- toYaml . | nindent 4 }} 19 | {{- end }} 20 | {{- end }} 21 | spec: 22 | selector: 23 | matchLabels: 24 | {{- include "atlantis.labels" . | nindent 6 }} 25 | namespaceSelector: 26 | matchNames: 27 | - {{ .Release.Namespace }} 28 | endpoints: 29 | - port: atlantis 30 | interval: {{ .Values.servicemonitor.interval }} 31 | path: {{ .Values.servicemonitor.path }} 32 | {{- with .Values.servicemonitor.metricRelabelings }} 33 | metricRelabelings: 34 | {{- toYaml . | nindent 6 }} 35 | {{- end }} 36 | {{- if .Values.servicemonitor.auth.basicAuth.enabled }} 37 | basicAuth: 38 | username: 39 | key: username 40 | name: {{ template "atlantis.fullname" . }}-basic-auth 41 | password: 42 | key: password 43 | name: {{ template "atlantis.fullname" . }}-basic-auth 44 | {{- else if .Values.servicemonitor.auth.externalSecret.enabled }} 45 | basicAuth: 46 | username: 47 | key: {{ .Values.servicemonitor.auth.externalSecret.keys.username }} 48 | name: {{ .Values.servicemonitor.auth.externalSecret.name }} 49 | password: 50 | key: {{ .Values.servicemonitor.auth.externalSecret.keys.password }} 51 | name: {{ .Values.servicemonitor.auth.externalSecret.name }} 52 | {{- end }} 53 | {{- end }} 54 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Atlantis 2 | 3 | [![Lint Code Base](https://github.com/runatlantis/helm-charts/actions/workflows/linter.yaml/badge.svg)](https://github.com/runatlantis/helm-charts/actions/workflows/linter.yaml) 4 | [![Lint and Test Charts](https://github.com/runatlantis/helm-charts/actions/workflows/lint-test.yaml/badge.svg)](https://github.com/runatlantis/helm-charts/actions/workflows/lint-test.yaml) 5 | [![Release Charts](https://github.com/runatlantis/helm-charts/actions/workflows/release.yaml/badge.svg)](https://github.com/runatlantis/helm-charts/actions/workflows/release.yaml) 6 | [![pages-build-deployment](https://github.com/runatlantis/helm-charts/actions/workflows/pages/pages-build-deployment/badge.svg)](https://github.com/runatlantis/helm-charts/actions/workflows/pages/pages-build-deployment) 7 | [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Frunatlantis%2Fhelm-charts.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Frunatlantis%2Fhelm-charts?ref=badge_shield) 8 | 9 | [Atlantis](https://www.runatlantis.io/) is a tool for safe collaboration on [Terraform](https://www.terraform.io/) repositories. 10 | 11 | ## Usage 12 | 13 | [Helm](https://helm.sh) must be installed to use the charts. 14 | Please refer to Helm's [documentation](https://helm.sh/docs/) to get started. 15 | 16 | Once Helm is set up properly, add the repository as follows: 17 | 18 | ```console 19 | helm repo add runatlantis https://runatlantis.github.io/helm-charts 20 | ``` 21 | 22 | You can then run `helm search repo runatlantis` to see the charts. 23 | 24 | OCI artifacts of all Atlantis Helm charts are available in [ghcr.io](https://github.com/orgs/runatlantis/packages?repo_name=charts). 25 | 26 | ## Commands 27 | 28 | Run `make help` to check available commands. 29 | 30 | ## License 31 | 32 | [Apache 2.0 License](../LICENSE). 33 | 34 | 35 | [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Frunatlantis%2Fhelm-charts.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Frunatlantis%2Fhelm-charts?ref=badge_large) -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: Release Charts 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | paths: 8 | - 'charts/atlantis/**' 9 | 10 | permissions: read-all 11 | 12 | jobs: 13 | release: 14 | runs-on: ubuntu-latest 15 | permissions: 16 | contents: write # to push chart release and create a release (helm/chart-releaser-action) 17 | packages: write # needed for ghcr access 18 | id-token: write # needed for keyless signing 19 | attestations: write # needed for artifact attestation 20 | steps: 21 | - name: Checkout 22 | uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 23 | with: 24 | fetch-depth: 0 25 | 26 | - name: Configure Git 27 | run: | 28 | git config user.name "$GITHUB_ACTOR" 29 | git config user.email "$GITHUB_ACTOR@users.noreply.github.com" 30 | 31 | - name: Install Helm 32 | uses: azure/setup-helm@b9e51907a09c216f16ebe8536097933489208112 # v4 33 | with: 34 | # renovate: datasource=github-tags depName=helm packageName=helm/helm 35 | version: v4.0.4 36 | 37 | - name: Run chart-releaser 38 | uses: helm/chart-releaser-action@cae68fefc6b5f367a0275617c9f83181ba54714f # v1.7.0 39 | env: 40 | CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 41 | CR_SKIP_EXISTING: true 42 | CR_GENERATE_RELEASE_NOTES: true 43 | 44 | # see https://github.com/helm/chart-releaser/issues/183 45 | - name: Login to GitHub Container Registry 46 | uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 47 | with: 48 | registry: ghcr.io 49 | username: ${{ github.actor }} 50 | password: ${{ secrets.GITHUB_TOKEN }} 51 | 52 | - name: Push chart to GHCR 53 | id: push-chart 54 | run: | 55 | helm package charts/atlantis 56 | 57 | # Push and capture output to get the OCI digest 58 | PUSH_OUTPUT=$(helm push atlantis-*.tgz oci://ghcr.io/${GITHUB_REPOSITORY_OWNER}/charts 2>&1) 59 | 60 | # Extract the OCI digest from helm push output 61 | DIGEST=$(echo "${PUSH_OUTPUT}" | grep -o 'sha256:[a-f0-9]\{64\}') 62 | echo "digest=${DIGEST}" >> $GITHUB_OUTPUT 63 | 64 | - name: Attest chart OCI artifact 65 | uses: actions/attest-build-provenance@v3 66 | with: 67 | subject-name: ghcr.io/${{ github.repository_owner }}/charts/atlantis 68 | subject-digest: ${{ steps.push-chart.outputs.digest }} 69 | push-to-registry: true 70 | -------------------------------------------------------------------------------- /charts/atlantis/templates/secret-webhook.yaml: -------------------------------------------------------------------------------- 1 | {{- if not .Values.vcsSecretName }} 2 | apiVersion: v1 3 | kind: Secret 4 | metadata: 5 | name: {{ template "atlantis.fullname" . }}-webhook 6 | namespace: {{ .Release.Namespace }} 7 | labels: 8 | {{- include "atlantis.labels" . | nindent 4 }} 9 | {{- if or .Values.secret.annotations .Values.extraAnnotations }} 10 | annotations: 11 | {{- with .Values.secret.annotations }} 12 | {{- toYaml . | nindent 4 }} 13 | {{- end }} 14 | {{- with .Values.extraAnnotations }} 15 | {{- toYaml . | nindent 4 }} 16 | {{- end }} 17 | {{- end }} 18 | data: 19 | {{- if .Values.githubApp }} 20 | key.pem: {{ required "githubApp.key is required if githubApp configuration is specified." .Values.githubApp.key | b64enc }} 21 | github_secret: {{ required "githubApp.secret is required if githubApp configuration is specified." .Values.githubApp.secret | b64enc }} 22 | {{- end }} 23 | {{- if .Values.github.user }} 24 | github_token: {{ required "github.token is required if github configuration is specified." .Values.github.token | b64enc }} 25 | github_secret: {{ required "github.secret is required if github configuration is specified." .Values.github.secret | b64enc }} 26 | {{- end }} 27 | {{- if .Values.gitea }} 28 | gitea_token: {{ required "gitea.token is required if gitea configuration is specified." .Values.gitea.token | b64enc }} 29 | gitea_secret: {{ required "gitea.secret is required if gitea configuration is specified." .Values.gitea.secret | b64enc }} 30 | {{- end }} 31 | {{- if .Values.gitlab }} 32 | gitlab_token: {{ required "gitlab.token is required if gitlab configuration is specified." .Values.gitlab.token | b64enc }} 33 | gitlab_secret: {{ required "gitlab.secret is required if gitlab configuration is specified." .Values.gitlab.secret | b64enc }} 34 | {{- end }} 35 | {{- if .Values.bitbucket }} 36 | bitbucket_token: {{ required "bitbucket.token is required if bitbucket configuration is specified." .Values.bitbucket.token | b64enc }} 37 | {{- if .Values.bitbucket.baseURL }} 38 | bitbucket_secret: {{ required "bitbucket.secret is required if bitbucket.baseURL is specified." .Values.bitbucket.secret | b64enc }} 39 | {{- end }} 40 | {{- end }} 41 | {{- if .Values.azuredevops }} 42 | azuredevops_token: {{ required "azuredevops.token is required if azuredevops configuration is specified." .Values.azuredevops.token | b64enc }} 43 | azuredevops_webhook_password: {{ required "azuredevops.webhookPassword is required if azuredevops configuration is specified." .Values.azuredevops.webhookPassword | b64enc }} 44 | {{- end }} 45 | {{- end }} 46 | -------------------------------------------------------------------------------- /charts/atlantis/tests/podmonitor.yaml: -------------------------------------------------------------------------------- 1 | suite: test podmonitoring 2 | templates: 3 | - "podmonitor.yaml" 4 | chart: 5 | appVersion: test-appVersion 6 | release: 7 | name: my-release 8 | namespace: my-namespace 9 | tests: 10 | - it: does not render when disabled 11 | set: 12 | podMonitor: 13 | enabled: false 14 | asserts: 15 | - hasDocuments: 16 | count: 0 17 | 18 | - it: renders with defaults 19 | set: 20 | podMonitor: 21 | enabled: true 22 | asserts: 23 | - hasDocuments: 24 | count: 1 25 | - isKind: 26 | of: PodMonitoring 27 | - equal: 28 | path: metadata.name 29 | value: my-release-atlantis 30 | - equal: 31 | path: metadata.namespace 32 | value: my-namespace 33 | - equal: 34 | path: spec.endpoints[0].interval 35 | value: "30s" 36 | 37 | - it: allows overriding interval 38 | set: 39 | podMonitor: 40 | enabled: true 41 | interval: "15s" 42 | asserts: 43 | - equal: 44 | path: spec.endpoints[0].interval 45 | value: "15s" 46 | 47 | - it: applies metricRelabeling - replace 48 | set: 49 | podMonitor: 50 | enabled: true 51 | metricRelabeling: 52 | - action: replace 53 | separator: "_" 54 | sourceLabels: ["atlantis_metric"] 55 | targetLabel: atlantis_metric_custom 56 | asserts: 57 | - lengthEqual: 58 | path: spec.endpoints[0].metricRelabeling 59 | count: 1 60 | - equal: 61 | path: spec.endpoints[0].metricRelabeling[0].action 62 | value: replace 63 | - equal: 64 | path: spec.endpoints[0].metricRelabeling[0].separator 65 | value: "_" 66 | - equal: 67 | path: spec.endpoints[0].metricRelabeling[0].sourceLabels 68 | value: ["atlantis_metric"] 69 | - equal: 70 | path: spec.endpoints[0].metricRelabeling[0].targetLabel 71 | value: atlantis_metric_custom 72 | 73 | - it: applies metricRelabeling - regex 74 | set: 75 | podMonitor: 76 | enabled: true 77 | metricRelabeling: 78 | - action: keep 79 | sourceLabels: ["__name__"] 80 | regex: (atlantis_(.+)|one_(.+)|two_(.+)) 81 | asserts: 82 | - lengthEqual: 83 | path: spec.endpoints[0].metricRelabeling 84 | count: 1 85 | - equal: 86 | path: spec.endpoints[0].metricRelabeling[0].action 87 | value: keep 88 | - equal: 89 | path: spec.endpoints[0].metricRelabeling[0].sourceLabels 90 | value: ["__name__"] 91 | - equal: 92 | path: spec.endpoints[0].metricRelabeling[0].regex 93 | value: "(atlantis_(.+)|one_(.+)|two_(.+))" 94 | -------------------------------------------------------------------------------- /charts/atlantis/tests/service_test.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | suite: test service 3 | templates: 4 | - service.yaml 5 | release: 6 | name: my-release 7 | tests: 8 | - it: default values 9 | asserts: 10 | - isKind: 11 | of: Service 12 | - equal: 13 | path: apiVersion 14 | value: v1 15 | - equal: 16 | path: metadata.name 17 | value: my-release-atlantis 18 | - equal: 19 | path: spec 20 | value: 21 | ports: 22 | - name: atlantis 23 | port: 80 24 | protocol: TCP 25 | targetPort: 4141 26 | selector: 27 | app: atlantis 28 | release: my-release 29 | type: NodePort 30 | - it: externalTrafficPolicy 31 | set: 32 | service: 33 | externalTrafficPolicy: Local 34 | asserts: 35 | - equal: 36 | path: spec.externalTrafficPolicy 37 | value: Local 38 | - it: portName 39 | set: 40 | service: 41 | portName: http-atlantis 42 | asserts: 43 | - equal: 44 | path: spec.ports[0].name 45 | value: http-atlantis 46 | - it: loadBalancerSourceRanges 47 | set: 48 | service: 49 | loadBalancerSourceRanges: 50 | - 10.0.0.0/8 51 | asserts: 52 | - equal: 53 | path: spec.loadBalancerSourceRanges 54 | value: 55 | - 10.0.0.0/8 56 | - it: loadBalancerIP 57 | set: 58 | service: 59 | loadBalancerIP: 172.16.5.2 60 | asserts: 61 | - equal: 62 | path: spec.loadBalancerIP 63 | value: 172.16.5.2 64 | - it: service type 65 | set: 66 | service: 67 | type: ClusterIP 68 | annotations: 69 | haproxy.org/check: "true" 70 | port: 8080 71 | targetPort: 8181 72 | asserts: 73 | - equal: 74 | path: metadata.annotations 75 | value: 76 | haproxy.org/check: "true" 77 | - equal: 78 | path: spec 79 | value: 80 | ports: 81 | - name: atlantis 82 | port: 8080 83 | protocol: TCP 84 | targetPort: 8181 85 | selector: 86 | app: atlantis 87 | release: my-release 88 | type: ClusterIP 89 | - it: nodePort 90 | set: 91 | service: 92 | type: NodePort 93 | nodePort: 30000 94 | asserts: 95 | - equal: 96 | path: spec.ports[0].nodePort 97 | value: 30000 98 | - it: commonLabels 99 | set: 100 | commonLabels: 101 | team: infra 102 | asserts: 103 | - equal: 104 | path: metadata.labels.team 105 | value: infra 106 | -------------------------------------------------------------------------------- /charts/atlantis/templates/ingress.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.ingress.enabled }} 2 | {{- $apiVersion := .Values.ingress.apiVersion }} 3 | {{- if and $apiVersion (or (eq $apiVersion "networking.k8s.io/v1") (eq $apiVersion "networking.k8s.io/v1beta1") (eq $apiVersion "extensions/v1beta1")) -}} 4 | {{- else -}} 5 | {{- $kubeVersion := .Capabilities.KubeVersion.GitVersion }} 6 | {{- if semverCompare ">=1.19-0" $kubeVersion -}} 7 | {{- $apiVersion = "networking.k8s.io/v1" -}} 8 | {{- else if semverCompare ">=1.14-0" $kubeVersion -}} 9 | {{- $apiVersion = "networking.k8s.io/v1beta1" -}} 10 | {{- else -}} 11 | {{- $apiVersion = "extensions/v1beta1" -}} 12 | {{- end }} 13 | {{- end }} 14 | {{- $fullName := include "atlantis.fullname" . -}} 15 | {{- $svcPort := .Values.service.port -}} 16 | {{- $pathType := .Values.ingress.pathType -}} 17 | apiVersion: {{ $apiVersion }} 18 | kind: Ingress 19 | metadata: 20 | name: {{ $fullName }} 21 | namespace: {{ .Release.Namespace }} 22 | labels: 23 | {{- include "atlantis.labels" . | nindent 4 }} 24 | {{- if .Values.ingress.labels }} 25 | {{- toYaml .Values.ingress.labels | nindent 4 }} 26 | {{- end }} 27 | {{- if or .Values.ingress.annotations .Values.extraAnnotations }} 28 | annotations: 29 | {{- with .Values.ingress.annotations }} 30 | {{- toYaml . | nindent 4 }} 31 | {{- end }} 32 | {{- with .Values.extraAnnotations }} 33 | {{- toYaml . | nindent 4 }} 34 | {{- end }} 35 | {{- end }} 36 | spec: 37 | {{- if .Values.ingress.ingressClassName }} 38 | ingressClassName: {{ .Values.ingress.ingressClassName }} 39 | {{- end }} 40 | {{- if .Values.ingress.tls }} 41 | tls: 42 | {{- toYaml .Values.ingress.tls | nindent 4 }} 43 | {{- end }} 44 | rules: 45 | {{- if not .Values.ingress.hosts }} 46 | - 47 | {{- if .Values.ingress.host }} 48 | host: {{ .Values.ingress.host | quote }} 49 | {{- end }} 50 | http: 51 | paths: 52 | {{- if .Values.ingress.paths }} 53 | {{- range .Values.ingress.paths }} 54 | - path: {{ .path }} 55 | backend: 56 | {{- if eq $apiVersion "networking.k8s.io/v1" }} 57 | service: 58 | name: {{ .service }} 59 | port: 60 | number: {{ .port }} 61 | pathType: {{ $.Values.ingress.pathType }} 62 | {{- else }} 63 | serviceName: {{ .service }} 64 | servicePort: {{ .port }} 65 | {{- end }} 66 | {{- end }} 67 | {{ else }} 68 | - path: {{ .Values.ingress.path }} 69 | backend: 70 | {{- if eq $apiVersion "networking.k8s.io/v1" }} 71 | service: 72 | name: {{ $fullName }} 73 | port: 74 | number: {{ .Values.service.port }} 75 | pathType: {{ .Values.ingress.pathType }} 76 | {{ else }} 77 | serviceName: {{ $fullName }} 78 | servicePort: {{ .Values.service.port }} 79 | {{- end }} 80 | {{- end }} 81 | {{ else }} 82 | {{- range $k := .Values.ingress.hosts }} 83 | - 84 | {{- if .host }} 85 | host: {{ .host | quote }} 86 | {{- end }} 87 | http: 88 | paths: 89 | {{- range .paths }} 90 | - path: {{ . }} 91 | backend: 92 | {{- if eq $apiVersion "networking.k8s.io/v1" }} 93 | service: 94 | {{- if $k.service }} 95 | name: {{ $k.service }} 96 | {{- else }} 97 | name: {{ $fullName }} 98 | {{- end }} 99 | port: 100 | number: {{ $svcPort }} 101 | pathType: {{ $pathType }} 102 | {{- else -}} 103 | {{- if $k.service }} 104 | serviceName: {{ $k.service }} 105 | {{- else }} 106 | serviceName: {{ $fullName }} 107 | {{- end }} 108 | servicePort: {{ $svcPort }} 109 | {{- end }} 110 | {{- end }} 111 | {{- end }} 112 | {{- end }} 113 | {{- end }} 114 | -------------------------------------------------------------------------------- /.github/workflows/lint-test.yaml: -------------------------------------------------------------------------------- 1 | name: Lint and Test Charts 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - "charts/atlantis/**" 7 | - "ct.yaml" 8 | 9 | defaults: 10 | run: 11 | shell: bash 12 | 13 | permissions: read-all 14 | 15 | jobs: 16 | lint-test: 17 | runs-on: ubuntu-latest 18 | steps: 19 | - name: Checkout 20 | uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 21 | with: 22 | fetch-depth: 0 23 | 24 | - name: Set up Helm 25 | uses: azure/setup-helm@b9e51907a09c216f16ebe8536097933489208112 # v4 26 | with: 27 | # renovate: datasource=github-tags depName=helm packageName=helm/helm 28 | version: v4.0.4 29 | 30 | - uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6 31 | with: 32 | # renovate: datasource=docker depName=python 33 | python-version: "3.14" 34 | check-latest: true 35 | 36 | - name: Set up chart-testing 37 | uses: helm/chart-testing-action@6ec842c01de15ebb84c8627d2744a0c2f2755c9f # v2.8.0 38 | with: 39 | yamale_version: "6.0.0" 40 | 41 | - name: Run chart-testing (list-changed) 42 | id: list-changed 43 | run: | 44 | changed=$(ct list-changed \ 45 | --config ct.yaml \ 46 | --target-branch ${{ github.event.repository.default_branch }}) 47 | if [[ -n "$changed" ]]; then 48 | echo "changed=true" >> "$GITHUB_OUTPUT" 49 | fi 50 | 51 | - name: Check if docs are updated 52 | if: steps.list-changed.outputs.changed == 'true' 53 | run: | 54 | make docs 55 | if [[ -n "$(git status --porcelain --untracked-files=no)" ]]; then 56 | echo "Documentation not up to date." >&2 57 | echo "Please run 'make docs' from the repository root and commit changes!" >&2 58 | git diff 59 | exit 1 60 | else 61 | echo "Documentation is up to date." >&2 62 | fi 63 | 64 | # - name: Install helm unittests 65 | # if: steps.list-changed.outputs.changed == 'true' 66 | # run: | 67 | # make unit-test-install 68 | 69 | # Required until https://github.com/helm-unittest/helm-unittest/issues/777 is fixed 70 | - name: Install helm-unittest plugin with checksum validation 71 | if: steps.list-changed.outputs.changed == 'true' 72 | shell: bash 73 | run: | 74 | set -euo pipefail 75 | 76 | VERSION="1.0.3" # without v 77 | ARCH="$(uname -m)" 78 | 79 | case "${ARCH}" in 80 | x86_64) 81 | ARCH=amd64 82 | SUM="12a9ef198e21166fe5f7487544903d91355b4ea08b1d59220f1543234caf4371" 83 | ;; 84 | aarch64|arm64) 85 | ARCH=arm64 86 | SUM="540aec896945e0e26f443b0d1976d556ce0a3bfa7b10255ed1beecc8d2f7a1cc" 87 | ;; 88 | *) 89 | echo "Unsupported arch: ${ARCH}" 90 | exit 1 91 | ;; 92 | esac 93 | 94 | ASSET="helm-unittest-linux-${ARCH}-${VERSION}.tgz" 95 | 96 | wget "https://github.com/helm-unittest/helm-unittest/releases/download/v${VERSION}/${ASSET}" 97 | echo "${SUM} ${ASSET}" | sha256sum -c 98 | 99 | mkdir -p "$(helm env HELM_PLUGINS)/${ASSET%.*}" 100 | tar -xzf "${ASSET}" -C "$(helm env HELM_PLUGINS)/${ASSET%.*}" 101 | 102 | helm plugin list 103 | 104 | - name: Run chart-testing (lint) 105 | if: steps.list-changed.outputs.changed == 'true' 106 | run: | 107 | ct lint \ 108 | --config ct.yaml \ 109 | --target-branch ${{ github.event.repository.default_branch }} 110 | 111 | - name: Create kind cluster 112 | if: steps.list-changed.outputs.changed == 'true' 113 | uses: helm/kind-action@92086f6be054225fa813e0a4b13787fc9088faab # v1.13.0 114 | 115 | - name: Run chart-testing (install) 116 | if: steps.list-changed.outputs.changed == 'true' 117 | run: | 118 | ct install \ 119 | --config ct.yaml \ 120 | --target-branch ${{ github.event.repository.default_branch }} 121 | -------------------------------------------------------------------------------- /charts/atlantis/templates/webhook-ingress.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.webhook_ingress.enabled }} 2 | {{- $apiVersion := .Values.webhook_ingress.apiVersion }} 3 | {{- if and $apiVersion (or (eq $apiVersion "networking.k8s.io/v1") (eq $apiVersion "networking.k8s.io/v1beta1") (eq $apiVersion "extensions/v1beta1")) -}} 4 | {{- else -}} 5 | {{- $kubeVersion := .Capabilities.KubeVersion.GitVersion }} 6 | {{- if semverCompare ">=1.19-0" $kubeVersion -}} 7 | {{- $apiVersion = "networking.k8s.io/v1" -}} 8 | {{- else if semverCompare ">=1.14-0" $kubeVersion -}} 9 | {{- $apiVersion = "networking.k8s.io/v1beta1" -}} 10 | {{- else -}} 11 | {{- $apiVersion = "extensions/v1beta1" -}} 12 | {{- end }} 13 | {{- end }} 14 | {{- $fullName := include "atlantis.fullname" . -}} 15 | {{- $svcPort := .Values.service.port -}} 16 | {{- $pathType := .Values.webhook_ingress.pathType -}} 17 | apiVersion: {{ $apiVersion }} 18 | kind: Ingress 19 | metadata: 20 | name: {{ $fullName }}-secondary 21 | namespace: {{ .Release.Namespace }} 22 | labels: 23 | {{- include "atlantis.labels" . | nindent 4 }} 24 | {{- with .Values.webhook_ingress.labels }} 25 | {{- toYaml . | nindent 4 }} 26 | {{- end }} 27 | {{- if or .Values.webhook_ingress.annotations .Values.extraAnnotations }} 28 | annotations: 29 | {{- with .Values.webhook_ingress.annotations }} 30 | {{- toYaml . | nindent 4 }} 31 | {{- end }} 32 | {{- with .Values.extraAnnotations }} 33 | {{- toYaml . | nindent 4 }} 34 | {{- end }} 35 | {{- end }} 36 | spec: 37 | {{- if .Values.webhook_ingress.ingressClassName }} 38 | ingressClassName: {{ .Values.webhook_ingress.ingressClassName }} 39 | {{- end }} 40 | {{- if .Values.webhook_ingress.tls }} 41 | tls: 42 | {{- toYaml .Values.webhook_ingress.tls | nindent 4 }} 43 | {{- end }} 44 | rules: 45 | {{- if not .Values.webhook_ingress.hosts }} 46 | - 47 | {{- if .Values.webhook_ingress.host }} 48 | host: {{ .Values.webhook_ingress.host | quote }} 49 | {{- end }} 50 | http: 51 | paths: 52 | {{- if .Values.webhook_ingress.paths }} 53 | {{- range .Values.webhook_ingress.paths }} 54 | - path: {{ .path }} 55 | backend: 56 | {{- if eq $apiVersion "networking.k8s.io/v1" }} 57 | service: 58 | name: {{ .service }} 59 | port: 60 | number: {{ .port }} 61 | pathType: {{ $.Values.webhook_ingress.pathType }} 62 | {{- else }} 63 | serviceName: {{ .service }} 64 | servicePort: {{ .port }} 65 | {{- end }} 66 | {{- end }} 67 | {{ else }} 68 | - path: {{ .Values.webhook_ingress.path }} 69 | backend: 70 | {{- if eq $apiVersion "networking.k8s.io/v1" }} 71 | service: 72 | name: {{ $fullName }} 73 | port: 74 | number: {{ .Values.service.port }} 75 | pathType: {{ .Values.webhook_ingress.pathType }} 76 | {{ else }} 77 | serviceName: {{ $fullName }} 78 | servicePort: {{ .Values.service.port }} 79 | {{- end }} 80 | {{- end }} 81 | {{ else }} 82 | {{- range $k := .Values.webhook_ingress.hosts }} 83 | - 84 | {{- if .host }} 85 | host: {{ .host | quote }} 86 | {{- end }} 87 | http: 88 | paths: 89 | {{- range .paths }} 90 | - path: {{ . }} 91 | backend: 92 | {{- if eq $apiVersion "networking.k8s.io/v1" }} 93 | service: 94 | {{- if $k.service }} 95 | name: {{ $k.service }} 96 | {{- else }} 97 | name: {{ $fullName }} 98 | {{- end }} 99 | port: 100 | number: {{ $svcPort }} 101 | pathType: {{ $pathType }} 102 | {{- else -}} 103 | {{- if $k.service }} 104 | serviceName: {{ $k.service }} 105 | {{- else }} 106 | serviceName: {{ $fullName }} 107 | {{- end }} 108 | servicePort: {{ $svcPort }} 109 | {{- end }} 110 | {{- end }} 111 | {{- end }} 112 | {{- end }} 113 | {{- end }} 114 | -------------------------------------------------------------------------------- /charts/atlantis/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=mustache: */}} 2 | {{/* 3 | Expand the name of the chart. 4 | */}} 5 | {{- define "atlantis.name" -}} 6 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} 7 | {{- end -}} 8 | 9 | {{/* 10 | Create a default fully qualified app name. 11 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 12 | If release name contains chart name it will be used as a full name. 13 | */}} 14 | {{- define "atlantis.fullname" -}} 15 | {{- if .Values.fullnameOverride -}} 16 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} 17 | {{- else -}} 18 | {{- $name := default .Chart.Name .Values.nameOverride -}} 19 | {{- if contains $name .Release.Name -}} 20 | {{- .Release.Name | trunc 63 | trimSuffix "-" -}} 21 | {{- else -}} 22 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} 23 | {{- end -}} 24 | {{- end -}} 25 | {{- end -}} 26 | 27 | {{/* 28 | Create chart name and version as used by the chart label. 29 | */}} 30 | {{- define "atlantis.chart" -}} 31 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} 32 | {{- end -}} 33 | 34 | {{/* 35 | Create the name of the service account to use 36 | */}} 37 | {{- define "atlantis.serviceAccountName" -}} 38 | {{- if .Values.serviceAccount.create -}} 39 | {{ default (include "atlantis.fullname" .) .Values.serviceAccount.name }} 40 | {{- else -}} 41 | {{ default "default" .Values.serviceAccount.name }} 42 | {{- end -}} 43 | {{- end -}} 44 | 45 | {{/* 46 | Defines the scheme (http or https) of the Atlantis service 47 | */}} 48 | {{- define "atlantis.url.scheme" -}} 49 | {{- if .Values.tlsSecretName -}} 50 | https 51 | {{- else -}} 52 | http 53 | {{- end -}} 54 | {{- end -}} 55 | 56 | {{/* 57 | Defines the internal kubernetes address to Atlantis 58 | */}} 59 | {{- define "atlantis.url" -}} 60 | {{ template "atlantis.url.scheme" . }}://{{ template "atlantis.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local:{{ .Values.service.port }} 61 | {{- end -}} 62 | 63 | {{/* 64 | Generates secret-webhook name 65 | */}} 66 | {{- define "atlantis.vcsSecretName" -}} 67 | {{- if .Values.vcsSecretName -}} 68 | {{ .Values.vcsSecretName }} 69 | {{- else -}} 70 | {{ template "atlantis.fullname" . }}-webhook 71 | {{- end -}} 72 | {{- end -}} 73 | 74 | {{/* 75 | Generates AWS Secret name 76 | */}} 77 | {{- define "atlantis.awsSecretName" -}} 78 | {{- if .Values.awsSecretName -}} 79 | {{ .Values.awsSecretName }} 80 | {{- else -}} 81 | {{ template "atlantis.fullname" . }}-aws 82 | {{- end -}} 83 | {{- end -}} 84 | 85 | {{/* 86 | Generates Basic Auth name 87 | */}} 88 | {{- define "atlantis.basicAuthSecretName" -}} 89 | {{- if .Values.basicAuthSecretName -}} 90 | {{ .Values.basicAuthSecretName }} 91 | {{- else -}} 92 | {{ template "atlantis.fullname" . }}-basic-auth 93 | {{- end -}} 94 | {{- end -}} 95 | 96 | {{/* 97 | Generates API Secret name 98 | */}} 99 | {{- define "atlantis.apiSecretName" -}} 100 | {{- if .Values.apiSecretName -}} 101 | {{ .Values.apiSecretName }} 102 | {{- else -}} 103 | {{ template "atlantis.fullname" . }}-api 104 | {{- end -}} 105 | {{- end -}} 106 | 107 | {{/* 108 | Generates Redis Secret name 109 | */}} 110 | {{- define "atlantis.redisSecretName" -}} 111 | {{- if .Values.redisSecretName -}} 112 | {{ .Values.redisSecretName }} 113 | {{- else -}} 114 | {{ template "atlantis.fullname" . }}-redis 115 | {{- end -}} 116 | {{- end -}} 117 | 118 | {{/* 119 | Common labels 120 | */}} 121 | {{- define "atlantis.labels" -}} 122 | app: {{ template "atlantis.name" . }} 123 | chart: {{ template "atlantis.chart" . }} 124 | helm.sh/chart: {{ template "atlantis.chart" . }} 125 | release: {{ .Release.Name }} 126 | heritage: {{ .Release.Service }} 127 | {{- if .Values.commonLabels}} 128 | {{ toYaml .Values.commonLabels }} 129 | {{- end }} 130 | {{- end -}} 131 | 132 | {{/* 133 | Define PATH environment variable that will be used system-wide. 134 | */}} 135 | {{- define "atlantis.pathEnvironmentVariable" -}} 136 | {{- if .Values.extraPath }} 137 | {{- printf "%s:" .Values.extraPath -}} 138 | {{- end -}} 139 | {{- if .Values.initConfig.sharedDir }} 140 | {{- printf "%s:" .Values.initConfig.sharedDir -}} 141 | {{- end -}} 142 | {{- printf "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" }} 143 | {{- end -}} 144 | 145 | {{/* 146 | Sets the container port based on the defined values. 147 | */}} 148 | {{- define "atlantis.containerPort" -}} 149 | {{- default .Values.service.targetPort .Values.containerPort }} 150 | {{- end -}} 151 | -------------------------------------------------------------------------------- /charts/atlantis/tests/secret-webhook_test.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | suite: test secret-webhook for git webhook secret 3 | templates: 4 | - secret-webhook.yaml 5 | release: 6 | name: my-release 7 | tests: 8 | - it: default values 9 | asserts: 10 | - isKind: 11 | of: Secret 12 | - isAPIVersion: 13 | of: v1 14 | - equal: 15 | path: metadata.name 16 | value: my-release-atlantis-webhook 17 | - isNullOrEmpty: 18 | path: data 19 | - it: vcsSecretName 20 | set: 21 | vcsSecretName: atlantis-vcs 22 | asserts: 23 | - hasDocuments: 24 | count: 0 25 | - it: githubApp only id set 26 | set: 27 | githubApp: 28 | id: 123456 29 | asserts: 30 | - failedTemplate: 31 | errorMessage: githubApp.key is required if githubApp configuration is specified. 32 | - it: githubApp only id and key are set 33 | set: 34 | githubApp: 35 | id: 123456 36 | key: | 37 | -----BEGIN PRIVATE KEY----- 38 | ... 39 | -----END PRIVATE KEY----- 40 | asserts: 41 | - failedTemplate: 42 | errorMessage: githubApp.secret is required if githubApp configuration is specified. 43 | - it: githubApp 44 | set: 45 | githubApp: 46 | id: 123456 47 | key: | 48 | -----BEGIN PRIVATE KEY----- 49 | ... 50 | -----END PRIVATE KEY----- 51 | secret: baz 52 | asserts: 53 | - equal: 54 | path: data 55 | value: 56 | github_secret: YmF6 57 | key.pem: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi4uLgotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tCg== 58 | - it: github only user set 59 | set: 60 | github: 61 | user: foo 62 | asserts: 63 | - failedTemplate: 64 | errorMessage: github.token is required if github configuration is specified. 65 | - it: github only user and token are set 66 | set: 67 | github: 68 | user: foo 69 | token: bar 70 | asserts: 71 | - failedTemplate: 72 | errorMessage: github.secret is required if github configuration is specified. 73 | - it: github 74 | set: 75 | github: 76 | user: foo 77 | token: bar 78 | secret: baz 79 | asserts: 80 | - equal: 81 | path: data 82 | value: 83 | github_secret: YmF6 84 | github_token: YmFy 85 | - it: gitea only user set 86 | set: 87 | gitea: 88 | user: foo 89 | asserts: 90 | - failedTemplate: 91 | errorMessage: gitea.token is required if gitea configuration is specified. 92 | - it: gitea only user and token are set 93 | set: 94 | gitea: 95 | user: foo 96 | token: bar 97 | asserts: 98 | - failedTemplate: 99 | errorMessage: gitea.secret is required if gitea configuration is specified. 100 | - it: gitea 101 | set: 102 | gitea: 103 | user: foo 104 | token: bar 105 | secret: baz 106 | asserts: 107 | - equal: 108 | path: data 109 | value: 110 | gitea_secret: YmF6 111 | gitea_token: YmFy 112 | - it: gitlab only user set 113 | set: 114 | gitlab: 115 | user: foo 116 | asserts: 117 | - failedTemplate: 118 | errorMessage: gitlab.token is required if gitlab configuration is specified. 119 | - it: gitlab only user and token are set 120 | set: 121 | gitlab: 122 | user: foo 123 | token: bar 124 | asserts: 125 | - failedTemplate: 126 | errorMessage: gitlab.secret is required if gitlab configuration is specified. 127 | - it: gitlab 128 | set: 129 | github: 130 | user: foo 131 | token: bar 132 | secret: baz 133 | asserts: 134 | - equal: 135 | path: data 136 | value: 137 | github_secret: YmF6 138 | github_token: YmFy 139 | - it: bitbucket only user set 140 | set: 141 | bitbucket: 142 | user: foo 143 | asserts: 144 | - failedTemplate: 145 | errorMessage: bitbucket.token is required if bitbucket configuration is specified. 146 | - it: bitbucket user and token are set 147 | set: 148 | bitbucket: 149 | user: foo 150 | token: bar 151 | asserts: 152 | - equal: 153 | path: data 154 | value: 155 | bitbucket_token: YmFy 156 | - it: bitbucket server only user and token are set 157 | set: 158 | bitbucket: 159 | user: foo 160 | token: bar 161 | baseURL: https://bitbucket.yourorganization.com 162 | asserts: 163 | - failedTemplate: 164 | errorMessage: bitbucket.secret is required if bitbucket.baseURL is specified. 165 | - it: bitbucket server 166 | set: 167 | bitbucket: 168 | user: foo 169 | token: bar 170 | secret: baz 171 | baseURL: https://bitbucket.yourorganization.com 172 | asserts: 173 | - equal: 174 | path: data 175 | value: 176 | bitbucket_secret: YmF6 177 | bitbucket_token: YmFy 178 | - it: azuredevops only token set 179 | set: 180 | azuredevops: 181 | token: bar 182 | asserts: 183 | - failedTemplate: 184 | errorMessage: azuredevops.webhookPassword is required if azuredevops 185 | configuration is specified. 186 | - it: azuredevops 187 | set: 188 | azuredevops: 189 | token: bar 190 | webhookPassword: baz 191 | asserts: 192 | - equal: 193 | path: data 194 | value: 195 | azuredevops_token: YmFy 196 | azuredevops_webhook_password: YmF6 197 | - it: commonLabels 198 | set: 199 | commonLabels: 200 | team: infra 201 | asserts: 202 | - equal: 203 | path: metadata.labels.team 204 | value: infra 205 | -------------------------------------------------------------------------------- /charts/atlantis/README.md.gotmpl: -------------------------------------------------------------------------------- 1 | # Atlantis 2 | 3 | [Atlantis](https://www.runatlantis.io/) is a tool for safe collaboration on [Terraform](https://www.terraform.io/) repositories. 4 | 5 | {{ template "chart.maintainersSection" . }} 6 | 7 | {{ template "chart.requirementsSection" . }} 8 | 9 | ## Links 10 | 11 | - [Introduction](#introduction) 12 | - [Prerequisites](#prerequisites) 13 | - [Usage](#usage) 14 | - [Install Helm Chart](#install-helm-chart) 15 | - [Required Configuration](#required-configuration) 16 | - [Additional manifests](#additional-manifests) 17 | - [Values](#values) 18 | - [Upgrading](#upgrading) 19 | - [From `4.*` to `5.*`](#from-4-to-5) 20 | - [From `2.*` to `3.*`](#from-2-to-3) 21 | - [From `1.*` to `2.*`](#from-1-to-2) 22 | - [Testing the Deployment](#testing-the-deployment) 23 | - [Update documentation](#update-documentation) 24 | - [Run unit tests](#run-unit-tests) 25 | 26 | ## Introduction 27 | 28 | This chart creates a single pod in a StatefulSet running Atlantis. Atlantis persists Terraform [plan files](https://www.terraform.io/docs/commands/plan.html) and [lockfiles](https://www.terraform.io/docs/state/locking.html) to disk for the duration of a Pull/Merge Request. These files are stored in a PersistentVolumeClaim to survive Pod failures. 29 | 30 | ## Prerequisites 31 | 32 | - Kubernetes 1.9+ 33 | - PersistentVolume support 34 | 35 | ## Usage 36 | 37 | The chart is distributed as an [OCI Artifact](https://helm.sh/docs/topics/registries/) as well as via a traditional [Helm Repository](https://helm.sh/docs/topics/chart_repository/). 38 | 39 | - OCI Artifact: `oci://ghcr.io/runatlantis/charts/atlantis` 40 | - Helm Repository: `https://runatlantis.github.io/helm-charts` with chart `atlantis` 41 | 42 | The installation instructions use the OCI registry. Refer to the [`helm repo`](https://helm.sh/docs/helm/helm_repo/) command documentation for information on installing charts via the traditional repository. 43 | 44 | ### Install Helm Chart 45 | 46 | ```console 47 | helm install [RELEASE_NAME] oci://ghcr.io/runatlantis/charts/atlantis 48 | ``` 49 | 50 | ## Required Configuration 51 | 52 | In order for Atlantis to start and run successfully: 53 | 54 | 1. At least one of the following sets of credentials must be defined: 55 | - `github` 56 | - `gitea` 57 | - `gitlab` 58 | - `bitbucket` 59 | - `azuredevops` 60 | 61 | Refer to [values.yaml](/charts/atlantis/values.yaml) for detailed examples. 62 | They can also be provided directly through a Kubernetes `Secret`, use the variable `vcsSecretName` to reference it. 63 | 64 | 1. Supply a value for `orgAllowlist`, e.g. `github.com/myorg/*`. 65 | 66 | ## Additional manifests 67 | 68 | It is possible to add additional manifests into a deployment, to extend the chart. One of the reason is to deploy a manifest specific to a cloud provider ( BackendConfig on GKE for example ). 69 | 70 | ```yaml 71 | extraManifests: 72 | - apiVersion: cloud.google.com/v1beta1 73 | kind: BackendConfig 74 | metadata: 75 | name: "{{ `.Release.Name` }}-test" 76 | spec: 77 | securityPolicy: 78 | name: "gcp-cloud-armor-policy-test" 79 | ``` 80 | 81 | {{ template "chart.valuesSection" . }} 82 | 83 | ## Upgrading 84 | 85 | ### From `4.*` to `5.*` 86 | 87 | A breaking change was merged on [#304](https://github.com/runatlantis/helm-charts/pull/304). 88 | This change moves the atlantis data volume to a separate PVC to allow changing the volume size without removing the statefulset. 89 | Unmistakingly, this change only bumped the minor version, released as `4.22.0`, instead of incrementing the major version. The release `5.0.0` addresses this issue. Please find the required upgrade manual steps below. 90 | 91 | #### Upgrade steps 92 | 93 | 94 | Trying to upgrade the release directly will return the following error: 95 | 96 | > Error: UPGRADE FAILED: cannot patch "atlantis" with kind StatefulSet: StatefulSet.apps "atlantis" is invalid: spec: Forbidden: updates to statefulset spec for fields other than 'replicas', 'ordinals', 'template', 'updateStrategy', 'persistentVolumeClaimRetentionPolicy' and 'minReadySeconds' are forbidden 97 | 98 | To allow the upgrade to proceed, first we need to remove the statefulset controller, copy all the data from the old volume to the new one and then cleanup. 99 | 100 | NOTE: These steps will ensure no data is lost, however during the copy process the atlantis server is unavailable and any webhooks sent to atlantis during that window are missed and won't be processed. 101 | 102 | Upgrade steps: 103 | 104 | 1. For atlantis deployments managed by GitOps solutions such as ArgoCD, disabling the automatic synchronization is required 105 | 106 | 1. Create a temporary helm configuration file named `migration-4-to-5.yaml`, the configuration includes the required settings to allow the atlantis data to be copied to the new volume before the atlantis server is started. The suggested configuration implies that the default command for atlantis has not been customized. If required, adjust the `persistentVolumeClaim.claimName` value. 107 | 108 | ```yaml 109 | command: 110 | - sh 111 | - -c 112 | - 'cp -Rv /atlantis-data-old/* "${ATLANTIS_DATA_DIR}" && exec /usr/local/bin/docker-entrypoint.sh server' 113 | 114 | extraVolumes: 115 | - name: atlantis-data-old 116 | persistentVolumeClaim: 117 | claimName: atlantis-data-atlantis-0 118 | 119 | extraVolumeMounts: 120 | - name: atlantis-data-old 121 | mountPath: /atlantis-data-old 122 | ``` 123 | 124 | 1. Delete the current statefulset without removing the atlantis pod. This can be achieved with the parameter [--cascade=orphan](https://kubernetes.io/docs/tasks/administer-cluster/use-cascading-deletion/#set-orphan-deletion-policy): 125 | 126 | NOTE: If required, adjust the namespace and the statefulset name. 127 | 128 | ```sh 129 | kubectl delete statefulsets.apps atlantis --namespace atlantis --cascade=orphan 130 | ``` 131 | 132 | 1. Deploy the new atlantis version, this will recreate the statefulset and update the atlantis pod acordingly. E.g.: 133 | 134 | ```sh 135 | helm upgrade -i atlantis runatlantis/atlantis --version 5.0.0 -f my-config.yaml -f migration-4-to-5.yaml 136 | ``` 137 | 138 | 1. Check the logs for the atlantis pod, it should show the copy process followed by start of the atlantis server. E.g.: 139 | 140 | ```json 141 | '/atlantis-data-old/atlantis.db' -> '/atlantis-data/atlantis.db' 142 | '/atlantis-data-old/bin' -> '/atlantis-data/bin' 143 | '/atlantis-data-old/existing-data.example' -> '/atlantis-data/existing-data.example' 144 | '/atlantis-data-old/plugin-cache' -> '/atlantis-data/plugin-cache' 145 | No files found in /docker-entrypoint.d/, skipping 146 | {"level":"info","ts":"2024-05-01T17:17:03.406Z","caller":"server/server.go:447","msg":"Utilizing BoltDB","json":{}} 147 | {"level":"info","ts":"2024-05-01T17:17:03.411Z","caller":"policy/conftest_client.go:153","msg":"failed to get default conftest version. Will attempt request scoped lazy loads DEFAULT_CONFTEST_VERSION not set","json":{}} 148 | {"level":"info","ts":"2024-05-01T17:17:03.413Z","caller":"server/server.go:985","msg":"Atlantis started - listening on port 4141","json":{}} 149 | {"level":"info","ts":"2024-05-01T17:17:03.413Z","caller":"scheduled/executor_service.go:51","msg":"Scheduled Executor Service started","json":{}} 150 | ``` 151 | 152 | 1. Run a second deployment without the extra configuration file. E.g.: 153 | 154 | ```sh 155 | helm upgrade -i atlantis runatlantis/atlantis --version 5.0.0 -f my-config.yaml 156 | ``` 157 | 158 | 1. Remove the old `persistentVolumeClaim`: 159 | 160 | ```sh 161 | kubectl delete persistentvolumeclaims atlantis-data-atlantis-0 --namespace atlantis 162 | ``` 163 | 164 | 1. For atlantis deployments managed by GitOps solutions such as ArgoCD, the automatic synchronization can now be enabled 165 | 166 | ### From `4.0.*` to `4.1.*` 167 | 168 | - The following value are deprecated: 169 | - `dataStorage` 170 | - `storageClassName` 171 | 172 | - In favor of the new working way: 173 | - `volumeClaim.enabled` 174 | - `volumeClaim.dataStorage` 175 | - `volumeClaim.storageClassName` 176 | 177 | ### From `2.*` to `3.*` 178 | 179 | - The following value names have been removed. They are replaced by [Server-side Repository Configuration](https://www.runatlantis.io/docs/server-side-repo-config.html) 180 | - `requireApproval` 181 | - `requireMergeable` 182 | - `allowRepoConfig` 183 | 184 | To replicate your previous configuration, run Atlantis locally with your previous flags and Atlantis will print out the equivalent repo-config, for example: 185 | 186 | ```bash 187 | $ atlantis server --allow-repo-config --require-approval --require-mergeable --gh-user=foo --gh-token=bar --repo-allowlist='*' 188 | WARNING: Flags --require-approval, --require-mergeable and --allow-repo-config have been deprecated. 189 | Create a --repo-config file with the following config instead: 190 | 191 | --- 192 | repos: 193 | - id: /.*/ 194 | apply_requirements: [approved, mergeable] 195 | allowed_overrides: [apply_requirements, workflow] 196 | allow_custom_workflows: true 197 | 198 | or use --repo-config-json='{"repos":[{"id":"/.*/", "apply_requirements":["approved", "mergeable"], "allowed_overrides":["apply_requirements","workflow"], "allow_custom_workflows":true}]}' 199 | ``` 200 | 201 | Then use this YAML in the new repoConfig value: 202 | 203 | ```yaml 204 | repoConfig: | 205 | --- 206 | repos: 207 | - id: /.*/ 208 | apply_requirements: [approved, mergeable] 209 | allowed_overrides: [apply_requirements, workflow] 210 | allow_custom_workflows: true 211 | ``` 212 | 213 | ### From `1.*` to `2.*` 214 | 215 | - The following value names have changed: 216 | - `allow_repo_config` => `allowRepoConfig` 217 | - `atlantis_data_storage` => `dataStorage` **NOTE: more than just a snake_case change** 218 | - `atlantis_data_storageClass` => `storageClassName` **NOTE: more than just a snake_case change** 219 | - `bitbucket.base_url` => `bitbucket.baseURL` 220 | 221 | ## Testing the Deployment 222 | 223 | To perform a smoke test of the deployment (i.e. ensure that the Atlantis UI is up and running): 224 | 225 | 1. Install the chart. Supply your own values file or use `test-values.yaml`, which has a minimal set of values required in order for Atlantis to start. 226 | 227 | ```bash 228 | helm install -f test-values.yaml my-atlantis oci://ghcr.io/runatlantis/charts/atlantis --debug 229 | ``` 230 | 231 | 1. Run the tests: 232 | 233 | ```bash 234 | helm test my-atlantis 235 | ``` 236 | 237 | ## Update documentation 238 | 239 | Documentation is auto-generated using [helm-docs](https://github.com/norwoodj/helm-docs). 240 | 241 | To update run the following (from the root path of the repository): 242 | 243 | 1. If required, update `charts/atlantis/README.md.gotmpl` 244 | 2. Run `make docs` 245 | 246 | ## Run unit tests 247 | 248 | From the root of the repository, run: 249 | 250 | ```sh 251 | make unit-test-run-atlantis 252 | ``` 253 | 254 | {{ template "helm-docs.versionFooter" . }} 255 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /charts/atlantis/values.yaml: -------------------------------------------------------------------------------- 1 | ## -------------------------- ## 2 | # Values to override for your instance. 3 | ## -------------------------- ## 4 | 5 | # -- Provide a name to substitute for the full names of resources. 6 | fullnameOverride: "" 7 | 8 | # -- Provide a name to substitute for the name of the chart. 9 | nameOverride: "" 10 | 11 | # -- An option to override the atlantis url, 12 | # if not using an ingress, set it to the external IP. 13 | # Check values.yaml for examples. 14 | atlantisUrl: "" 15 | # Example: http://10.0.0.0 16 | 17 | # -- Replace this with your own repo allowlist. 18 | orgAllowlist: "" 19 | 20 | # -- Deprecated in favor of orgAllowlist. 21 | orgWhitelist: "" 22 | 23 | # -- Specify the log level for Atlantis. 24 | # Accepts: debug, info, warn, or error. 25 | logLevel: "" 26 | 27 | # -- If using GitHub, please enter your values as follows. 28 | # The chart will perform the base64 encoding for values that are stored in secrets. 29 | # The 'hostname' key is exclusive to GitHub Enterprise installations. 30 | # Check values.yaml for examples. 31 | github: {} 32 | # github: 33 | # user: foo 34 | # token: bar 35 | # secret: baz 36 | # hostname: github.your.org 37 | 38 | # -- If using a GitHub App, please enter your values as follows. 39 | # The chart will perform the base64 encoding for you for values that are stored in secrets. 40 | # installationId is necessary when there are multiple installs of the Github App. 41 | # Check values.yaml for examples. 42 | githubApp: {} 43 | # githubApp: 44 | # id: 123456 45 | # installationId: 1 46 | # slug: foo 47 | # key: | 48 | # -----BEGIN PRIVATE KEY----- 49 | # ... 50 | # -----END PRIVATE KEY----- 51 | # secret: baz 52 | 53 | # -- If using Gitea, please enter your values as follows. 54 | # The 'baseUrl' key is exclusive to self-hosted Gitea installations. 55 | # The chart will perform the base64 encoding for you for values that are stored in secrets. 56 | # Check values.yaml for examples. 57 | gitea: {} 58 | # gitea: 59 | # user: foo 60 | # token: bar 61 | # secret: baz 62 | # baseUrl: gitea.your.org 63 | 64 | # -- If using GitLab, please enter your values as follows. 65 | # The 'hostname' key is exclusive to GitLab Enterprise installations. 66 | # The chart will perform the base64 encoding for you for values that are stored in secrets. 67 | # Check values.yaml for examples. 68 | gitlab: {} 69 | # gitlab: 70 | # user: foo 71 | # token: bar 72 | # secret: baz 73 | # hostname: gitlab.your.org 74 | 75 | # -- If using Bitbucket, there are two approaches: 76 | # Bitbucket Server, deployed in your own infrastructure 77 | # and Cloud available at (https://Bitbucket.org). 78 | # The chart will perform the base64 encoding for you for values that are stored in secrets. 79 | # Check values.yaml for examples. 80 | bitbucket: {} 81 | 82 | # Bitbucket Server 83 | # bitbucket: 84 | # user: foo 85 | # token: bar 86 | # secret: baz 87 | # baseURL: https://bitbucket.yourorganization.com 88 | 89 | # Bitbucket Cloud 90 | # The recommendation is to genarate a service user on your cloud environment, but you can live on the edge using your own user :). 91 | # Create an APP PASSWORD to the user for the token value. 92 | # Base URL are not needed here, but keep in mind to provide an IP Whitelist as the Atlantis documentation. 93 | # bitbucket: 94 | # user: foo 95 | # token: bar 96 | 97 | # -- If using Azure DevOps, please enter your values as follows. 98 | # The chart will perform the base64 encoding for you for values that are stored in secrets. 99 | # Check values.yaml for examples. 100 | azuredevops: {} 101 | # azuredevops: 102 | # user: foo 103 | # token: bar 104 | # webhookUser: foo 105 | # webhookPassword: baz 106 | 107 | # -- If managing secrets outside the chart for the webhook, use this variable to reference the secret name 108 | vcsSecretName: "" 109 | 110 | # -- When referencing Terraform modules in private repositories, it may be helpful 111 | # (necessary?) to use redirection in a .gitconfig. 112 | # Check values.yaml for examples. 113 | gitconfig: "" 114 | # gitconfig: | 115 | # [url "https://YOUR_GH_TOKEN@github.com"] 116 | # insteadOf = https://github.com 117 | # [url "https://YOUR_GH_TOKEN@github.com"] 118 | # insteadOf = ssh://git@github.com 119 | # [url "https://oauth2:YOUR_GITLAB_TOKEN@gitlab.com"] 120 | # insteadOf = https://gitlab.com 121 | # [url "https://oauth2:YOUR_GITLAB_TOKEN@gitlab.com"] 122 | # insteadOf = ssh://git@gitlab.com 123 | # Source: https://stackoverflow.com/questions/42148841/github-clone-with-oauth-access-token 124 | 125 | # -- When true gitconfig file is mounted as read only. 126 | # When false, the gitconfig value will be copied to '/home/atlantis/.gitconfig' before starting the atlantis process, 127 | # instead of being mounted as a file. 128 | gitconfigReadOnly: true 129 | 130 | # -- If managing secrets outside the chart for the gitconfig, use this variable to reference the secret name 131 | gitconfigSecretName: "" 132 | 133 | # -- When referencing Terraform modules in private repositories or registries (such as Artfactory) 134 | # configuing a .netrc file for authentication may be required. 135 | # Check values.yaml for examples. 136 | netrc: "" 137 | # netrc: | 138 | # machine artifactory.myapp.com login YOUR_USERNAME password YOUR_PASSWORD 139 | # machine bitbucket.myapp.com login YOUR_USERNAME password YOUR_PASSWORD 140 | 141 | # -- If managing secrets outside the chart for the netrc file, use this variable to reference the secret name 142 | netrcSecretName: "" 143 | 144 | # -- To specify AWS credentials to be mapped to ~/.aws or to aws.directory. 145 | # Check values.yaml for examples. 146 | aws: {} 147 | # aws: 148 | # credentials: | 149 | # [default] 150 | # aws_access_key_id=YOUR_ACCESS_KEY_ID 151 | # aws_secret_access_key=YOUR_SECRET_ACCESS_KEY 152 | # region=us-east-1 153 | # config: | 154 | # [profile a_role_to_assume] 155 | # role_arn = arn:aws:iam::123456789:role/service-role/roleToAssume 156 | # source_profile = default 157 | # directory: "/home/atlantis/.aws" 158 | 159 | # -- To reference an already existing Secret object with AWS credentials 160 | awsSecretName: "" 161 | 162 | # -- To keep backwards compatibility only. 163 | # Deprecated (see googleServiceAccountSecrets). 164 | # To be used for mounting credential files (when using google provider). 165 | # Check values.yaml for examples. 166 | serviceAccountSecrets: {} 167 | # serviceAccountSecrets: 168 | # credentials: 169 | # credentials-staging: 170 | 171 | ## -------------------------- ## 172 | # Default values for atlantis (override as needed). 173 | ## -------------------------- ## 174 | 175 | # -- (int) [optional] Define the port you would like atlantis to run on. When 0, the value of service.targetPort is used. 176 | containerPort: 0 177 | 178 | image: 179 | repository: ghcr.io/runatlantis/atlantis 180 | # -- If not set appVersion field from Chart.yaml is used 181 | tag: "" 182 | pullPolicy: Always 183 | 184 | # -- Optionally specify an array of imagePullSecrets. 185 | # Secrets must be manually created in the namespace. 186 | # ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/. 187 | # Check values.yaml for examples. 188 | imagePullSecrets: [] 189 | # imagePullSecrets: 190 | # - myRegistryKeySecretName 191 | 192 | # -- Override atlantis main configuration by config map, 193 | # ref: https://www.runatlantis.io/docs/using-slack-hooks.html#configuring-atlantis. 194 | # Check values.yaml for examples. 195 | config: "" 196 | # config: | 197 | # --- 198 | # webhooks: 199 | # - event: apply 200 | # workspace-regex: .* 201 | # branch-regex: .* 202 | # kind: slack 203 | # channel: my-channel 204 | 205 | # -- Use Server Side Repo Config, 206 | # ref: https://www.runatlantis.io/docs/server-side-repo-config.html. 207 | # Check values.yaml for examples. 208 | repoConfig: "" 209 | # Example with default configuration: 210 | # repoConfig: | 211 | # --- 212 | # repos: 213 | # - id: /.*/ 214 | # apply_requirements: [] 215 | # workflow: default 216 | # allowed_overrides: [] 217 | # allow_custom_workflows: false 218 | # workflows: 219 | # default: 220 | # plan: 221 | # steps: [init, plan] 222 | # apply: 223 | # steps: [apply] 224 | # metrics: 225 | # prometheus: 226 | # endpoint: /metrics 227 | 228 | # -- Enables atlantis to run on a fork Pull Requests. 229 | allowForkPRs: false 230 | 231 | # -- Enables atlantis to run on a draft Pull Requests. 232 | allowDraftPRs: false 233 | 234 | # -- Enables atlantis to hide previous plan comments. 235 | hidePrevPlanComments: false 236 | 237 | # -- Enables atlantis to hide no-changes plan comments from the pull request. 238 | hideUnchangedPlanComments: false 239 | 240 | # -- Sets the default terraform distribution to use. Can be set to terraform or opentofu. 241 | defaultTFDistribution: terraform 242 | 243 | # -- Sets the default terraform version to be used in atlantis server. 244 | # Check values.yaml for examples. 245 | defaultTFVersion: "" 246 | # Example: "0.12.0". 247 | 248 | # -- Disables running `atlantis apply` regardless of which flags are sent with it. 249 | disableApply: false 250 | 251 | # -- Disables running `atlantis apply` without any flags. 252 | disableApplyAll: false 253 | 254 | # -- Stops atlantis locking projects and or workspaces when running terraform. 255 | disableRepoLocking: false 256 | 257 | # -- Use Diff Markdown Format for color coding diffs. 258 | enableDiffMarkdownFormat: false 259 | 260 | # -- Optionally specify an username and a password for basic authentication. 261 | basicAuth: 262 | username: "" 263 | password: "" 264 | 265 | # -- If managing secrets outside the chart for the Basic Auth secret, use this variable to reference the secret name. 266 | basicAuthSecretName: "" 267 | 268 | # -- Optionally specify an API secret to enable the API. 269 | # Check values.yaml for examples. 270 | api: {} 271 | # api: 272 | # secret: "s3cr3t" 273 | 274 | # -- If managing secrets outside the chart for the API secret, use this variable to reference the secret name. The key containing the secret must be called 'apisecret'. 275 | apiSecretName: "" 276 | 277 | # -- Override the command field of the Atlantis container. 278 | command: [] 279 | 280 | # -- Common Labels for all resources created by this chart. 281 | commonLabels: {} 282 | 283 | livenessProbe: 284 | enabled: true 285 | # -- We only need to check every 60s since Atlantis is not a high-throughput service. 286 | periodSeconds: 60 287 | initialDelaySeconds: 5 288 | timeoutSeconds: 5 289 | successThreshold: 1 290 | failureThreshold: 5 291 | scheme: HTTP 292 | 293 | readinessProbe: 294 | enabled: true 295 | periodSeconds: 60 296 | initialDelaySeconds: 5 297 | timeoutSeconds: 5 298 | successThreshold: 1 299 | failureThreshold: 5 300 | scheme: HTTP 301 | 302 | service: 303 | type: NodePort 304 | annotations: {} 305 | port: 80 306 | portName: atlantis 307 | nodePort: null 308 | # -- (int) [optional] Define the port you would like atlantis to run on. Defaults to 4141. 309 | targetPort: 4141 310 | loadBalancerIP: null 311 | loadBalancerSourceRanges: [] 312 | externalTrafficPolicy: null 313 | 314 | podTemplate: 315 | # -- Check values.yaml for examples. 316 | annotations: {} 317 | # annotations: 318 | # iam.amazonaws.com/role: role-arn # kube2iam example. 319 | labels: {} 320 | 321 | statefulSet: 322 | annotations: {} 323 | labels: {} 324 | securityContext: 325 | fsGroup: 1000 326 | # -- It is not recommended to run atlantis as root. 327 | runAsUser: 100 328 | fsGroupChangePolicy: "OnRootMismatch" 329 | priorityClassName: "" 330 | updateStrategy: {} 331 | # -- Option to share process namespace with atlantis container. 332 | shareProcessNamespace: false 333 | 334 | ingress: 335 | enabled: true 336 | ingressClassName: 337 | apiVersion: "" 338 | labels: {} 339 | # -- Check values.yaml for examples. 340 | annotations: {} 341 | # annotations: 342 | # kubernetes.io/ingress.class: nginx 343 | # kubernetes.io/tls-acme: "true" 344 | # -- Use / for nginx. 345 | path: /* 346 | # -- Used when several paths under the same host, with different backend services, are required. 347 | # Check values.yaml for examples. 348 | paths: [] 349 | # - path: "/path1" 350 | # service: test1 351 | # port: 352 | # - path: "/path2" 353 | # service: test2 354 | # port: 355 | pathType: ImplementationSpecific 356 | host: "" 357 | # -- Used when several hosts are required. 358 | # Check values.yaml for examples. 359 | hosts: [] 360 | # - host: chart-example.local 361 | # paths: ["/"] 362 | # service: chart-example1 363 | # - host: chart-example.local2 364 | # service: chart-example1 365 | # paths: ["/lala"] 366 | # -- Check values.yaml for examples. 367 | tls: [] 368 | # - secretName: chart-example-tls 369 | # hosts: 370 | # - chart-example.local 371 | 372 | webhook_ingress: 373 | # -- When true creates a secondary webhook. 374 | enabled: false 375 | ingressClassName: 376 | apiVersion: "" 377 | # -- Check values.yaml for examples. 378 | annotations: {} 379 | # annotations: 380 | # kubernetes.io/ingress.class: nginx 381 | # kubernetes.io/tls-acme: "true" 382 | # -- Use / for nginx. 383 | path: /* 384 | # -- Used when several paths under the same host, with different backend services, are required. 385 | # Check values.yaml for examples. 386 | paths: [] 387 | # - path: "/path1" 388 | # service: test1 389 | # port: 390 | # - path: "/path2" 391 | # service: test2 392 | # port: 393 | pathType: ImplementationSpecific 394 | host: "" 395 | # -- Used when several hosts are required. 396 | # Check values.yaml for examples. 397 | hosts: [] 398 | # - host: chart-example.local 399 | # paths: ["/"] 400 | # service: chart-example1 401 | # - host: chart-example.local2 402 | # service: chart-example1 403 | # paths: ["/lala"] 404 | # -- TLS configuration. 405 | # Check values.yaml for examples. 406 | tls: [] 407 | # - secretName: chart-example-tls 408 | # hosts: 409 | # - chart-example.local 410 | labels: {} 411 | 412 | # -- Allows to override the /etc/ssl/certs/ca-certificates.cer with your custom one. 413 | # You have to create a secret with the specified name. 414 | customPem: "" 415 | 416 | # -- Resources for Atlantis. 417 | # Check values.yaml for examples. 418 | resources: {} 419 | # resources: 420 | # requests: 421 | # memory: 1Gi 422 | # cpu: 100m 423 | # limits: 424 | # memory: 1Gi 425 | # cpu: 100m 426 | 427 | # -- Path to the data directory for the volumeMount. 428 | atlantisDataDirectory: /atlantis-data 429 | 430 | volumeClaim: 431 | enabled: true 432 | # -- Disk space available to check out repositories. 433 | dataStorage: 5Gi 434 | # -- Storage class name (if possible, use a resizable one). 435 | storageClassName: "" 436 | accessModes: ["ReadWriteOnce"] 437 | 438 | # -- DEPRECATED - Disk space available to check out repositories. 439 | # Example: 5Gi. 440 | dataStorage: "" 441 | # -- DEPRECATED - Storage class name for Atlantis disk. 442 | storageClassName: "" 443 | 444 | # -- Replica count for Atlantis pods. 445 | replicaCount: 1 446 | 447 | test: 448 | # -- Enables test container. 449 | enabled: true 450 | image: bats/bats 451 | imageTag: 1.9.0 452 | annotations: {} 453 | 454 | nodeSelector: {} 455 | 456 | tolerations: [] 457 | 458 | affinity: {} 459 | 460 | # -- You can use topology spread constraints to control how Pods are spread across your cluster among failure-domains such as regions, 461 | # zones, nodes, and other user-defined topology domains. (requires Kubernetes >= 1.19). 462 | # Check values.yaml for examples. 463 | topologySpreadConstraints: [] 464 | # - labelSelector: 465 | # matchLabels: 466 | # app.kubernetes.io/name: aws-example-cluster 467 | # maxSkew: 1 468 | # topologyKey: topology.kubernetes.io/zone 469 | # whenUnsatisfiable: DoNotSchedule 470 | 471 | serviceAccount: 472 | # -- Specifies whether a ServiceAccount should be created. 473 | create: true 474 | # -- Set the `automountServiceAccountToken` field on the pod template spec. 475 | # -- If false, no kubernetes service account token will be mounted to the pod. 476 | mount: true 477 | # -- The name of the ServiceAccount to use. 478 | # If not set and create is true, a name is generated using the fullname template. 479 | name: null 480 | # -- Annotations for the Service Account. 481 | # Check values.yaml for examples. 482 | annotations: {} 483 | # annotations: 484 | # annotation1: value 485 | # annotation2: value 486 | # IRSA example: 487 | # annotations: 488 | # eks.amazonaws.com/role-arn: role-arn 489 | 490 | # -- Optionally deploy rbac to allow for the serviceAccount to manage terraform state via the kubernetes backend. 491 | enableKubernetesBackend: false 492 | 493 | # -- TLS Secret Name for Atlantis pod. 494 | tlsSecretName: "" 495 | 496 | # -- Additional path (`:` separated) that will be appended to the system `PATH` environment variable. 497 | extraPath: "" 498 | 499 | # -- Environment values to add to the Atlantis pod. 500 | # Check values.yaml for examples. 501 | environment: {} 502 | # environment: 503 | # ATLANTIS_DEFAULT_TF_VERSION: v1.2.9 504 | 505 | # -- Optionally specify additional environment variables to be populated from Kubernetes secrets. 506 | # Useful for passing in TF_VAR_foo or other secret environment variables from Kubernetes secrets. 507 | # Check values.yaml for examples. 508 | environmentSecrets: [] 509 | # environmentSecrets: 510 | # - name: THE_ENV_VAR 511 | # secretKeyRef: 512 | # name: the_k8s_secret_name 513 | # key: the_key_of_the_value_in_the_secret 514 | 515 | # -- Optionally specify additional environment variables in raw yaml format. 516 | # Useful to specify variables refering to k8s objects. 517 | # Check values.yaml for examples. 518 | environmentRaw: [] 519 | # environmentRaw: 520 | # - name: POD_IP 521 | # valueFrom: 522 | # fieldRef: 523 | # fieldPath: status.podIP 524 | 525 | # -- Optionally specify additional Kubernetes secrets to load environment variables from. 526 | # All key-value pairs within these secrets will be set as environment variables. 527 | # Note that any variables set here will be ignored if also defined in the env block of the atlantis statefulset. 528 | # For example, providing ATLANTIS_GH_USER here and defining a value for github.user will result in the github.user value being used. 529 | # Check values.yaml for examples. 530 | loadEnvFromSecrets: [] 531 | # loadEnvFromSecrets: 532 | # - secret_one 533 | # - secret_two 534 | 535 | # -- Optionally specify additional Kubernetes ConfigMaps to load environment variables from. 536 | # All key-value pairs within these ConfigMaps will be set as environment variables. 537 | # Note that any variables set here will be ignored if also defined in the env block of the atlantis statefulset. 538 | # For example, providing ATLANTIS_ALLOW_FORK_PRS here and defining a value for allowForkPRs will result in the allowForkPRs value being used. 539 | # Check values.yaml for examples. 540 | loadEnvFromConfigMaps: [] 541 | # loadEnvFromConfigMaps: 542 | # - config_one 543 | # - config_two 544 | 545 | # -- Optionally specify google service account credentials as Kubernetes secrets. If you are using the terraform google provider you can specify the credentials as "${file("/var/secrets/some-secret-name/key.json")}". 546 | # Check values.yaml for examples. 547 | googleServiceAccountSecrets: [] 548 | # googleServiceAccountSecrets: 549 | # - name: some-secret-name 550 | # secretName: the_k8s_secret_name 551 | 552 | # -- Optionally specify additional volumes for the pod. 553 | # Check values.yaml for examples. 554 | extraVolumes: [] 555 | # extraVolumes: 556 | # - name: some-volume-name 557 | # emptyDir: {} 558 | 559 | # -- Optionally specify additional volume mounts for the container. 560 | # Check values.yaml for examples. 561 | extraVolumeMounts: [] 562 | # extraVolumeMounts: 563 | # - name: some-volume-name 564 | # mountPath: /path/in/container 565 | 566 | # -- Optionally specify additional manifests to be created. 567 | # Check values.yaml for examples. 568 | extraManifests: [] 569 | # extraManifests: 570 | # - apiVersion: cloud.google.com/v1beta1 571 | # kind: BackendConfig 572 | # metadata: 573 | # name: "{{ .Release.Name }}-test" 574 | # spec: 575 | # securityPolicy: 576 | # name: "gcp-cloud-armor-policy-test" 577 | 578 | # -- Optionally specify init containers manifests to be added to the Atlantis pod. 579 | # Check values.yaml for examples. 580 | initContainers: [] 581 | # initContainers: 582 | # - name: example 583 | # image: alpine:latest 584 | # command: ['sh', '-c', 'echo The init container is running! && sleep 10'] 585 | 586 | initConfig: 587 | # -- Install providers/plugins into a path shared with the Atlantis pod. 588 | enabled: false 589 | image: alpine:latest 590 | imagePullPolicy: IfNotPresent 591 | # -- SharedDir is set as env var INIT_SHARED_DIR. 592 | sharedDir: /plugins 593 | sharedDirReadOnly: true 594 | workDir: /tmp 595 | # -- Size for the shared volume. 596 | sizeLimit: 300Mi 597 | # -- Security context for the container. 598 | containerSecurityContext: {} 599 | # -- Script to run on the init container. 600 | # @default -- Check values.yaml. 601 | script: | 602 | #!/bin/sh 603 | set -eoux pipefail 604 | 605 | # example for terragrunt 606 | TG_VERSION="v0.67.5" 607 | TG_SHA256_SUM="4e5ae67854a774be6419f7215733990b481662375dc0bd5f2eda05211a692cf0" 608 | TG_FILE="${INIT_SHARED_DIR}/terragrunt" 609 | wget https://github.com/gruntwork-io/terragrunt/releases/download/${TG_VERSION}/terragrunt_linux_amd64 -O "${TG_FILE}" 610 | echo "${TG_SHA256_SUM} ${TG_FILE}" | sha256sum -c 611 | chmod 755 "${TG_FILE}" 612 | terragrunt -v 613 | 614 | # example for terragrunt-atlantis-config 615 | TAC_VERSION="1.18.0" # without v 616 | TAC_SHA256_SUM="59178dcd3e426abf4b5d8fcb1ac8dbdea548a04aa64eaf39be200484a5e6f2ca" 617 | TAC_FILE="${INIT_SHARED_DIR}/terragrunt-atlantis-config" 618 | wget "https://github.com/transcend-io/terragrunt-atlantis-config/releases/download/v${TAC_VERSION}/terragrunt-atlantis-config_${TAC_VERSION}_linux_amd64" 619 | echo "${TAC_SHA256_SUM} terragrunt-atlantis-config_${TAC_VERSION}_linux_amd64" | sha256sum -c 620 | cp -fv "terragrunt-atlantis-config_${TAC_VERSION}_linux_amd64" "${TAC_FILE}" 621 | chmod 755 "${TAC_FILE}" 622 | terragrunt-atlantis-config version 623 | 624 | # -- Optionally specify hostAliases for the Atlantis pod. 625 | # Check values.yaml for examples. 626 | hostAliases: [] 627 | # hostAliases: 628 | # - hostnames: 629 | # - aaa.com 630 | # - test.ccc.com 631 | # ip: 10.0.0.0 632 | # - hostnames: 633 | # - bbb.com 634 | # ip: 10.0.0.2 635 | 636 | # -- Optionally specify dnsPolicy parameter to specify a DNS policy for a pod 637 | # Check https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy 638 | dnsPolicy: "ClusterFirst" 639 | 640 | # -- Optionally specify dnsConfig for the Atlantis pod. 641 | # Check values.yaml for examples. 642 | dnsConfig: {} 643 | # dnsConfig: 644 | # nameservers: 645 | # - 8.8.8.8 646 | # searches: 647 | # - mydomain.com 648 | 649 | hostNetwork: false 650 | 651 | secret: 652 | # -- Annotations for the Secrets. 653 | # Check values.yaml for examples. 654 | annotations: {} 655 | # annotations: 656 | # annotation1: value 657 | # annotation2: value 658 | 659 | # -- These annotations will be added to all the resources. 660 | # Check values.yaml for examples. 661 | extraAnnotations: {} 662 | # extraAnnotations: 663 | # team: example 664 | 665 | # -- Optionally specify extra arguments for the Atlantis pod. 666 | # Check values.yaml for examples. 667 | extraArgs: [] 668 | # extraArgs: 669 | # - --disable-autoplan 670 | # - --disable-repo-locking 671 | 672 | # -- Optionally specify extra containers for the Atlantis pod. 673 | # Check values.yaml for examples. 674 | extraContainers: [] 675 | # extraContainers: 676 | # - name: 677 | # args: 678 | # - ... 679 | # image: 680 | # imagePullPolicy: IfNotPresent 681 | # resources: 682 | # limits: 683 | # memory: 128Mi 684 | # requests: 685 | # cpu: 100m 686 | # memory: 128Mi 687 | # volumeMounts: 688 | # - ... 689 | 690 | # -- Check values.yaml for examples. 691 | containerSecurityContext: {} 692 | # containerSecurityContext: 693 | # allowPrivilegeEscalation: false 694 | # readOnlyRootFilesystem: true 695 | 696 | servicemonitor: 697 | # -- To enable a Prometheus servicemonitor, set enabled to true, 698 | # and enable the metrics in this file's repoConfig 699 | # by setting a value for metrics.prometheus.endpoint. 700 | enabled: false 701 | interval: "30s" 702 | path: /metrics 703 | # -- Prometheus ServiceMonitor labels. 704 | additionalLabels: {} 705 | auth: 706 | # -- If auth is enabled on Atlantis, use one of the following mechanism. 707 | basicAuth: 708 | # -- Authentication from the secret generated with the basicAuth values 709 | # this will reference the username and password keys 710 | # from the atlantis-basic-auth secret. 711 | enabled: false 712 | externalSecret: 713 | # -- Authentication based on an external secret 714 | enabled: false 715 | name: "" 716 | # -- Check values.yaml for examples. 717 | keys: {} 718 | # keys: 719 | # username: USERNAME 720 | # password: ATLANTIS_WEB_PASSWORD 721 | # -- Optional metric relabelings to drop or modify metrics. 722 | metricRelabelings: [] 723 | # metricRelabelings: 724 | # - action: drop 725 | # regex: "atlantis_project_apply_execution_.*" 726 | # sourceLabels: [__name__] 727 | 728 | # -- Enable this if you're using Google Managed Prometheus. 729 | podMonitor: 730 | enabled: false 731 | interval: "30s" 732 | metricRelabeling: [] 733 | 734 | # -- Set the desired Locking DB type 735 | # Accepts boltdb or redis. 736 | lockingDbType: "" 737 | 738 | # -- Configure Redis Locking DB. 739 | # lockingDbType value must be redis for the config to take effect. 740 | # Check values.yaml for examples. 741 | redis: {} 742 | # redis: 743 | # host: redis.host.name 744 | # password: myRedisPassword 745 | # port: 6379 746 | # db: 0 747 | # tlsEnabled: false 748 | # insecureSkipVerify: false 749 | 750 | # -- When managing secrets outside the chart for the Redis secret, use this variable to reference the secret name. 751 | redisSecretName: "" 752 | 753 | # -- Key within the existing Redis secret that contains the password value. 754 | redisSecretPasswordKey: password 755 | 756 | # -- (int) Optionally customize the termination grace period in seconds. 757 | # @default -- default depends on the kubernetes version. 758 | terminationGracePeriodSeconds: 759 | # terminationGracePeriodSeconds: 300 760 | 761 | # -- Set lifecycle hooks. 762 | # https://kubernetes.io/docs/tasks/configure-pod-container/attach-handler-lifecycle-event/. 763 | lifecycle: {} 764 | # lifecycle: 765 | # preStop: 766 | # exec: 767 | # command: 768 | # - /bin/sh 769 | # - -c 770 | # - while pgrep -x "terraform|tofu|terragrunt" > /dev/null; do sleep 1; done 771 | -------------------------------------------------------------------------------- /charts/atlantis/templates/statefulset.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: StatefulSet 3 | metadata: 4 | name: {{ template "atlantis.fullname" . }} 5 | namespace: {{ .Release.Namespace }} 6 | labels: 7 | {{- include "atlantis.labels" . | nindent 4 }} 8 | {{- with .Values.statefulSet.labels }} 9 | {{- toYaml . | nindent 4 }} 10 | {{- end }} 11 | {{- if or .Values.statefulSet.annotations .Values.extraAnnotations }} 12 | annotations: 13 | {{- with .Values.statefulSet.annotations }} 14 | {{- toYaml . | nindent 4 }} 15 | {{- end }} 16 | {{- with .Values.extraAnnotations }} 17 | {{- toYaml . | nindent 4 }} 18 | {{- end }} 19 | {{- end }} 20 | spec: 21 | serviceName: {{ template "atlantis.fullname" . }} 22 | replicas: {{ .Values.replicaCount }} 23 | selector: 24 | matchLabels: 25 | app: {{ template "atlantis.name" . }} 26 | release: {{ .Release.Name }} 27 | template: 28 | metadata: 29 | labels: 30 | app: {{ template "atlantis.name" . }} 31 | release: {{ .Release.Name }} 32 | {{- if .Values.podTemplate.labels }} 33 | {{- toYaml .Values.podTemplate.labels | nindent 8 }} 34 | {{- end }} 35 | annotations: 36 | checksum/config: {{ include (print $.Template.BasePath "/configmap-config.yaml") . | sha256sum }} 37 | checksum/repo-config: {{ include (print $.Template.BasePath "/configmap-repo-config.yaml") . | sha256sum }} 38 | {{- if .Values.initConfig.enabled }} 39 | checksum/init-config: {{ include (print $.Template.BasePath "/configmap-init-config.yaml") . | sha256sum }} 40 | {{- end }} 41 | {{- if .Values.podTemplate.annotations }} 42 | {{- toYaml .Values.podTemplate.annotations | nindent 8 }} 43 | {{- end }} 44 | spec: 45 | {{- if and (or .Values.dnsPolicy (and .Values.dnsPolicy .Values.dnsConfig)) (ne .Values.dnsPolicy "ClusterFirst") }} 46 | dnsPolicy: {{ .Values.dnsPolicy}} 47 | {{- end }} 48 | {{- if or .Values.dnsConfig (eq .Values.dnsPolicy "None") }} 49 | {{- if not .Values.dnsConfig }} 50 | {{- fail "dnsPolicy is set to 'None', but dnsConfig is not provided" }} 51 | {{- end }} 52 | dnsConfig: 53 | nameservers: 54 | {{- range .Values.dnsConfig.nameservers }} 55 | - {{ . }} 56 | {{- end }} 57 | {{- if .Values.dnsConfig.searches }} 58 | searches: 59 | {{- range .Values.dnsConfig.searches }} 60 | - {{ . }} 61 | {{- end }} 62 | {{- end }} 63 | {{- end }} 64 | {{- if .Values.hostAliases }} 65 | hostAliases: 66 | {{- range .Values.hostAliases }} 67 | - hostnames: 68 | {{- range .hostnames }} 69 | - {{ . }} 70 | {{- end }} 71 | ip: {{ .ip }} 72 | {{- end }} 73 | {{- end }} 74 | hostNetwork: {{ .Values.hostNetwork }} 75 | serviceAccountName: {{ template "atlantis.serviceAccountName" . }} 76 | shareProcessNamespace: {{ .Values.statefulSet.shareProcessNamespace }} 77 | automountServiceAccountToken: {{ .Values.serviceAccount.mount }} 78 | {{- if .Values.terminationGracePeriodSeconds }} 79 | terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }} 80 | {{- end }} 81 | securityContext: {{ .Values.statefulSet.securityContext | toYaml | nindent 8 }} 82 | {{- if .Values.statefulSet.priorityClassName }} 83 | priorityClassName: {{ .Values.statefulSet.priorityClassName }} 84 | {{- end }} 85 | volumes: 86 | {{- if and .Values.volumeClaim.enabled ( not .Values.dataStorage ) }} 87 | - name : atlantis-data 88 | persistentVolumeClaim: 89 | claimName: {{ template "atlantis.fullname" . }}-data 90 | {{- end }} 91 | {{- if .Values.tlsSecretName }} 92 | - name: tls 93 | secret: 94 | secretName: {{ .Values.tlsSecretName }} 95 | {{- end }} 96 | {{- range $name, $_ := .Values.serviceAccountSecrets }} 97 | - name: {{ $name }}-volume 98 | secret: 99 | secretName: {{ $name }} 100 | {{- end }} 101 | {{- range .Values.googleServiceAccountSecrets }} 102 | - name: {{ .name }} 103 | secret: 104 | secretName: {{ .secretName }} 105 | {{- end }} 106 | {{- if .Values.gitconfig }} 107 | - name: gitconfig-volume 108 | secret: 109 | secretName: {{ template "atlantis.fullname" . }}-gitconfig 110 | {{- else if .Values.gitconfigSecretName }} 111 | - name: gitconfig-volume 112 | secret: 113 | secretName: {{ .Values.gitconfigSecretName }} 114 | {{- end }} 115 | {{- if not .Values.gitconfigReadOnly }} 116 | - name: gitconfig-init 117 | configMap: 118 | name: {{ template "atlantis.fullname" . }}-gitconfig-init 119 | items: 120 | - key: gitconfig-init.sh 121 | path: gitconfig-init.sh 122 | mode: 0555 123 | {{- end }} 124 | {{- if .Values.netrc }} 125 | - name: netrc-volume 126 | secret: 127 | secretName: {{ template "atlantis.fullname" . }}-netrc 128 | {{- else if .Values.netrcSecretName }} 129 | - name: netrc-volume 130 | secret: 131 | secretName: {{ .Values.netrcSecretName }} 132 | {{- end }} 133 | {{- if or .Values.aws.credentials .Values.aws.config .Values.awsSecretName }} 134 | - name: aws-volume 135 | secret: 136 | secretName: {{ template "atlantis.awsSecretName" . }} 137 | {{- end }} 138 | {{- if .Values.githubApp }} 139 | {{- if or .Values.githubApp.key .Values.vcsSecretName}} 140 | - name: github-app-key-volume 141 | secret: 142 | secretName: {{ template "atlantis.vcsSecretName" . }} 143 | items: 144 | - key: key.pem 145 | path: key.pem 146 | {{- end }} 147 | {{- end }} 148 | {{- if .Values.repoConfig }} 149 | - name: repo-config 150 | configMap: 151 | name: {{ template "atlantis.fullname" . }}-repo-config 152 | {{- end }} 153 | {{- if .Values.config }} 154 | - name: config 155 | configMap: 156 | name: {{ template "atlantis.fullname" . }} 157 | {{- end }} 158 | {{- if .Values.containerSecurityContext.readOnlyRootFilesystem }} 159 | - name: atlantis-home-dir 160 | emptyDir: {} 161 | - name: tmp-dir 162 | emptyDir: {} 163 | {{- end }} 164 | {{- if .Values.customPem }} 165 | - name: additional-trust-certs 166 | secret: 167 | secretName: {{ .Values.customPem }} 168 | {{- end }} 169 | {{- if .Values.extraVolumes }} 170 | {{- toYaml .Values.extraVolumes | nindent 6 }} 171 | {{- end }} 172 | {{- if .Values.initConfig.enabled }} 173 | - name: init-config 174 | configMap: 175 | name: {{ template "atlantis.fullname" . }}-init-config 176 | items: 177 | - key: init-config.sh 178 | path: init-config.sh 179 | mode: 0555 180 | - name: init-shared-path 181 | emptyDir: 182 | sizeLimit: {{ .Values.initConfig.sizeLimit }} 183 | {{- end }} 184 | {{- if .Values.imagePullSecrets }} 185 | imagePullSecrets: 186 | {{- range .Values.imagePullSecrets }} 187 | - name: {{ . }} 188 | {{- end }} 189 | {{- end }} 190 | {{- if or .Values.initContainers .Values.initConfig.enabled }} 191 | initContainers: 192 | {{- with .Values.initContainers }} 193 | {{- toYaml . | nindent 8 }} 194 | {{- end }} 195 | {{- if .Values.initConfig.enabled }} 196 | - name: init-config 197 | image: {{ .Values.initConfig.image }} 198 | imagePullPolicy: {{ .Values.initConfig.pullPolicy }} 199 | command: 200 | - /init-config.sh 201 | workingDir: {{ .Values.initConfig.workDir }} 202 | env: 203 | - name: PATH 204 | value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:{{ .Values.initConfig.sharedDir }} 205 | - name: INIT_SHARED_DIR 206 | value: {{ .Values.initConfig.sharedDir }} 207 | volumeMounts: 208 | - name: init-config 209 | mountPath: /init-config.sh 210 | subPath: init-config.sh 211 | - name: init-shared-path 212 | mountPath: {{ .Values.initConfig.sharedDir }} 213 | {{- if .Values.initConfig.containerSecurityContext }} 214 | securityContext: {{- toYaml .Values.initConfig.containerSecurityContext | nindent 12 }} 215 | {{- end }} 216 | {{- end }} 217 | {{- end }} 218 | containers: 219 | - name: {{ .Chart.Name }} 220 | image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" 221 | imagePullPolicy: {{ .Values.image.pullPolicy }} 222 | {{- if .Values.containerSecurityContext }} 223 | securityContext: {{- toYaml .Values.containerSecurityContext | nindent 12 }} 224 | {{- end }} 225 | {{- if .Values.command }} 226 | command: 227 | {{- range .Values.command }} 228 | - {{ . }} 229 | {{- end }} 230 | {{- end }} 231 | args: 232 | - server 233 | {{- if .Values.config }} 234 | - --config=/etc/atlantis/atlantis.yaml 235 | {{- end }} 236 | {{- if .Values.extraArgs }} 237 | {{ toYaml .Values.extraArgs | indent 12 | trim }} 238 | {{- end }} 239 | ports: 240 | - name: atlantis 241 | containerPort: {{ include "atlantis.containerPort" . }} 242 | {{- with .Values.lifecycle }} 243 | lifecycle: {{ toYaml . | nindent 12 }} 244 | {{- end }} 245 | {{- if or .Values.loadEnvFromSecrets .Values.loadEnvFromConfigMaps }} 246 | envFrom: 247 | {{- range .Values.loadEnvFromSecrets }} 248 | - secretRef: 249 | name: {{ . }} 250 | {{- end }} 251 | {{- range .Values.loadEnvFromConfigMaps }} 252 | - configMapRef: 253 | name: {{ . }} 254 | {{- end }} 255 | {{- end }} 256 | env: 257 | {{- if .Values.environmentRaw }} 258 | {{- with .Values.environmentRaw }} 259 | {{- toYaml . | nindent 10 }} 260 | {{- end }} 261 | {{- end }} 262 | - name: PATH 263 | value: {{ template "atlantis.pathEnvironmentVariable" . }} 264 | {{- range $key, $value := .Values.environment }} 265 | - name: {{ $key }} 266 | value: {{ $value | quote }} 267 | {{- end }} 268 | {{- range .Values.environmentSecrets }} 269 | - name: {{ .name }} 270 | valueFrom: 271 | secretKeyRef: 272 | name: {{ .secretKeyRef.name }} 273 | key: {{ .secretKeyRef.key }} 274 | {{- end }} 275 | {{- if .Values.allowForkPRs }} 276 | - name: ATLANTIS_ALLOW_FORK_PRS 277 | value: {{ .Values.allowForkPRs | quote }} 278 | {{- end }} 279 | {{- if .Values.allowDraftPRs }} 280 | - name: ATLANTIS_ALLOW_DRAFT_PRS 281 | value: {{ .Values.allowDraftPRs | quote }} 282 | {{- end }} 283 | {{- if .Values.hidePrevPlanComments }} 284 | - name: ATLANTIS_HIDE_PREV_PLAN_COMMENTS 285 | value: {{ .Values.hidePrevPlanComments | quote }} 286 | {{- end }} 287 | {{- if .Values.hideUnchangedPlanComments }} 288 | - name: ATLANTIS_HIDE_UNCHANGED_PLAN_COMMENTS 289 | value: {{ .Values.hideUnchangedPlanComments | quote }} 290 | {{- end }} 291 | {{- if .Values.disableApply }} 292 | - name: ATLANTIS_DISABLE_APPLY 293 | value: {{ .Values.disableApply | quote }} 294 | {{- end }} 295 | {{- if .Values.disableApplyAll }} 296 | - name: ATLANTIS_DISABLE_APPLY_ALL 297 | value: {{ .Values.disableApplyAll | quote }} 298 | {{- end }} 299 | {{- if .Values.disableRepoLocking }} 300 | - name: ATLANTIS_DISABLE_REPO_LOCKING 301 | value: {{ .Values.disableRepoLocking | quote }} 302 | {{- end }} 303 | {{- if .Values.enableDiffMarkdownFormat }} 304 | - name: ATLANTIS_ENABLE_DIFF_MARKDOWN_FORMAT 305 | value: {{ .Values.enableDiffMarkdownFormat | quote }} 306 | {{- end }} 307 | {{- if .Values.defaultTFVersion }} 308 | - name: ATLANTIS_DEFAULT_TF_VERSION 309 | value: {{ .Values.defaultTFVersion }} 310 | {{- end }} 311 | {{- if .Values.defaultTFDistribution }} 312 | - name: ATLANTIS_DEFAULT_TF_DISTRIBUTION 313 | value: {{ .Values.defaultTFDistribution }} 314 | {{- end }} 315 | {{- if .Values.logLevel }} 316 | - name: ATLANTIS_LOG_LEVEL 317 | value: {{ .Values.logLevel | quote}} 318 | {{- end }} 319 | {{- if .Values.tlsSecretName }} 320 | - name: ATLANTIS_SSL_CERT_FILE 321 | value: /etc/tls/tls.crt 322 | - name: ATLANTIS_SSL_KEY_FILE 323 | value: /etc/tls/tls.key 324 | {{- end }} 325 | - name: ATLANTIS_DATA_DIR 326 | value: {{ .Values.atlantisDataDirectory }} 327 | - name: ATLANTIS_REPO_ALLOWLIST 328 | {{- if .Values.orgAllowlist }} 329 | value: {{ .Values.orgAllowlist | quote }} 330 | {{- else }} 331 | value: {{ .Values.orgWhitelist | quote }} 332 | {{- end }} 333 | - name: ATLANTIS_PORT 334 | value: {{ include "atlantis.containerPort" . | quote }} 335 | {{- if .Values.repoConfig }} 336 | - name: ATLANTIS_REPO_CONFIG 337 | value: /etc/atlantis/repos.yaml 338 | {{- end }} 339 | {{- if .Values.atlantisUrl }} 340 | - name: ATLANTIS_ATLANTIS_URL 341 | value: {{ .Values.atlantisUrl }} 342 | {{- else if .Values.ingress.enabled }} 343 | - name: ATLANTIS_ATLANTIS_URL 344 | {{- if .Values.ingress.tls }} 345 | value: https://{{ .Values.ingress.host }} 346 | {{- else }} 347 | value: http://{{ .Values.ingress.host }} 348 | {{- end }} 349 | {{- end }} 350 | {{- if .Values.github.user }} 351 | - name: ATLANTIS_GH_USER 352 | value: {{ required "github.user is required if github configuration is specified." .Values.github.user }} 353 | - name: ATLANTIS_GH_TOKEN 354 | valueFrom: 355 | secretKeyRef: 356 | name: {{ template "atlantis.vcsSecretName" . }} 357 | key: github_token 358 | - name: ATLANTIS_GH_WEBHOOK_SECRET 359 | valueFrom: 360 | secretKeyRef: 361 | name: {{ template "atlantis.vcsSecretName" . }} 362 | key: github_secret 363 | {{- end }} 364 | {{- if .Values.github.hostname }} 365 | - name: ATLANTIS_GH_HOSTNAME 366 | value: {{ .Values.github.hostname }} 367 | {{- end }} 368 | {{- if .Values.githubApp }} 369 | {{- if .Values.githubApp.id }} 370 | - name: ATLANTIS_GH_APP_ID 371 | value: {{ .Values.githubApp.id | quote}} 372 | {{- end }} 373 | {{- if .Values.githubApp.installationId }} 374 | - name: ATLANTIS_GH_APP_INSTALLATION_ID 375 | value: {{ .Values.githubApp.installationId | quote}} 376 | {{- end }} 377 | {{- if .Values.githubApp.slug }} 378 | - name: ATLANTIS_GH_APP_SLUG 379 | value: {{ .Values.githubApp.slug | quote}} 380 | {{- end }} 381 | - name: ATLANTIS_WRITE_GIT_CREDS 382 | value: "true" 383 | {{- if or .Values.githubApp.secret .Values.vcsSecretName}} 384 | - name: ATLANTIS_GH_WEBHOOK_SECRET 385 | valueFrom: 386 | secretKeyRef: 387 | name: {{ template "atlantis.vcsSecretName" . }} 388 | key: github_secret 389 | {{- end }} 390 | {{- if or .Values.githubApp.key .Values.vcsSecretName}} 391 | - name: ATLANTIS_GH_APP_KEY_FILE 392 | value: "/var/github-app/key.pem" 393 | {{- end }} 394 | {{- end }} 395 | {{- if .Values.gitea }} 396 | - name: ATLANTIS_GITEA_USER 397 | value: {{ required "gitea.user is required if gitea configuration is specified." .Values.gitea.user }} 398 | - name: ATLANTIS_GITEA_TOKEN 399 | valueFrom: 400 | secretKeyRef: 401 | name: {{ template "atlantis.vcsSecretName" . }} 402 | key: gitea_token 403 | - name: ATLANTIS_GITEA_WEBHOOK_SECRET 404 | valueFrom: 405 | secretKeyRef: 406 | name: {{ template "atlantis.vcsSecretName" . }} 407 | key: gitea_secret 408 | {{- if .Values.gitea.baseUrl }} 409 | - name: ATLANTIS_GITEA_BASE_URL 410 | value: {{ .Values.gitea.baseUrl }} 411 | {{- end }} 412 | {{- end }} 413 | {{- if .Values.gitlab }} 414 | - name: ATLANTIS_GITLAB_USER 415 | value: {{ required "gitlab.user is required if gitlab configuration is specified." .Values.gitlab.user }} 416 | - name: ATLANTIS_GITLAB_TOKEN 417 | valueFrom: 418 | secretKeyRef: 419 | name: {{ template "atlantis.vcsSecretName" . }} 420 | key: gitlab_token 421 | - name: ATLANTIS_GITLAB_WEBHOOK_SECRET 422 | valueFrom: 423 | secretKeyRef: 424 | name: {{ template "atlantis.vcsSecretName" . }} 425 | key: gitlab_secret 426 | {{- if .Values.gitlab.hostname }} 427 | - name: ATLANTIS_GITLAB_HOSTNAME 428 | value: {{ .Values.gitlab.hostname }} 429 | {{- end }} 430 | {{- end }} 431 | {{- if .Values.bitbucket }} 432 | - name: ATLANTIS_BITBUCKET_USER 433 | value: {{ required "bitbucket.user is required if bitbucket configuration is specified." .Values.bitbucket.user }} 434 | - name: ATLANTIS_BITBUCKET_TOKEN 435 | valueFrom: 436 | secretKeyRef: 437 | name: {{ template "atlantis.vcsSecretName" . }} 438 | key: bitbucket_token 439 | {{- if .Values.bitbucket.baseURL }} 440 | - name: ATLANTIS_BITBUCKET_BASE_URL 441 | value: {{ .Values.bitbucket.baseURL }} 442 | - name: ATLANTIS_BITBUCKET_WEBHOOK_SECRET 443 | valueFrom: 444 | secretKeyRef: 445 | name: {{ template "atlantis.vcsSecretName" . }} 446 | key: bitbucket_secret 447 | {{- end }} 448 | {{- end }} 449 | {{- if .Values.azuredevops }} 450 | - name: ATLANTIS_AZUREDEVOPS_USER 451 | value: {{ required "azuredevops.user is required if azuredevops configuration is specified." .Values.azuredevops.user }} 452 | - name: ATLANTIS_AZUREDEVOPS_TOKEN 453 | valueFrom: 454 | secretKeyRef: 455 | name: {{ template "atlantis.vcsSecretName" . }} 456 | key: azuredevops_token 457 | - name: ATLANTIS_AZUREDEVOPS_WEBHOOK_USER 458 | value: {{ required "azuredevops.webhookUser is required if azuredevops configuration is specified." .Values.azuredevops.webhookUser }} 459 | - name: ATLANTIS_AZUREDEVOPS_WEBHOOK_PASSWORD 460 | valueFrom: 461 | secretKeyRef: 462 | name: {{ template "atlantis.vcsSecretName" . }} 463 | key: azuredevops_webhook_password 464 | {{- end }} 465 | {{- if or .Values.basicAuthSecretName ( and .Values.basicAuth.username .Values.basicAuth.password ) }} 466 | - name: ATLANTIS_WEB_BASIC_AUTH 467 | value: "true" 468 | - name: ATLANTIS_WEB_USERNAME 469 | valueFrom: 470 | secretKeyRef: 471 | name: {{ template "atlantis.basicAuthSecretName" . }} 472 | key: username 473 | - name: ATLANTIS_WEB_PASSWORD 474 | valueFrom: 475 | secretKeyRef: 476 | name: {{ template "atlantis.basicAuthSecretName" . }} 477 | key: password 478 | {{- end }} 479 | {{- if or .Values.api .Values.apiSecretName }} 480 | - name: ATLANTIS_API_SECRET 481 | valueFrom: 482 | secretKeyRef: 483 | name: {{ template "atlantis.apiSecretName" . }} 484 | key: apisecret 485 | {{- end }} 486 | {{- if .Values.lockingDbType }} 487 | - name: ATLANTIS_LOCKING_DB_TYPE 488 | value: {{ .Values.lockingDbType | quote }} 489 | {{- end }} 490 | {{- if .Values.redis.host }} 491 | - name: ATLANTIS_REDIS_HOST 492 | value: {{ .Values.redis.host | quote }} 493 | {{- end }} 494 | {{- if or .Values.redis.password .Values.redisSecretName }} 495 | - name: ATLANTIS_REDIS_PASSWORD 496 | valueFrom: 497 | secretKeyRef: 498 | name: {{ template "atlantis.redisSecretName" . }} 499 | key: {{ .Values.redisSecretPasswordKey | quote }} 500 | {{- end }} 501 | {{- if .Values.redis.port }} 502 | - name: ATLANTIS_REDIS_PORT 503 | value: {{ .Values.redis.port | quote }} 504 | {{- end }} 505 | {{- if .Values.redis.db }} 506 | - name: ATLANTIS_REDIS_DB 507 | value: {{ .Values.redis.db | quote }} 508 | {{- end }} 509 | {{- if .Values.redis.tlsEnabled }} 510 | - name: ATLANTIS_REDIS_TLS_ENABLED 511 | value: {{ .Values.redis.tlsEnabled | quote }} 512 | {{- end }} 513 | {{- if .Values.redis.insecureSkipVerify }} 514 | - name: ATLANTIS_REDIS_INSECURE_SKIP_VERIFY 515 | value: {{ .Values.redis.insecureSkipVerify | quote }} 516 | {{- end }} 517 | {{- if .Values.aws.directory }} 518 | - name: AWS_SHARED_CREDENTIALS_FILE 519 | value: {{ .Values.aws.directory }}/credentials 520 | - name: AWS_CONFIG_FILE 521 | value: {{ .Values.aws.directory }}/config 522 | {{- end }} 523 | {{- if .Values.initConfig.enabled }} 524 | - name: INIT_SHARED_DIR 525 | value: {{ .Values.initConfig.sharedDir }} 526 | {{- end }} 527 | {{- if .Values.livenessProbe.enabled }} 528 | livenessProbe: 529 | httpGet: 530 | path: /healthz 531 | port: {{ include "atlantis.containerPort" . }} 532 | scheme: {{ .Values.livenessProbe.scheme }} 533 | initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} 534 | periodSeconds: {{ .Values.livenessProbe.periodSeconds }} 535 | timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} 536 | successThreshold: {{ .Values.livenessProbe.successThreshold }} 537 | failureThreshold: {{ .Values.livenessProbe.failureThreshold }} 538 | {{- end }} 539 | {{- if .Values.readinessProbe.enabled }} 540 | readinessProbe: 541 | httpGet: 542 | path: /healthz 543 | port: {{ include "atlantis.containerPort" . }} 544 | scheme: {{ .Values.readinessProbe.scheme }} 545 | initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} 546 | periodSeconds: {{ .Values.readinessProbe.periodSeconds }} 547 | timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} 548 | successThreshold: {{ .Values.readinessProbe.successThreshold }} 549 | failureThreshold: {{ .Values.readinessProbe.failureThreshold }} 550 | {{- end }} 551 | volumeMounts: 552 | {{- if or .Values.volumeClaim.enabled .Values.dataStorage }} 553 | - name: atlantis-data 554 | mountPath: {{ .Values.atlantisDataDirectory }} 555 | {{- end }} 556 | {{- range $name, $_ := .Values.serviceAccountSecrets }} 557 | - name: {{ $name }}-volume 558 | readOnly: true 559 | mountPath: /etc/{{ $name }} 560 | {{- end }} 561 | {{- range .Values.googleServiceAccountSecrets }} 562 | - name: {{ .name }} 563 | readOnly: true 564 | mountPath: /var/secrets/{{ .name }} 565 | {{- end }} 566 | {{- if or .Values.gitconfig .Values.gitconfigSecretName }} 567 | - name: gitconfig-volume 568 | readOnly: true 569 | {{- if .Values.gitconfigReadOnly }} 570 | mountPath: /home/atlantis/.gitconfig 571 | {{- else }} 572 | mountPath: /etc/.gitconfig 573 | {{- end }} 574 | subPath: gitconfig 575 | {{- end }} 576 | {{- if not .Values.gitconfigReadOnly }} 577 | - name: gitconfig-init 578 | mountPath: /docker-entrypoint.d/gitconfig-init.sh 579 | subPath: gitconfig-init.sh 580 | {{- end }} 581 | {{- if or .Values.netrc .Values.netrcSecretName }} 582 | - name: netrc-volume 583 | readOnly: true 584 | mountPath: /home/atlantis/.netrc 585 | subPath: netrc 586 | {{- end }} 587 | {{- if or .Values.aws.credentials .Values.aws.config .Values.awsSecretName }} 588 | - name: aws-volume 589 | readOnly: true 590 | mountPath: {{ .Values.aws.directory | default "/home/atlantis/.aws" }} 591 | {{- end }} 592 | {{- if .Values.tlsSecretName }} 593 | - name: tls 594 | mountPath: /etc/tls/ 595 | {{- end }} 596 | {{- if .Values.repoConfig }} 597 | - name: repo-config 598 | mountPath: /etc/atlantis/repos.yaml 599 | subPath: repos.yaml 600 | readOnly: true 601 | {{- end }} 602 | {{- if .Values.githubApp }} 603 | {{- if or .Values.githubApp.key .Values.vcsSecretName}} 604 | - name: github-app-key-volume 605 | mountPath: /var/github-app 606 | readOnly: true 607 | {{- end }} 608 | {{- end }} 609 | {{- if .Values.config }} 610 | - name: config 611 | mountPath: /etc/atlantis/atlantis.yaml 612 | subPath: atlantis.yaml 613 | readOnly: true 614 | {{- end }} 615 | {{- if .Values.containerSecurityContext.readOnlyRootFilesystem }} 616 | - name: atlantis-home-dir 617 | mountPath: /home/atlantis 618 | - name: tmp-dir 619 | mountPath: /tmp 620 | {{- end }} 621 | {{- if .Values.customPem }} 622 | - name: additional-trust-certs 623 | mountPath: /etc/ssl/certs/ca-certificates.crt 624 | subPath: ca-certificates.crt 625 | {{- end }} 626 | {{- if .Values.extraVolumeMounts }} 627 | {{- toYaml .Values.extraVolumeMounts | nindent 10 }} 628 | {{- end }} 629 | {{- if .Values.initConfig.enabled }} 630 | - name: init-shared-path 631 | mountPath: {{ .Values.initConfig.sharedDir }} 632 | readOnly: {{ .Values.initConfig.sharedDirReadOnly }} 633 | {{- end }} 634 | resources: 635 | {{- toYaml .Values.resources | nindent 12 }} 636 | {{- with .Values.extraContainers }} 637 | {{- toYaml . | nindent 8 }} 638 | {{- end }} 639 | {{- with .Values.nodeSelector }} 640 | nodeSelector: 641 | {{- toYaml . | nindent 8 }} 642 | {{- end }} 643 | {{- with .Values.affinity }} 644 | affinity: 645 | {{- toYaml . | nindent 8 }} 646 | {{- end }} 647 | {{- with .Values.tolerations }} 648 | tolerations: 649 | {{- toYaml . | nindent 8 }} 650 | {{- end }} 651 | {{- with .Values.topologySpreadConstraints }} 652 | topologySpreadConstraints: 653 | {{- toYaml . | nindent 8 }} 654 | {{- end }} 655 | {{- with .Values.statefulSet.updateStrategy }} 656 | updateStrategy: 657 | {{- toYaml . | nindent 4 }} 658 | {{- end }} 659 | {{- if .Values.dataStorage }} 660 | volumeClaimTemplates: 661 | - metadata: 662 | name: atlantis-data 663 | spec: 664 | accessModes: ["ReadWriteOnce"] # Volume should not be shared by multiple nodes. 665 | {{- if .Values.storageClassName }} 666 | storageClassName: {{ .Values.storageClassName }} # Storage class of the volume 667 | {{- end }} 668 | resources: 669 | requests: 670 | # The biggest thing Atlantis stores is the Git repo when it checks it out. 671 | # It deletes the repo after the pull request is merged. 672 | storage: {{ .Values.dataStorage }} 673 | {{- end }} 674 | -------------------------------------------------------------------------------- /charts/atlantis/README.md: -------------------------------------------------------------------------------- 1 | # Atlantis 2 | 3 | [Atlantis](https://www.runatlantis.io/) is a tool for safe collaboration on [Terraform](https://www.terraform.io/) repositories. 4 | 5 | ## Maintainers 6 | 7 | | Name | Email | Url | 8 | | ---- | ------ | --- | 9 | | lkysow | | | 10 | | jamengual | | | 11 | | chenrui333 | | | 12 | | nitrocode | | | 13 | | genpage | | | 14 | | gmartinez-sisti | | | 15 | 16 | ## Links 17 | 18 | - [Introduction](#introduction) 19 | - [Prerequisites](#prerequisites) 20 | - [Usage](#usage) 21 | - [Install Helm Chart](#install-helm-chart) 22 | - [Required Configuration](#required-configuration) 23 | - [Additional manifests](#additional-manifests) 24 | - [Values](#values) 25 | - [Upgrading](#upgrading) 26 | - [From `4.*` to `5.*`](#from-4-to-5) 27 | - [From `2.*` to `3.*`](#from-2-to-3) 28 | - [From `1.*` to `2.*`](#from-1-to-2) 29 | - [Testing the Deployment](#testing-the-deployment) 30 | - [Update documentation](#update-documentation) 31 | - [Run unit tests](#run-unit-tests) 32 | 33 | ## Introduction 34 | 35 | This chart creates a single pod in a StatefulSet running Atlantis. Atlantis persists Terraform [plan files](https://www.terraform.io/docs/commands/plan.html) and [lockfiles](https://www.terraform.io/docs/state/locking.html) to disk for the duration of a Pull/Merge Request. These files are stored in a PersistentVolumeClaim to survive Pod failures. 36 | 37 | ## Prerequisites 38 | 39 | - Kubernetes 1.9+ 40 | - PersistentVolume support 41 | 42 | ## Usage 43 | 44 | The chart is distributed as an [OCI Artifact](https://helm.sh/docs/topics/registries/) as well as via a traditional [Helm Repository](https://helm.sh/docs/topics/chart_repository/). 45 | 46 | - OCI Artifact: `oci://ghcr.io/runatlantis/charts/atlantis` 47 | - Helm Repository: `https://runatlantis.github.io/helm-charts` with chart `atlantis` 48 | 49 | The installation instructions use the OCI registry. Refer to the [`helm repo`](https://helm.sh/docs/helm/helm_repo/) command documentation for information on installing charts via the traditional repository. 50 | 51 | ### Install Helm Chart 52 | 53 | ```console 54 | helm install [RELEASE_NAME] oci://ghcr.io/runatlantis/charts/atlantis 55 | ``` 56 | 57 | ## Required Configuration 58 | 59 | In order for Atlantis to start and run successfully: 60 | 61 | 1. At least one of the following sets of credentials must be defined: 62 | - `github` 63 | - `gitea` 64 | - `gitlab` 65 | - `bitbucket` 66 | - `azuredevops` 67 | 68 | Refer to [values.yaml](/charts/atlantis/values.yaml) for detailed examples. 69 | They can also be provided directly through a Kubernetes `Secret`, use the variable `vcsSecretName` to reference it. 70 | 71 | 1. Supply a value for `orgAllowlist`, e.g. `github.com/myorg/*`. 72 | 73 | ## Additional manifests 74 | 75 | It is possible to add additional manifests into a deployment, to extend the chart. One of the reason is to deploy a manifest specific to a cloud provider ( BackendConfig on GKE for example ). 76 | 77 | ```yaml 78 | extraManifests: 79 | - apiVersion: cloud.google.com/v1beta1 80 | kind: BackendConfig 81 | metadata: 82 | name: ".Release.Name-test" 83 | spec: 84 | securityPolicy: 85 | name: "gcp-cloud-armor-policy-test" 86 | ``` 87 | 88 | ## Values 89 | 90 | | Key | Type | Default | Description | 91 | |-----|------|---------|-------------| 92 | | affinity | object | `{}` | | 93 | | allowDraftPRs | bool | `false` | Enables atlantis to run on a draft Pull Requests. | 94 | | allowForkPRs | bool | `false` | Enables atlantis to run on a fork Pull Requests. | 95 | | api | object | `{}` | Optionally specify an API secret to enable the API. Check values.yaml for examples. | 96 | | apiSecretName | string | `""` | If managing secrets outside the chart for the API secret, use this variable to reference the secret name. The key containing the secret must be called 'apisecret'. | 97 | | atlantisDataDirectory | string | `"/atlantis-data"` | Path to the data directory for the volumeMount. | 98 | | atlantisUrl | string | `""` | An option to override the atlantis url, if not using an ingress, set it to the external IP. Check values.yaml for examples. | 99 | | aws | object | `{}` | To specify AWS credentials to be mapped to ~/.aws or to aws.directory. Check values.yaml for examples. | 100 | | awsSecretName | string | `""` | To reference an already existing Secret object with AWS credentials | 101 | | azuredevops | object | `{}` | If using Azure DevOps, please enter your values as follows. The chart will perform the base64 encoding for you for values that are stored in secrets. Check values.yaml for examples. | 102 | | basicAuth | object | `{"password":"","username":""}` | Optionally specify an username and a password for basic authentication. | 103 | | basicAuthSecretName | string | `""` | If managing secrets outside the chart for the Basic Auth secret, use this variable to reference the secret name. | 104 | | bitbucket | object | `{}` | If using Bitbucket, there are two approaches: Bitbucket Server, deployed in your own infrastructure and Cloud available at (https://Bitbucket.org). The chart will perform the base64 encoding for you for values that are stored in secrets. Check values.yaml for examples. | 105 | | command | list | `[]` | Override the command field of the Atlantis container. | 106 | | commonLabels | object | `{}` | Common Labels for all resources created by this chart. | 107 | | config | string | `""` | Override atlantis main configuration by config map, ref: https://www.runatlantis.io/docs/using-slack-hooks.html#configuring-atlantis. Check values.yaml for examples. | 108 | | containerPort | int | `0` | [optional] Define the port you would like atlantis to run on. When 0, the value of service.targetPort is used. | 109 | | containerSecurityContext | object | `{}` | Check values.yaml for examples. | 110 | | customPem | string | `""` | Allows to override the /etc/ssl/certs/ca-certificates.cer with your custom one. You have to create a secret with the specified name. | 111 | | dataStorage | string | `""` | DEPRECATED - Disk space available to check out repositories. Example: 5Gi. | 112 | | defaultTFDistribution | string | `"terraform"` | Sets the default terraform distribution to use. Can be set to terraform or opentofu. | 113 | | defaultTFVersion | string | `""` | Sets the default terraform version to be used in atlantis server. Check values.yaml for examples. | 114 | | disableApply | bool | `false` | Disables running `atlantis apply` regardless of which flags are sent with it. | 115 | | disableApplyAll | bool | `false` | Disables running `atlantis apply` without any flags. | 116 | | disableRepoLocking | bool | `false` | Stops atlantis locking projects and or workspaces when running terraform. | 117 | | dnsConfig | object | `{}` | Optionally specify dnsConfig for the Atlantis pod. Check values.yaml for examples. | 118 | | dnsPolicy | string | `"ClusterFirst"` | Optionally specify dnsPolicy parameter to specify a DNS policy for a pod Check https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy | 119 | | enableDiffMarkdownFormat | bool | `false` | Use Diff Markdown Format for color coding diffs. | 120 | | enableKubernetesBackend | bool | `false` | Optionally deploy rbac to allow for the serviceAccount to manage terraform state via the kubernetes backend. | 121 | | environment | object | `{}` | Environment values to add to the Atlantis pod. Check values.yaml for examples. | 122 | | environmentRaw | list | `[]` | Optionally specify additional environment variables in raw yaml format. Useful to specify variables refering to k8s objects. Check values.yaml for examples. | 123 | | environmentSecrets | list | `[]` | Optionally specify additional environment variables to be populated from Kubernetes secrets. Useful for passing in TF_VAR_foo or other secret environment variables from Kubernetes secrets. Check values.yaml for examples. | 124 | | extraAnnotations | object | `{}` | These annotations will be added to all the resources. Check values.yaml for examples. | 125 | | extraArgs | list | `[]` | Optionally specify extra arguments for the Atlantis pod. Check values.yaml for examples. | 126 | | extraContainers | list | `[]` | Optionally specify extra containers for the Atlantis pod. Check values.yaml for examples. | 127 | | extraManifests | list | `[]` | Optionally specify additional manifests to be created. Check values.yaml for examples. | 128 | | extraPath | string | `""` | Additional path (`:` separated) that will be appended to the system `PATH` environment variable. | 129 | | extraVolumeMounts | list | `[]` | Optionally specify additional volume mounts for the container. Check values.yaml for examples. | 130 | | extraVolumes | list | `[]` | Optionally specify additional volumes for the pod. Check values.yaml for examples. | 131 | | fullnameOverride | string | `""` | Provide a name to substitute for the full names of resources. | 132 | | gitconfig | string | `""` | When referencing Terraform modules in private repositories, it may be helpful (necessary?) to use redirection in a .gitconfig. Check values.yaml for examples. | 133 | | gitconfigReadOnly | bool | `true` | When true gitconfig file is mounted as read only. When false, the gitconfig value will be copied to '/home/atlantis/.gitconfig' before starting the atlantis process, instead of being mounted as a file. | 134 | | gitconfigSecretName | string | `""` | If managing secrets outside the chart for the gitconfig, use this variable to reference the secret name | 135 | | gitea | object | `{}` | If using Gitea, please enter your values as follows. The 'baseUrl' key is exclusive to self-hosted Gitea installations. The chart will perform the base64 encoding for you for values that are stored in secrets. Check values.yaml for examples. | 136 | | github | object | `{}` | If using GitHub, please enter your values as follows. The chart will perform the base64 encoding for values that are stored in secrets. The 'hostname' key is exclusive to GitHub Enterprise installations. Check values.yaml for examples. | 137 | | githubApp | object | `{}` | If using a GitHub App, please enter your values as follows. The chart will perform the base64 encoding for you for values that are stored in secrets. installationId is necessary when there are multiple installs of the Github App. Check values.yaml for examples. | 138 | | gitlab | object | `{}` | If using GitLab, please enter your values as follows. The 'hostname' key is exclusive to GitLab Enterprise installations. The chart will perform the base64 encoding for you for values that are stored in secrets. Check values.yaml for examples. | 139 | | googleServiceAccountSecrets | list | `[]` | Optionally specify google service account credentials as Kubernetes secrets. If you are using the terraform google provider you can specify the credentials as "${file("/var/secrets/some-secret-name/key.json")}". Check values.yaml for examples. | 140 | | hidePrevPlanComments | bool | `false` | Enables atlantis to hide previous plan comments. | 141 | | hideUnchangedPlanComments | bool | `false` | Enables atlantis to hide no-changes plan comments from the pull request. | 142 | | hostAliases | list | `[]` | Optionally specify hostAliases for the Atlantis pod. Check values.yaml for examples. | 143 | | hostNetwork | bool | `false` | | 144 | | image.pullPolicy | string | `"Always"` | | 145 | | image.repository | string | `"ghcr.io/runatlantis/atlantis"` | | 146 | | image.tag | string | `""` | If not set appVersion field from Chart.yaml is used | 147 | | imagePullSecrets | list | `[]` | Optionally specify an array of imagePullSecrets. Secrets must be manually created in the namespace. ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/. Check values.yaml for examples. | 148 | | ingress.annotations | object | `{}` | Check values.yaml for examples. | 149 | | ingress.apiVersion | string | `""` | | 150 | | ingress.enabled | bool | `true` | | 151 | | ingress.host | string | `""` | | 152 | | ingress.hosts | list | `[]` | Used when several hosts are required. Check values.yaml for examples. | 153 | | ingress.ingressClassName | string | `nil` | | 154 | | ingress.labels | object | `{}` | | 155 | | ingress.path | string | `"/*"` | Use / for nginx. | 156 | | ingress.pathType | string | `"ImplementationSpecific"` | | 157 | | ingress.paths | list | `[]` | Used when several paths under the same host, with different backend services, are required. Check values.yaml for examples. | 158 | | ingress.tls | list | `[]` | Check values.yaml for examples. | 159 | | initConfig.containerSecurityContext | object | `{}` | Security context for the container. | 160 | | initConfig.enabled | bool | `false` | Install providers/plugins into a path shared with the Atlantis pod. | 161 | | initConfig.image | string | `"alpine:latest"` | | 162 | | initConfig.imagePullPolicy | string | `"IfNotPresent"` | | 163 | | initConfig.script | string | Check values.yaml. | Script to run on the init container. | 164 | | initConfig.sharedDir | string | `"/plugins"` | SharedDir is set as env var INIT_SHARED_DIR. | 165 | | initConfig.sharedDirReadOnly | bool | `true` | | 166 | | initConfig.sizeLimit | string | `"300Mi"` | Size for the shared volume. | 167 | | initConfig.workDir | string | `"/tmp"` | | 168 | | initContainers | list | `[]` | Optionally specify init containers manifests to be added to the Atlantis pod. Check values.yaml for examples. | 169 | | lifecycle | object | `{}` | Set lifecycle hooks. https://kubernetes.io/docs/tasks/configure-pod-container/attach-handler-lifecycle-event/. | 170 | | livenessProbe.enabled | bool | `true` | | 171 | | livenessProbe.failureThreshold | int | `5` | | 172 | | livenessProbe.initialDelaySeconds | int | `5` | | 173 | | livenessProbe.periodSeconds | int | `60` | We only need to check every 60s since Atlantis is not a high-throughput service. | 174 | | livenessProbe.scheme | string | `"HTTP"` | | 175 | | livenessProbe.successThreshold | int | `1` | | 176 | | livenessProbe.timeoutSeconds | int | `5` | | 177 | | loadEnvFromConfigMaps | list | `[]` | Optionally specify additional Kubernetes ConfigMaps to load environment variables from. All key-value pairs within these ConfigMaps will be set as environment variables. Note that any variables set here will be ignored if also defined in the env block of the atlantis statefulset. For example, providing ATLANTIS_ALLOW_FORK_PRS here and defining a value for allowForkPRs will result in the allowForkPRs value being used. Check values.yaml for examples. | 178 | | loadEnvFromSecrets | list | `[]` | Optionally specify additional Kubernetes secrets to load environment variables from. All key-value pairs within these secrets will be set as environment variables. Note that any variables set here will be ignored if also defined in the env block of the atlantis statefulset. For example, providing ATLANTIS_GH_USER here and defining a value for github.user will result in the github.user value being used. Check values.yaml for examples. | 179 | | lockingDbType | string | `""` | Set the desired Locking DB type Accepts boltdb or redis. | 180 | | logLevel | string | `""` | Specify the log level for Atlantis. Accepts: debug, info, warn, or error. | 181 | | nameOverride | string | `""` | Provide a name to substitute for the name of the chart. | 182 | | netrc | string | `""` | When referencing Terraform modules in private repositories or registries (such as Artfactory) configuing a .netrc file for authentication may be required. Check values.yaml for examples. | 183 | | netrcSecretName | string | `""` | If managing secrets outside the chart for the netrc file, use this variable to reference the secret name | 184 | | nodeSelector | object | `{}` | | 185 | | orgAllowlist | string | `""` | Replace this with your own repo allowlist. | 186 | | orgWhitelist | string | `""` | Deprecated in favor of orgAllowlist. | 187 | | podMonitor | object | `{"enabled":false,"interval":"30s","metricRelabeling":[]}` | Enable this if you're using Google Managed Prometheus. | 188 | | podTemplate.annotations | object | `{}` | Check values.yaml for examples. | 189 | | podTemplate.labels | object | `{}` | | 190 | | readinessProbe.enabled | bool | `true` | | 191 | | readinessProbe.failureThreshold | int | `5` | | 192 | | readinessProbe.initialDelaySeconds | int | `5` | | 193 | | readinessProbe.periodSeconds | int | `60` | | 194 | | readinessProbe.scheme | string | `"HTTP"` | | 195 | | readinessProbe.successThreshold | int | `1` | | 196 | | readinessProbe.timeoutSeconds | int | `5` | | 197 | | redis | object | `{}` | Configure Redis Locking DB. lockingDbType value must be redis for the config to take effect. Check values.yaml for examples. | 198 | | redisSecretName | string | `""` | When managing secrets outside the chart for the Redis secret, use this variable to reference the secret name. | 199 | | redisSecretPasswordKey | string | `"password"` | Key within the existing Redis secret that contains the password value. | 200 | | replicaCount | int | `1` | Replica count for Atlantis pods. | 201 | | repoConfig | string | `""` | Use Server Side Repo Config, ref: https://www.runatlantis.io/docs/server-side-repo-config.html. Check values.yaml for examples. | 202 | | resources | object | `{}` | Resources for Atlantis. Check values.yaml for examples. | 203 | | secret.annotations | object | `{}` | Annotations for the Secrets. Check values.yaml for examples. | 204 | | service.annotations | object | `{}` | | 205 | | service.externalTrafficPolicy | string | `nil` | | 206 | | service.loadBalancerIP | string | `nil` | | 207 | | service.loadBalancerSourceRanges | list | `[]` | | 208 | | service.nodePort | string | `nil` | | 209 | | service.port | int | `80` | | 210 | | service.portName | string | `"atlantis"` | | 211 | | service.targetPort | int | `4141` | [optional] Define the port you would like atlantis to run on. Defaults to 4141. | 212 | | service.type | string | `"NodePort"` | | 213 | | serviceAccount.annotations | object | `{}` | Annotations for the Service Account. Check values.yaml for examples. | 214 | | serviceAccount.create | bool | `true` | Specifies whether a ServiceAccount should be created. | 215 | | serviceAccount.mount | bool | `true` | If false, no kubernetes service account token will be mounted to the pod. | 216 | | serviceAccount.name | string | `nil` | The name of the ServiceAccount to use. If not set and create is true, a name is generated using the fullname template. | 217 | | serviceAccountSecrets | object | `{}` | To keep backwards compatibility only. Deprecated (see googleServiceAccountSecrets). To be used for mounting credential files (when using google provider). Check values.yaml for examples. | 218 | | servicemonitor.additionalLabels | object | `{}` | Prometheus ServiceMonitor labels. | 219 | | servicemonitor.auth.basicAuth | object | `{"enabled":false}` | If auth is enabled on Atlantis, use one of the following mechanism. | 220 | | servicemonitor.auth.basicAuth.enabled | bool | `false` | Authentication from the secret generated with the basicAuth values this will reference the username and password keys from the atlantis-basic-auth secret. | 221 | | servicemonitor.auth.externalSecret.enabled | bool | `false` | Authentication based on an external secret | 222 | | servicemonitor.auth.externalSecret.keys | object | `{}` | Check values.yaml for examples. | 223 | | servicemonitor.auth.externalSecret.name | string | `""` | | 224 | | servicemonitor.enabled | bool | `false` | To enable a Prometheus servicemonitor, set enabled to true, and enable the metrics in this file's repoConfig by setting a value for metrics.prometheus.endpoint. | 225 | | servicemonitor.interval | string | `"30s"` | | 226 | | servicemonitor.metricRelabelings | list | `[]` | Optional metric relabelings to drop or modify metrics. | 227 | | servicemonitor.path | string | `"/metrics"` | | 228 | | statefulSet.annotations | object | `{}` | | 229 | | statefulSet.labels | object | `{}` | | 230 | | statefulSet.priorityClassName | string | `""` | | 231 | | statefulSet.securityContext.fsGroup | int | `1000` | | 232 | | statefulSet.securityContext.fsGroupChangePolicy | string | `"OnRootMismatch"` | | 233 | | statefulSet.securityContext.runAsUser | int | `100` | It is not recommended to run atlantis as root. | 234 | | statefulSet.shareProcessNamespace | bool | `false` | Option to share process namespace with atlantis container. | 235 | | statefulSet.updateStrategy | object | `{}` | | 236 | | storageClassName | string | `""` | DEPRECATED - Storage class name for Atlantis disk. | 237 | | terminationGracePeriodSeconds | int | default depends on the kubernetes version. | Optionally customize the termination grace period in seconds. | 238 | | test.annotations | object | `{}` | | 239 | | test.enabled | bool | `true` | Enables test container. | 240 | | test.image | string | `"bats/bats"` | | 241 | | test.imageTag | string | `"1.9.0"` | | 242 | | tlsSecretName | string | `""` | TLS Secret Name for Atlantis pod. | 243 | | tolerations | list | `[]` | | 244 | | topologySpreadConstraints | list | `[]` | You can use topology spread constraints to control how Pods are spread across your cluster among failure-domains such as regions, zones, nodes, and other user-defined topology domains. (requires Kubernetes >= 1.19). Check values.yaml for examples. | 245 | | vcsSecretName | string | `""` | If managing secrets outside the chart for the webhook, use this variable to reference the secret name | 246 | | volumeClaim.accessModes[0] | string | `"ReadWriteOnce"` | | 247 | | volumeClaim.dataStorage | string | `"5Gi"` | Disk space available to check out repositories. | 248 | | volumeClaim.enabled | bool | `true` | | 249 | | volumeClaim.storageClassName | string | `""` | Storage class name (if possible, use a resizable one). | 250 | | webhook_ingress.annotations | object | `{}` | Check values.yaml for examples. | 251 | | webhook_ingress.apiVersion | string | `""` | | 252 | | webhook_ingress.enabled | bool | `false` | When true creates a secondary webhook. | 253 | | webhook_ingress.host | string | `""` | | 254 | | webhook_ingress.hosts | list | `[]` | Used when several hosts are required. Check values.yaml for examples. | 255 | | webhook_ingress.ingressClassName | string | `nil` | | 256 | | webhook_ingress.labels | object | `{}` | | 257 | | webhook_ingress.path | string | `"/*"` | Use / for nginx. | 258 | | webhook_ingress.pathType | string | `"ImplementationSpecific"` | | 259 | | webhook_ingress.paths | list | `[]` | Used when several paths under the same host, with different backend services, are required. Check values.yaml for examples. | 260 | | webhook_ingress.tls | list | `[]` | TLS configuration. Check values.yaml for examples. | 261 | 262 | ## Upgrading 263 | 264 | ### From `4.*` to `5.*` 265 | 266 | A breaking change was merged on [#304](https://github.com/runatlantis/helm-charts/pull/304). 267 | This change moves the atlantis data volume to a separate PVC to allow changing the volume size without removing the statefulset. 268 | Unmistakingly, this change only bumped the minor version, released as `4.22.0`, instead of incrementing the major version. The release `5.0.0` addresses this issue. Please find the required upgrade manual steps below. 269 | 270 | #### Upgrade steps 271 | 272 | Trying to upgrade the release directly will return the following error: 273 | 274 | > Error: UPGRADE FAILED: cannot patch "atlantis" with kind StatefulSet: StatefulSet.apps "atlantis" is invalid: spec: Forbidden: updates to statefulset spec for fields other than 'replicas', 'ordinals', 'template', 'updateStrategy', 'persistentVolumeClaimRetentionPolicy' and 'minReadySeconds' are forbidden 275 | 276 | To allow the upgrade to proceed, first we need to remove the statefulset controller, copy all the data from the old volume to the new one and then cleanup. 277 | 278 | NOTE: These steps will ensure no data is lost, however during the copy process the atlantis server is unavailable and any webhooks sent to atlantis during that window are missed and won't be processed. 279 | 280 | Upgrade steps: 281 | 282 | 1. For atlantis deployments managed by GitOps solutions such as ArgoCD, disabling the automatic synchronization is required 283 | 284 | 1. Create a temporary helm configuration file named `migration-4-to-5.yaml`, the configuration includes the required settings to allow the atlantis data to be copied to the new volume before the atlantis server is started. The suggested configuration implies that the default command for atlantis has not been customized. If required, adjust the `persistentVolumeClaim.claimName` value. 285 | 286 | ```yaml 287 | command: 288 | - sh 289 | - -c 290 | - 'cp -Rv /atlantis-data-old/* "${ATLANTIS_DATA_DIR}" && exec /usr/local/bin/docker-entrypoint.sh server' 291 | 292 | extraVolumes: 293 | - name: atlantis-data-old 294 | persistentVolumeClaim: 295 | claimName: atlantis-data-atlantis-0 296 | 297 | extraVolumeMounts: 298 | - name: atlantis-data-old 299 | mountPath: /atlantis-data-old 300 | ``` 301 | 302 | 1. Delete the current statefulset without removing the atlantis pod. This can be achieved with the parameter [--cascade=orphan](https://kubernetes.io/docs/tasks/administer-cluster/use-cascading-deletion/#set-orphan-deletion-policy): 303 | 304 | NOTE: If required, adjust the namespace and the statefulset name. 305 | 306 | ```sh 307 | kubectl delete statefulsets.apps atlantis --namespace atlantis --cascade=orphan 308 | ``` 309 | 310 | 1. Deploy the new atlantis version, this will recreate the statefulset and update the atlantis pod acordingly. E.g.: 311 | 312 | ```sh 313 | helm upgrade -i atlantis runatlantis/atlantis --version 5.0.0 -f my-config.yaml -f migration-4-to-5.yaml 314 | ``` 315 | 316 | 1. Check the logs for the atlantis pod, it should show the copy process followed by start of the atlantis server. E.g.: 317 | 318 | ```json 319 | '/atlantis-data-old/atlantis.db' -> '/atlantis-data/atlantis.db' 320 | '/atlantis-data-old/bin' -> '/atlantis-data/bin' 321 | '/atlantis-data-old/existing-data.example' -> '/atlantis-data/existing-data.example' 322 | '/atlantis-data-old/plugin-cache' -> '/atlantis-data/plugin-cache' 323 | No files found in /docker-entrypoint.d/, skipping 324 | {"level":"info","ts":"2024-05-01T17:17:03.406Z","caller":"server/server.go:447","msg":"Utilizing BoltDB","json":{}} 325 | {"level":"info","ts":"2024-05-01T17:17:03.411Z","caller":"policy/conftest_client.go:153","msg":"failed to get default conftest version. Will attempt request scoped lazy loads DEFAULT_CONFTEST_VERSION not set","json":{}} 326 | {"level":"info","ts":"2024-05-01T17:17:03.413Z","caller":"server/server.go:985","msg":"Atlantis started - listening on port 4141","json":{}} 327 | {"level":"info","ts":"2024-05-01T17:17:03.413Z","caller":"scheduled/executor_service.go:51","msg":"Scheduled Executor Service started","json":{}} 328 | ``` 329 | 330 | 1. Run a second deployment without the extra configuration file. E.g.: 331 | 332 | ```sh 333 | helm upgrade -i atlantis runatlantis/atlantis --version 5.0.0 -f my-config.yaml 334 | ``` 335 | 336 | 1. Remove the old `persistentVolumeClaim`: 337 | 338 | ```sh 339 | kubectl delete persistentvolumeclaims atlantis-data-atlantis-0 --namespace atlantis 340 | ``` 341 | 342 | 1. For atlantis deployments managed by GitOps solutions such as ArgoCD, the automatic synchronization can now be enabled 343 | 344 | ### From `4.0.*` to `4.1.*` 345 | 346 | - The following value are deprecated: 347 | - `dataStorage` 348 | - `storageClassName` 349 | 350 | - In favor of the new working way: 351 | - `volumeClaim.enabled` 352 | - `volumeClaim.dataStorage` 353 | - `volumeClaim.storageClassName` 354 | 355 | ### From `2.*` to `3.*` 356 | 357 | - The following value names have been removed. They are replaced by [Server-side Repository Configuration](https://www.runatlantis.io/docs/server-side-repo-config.html) 358 | - `requireApproval` 359 | - `requireMergeable` 360 | - `allowRepoConfig` 361 | 362 | To replicate your previous configuration, run Atlantis locally with your previous flags and Atlantis will print out the equivalent repo-config, for example: 363 | 364 | ```bash 365 | $ atlantis server --allow-repo-config --require-approval --require-mergeable --gh-user=foo --gh-token=bar --repo-allowlist='*' 366 | WARNING: Flags --require-approval, --require-mergeable and --allow-repo-config have been deprecated. 367 | Create a --repo-config file with the following config instead: 368 | 369 | --- 370 | repos: 371 | - id: /.*/ 372 | apply_requirements: [approved, mergeable] 373 | allowed_overrides: [apply_requirements, workflow] 374 | allow_custom_workflows: true 375 | 376 | or use --repo-config-json='{"repos":[{"id":"/.*/", "apply_requirements":["approved", "mergeable"], "allowed_overrides":["apply_requirements","workflow"], "allow_custom_workflows":true}]}' 377 | ``` 378 | 379 | Then use this YAML in the new repoConfig value: 380 | 381 | ```yaml 382 | repoConfig: | 383 | --- 384 | repos: 385 | - id: /.*/ 386 | apply_requirements: [approved, mergeable] 387 | allowed_overrides: [apply_requirements, workflow] 388 | allow_custom_workflows: true 389 | ``` 390 | 391 | ### From `1.*` to `2.*` 392 | 393 | - The following value names have changed: 394 | - `allow_repo_config` => `allowRepoConfig` 395 | - `atlantis_data_storage` => `dataStorage` **NOTE: more than just a snake_case change** 396 | - `atlantis_data_storageClass` => `storageClassName` **NOTE: more than just a snake_case change** 397 | - `bitbucket.base_url` => `bitbucket.baseURL` 398 | 399 | ## Testing the Deployment 400 | 401 | To perform a smoke test of the deployment (i.e. ensure that the Atlantis UI is up and running): 402 | 403 | 1. Install the chart. Supply your own values file or use `test-values.yaml`, which has a minimal set of values required in order for Atlantis to start. 404 | 405 | ```bash 406 | helm install -f test-values.yaml my-atlantis oci://ghcr.io/runatlantis/charts/atlantis --debug 407 | ``` 408 | 409 | 1. Run the tests: 410 | 411 | ```bash 412 | helm test my-atlantis 413 | ``` 414 | 415 | ## Update documentation 416 | 417 | Documentation is auto-generated using [helm-docs](https://github.com/norwoodj/helm-docs). 418 | 419 | To update run the following (from the root path of the repository): 420 | 421 | 1. If required, update `charts/atlantis/README.md.gotmpl` 422 | 2. Run `make docs` 423 | 424 | ## Run unit tests 425 | 426 | From the root of the repository, run: 427 | 428 | ```sh 429 | make unit-test-run-atlantis 430 | ``` 431 | 432 | ---------------------------------------------- 433 | Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2) 434 | -------------------------------------------------------------------------------- /charts/atlantis/tests/statefulset_test.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | suite: test statefulset 3 | templates: 4 | - configmap-config.yaml 5 | - configmap-repo-config.yaml 6 | - statefulset.yaml 7 | chart: 8 | appVersion: test-appVersion 9 | release: 10 | name: my-release 11 | tests: 12 | - it: default values 13 | template: statefulset.yaml 14 | asserts: 15 | - isKind: 16 | of: StatefulSet 17 | - equal: 18 | path: apiVersion 19 | value: apps/v1 20 | - equal: 21 | path: metadata.name 22 | value: my-release-atlantis 23 | - equal: 24 | path: metadata.labels.app 25 | value: atlantis 26 | - matchRegex: 27 | path: metadata.labels.chart 28 | pattern: ^atlantis- 29 | - equal: 30 | path: metadata.labels.heritage 31 | value: Helm 32 | - equal: 33 | path: metadata.labels.release 34 | value: my-release 35 | - notExists: 36 | path: metadata.annotations 37 | - equal: 38 | path: spec.serviceName 39 | value: my-release-atlantis 40 | - equal: 41 | path: spec.replicas 42 | value: 1 43 | - equal: 44 | path: spec.selector 45 | value: 46 | matchLabels: 47 | app: atlantis 48 | release: my-release 49 | - equal: 50 | path: spec.template.metadata.labels 51 | value: 52 | app: atlantis 53 | release: my-release 54 | - equal: 55 | path: spec.template.metadata.annotations 56 | value: 57 | checksum/config: 01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b 58 | checksum/repo-config: 01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b 59 | - notExists: 60 | path: spec.template.spec.hostAliases 61 | - equal: 62 | path: spec.template.spec.hostNetwork 63 | value: false 64 | - equal: 65 | path: spec.template.spec.serviceAccountName 66 | value: my-release-atlantis 67 | - equal: 68 | path: spec.template.spec.shareProcessNamespace 69 | value: false 70 | - equal: 71 | path: spec.template.spec.automountServiceAccountToken 72 | value: true 73 | - notExists: 74 | path: spec.template.spec.terminationGracePeriodSeconds 75 | - equal: 76 | path: spec.template.spec.securityContext 77 | value: 78 | fsGroup: 1000 79 | fsGroupChangePolicy: OnRootMismatch 80 | runAsUser: 100 81 | - notExists: 82 | path: spec.template.spec.priorityClassName 83 | - equal: 84 | path: spec.template.spec.volumes 85 | value: 86 | - name: atlantis-data 87 | persistentVolumeClaim: 88 | claimName: my-release-atlantis-data 89 | - notExists: 90 | path: spec.template.spec.imagePullSecrets 91 | - notExists: 92 | path: spec.template.spec.initContainers 93 | - equal: 94 | path: spec.template.spec.containers[0].name 95 | value: atlantis 96 | - equal: 97 | path: spec.template.spec.containers[0].image 98 | value: ghcr.io/runatlantis/atlantis:test-appVersion 99 | - equal: 100 | path: spec.template.spec.containers[0].imagePullPolicy 101 | value: Always 102 | - notExists: 103 | path: spec.template.spec.containers[0].securityContext 104 | - equal: 105 | path: spec.template.spec.containers[0].args 106 | value: 107 | - server 108 | - equal: 109 | path: spec.template.spec.containers[0].ports 110 | value: 111 | - containerPort: 4141 112 | name: atlantis 113 | - notExists: 114 | path: spec.template.spec.containers[0].lifecycle 115 | - notExists: 116 | path: spec.template.spec.containers[0].envFrom 117 | - equal: 118 | path: spec.template.spec.containers[0].env 119 | value: 120 | - name: PATH 121 | value: /plugins:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin 122 | - name: ATLANTIS_DEFAULT_TF_DISTRIBUTION 123 | value: terraform 124 | - name: ATLANTIS_DATA_DIR 125 | value: /atlantis-data 126 | - name: ATLANTIS_REPO_ALLOWLIST 127 | value: 128 | - name: ATLANTIS_PORT 129 | value: "4141" 130 | - name: ATLANTIS_ATLANTIS_URL 131 | value: http:// 132 | - equal: 133 | path: spec.template.spec.containers[0].livenessProbe 134 | value: 135 | failureThreshold: 5 136 | httpGet: 137 | path: /healthz 138 | port: 4141 139 | scheme: HTTP 140 | initialDelaySeconds: 5 141 | periodSeconds: 60 142 | successThreshold: 1 143 | timeoutSeconds: 5 144 | - equal: 145 | path: spec.template.spec.containers[0].readinessProbe 146 | value: 147 | failureThreshold: 5 148 | httpGet: 149 | path: /healthz 150 | port: 4141 151 | scheme: HTTP 152 | initialDelaySeconds: 5 153 | periodSeconds: 60 154 | successThreshold: 1 155 | timeoutSeconds: 5 156 | - equal: 157 | path: spec.template.spec.containers[0].volumeMounts 158 | value: 159 | - mountPath: /atlantis-data 160 | name: atlantis-data 161 | - isNullOrEmpty: 162 | path: spec.template.spec.containers[0].resources 163 | - notExists: 164 | path: spec.template.spec.nodeSelector 165 | - notExists: 166 | path: spec.template.spec.tolerations 167 | - notExists: 168 | path: spec.template.spec.topologySpreadConstraints 169 | - notExists: 170 | path: spec.template.spec.updateStrategy 171 | - notExists: 172 | path: spec.volumeClaimTemplates 173 | - it: custom port values 174 | template: statefulset.yaml 175 | set: 176 | service: 177 | targetPort: 8888 178 | asserts: 179 | - equal: 180 | path: spec.template.spec.containers[0].ports 181 | value: 182 | - containerPort: 8888 183 | name: atlantis 184 | - equal: 185 | path: spec.template.spec.containers[0].env 186 | value: 187 | - name: PATH 188 | value: /plugins:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin 189 | - name: ATLANTIS_DEFAULT_TF_DISTRIBUTION 190 | value: terraform 191 | - name: ATLANTIS_DATA_DIR 192 | value: /atlantis-data 193 | - name: ATLANTIS_REPO_ALLOWLIST 194 | value: 195 | - name: ATLANTIS_PORT 196 | value: "8888" 197 | - name: ATLANTIS_ATLANTIS_URL 198 | value: http:// 199 | - equal: 200 | path: spec.template.spec.containers[0].livenessProbe 201 | value: 202 | failureThreshold: 5 203 | httpGet: 204 | path: /healthz 205 | port: 8888 206 | scheme: HTTP 207 | initialDelaySeconds: 5 208 | periodSeconds: 60 209 | successThreshold: 1 210 | timeoutSeconds: 5 211 | - equal: 212 | path: spec.template.spec.containers[0].readinessProbe 213 | value: 214 | failureThreshold: 5 215 | httpGet: 216 | path: /healthz 217 | port: 8888 218 | scheme: HTTP 219 | initialDelaySeconds: 5 220 | periodSeconds: 60 221 | successThreshold: 1 222 | timeoutSeconds: 5 223 | - it: replicaCount 224 | template: statefulset.yaml 225 | set: 226 | replicaCount: 2 227 | asserts: 228 | - equal: 229 | path: spec.replicas 230 | value: 2 231 | - it: hostAliases 232 | template: statefulset.yaml 233 | set: 234 | hostAliases: 235 | - hostnames: 236 | - aaa.com 237 | - test.ccc.com 238 | ip: 10.0.0.0 239 | - hostnames: 240 | - bbb.com 241 | ip: 10.0.0.2 242 | asserts: 243 | - equal: 244 | path: spec.template.spec.hostAliases 245 | value: 246 | - hostnames: 247 | - aaa.com 248 | - test.ccc.com 249 | ip: 10.0.0.0 250 | - hostnames: 251 | - bbb.com 252 | ip: 10.0.0.2 253 | - it: hostNetwork 254 | template: statefulset.yaml 255 | set: 256 | hostNetwork: true 257 | asserts: 258 | - equal: 259 | path: spec.template.spec.hostNetwork 260 | value: true 261 | - it: serviceAccountName 262 | template: statefulset.yaml 263 | set: 264 | serviceAccount.name: atlantis-sa 265 | asserts: 266 | - equal: 267 | path: spec.template.spec.serviceAccountName 268 | value: atlantis-sa 269 | - it: shareProcessNamespace 270 | template: statefulset.yaml 271 | set: 272 | statefulSet.shareProcessNamespace: true 273 | asserts: 274 | - equal: 275 | path: spec.template.spec.shareProcessNamespace 276 | value: true 277 | - it: automountServiceAccountToken 278 | template: statefulset.yaml 279 | set: 280 | serviceAccount.mount: false 281 | asserts: 282 | - equal: 283 | path: spec.template.spec.automountServiceAccountToken 284 | value: false 285 | - it: tlsSecretName 286 | template: statefulset.yaml 287 | set: 288 | tlsSecretName: test-tls 289 | asserts: 290 | - equal: 291 | path: spec.template.spec.volumes[1] 292 | value: 293 | name: tls 294 | secret: 295 | secretName: test-tls 296 | - equal: 297 | path: spec.template.spec.containers[0].volumeMounts[?(@.name == "tls")] 298 | value: 299 | mountPath: /etc/tls/ 300 | name: tls 301 | - contains: 302 | path: spec.template.spec.containers[0].env 303 | content: 304 | name: ATLANTIS_SSL_CERT_FILE 305 | value: /etc/tls/tls.crt 306 | - contains: 307 | path: spec.template.spec.containers[0].env 308 | content: 309 | name: ATLANTIS_SSL_KEY_FILE 310 | value: /etc/tls/tls.key 311 | - it: serviceAccountSecrets 312 | template: statefulset.yaml 313 | set: 314 | serviceAccountSecrets: 315 | credentials: VG9ueSBTb3ByYW5v 316 | credentials-staging: Q2FybWVsYSBTb3ByYW5v 317 | asserts: 318 | - equal: 319 | path: spec.template.spec.volumes[1] 320 | value: 321 | name: credentials-volume 322 | secret: 323 | secretName: credentials 324 | - equal: 325 | path: spec.template.spec.volumes[2] 326 | value: 327 | name: credentials-staging-volume 328 | secret: 329 | secretName: credentials-staging 330 | - equal: 331 | path: spec.template.spec.containers[0].volumeMounts[?(@.name == 332 | "credentials-volume")] 333 | value: 334 | mountPath: /etc/credentials 335 | name: credentials-volume 336 | readOnly: true 337 | - equal: 338 | path: spec.template.spec.containers[0].volumeMounts[?(@.name == 339 | "credentials-staging-volume")] 340 | value: 341 | mountPath: /etc/credentials-staging 342 | name: credentials-staging-volume 343 | readOnly: true 344 | - it: googleServiceAccountSecrets 345 | template: statefulset.yaml 346 | set: 347 | googleServiceAccountSecrets: 348 | - name: gcp-ci 349 | secretName: gcp-ci-secret 350 | - name: gcp-staging 351 | secretName: gcp-staging-secret 352 | asserts: 353 | - equal: 354 | path: spec.template.spec.volumes[1] 355 | value: 356 | name: gcp-ci 357 | secret: 358 | secretName: gcp-ci-secret 359 | - equal: 360 | path: spec.template.spec.volumes[2] 361 | value: 362 | name: gcp-staging 363 | secret: 364 | secretName: gcp-staging-secret 365 | - equal: 366 | path: spec.template.spec.containers[0].volumeMounts[?(@.name == "gcp-ci")] 367 | value: 368 | mountPath: /var/secrets/gcp-ci 369 | name: gcp-ci 370 | readOnly: true 371 | - equal: 372 | path: spec.template.spec.containers[0].volumeMounts[?(@.name == "gcp-staging")] 373 | value: 374 | mountPath: /var/secrets/gcp-staging 375 | name: gcp-staging 376 | readOnly: true 377 | - it: gitconfig-read-only 378 | template: statefulset.yaml 379 | set: 380 | gitconfig: | 381 | [url "https://YOUR_GH_TOKEN@github.com"] 382 | insteadOf = https://github.com 383 | gitconfigReadOnly: true 384 | asserts: 385 | - equal: 386 | path: spec.template.spec.volumes[1] 387 | value: 388 | name: gitconfig-volume 389 | secret: 390 | secretName: my-release-atlantis-gitconfig 391 | - equal: 392 | path: spec.template.spec.containers[0].volumeMounts[?(@.name == 393 | "gitconfig-volume")] 394 | value: 395 | mountPath: /home/atlantis/.gitconfig 396 | name: gitconfig-volume 397 | readOnly: true 398 | subPath: gitconfig 399 | - it: gitconfig-read-write 400 | template: statefulset.yaml 401 | set: 402 | gitconfig: | 403 | [url "https://YOUR_GH_TOKEN@github.com"] 404 | insteadOf = https://github.com 405 | gitconfigReadOnly: false 406 | asserts: 407 | - equal: 408 | path: spec.template.spec.volumes[?(@.name == "gitconfig-volume")] 409 | value: 410 | name: gitconfig-volume 411 | secret: 412 | secretName: my-release-atlantis-gitconfig 413 | - equal: 414 | path: spec.template.spec.volumes[?(@.name == "gitconfig-init")] 415 | value: 416 | name: gitconfig-init 417 | configMap: 418 | name: my-release-atlantis-gitconfig-init 419 | items: 420 | - key: gitconfig-init.sh 421 | path: gitconfig-init.sh 422 | mode: 0555 423 | - equal: 424 | path: spec.template.spec.containers[0].volumeMounts[?(@.name == 425 | "gitconfig-volume")] 426 | value: 427 | mountPath: /etc/.gitconfig 428 | name: gitconfig-volume 429 | readOnly: true 430 | subPath: gitconfig 431 | - equal: 432 | path: spec.template.spec.containers[0].volumeMounts[?(@.name == 433 | "gitconfig-init")] 434 | value: 435 | mountPath: /docker-entrypoint.d/gitconfig-init.sh 436 | name: gitconfig-init 437 | subPath: gitconfig-init.sh 438 | - it: gitconfigSecretName 439 | template: statefulset.yaml 440 | set: 441 | gitconfigSecretName: atlantis-gitconfig 442 | asserts: 443 | - equal: 444 | path: spec.template.spec.volumes[1] 445 | value: 446 | name: gitconfig-volume 447 | secret: 448 | secretName: atlantis-gitconfig 449 | - equal: 450 | path: spec.template.spec.containers[0].volumeMounts[?(@.name == 451 | "gitconfig-volume")] 452 | value: 453 | mountPath: /home/atlantis/.gitconfig 454 | name: gitconfig-volume 455 | readOnly: true 456 | subPath: gitconfig 457 | - it: netrc 458 | template: statefulset.yaml 459 | set: 460 | netrc: | 461 | machine artifactory.myapp.com login YOUR_USERNAME password YOUR_PASSWORD 462 | machine bitbucket.myapp.com login YOUR_USERNAME password YOUR_PASSWORD 463 | asserts: 464 | - equal: 465 | path: spec.template.spec.volumes[1] 466 | value: 467 | name: netrc-volume 468 | secret: 469 | secretName: my-release-atlantis-netrc 470 | - equal: 471 | path: spec.template.spec.containers[0].volumeMounts[?(@.name == "netrc-volume")] 472 | value: 473 | mountPath: /home/atlantis/.netrc 474 | name: netrc-volume 475 | readOnly: true 476 | subPath: netrc 477 | - it: netrcSecretName 478 | template: statefulset.yaml 479 | set: 480 | netrcSecretName: atlantis-netrc 481 | asserts: 482 | - equal: 483 | path: spec.template.spec.volumes[1] 484 | value: 485 | name: netrc-volume 486 | secret: 487 | secretName: atlantis-netrc 488 | - equal: 489 | path: spec.template.spec.containers[0].volumeMounts[?(@.name == "netrc-volume")] 490 | value: 491 | mountPath: /home/atlantis/.netrc 492 | name: netrc-volume 493 | readOnly: true 494 | subPath: netrc 495 | - it: aws 496 | template: statefulset.yaml 497 | set: 498 | aws: 499 | credentials: | 500 | [default] 501 | aws_access_key_id=YOUR_ACCESS_KEY_ID 502 | aws_secret_access_key=YOUR_SECRET_ACCESS_KEY 503 | region=us-east-1 504 | config: | 505 | [profile a_role_to_assume] 506 | role_arn = arn:aws:iam::123456789:role/service-role/roleToAssume 507 | source_profile = default 508 | asserts: 509 | - equal: 510 | path: spec.template.spec.volumes[1] 511 | value: 512 | name: aws-volume 513 | secret: 514 | secretName: my-release-atlantis-aws 515 | - equal: 516 | path: spec.template.spec.containers[0].volumeMounts[?(@.name == "aws-volume")] 517 | value: 518 | mountPath: /home/atlantis/.aws 519 | name: aws-volume 520 | readOnly: true 521 | - it: aws directory 522 | template: statefulset.yaml 523 | set: 524 | aws: 525 | directory: /etc/aws_config 526 | asserts: 527 | - contains: 528 | path: spec.template.spec.containers[0].env 529 | content: 530 | name: AWS_CONFIG_FILE 531 | value: /etc/aws_config/config 532 | - contains: 533 | path: spec.template.spec.containers[0].env 534 | content: 535 | name: AWS_SHARED_CREDENTIALS_FILE 536 | value: /etc/aws_config/credentials 537 | - it: awsSecretName 538 | template: statefulset.yaml 539 | set: 540 | awsSecretName: atlantis-aws 541 | asserts: 542 | - equal: 543 | path: spec.template.spec.volumes[1] 544 | value: 545 | name: aws-volume 546 | secret: 547 | secretName: atlantis-aws 548 | - equal: 549 | path: spec.template.spec.containers[0].volumeMounts[?(@.name == "aws-volume")] 550 | value: 551 | mountPath: /home/atlantis/.aws 552 | name: aws-volume 553 | readOnly: true 554 | - it: githubApp 555 | template: statefulset.yaml 556 | set: 557 | githubApp: 558 | id: 123456 559 | slug: foo 560 | key: | 561 | -----BEGIN PRIVATE KEY----- 562 | ... 563 | -----END PRIVATE KEY----- 564 | secret: baz 565 | asserts: 566 | - equal: 567 | path: spec.template.spec.volumes[1] 568 | value: 569 | name: github-app-key-volume 570 | secret: 571 | items: 572 | - key: key.pem 573 | path: key.pem 574 | secretName: my-release-atlantis-webhook 575 | - equal: 576 | path: spec.template.spec.containers[0].volumeMounts[?(@.name == 577 | "github-app-key-volume")] 578 | value: 579 | mountPath: /var/github-app 580 | name: github-app-key-volume 581 | readOnly: true 582 | - contains: 583 | path: spec.template.spec.containers[0].env 584 | content: 585 | name: ATLANTIS_GH_APP_ID 586 | value: "123456" 587 | - contains: 588 | path: spec.template.spec.containers[0].env 589 | content: 590 | name: ATLANTIS_GH_APP_SLUG 591 | value: foo 592 | - contains: 593 | path: spec.template.spec.containers[0].env 594 | content: 595 | name: ATLANTIS_GH_WEBHOOK_SECRET 596 | valueFrom: 597 | secretKeyRef: 598 | key: github_secret 599 | name: my-release-atlantis-webhook 600 | - contains: 601 | path: spec.template.spec.containers[0].env 602 | content: 603 | name: ATLANTIS_GH_APP_KEY_FILE 604 | value: /var/github-app/key.pem 605 | - it: githubApp vcsSecretName 606 | template: statefulset.yaml 607 | set: 608 | vcsSecretName: atlantis-vcs 609 | githubApp: 610 | id: 123456 611 | slug: foo 612 | asserts: 613 | - equal: 614 | path: spec.template.spec.volumes[1] 615 | value: 616 | name: github-app-key-volume 617 | secret: 618 | items: 619 | - key: key.pem 620 | path: key.pem 621 | secretName: atlantis-vcs 622 | - equal: 623 | path: spec.template.spec.containers[0].volumeMounts[?(@.name == 624 | "github-app-key-volume")] 625 | value: 626 | mountPath: /var/github-app 627 | name: github-app-key-volume 628 | readOnly: true 629 | - contains: 630 | path: spec.template.spec.containers[0].env 631 | content: 632 | name: ATLANTIS_GH_WEBHOOK_SECRET 633 | valueFrom: 634 | secretKeyRef: 635 | key: github_secret 636 | name: atlantis-vcs 637 | - contains: 638 | path: spec.template.spec.containers[0].env 639 | content: 640 | name: ATLANTIS_GH_APP_KEY_FILE 641 | value: /var/github-app/key.pem 642 | - it: gitea 643 | template: statefulset.yaml 644 | set: 645 | gitea: 646 | user: foo 647 | token: bar 648 | secret: baz 649 | asserts: 650 | - contains: 651 | path: spec.template.spec.containers[0].env 652 | content: 653 | name: ATLANTIS_GITEA_USER 654 | value: foo 655 | - contains: 656 | path: spec.template.spec.containers[0].env 657 | content: 658 | name: ATLANTIS_GITEA_TOKEN 659 | valueFrom: 660 | secretKeyRef: 661 | key: gitea_token 662 | name: my-release-atlantis-webhook 663 | - contains: 664 | path: spec.template.spec.containers[0].env 665 | content: 666 | name: ATLANTIS_GITEA_WEBHOOK_SECRET 667 | valueFrom: 668 | secretKeyRef: 669 | key: gitea_secret 670 | name: my-release-atlantis-webhook 671 | - it: gitlab 672 | template: statefulset.yaml 673 | set: 674 | gitlab: 675 | user: foo 676 | token: bar 677 | secret: baz 678 | asserts: 679 | - contains: 680 | path: spec.template.spec.containers[0].env 681 | content: 682 | name: ATLANTIS_GITLAB_USER 683 | value: foo 684 | - contains: 685 | path: spec.template.spec.containers[0].env 686 | content: 687 | name: ATLANTIS_GITLAB_TOKEN 688 | valueFrom: 689 | secretKeyRef: 690 | key: gitlab_token 691 | name: my-release-atlantis-webhook 692 | - contains: 693 | path: spec.template.spec.containers[0].env 694 | content: 695 | name: ATLANTIS_GITLAB_WEBHOOK_SECRET 696 | valueFrom: 697 | secretKeyRef: 698 | key: gitlab_secret 699 | name: my-release-atlantis-webhook 700 | - it: bitbucket 701 | template: statefulset.yaml 702 | set: 703 | bitbucket: 704 | user: foo 705 | token: bar 706 | asserts: 707 | - contains: 708 | path: spec.template.spec.containers[0].env 709 | content: 710 | name: ATLANTIS_BITBUCKET_USER 711 | value: foo 712 | - contains: 713 | path: spec.template.spec.containers[0].env 714 | content: 715 | name: ATLANTIS_BITBUCKET_TOKEN 716 | valueFrom: 717 | secretKeyRef: 718 | key: bitbucket_token 719 | name: my-release-atlantis-webhook 720 | - it: bitbucket server 721 | template: statefulset.yaml 722 | set: 723 | bitbucket: 724 | user: foo 725 | token: bar 726 | secret: baz 727 | baseURL: https://bitbucket.yourorganization.com 728 | asserts: 729 | - contains: 730 | path: spec.template.spec.containers[0].env 731 | content: 732 | name: ATLANTIS_BITBUCKET_WEBHOOK_SECRET 733 | valueFrom: 734 | secretKeyRef: 735 | key: bitbucket_secret 736 | name: my-release-atlantis-webhook 737 | - contains: 738 | path: spec.template.spec.containers[0].env 739 | content: 740 | name: ATLANTIS_BITBUCKET_BASE_URL 741 | value: https://bitbucket.yourorganization.com 742 | - it: azuredevops 743 | template: statefulset.yaml 744 | set: 745 | azuredevops: 746 | user: foo 747 | token: bar 748 | webhookUser: bobby 749 | webhookPassword: bacala 750 | asserts: 751 | - contains: 752 | path: spec.template.spec.containers[0].env 753 | content: 754 | name: ATLANTIS_AZUREDEVOPS_USER 755 | value: foo 756 | - contains: 757 | path: spec.template.spec.containers[0].env 758 | content: 759 | name: ATLANTIS_AZUREDEVOPS_TOKEN 760 | valueFrom: 761 | secretKeyRef: 762 | key: azuredevops_token 763 | name: my-release-atlantis-webhook 764 | - contains: 765 | path: spec.template.spec.containers[0].env 766 | content: 767 | name: ATLANTIS_AZUREDEVOPS_WEBHOOK_USER 768 | value: bobby 769 | - contains: 770 | path: spec.template.spec.containers[0].env 771 | content: 772 | name: ATLANTIS_AZUREDEVOPS_WEBHOOK_PASSWORD 773 | valueFrom: 774 | secretKeyRef: 775 | key: azuredevops_webhook_password 776 | name: my-release-atlantis-webhook 777 | - it: basicAuth 778 | template: statefulset.yaml 779 | set: 780 | basicAuth: 781 | username: atlantis 782 | password: forever 783 | asserts: 784 | - contains: 785 | path: spec.template.spec.containers[0].env 786 | content: 787 | name: ATLANTIS_WEB_BASIC_AUTH 788 | value: "true" 789 | - contains: 790 | path: spec.template.spec.containers[0].env 791 | content: 792 | name: ATLANTIS_WEB_USERNAME 793 | valueFrom: 794 | secretKeyRef: 795 | key: username 796 | name: my-release-atlantis-basic-auth 797 | - contains: 798 | path: spec.template.spec.containers[0].env 799 | content: 800 | name: ATLANTIS_WEB_PASSWORD 801 | valueFrom: 802 | secretKeyRef: 803 | key: password 804 | name: my-release-atlantis-basic-auth 805 | - it: basicAuthSecretName 806 | template: statefulset.yaml 807 | set: 808 | basicAuthSecretName: atlantis-basic-auth 809 | asserts: 810 | - contains: 811 | path: spec.template.spec.containers[0].env 812 | content: 813 | name: ATLANTIS_WEB_BASIC_AUTH 814 | value: "true" 815 | - contains: 816 | path: spec.template.spec.containers[0].env 817 | content: 818 | name: ATLANTIS_WEB_USERNAME 819 | valueFrom: 820 | secretKeyRef: 821 | key: username 822 | name: atlantis-basic-auth 823 | - contains: 824 | path: spec.template.spec.containers[0].env 825 | content: 826 | name: ATLANTIS_WEB_PASSWORD 827 | valueFrom: 828 | secretKeyRef: 829 | key: password 830 | name: atlantis-basic-auth 831 | - it: apiSecret 832 | template: statefulset.yaml 833 | set: 834 | api.secret: spongebob 835 | asserts: 836 | - contains: 837 | path: spec.template.spec.containers[0].env 838 | content: 839 | name: ATLANTIS_API_SECRET 840 | valueFrom: 841 | secretKeyRef: 842 | key: apisecret 843 | name: my-release-atlantis-api 844 | - it: apiSecretSecretName 845 | template: statefulset.yaml 846 | set: 847 | apiSecretName: atlantis-api 848 | asserts: 849 | - contains: 850 | path: spec.template.spec.containers[0].env 851 | content: 852 | name: ATLANTIS_API_SECRET 853 | valueFrom: 854 | secretKeyRef: 855 | key: apisecret 856 | name: atlantis-api 857 | - it: redisHost 858 | template: statefulset.yaml 859 | set: 860 | redis.host: my-redis 861 | asserts: 862 | - contains: 863 | path: spec.template.spec.containers[0].env 864 | content: 865 | name: ATLANTIS_REDIS_HOST 866 | value: my-redis 867 | - it: redisPassword 868 | template: statefulset.yaml 869 | set: 870 | redis.password: SuperSecretPassword 871 | asserts: 872 | - contains: 873 | path: spec.template.spec.containers[0].env 874 | content: 875 | name: ATLANTIS_REDIS_PASSWORD 876 | valueFrom: 877 | secretKeyRef: 878 | name: my-release-atlantis-redis 879 | key: password 880 | - it: redisSecretName 881 | template: statefulset.yaml 882 | set: 883 | redisSecretName: existing-secret 884 | asserts: 885 | - contains: 886 | path: spec.template.spec.containers[0].env 887 | content: 888 | name: ATLANTIS_REDIS_PASSWORD 889 | valueFrom: 890 | secretKeyRef: 891 | name: existing-secret 892 | key: password 893 | - it: redisSecretPasswordKey 894 | template: statefulset.yaml 895 | set: 896 | redisSecretName: my-secret 897 | redisSecretPasswordKey: my-password-key 898 | asserts: 899 | - contains: 900 | path: spec.template.spec.containers[0].env 901 | content: 902 | name: ATLANTIS_REDIS_PASSWORD 903 | valueFrom: 904 | secretKeyRef: 905 | name: my-secret 906 | key: my-password-key 907 | - it: redisPort 908 | template: statefulset.yaml 909 | set: 910 | redis.port: 1234 911 | asserts: 912 | - contains: 913 | path: spec.template.spec.containers[0].env 914 | content: 915 | name: ATLANTIS_REDIS_PORT 916 | value: "1234" 917 | - it: redisDb 918 | template: statefulset.yaml 919 | set: 920 | redis.db: 1 921 | asserts: 922 | - contains: 923 | path: spec.template.spec.containers[0].env 924 | content: 925 | name: ATLANTIS_REDIS_DB 926 | value: "1" 927 | - it: redisTlsEnabled 928 | template: statefulset.yaml 929 | set: 930 | redis.tlsEnabled: true 931 | asserts: 932 | - contains: 933 | path: spec.template.spec.containers[0].env 934 | content: 935 | name: ATLANTIS_REDIS_TLS_ENABLED 936 | value: "true" 937 | - it: redisInsecureSkipVerify 938 | template: statefulset.yaml 939 | set: 940 | redis.insecureSkipVerify: true 941 | asserts: 942 | - contains: 943 | path: spec.template.spec.containers[0].env 944 | content: 945 | name: ATLANTIS_REDIS_INSECURE_SKIP_VERIFY 946 | value: "true" 947 | - it: command 948 | template: statefulset.yaml 949 | set: 950 | command: 951 | - printenv 952 | asserts: 953 | - equal: 954 | path: spec.template.spec.containers[0].command 955 | value: 956 | - printenv 957 | - it: commonLabels 958 | template: statefulset.yaml 959 | set: 960 | commonLabels: 961 | team: infra 962 | asserts: 963 | - equal: 964 | path: metadata.labels.team 965 | value: infra 966 | - it: liveneessProbe false 967 | template: statefulset.yaml 968 | set: 969 | livenessProbe: 970 | enabled: false 971 | asserts: 972 | - notExists: 973 | path: spec.template.spec.containers[0].livenessProbe 974 | - it: liveneessProbe 975 | template: statefulset.yaml 976 | set: 977 | livenessProbe: 978 | enabled: true 979 | periodSeconds: 10 980 | initialDelaySeconds: 2 981 | timeoutSeconds: 1 982 | successThreshold: 2 983 | failureThreshold: 3 984 | scheme: HTTP 985 | asserts: 986 | - equal: 987 | path: spec.template.spec.containers[0].livenessProbe 988 | value: 989 | failureThreshold: 3 990 | httpGet: 991 | path: /healthz 992 | port: 4141 993 | scheme: HTTP 994 | initialDelaySeconds: 2 995 | periodSeconds: 10 996 | successThreshold: 2 997 | timeoutSeconds: 1 998 | - it: readinessProbe false 999 | template: statefulset.yaml 1000 | set: 1001 | readinessProbe: 1002 | enabled: false 1003 | asserts: 1004 | - notExists: 1005 | path: spec.template.spec.containers[0].readinessProbe 1006 | - it: readinessProbe 1007 | template: statefulset.yaml 1008 | set: 1009 | readinessProbe: 1010 | enabled: true 1011 | periodSeconds: 10 1012 | initialDelaySeconds: 2 1013 | timeoutSeconds: 1 1014 | successThreshold: 2 1015 | failureThreshold: 3 1016 | scheme: HTTP 1017 | asserts: 1018 | - equal: 1019 | path: spec.template.spec.containers[0].readinessProbe 1020 | value: 1021 | failureThreshold: 3 1022 | httpGet: 1023 | path: /healthz 1024 | port: 4141 1025 | scheme: HTTP 1026 | initialDelaySeconds: 2 1027 | periodSeconds: 10 1028 | successThreshold: 2 1029 | timeoutSeconds: 1 1030 | - it: podTemplate 1031 | template: statefulset.yaml 1032 | set: 1033 | podTemplate: 1034 | annotations: 1035 | iam.amazonaws.com/role: arn:aws:iam::123456789123:role/atlantis-role 1036 | labels: 1037 | group: base 1038 | asserts: 1039 | - equal: 1040 | path: spec.template.metadata.labels.group 1041 | value: base 1042 | - equal: 1043 | path: spec.template.metadata.annotations["iam.amazonaws.com/role"] 1044 | value: arn:aws:iam::123456789123:role/atlantis-role 1045 | - it: Statefulset annotations 1046 | template: statefulset.yaml 1047 | set: 1048 | statefulSet.annotations: 1049 | strong-stuff: "true" 1050 | asserts: 1051 | - equal: 1052 | path: metadata.annotations 1053 | value: 1054 | strong-stuff: "true" 1055 | - it: securityContext 1056 | template: statefulset.yaml 1057 | set: 1058 | statefulSet.securityContext: 1059 | runAsUser: 1000 1060 | runAsGroup: 1000 1061 | fsGroup: 1000 1062 | fsGroupChangePolicy: Always 1063 | asserts: 1064 | - equal: 1065 | path: spec.template.spec.securityContext 1066 | value: 1067 | runAsUser: 1000 1068 | runAsGroup: 1000 1069 | fsGroup: 1000 1070 | fsGroupChangePolicy: Always 1071 | - it: priorityClassName 1072 | template: statefulset.yaml 1073 | set: 1074 | statefulSet.priorityClassName: high-priority 1075 | asserts: 1076 | - equal: 1077 | path: spec.template.spec.priorityClassName 1078 | value: high-priority 1079 | - it: updateStrategy 1080 | template: statefulset.yaml 1081 | set: 1082 | statefulSet.updateStrategy: 1083 | type: RollingUpdate 1084 | rollingUpdate: 1085 | partition: 0 1086 | asserts: 1087 | - equal: 1088 | path: spec.updateStrategy 1089 | value: 1090 | type: RollingUpdate 1091 | rollingUpdate: 1092 | partition: 0 1093 | - it: shareProcessNamespace 1094 | template: statefulset.yaml 1095 | set: 1096 | statefulSet.shareProcessNamespace: true 1097 | asserts: 1098 | - equal: 1099 | path: spec.template.spec.shareProcessNamespace 1100 | value: true 1101 | - it: terminationGracePeriodSeconds 1102 | template: statefulset.yaml 1103 | set: 1104 | terminationGracePeriodSeconds: 30 1105 | asserts: 1106 | - equal: 1107 | path: spec.template.spec.terminationGracePeriodSeconds 1108 | value: 30 1109 | - it: extraPath 1110 | template: statefulset.yaml 1111 | set: 1112 | extraPath: "/foo:/bar" 1113 | asserts: 1114 | - equal: 1115 | path: spec.template.spec.containers[0].env 1116 | value: 1117 | - name: PATH 1118 | value: /foo:/bar:/plugins:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin 1119 | - name: ATLANTIS_DEFAULT_TF_DISTRIBUTION 1120 | value: terraform 1121 | - name: ATLANTIS_DATA_DIR 1122 | value: /atlantis-data 1123 | - name: ATLANTIS_REPO_ALLOWLIST 1124 | value: 1125 | - name: ATLANTIS_PORT 1126 | value: "4141" 1127 | - name: ATLANTIS_ATLANTIS_URL 1128 | value: http:// 1129 | - it: sharedDirPath 1130 | template: statefulset.yaml 1131 | set: 1132 | initConfig.sharedDir: "/home/atlantis" 1133 | asserts: 1134 | - equal: 1135 | path: spec.template.spec.containers[0].env 1136 | value: 1137 | - name: PATH 1138 | value: /home/atlantis:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin 1139 | - name: ATLANTIS_DEFAULT_TF_DISTRIBUTION 1140 | value: terraform 1141 | - name: ATLANTIS_DATA_DIR 1142 | value: /atlantis-data 1143 | - name: ATLANTIS_REPO_ALLOWLIST 1144 | value: 1145 | - name: ATLANTIS_PORT 1146 | value: "4141" 1147 | - name: ATLANTIS_ATLANTIS_URL 1148 | value: http:// 1149 | - it: extraPathWithSharedDirPath 1150 | template: statefulset.yaml 1151 | set: 1152 | initConfig.sharedDir: "/home/atlantis" 1153 | extraPath: "/foo:/bar" 1154 | asserts: 1155 | - equal: 1156 | path: spec.template.spec.containers[0].env 1157 | value: 1158 | - name: PATH 1159 | value: /foo:/bar:/home/atlantis:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin 1160 | - name: ATLANTIS_DEFAULT_TF_DISTRIBUTION 1161 | value: terraform 1162 | - name: ATLANTIS_DATA_DIR 1163 | value: /atlantis-data 1164 | - name: ATLANTIS_REPO_ALLOWLIST 1165 | value: 1166 | - name: ATLANTIS_PORT 1167 | value: "4141" 1168 | - name: ATLANTIS_ATLANTIS_URL 1169 | value: http:// 1170 | - it: lifecycle 1171 | template: statefulset.yaml 1172 | set: 1173 | lifecycle: 1174 | preStop: 1175 | exec: 1176 | command: 1177 | - /bin/sh 1178 | - -c 1179 | - while pgrep -x "terraform|tofu|terragrunt" > /dev/null; do sleep 1; done 1180 | asserts: 1181 | - equal: 1182 | path: spec.template.spec.containers[0].lifecycle 1183 | value: 1184 | preStop: 1185 | exec: 1186 | command: 1187 | - /bin/sh 1188 | - -c 1189 | - while pgrep -x "terraform|tofu|terragrunt" > /dev/null; do sleep 1; done 1190 | --------------------------------------------------------------------------------