diff --git a/README.md b/README.md index 12dc4295..2d3ef3bf 100644 --- a/README.md +++ b/README.md @@ -18,14 +18,18 @@ - [Testing the Deployment](#testing-the-deployment) ## Introduction + 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. ## Prerequisites + - Kubernetes 1.9+ - PersistentVolume support ## Required Configuration + In order for Atlantis to start and run successfully: + 1. At least one of the following sets of credentials must be defined: - `github` - `gitlab` @@ -53,6 +57,7 @@ extraManifests: ``` ## Customization + The following options are supported. See [values.yaml](/charts/atlantis/values.yaml) for more detailed documentation and examples: | Parameter | Description | Default | @@ -132,6 +137,7 @@ The following options are supported. See [values.yaml](/charts/atlantis/values.y | `ingress.path` | Path to use in the `Ingress`. Should be set to `/*` if using gce-ingress in Google Cloud. | `/` | | `ingress.tls` | Kubernetes tls block. See [Kubernetes docs](https://kubernetes.io/docs/concepts/services-networking/ingress/#tls) for details. | `[]` | | `initContainers` | Containers used to initialize context for Atlantis pods | `[]` | +| `initConfig` | Init container used to install plugins/providers shared with Atlantis pods | n/a | | `lifecycle` | Configure pod container lifecycle hooks. See [Kubernetes docs](https://kubernetes.io/docs/tasks/configure-pod-container/attach-handler-lifecycle-event/) for details. | `{}` | | `loadEnvFromConfigMaps` | Array of Kubernetes `ConfigMap`s to set all key-value pairs as environment variables. See `values.yaml` for example. | `[]` | | `loadEnvFromSecrets` | Array of Kubernetes secrets to set all key-value pairs as environment variables. See `values.yaml` for example. | `[]` | @@ -189,20 +195,22 @@ The following options are supported. See [values.yaml](/charts/atlantis/values.y ## Upgrading ### From `4.0.*` to `4.1.*` -* The following value are deprecated: - * `dataStorage` - * `storageClassName` -* In favor of the new working way: - * `volumeClaim.enabled` - * `volumeClaim.dataStorage` - * `volumeClaim.storageClassName` + +- The following value are deprecated: + - `dataStorage` + - `storageClassName` + +- In favor of the new working way: + - `volumeClaim.enabled` + - `volumeClaim.dataStorage` + - `volumeClaim.storageClassName` ### From `2.*` to `3.*` -* 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) - * `requireApproval` - * `requireMergeable` - * `allowRepoConfig` +- 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) + - `requireApproval` + - `requireMergeable` + - `allowRepoConfig` To replicate your previous configuration, run Atlantis locally with your previous flags and Atlantis will print out the equivalent repo-config, for example: @@ -234,14 +242,15 @@ repoConfig: | ``` ### From `1.*` to `2.*` -* The following value names have changed: - * `allow_repo_config` => `allowRepoConfig` - * `atlantis_data_storage` => `dataStorage` **NOTE: more than just a snake_case change** - * `atlantis_data_storageClass` => `storageClassName` **NOTE: more than just a snake_case change** - * `bitbucket.base_url` => `bitbucket.baseURL` +- The following value names have changed: + - `allow_repo_config` => `allowRepoConfig` + - `atlantis_data_storage` => `dataStorage` **NOTE: more than just a snake_case change** + - `atlantis_data_storageClass` => `storageClassName` **NOTE: more than just a snake_case change** + - `bitbucket.base_url` => `bitbucket.baseURL` ## Testing the Deployment + To perform a smoke test of the deployment (i.e. ensure that the Atlantis UI is up and running): 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. @@ -252,6 +261,7 @@ To perform a smoke test of the deployment (i.e. ensure that the Atlantis UI is u ``` 1. Run the tests: + ```bash helm test my-atlantis ``` diff --git a/charts/atlantis/Chart.yaml b/charts/atlantis/Chart.yaml index ed81830d..3907e661 100644 --- a/charts/atlantis/Chart.yaml +++ b/charts/atlantis/Chart.yaml @@ -3,7 +3,7 @@ apiVersion: v1 appVersion: v0.26.0 description: A Helm chart for Atlantis https://www.runatlantis.io name: atlantis -version: 4.17.5 +version: 4.18.0 keywords: - terraform home: https://www.runatlantis.io diff --git a/charts/atlantis/ci/ci-init-config-values.yaml b/charts/atlantis/ci/ci-init-config-values.yaml new file mode 100644 index 00000000..f48d3141 --- /dev/null +++ b/charts/atlantis/ci/ci-init-config-values.yaml @@ -0,0 +1,22 @@ +--- +github: + user: foo + token: bar + secret: baz + +service: + type: ClusterIP + +ingress: + enabled: true + ingressClassName: nginx + host: atlantis.localdev.me + path: / +webhook_ingress: + enabled: true + ingressClassName: nginx + host: atlantis-webook.localdev.me + path: /events + +initConfig: + enabled: true diff --git a/charts/atlantis/templates/configmap-init-config.yaml b/charts/atlantis/templates/configmap-init-config.yaml new file mode 100644 index 00000000..6db15a0c --- /dev/null +++ b/charts/atlantis/templates/configmap-init-config.yaml @@ -0,0 +1,11 @@ +{{- if .Values.initConfig.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "atlantis.fullname" . }}-init-config + labels: +{{- include "atlantis.labels" . | nindent 4 }} +data: + init-config.sh: | + {{- .Values.initConfig.script | nindent 4 }} +{{- end -}} diff --git a/charts/atlantis/templates/statefulset.yaml b/charts/atlantis/templates/statefulset.yaml index 1accc53e..76e37382 100644 --- a/charts/atlantis/templates/statefulset.yaml +++ b/charts/atlantis/templates/statefulset.yaml @@ -29,9 +29,12 @@ spec: annotations: checksum/config: {{ include (print $.Template.BasePath "/configmap-config.yaml") . | sha256sum }} checksum/repo-config: {{ include (print $.Template.BasePath "/configmap-repo-config.yaml") . | sha256sum }} - {{- if .Values.podTemplate.annotations }} -{{ toYaml .Values.podTemplate.annotations | indent 8 }} - {{- end }} + {{- if .Values.initConfig.enabled }} + checksum/init-config: {{ include (print $.Template.BasePath "/configmap-init-config.yaml") . | sha256sum }} + {{- end }} + {{- if .Values.podTemplate.annotations }} + {{- toYaml .Values.podTemplate.annotations | nindent 8 }} + {{- end }} spec: {{- if .Values.hostAliases }} hostAliases: @@ -123,7 +126,19 @@ spec: secretName: {{ .Values.customPem }} {{- end }} {{- if .Values.extraVolumes }} -{{ toYaml .Values.extraVolumes | indent 6 }} + {{- toYaml .Values.extraVolumes | nindent 6 }} + {{- end }} + {{- if .Values.initConfig.enabled }} + - name: init-config + configMap: + name: {{ template "atlantis.fullname" . }}-init-config + items: + - key: init-config.sh + path: init-config.sh + mode: 0555 + - name: init-shared-path + emptyDir: + sizeLimit: {{ .Values.initConfig.sizeLimit }} {{- end }} {{- if .Values.imagePullSecrets }} imagePullSecrets: @@ -131,9 +146,30 @@ spec: - name: {{ . }} {{- end }} {{- end }} - {{- if .Values.initContainers }} + {{- if or .Values.initContainers .Values.initConfig.enabled }} initContainers: -{{ toYaml .Values.initContainers | indent 8 }} + {{- with .Values.initContainers }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.initConfig.enabled }} + - name: init-config + image: {{ .Values.initConfig.image }} + imagePullPolicy: {{ .Values.initConfig.pullPolicy }} + command: + - /init-config.sh + workingDir: {{ .Values.initConfig.workDir }} + env: + - name: PATH + value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:{{ .Values.initConfig.sharedDir }} + - name: INIT_SHARED_DIR + value: {{ .Values.initConfig.sharedDir }} + volumeMounts: + - name: init-config + mountPath: /init-config.sh + subPath: init-config.sh + - name: init-shared-path + mountPath: {{ .Values.initConfig.sharedDir }} + {{- end }} {{- end }} containers: - name: {{ .Chart.Name }} @@ -408,6 +444,12 @@ spec: - name: AWS_CONFIG_FILE value: {{ .Values.aws.directory }}/config {{- end }} + {{- if .Values.initConfig.enabled }} + - name: PATH + value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:{{ .Values.initConfig.sharedDir }} + - name: INIT_SHARED_DIR + value: {{ .Values.initConfig.sharedDir }} + {{- end }} {{- if .Values.livenessProbe.enabled }} livenessProbe: httpGet: @@ -499,32 +541,37 @@ spec: subPath: ca-certificates.crt {{- end }} {{- if .Values.extraVolumeMounts }} -{{ toYaml .Values.extraVolumeMounts | indent 10 }} + {{- toYaml .Values.extraVolumeMounts | nindent 10 }} + {{- end }} + {{- if .Values.initConfig.enabled }} + - name: init-shared-path + mountPath: {{ .Values.initConfig.sharedDir }} + readOnly: true {{- end }} resources: -{{ toYaml .Values.resources | indent 12 }} + {{- toYaml .Values.resources | nindent 12 }} {{- with .Values.extraContainers }} {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.nodeSelector }} nodeSelector: -{{ toYaml . | indent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.affinity }} affinity: -{{ toYaml . | indent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.tolerations }} tolerations: -{{ toYaml . | indent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.topologySpreadConstraints }} topologySpreadConstraints: -{{ toYaml . | indent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.statefulSet.updateStrategy }} updateStrategy: -{{ toYaml . | indent 4 }} + {{- toYaml . | nindent 4 }} {{- end }} {{- if .Values.dataStorage }} volumeClaimTemplates: diff --git a/charts/atlantis/values.schema.json b/charts/atlantis/values.schema.json index f8acb5b1..7b7f2b5d 100644 --- a/charts/atlantis/values.schema.json +++ b/charts/atlantis/values.schema.json @@ -977,9 +977,41 @@ "$ref":"#/definitions/io.k8s.api.core.v1.Container" }, "type":"array", - "default":[ - - ] + "default":[] + }, + "initConfig":{ + "type":"object", + "description":"Init container used to install plugins/providers shared with Atlantis pods", + "properties":{ + "enabled":{ + "type":"boolean", + "description":"Enable creation of init config" + }, + "image":{ + "type":"string", + "description":"Container image to use on init configs" + }, + "imagePullPolicy":{ + "type":"string", + "description":"Image pull policy. One of Always, Never, IfNotPresent. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. Cannot be updated. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images" + }, + "sharedDir":{ + "type":"string", + "description":"sharedDir is set as env var INIT_SHARED_DIR" + }, + "workDir":{ + "type":"string", + "description":"Starting directory for the script" + }, + "sizeLimit":{ + "type":"string", + "description":"Size for the init-shared-path emptyDir volume" + }, + "script":{ + "type":"string", + "description":"Script to install tools/providers required by the atlantis pod" + } + } }, "hostAliases":{ "description":"Specify HostAliases for Atlantis containers.", @@ -987,9 +1019,7 @@ "$ref":"#/definitions/io.k8s.api.core.v1.HostAlias" }, "type":"array", - "default":[ - - ], + "default":[], "examples":[ { "ip":"127.0.0.2", diff --git a/charts/atlantis/values.yaml b/charts/atlantis/values.yaml index c9795ff4..090b704b 100644 --- a/charts/atlantis/values.yaml +++ b/charts/atlantis/values.yaml @@ -485,6 +485,41 @@ initContainers: [] # image: alpine:latest # command: ['sh', '-c', 'echo The init container is running! && sleep 10'] +# Install providers/plugins into a path shared with the Atlantis pod +initConfig: + enabled: false + image: alpine:latest + imagePullPolicy: IfNotPresent + # sharedDir is set as env var INIT_SHARED_DIR + sharedDir: /plugins + workDir: /tmp + sizeLimit: 100Mi + # example of how the script can be configured to install tools/providers required by the atlantis pod + script: | + #!/bin/sh + set -eoux pipefail + + # example for terragrunt + TG_VERSION="v0.47.0" + TG_SHA256_SUM="98d45f6bfbfae84b51364c1ad6920f09ecb4d834908b0535e4e331a9fc6fc75b" + TG_FILE="${INIT_SHARED_DIR}/terragrunt" + wget https://github.com/gruntwork-io/terragrunt/releases/download/${TG_VERSION}/terragrunt_linux_amd64 -O "${TG_FILE}" + echo "${TG_SHA256_SUM} ${TG_FILE}" | sha256sum -c + chmod 755 "${TG_FILE}" + terragrunt -v + + # example for terragrunt-atlantis-config + TAC_VERSION="1.16.0" # without v + TAC_SHA256_SUM="fc3b069cf4ae51e9b7a7d01f09862d1974b260fffb3ec857d661d7b1756fe26f" + TAC_FILE="${INIT_SHARED_DIR}/terragrunt-atlantis-config" + wget "https://github.com/transcend-io/terragrunt-atlantis-config/releases/download/v${TAC_VERSION}/terragrunt-atlantis-config_${TAC_VERSION}_linux_amd64.tar.gz" + echo "${TAC_SHA256_SUM} terragrunt-atlantis-config_${TAC_VERSION}_linux_amd64.tar.gz" | sha256sum -c + tar xf "terragrunt-atlantis-config_${TAC_VERSION}_linux_amd64.tar.gz" + cp -fv "terragrunt-atlantis-config_${TAC_VERSION}_linux_amd64/terragrunt-atlantis-config_${TAC_VERSION}_linux_amd64" "${TAC_FILE}" + chmod 755 "${TG_FILE}" + terragrunt-atlantis-config version + + # hostAliases: # - hostnames: # - aaa.com