├── .github ├── FUNDING.yml ├── pull_request_template.md └── workflows │ └── nightly-merge.yml ├── .gitignore ├── .helmignore ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── Chart.lock ├── Chart.yaml ├── LICENSE.md ├── README.md ├── packaging-state ├── README.md ├── ignored-in-concourse └── ignored-in-distribution ├── templates ├── NOTES.txt ├── _helpers.tpl ├── namespace.yaml ├── required-check.yaml ├── web-api-svc.yaml ├── web-configmap.yaml ├── web-deployment.yaml ├── web-ingress.yaml ├── web-podsecuritypolicy.yaml ├── web-prometheus-svc.yaml ├── web-role.yaml ├── web-rolebinding.yaml ├── web-secrets.yaml ├── web-serviceaccount.yaml ├── web-servicemonitor.yaml ├── web-worker-gateway-svc.yaml ├── worker-deployment.yaml ├── worker-horizontal-pod-autoscaler.yaml ├── worker-podsecuritypolicy.yaml ├── worker-policy.yaml ├── worker-prestop-configmap.yaml ├── worker-role.yaml ├── worker-rolebinding.yaml ├── worker-secrets.yaml ├── worker-serviceaccount.yaml ├── worker-statefulset.yaml └── worker-svc.yaml └── values.yaml /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [taylorsilva] 2 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | 8 | 9 | # Existing Issue 10 | 13 | 14 | Fixes # . 15 | 16 | # Why do we need this PR? 17 | 20 | 21 | 22 | # Changes proposed in this pull request 23 | 26 | 27 | * 28 | * 29 | * 30 | 31 | # Contributor Checklist 32 | 35 | - [ ] Variables are documented in the `README.md` 36 | - [ ] Which branch are you merging into? 37 | - `master` is for changes related to the current release of the `concourse/concourse:latest` image and should be good to publish immediately 38 | - `dev` is for changes related to the next release of Concourse (aka unpublished code on `master` in [concourse/concourse](https://github.com/concourse/concourse)) 39 | 40 | 41 | # Reviewer Checklist 42 | > This section is intended for the core maintainers only, to track review progress. Please do not 43 | > fill out this section. 44 | - [ ] Code reviewed 45 | - [ ] Topgun tests run 46 | - [ ] Back-port if needed 47 | - [ ] Is the correct branch targeted? (`master` or `dev`) 48 | -------------------------------------------------------------------------------- /.github/workflows/nightly-merge.yml: -------------------------------------------------------------------------------- 1 | name: 'Merge master into dev' 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | nightly-merge: 10 | 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v1 16 | 17 | - name: Merge master into dev 18 | uses: robotology/gh-action-nightly-merge@v1.4.0 19 | with: 20 | stable_branch: 'master' 21 | development_branch: 'dev' 22 | allow_ff: false 23 | user_name: "Github Action" 24 | user_email: "concourse@pivotal.io" 25 | env: 26 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | charts 2 | .idea 3 | *.iml 4 | # Swap 5 | .*.swp 6 | [._]*.s[a-v][a-z] 7 | !*.svg # comment out if you don't need vector files 8 | [._]*.sw[a-p] 9 | [._]s[a-rt-v][a-z] 10 | [._]ss[a-gi-z] 11 | [._]sw[a-p] 12 | -------------------------------------------------------------------------------- /.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 | *.tmprojt 22 | tests/ 23 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # v6.0.0: 2 | 3 | - added the ability to create worker only and web-only deployments using `web.enabled` and `worker.enabled` 4 | - **[breaking]** worker and web secrets are now separated into 2 different templates, `worker-secrets.yaml` and `web-secrets.yaml`. Users bringing their own secrets will have to split them into 2 different k8s objects. 5 | 6 | # v7.0.0: 7 | 8 | - upgraded the PostgreSQL Chart (direct dependency of this Chart) from `0.13.1` to `5.3.8`. As various values (like `postgresUser`) changed (to, for instance, `postgresqlUsername`), a major bump was needed. 9 | 10 | # v8.0.0: 11 | 12 | - changed the format for worker-only deployments from `concourse.worker.tsa.host` and `concourse.worker.tsa.port` to `concourse.worker.tsa.hosts` to take in an array of parameters. 13 | 14 | # v9.0.0: 15 | 16 | - changed the input format for `concourse.web.auth.mainTeam.config`. Previously you would pass the path to a YAML file that contained the team config. This variable now expects the contents of a YAML file. The chart will then create a `ConfigMap` and store the contents of the `mainTeam.config` key in `main-team.yml`. 17 | 18 | # v10.0.0: 19 | 20 | - web: removed `concourse.web.enableLidar` and `concourse.web.resourceTypeCheckingInterval` 21 | 22 | with 6.0, lidar is enabled by default (there's no radar anymore!) 23 | 24 | - web: remove `concourse.web.noop` configuration 25 | 26 | with the algorithm, there's no way of making specific web nodes no-op w/ regards to scheduling & checking anymore. 27 | 28 | - web: split `concourse.web.maxConns` 29 | 30 | previously, there was a single `maxConns` configuration flag that'd be used to set a max number of conn for both api and backend. as this flag does not exist anymore, it was removed. 31 | 32 | - web: remove `concourse.web.riemann` 33 | 34 | in concourse/concourse#5141 (part of 6.0), riemann was completely removed, making those variables unecessary. 35 | 36 | # v11.0.0: 37 | 38 | - All settings that were under `web.service` have been moved to three sub-keys: `web.service.api`, `web.service.workerGateway`, and `web.service.prometheus`. This allows users to, for example, expose the `api` component via an ingress while exposing the `workerGateway` via a `LoadBalancer` for registering external workers. Any values previously set under `web.service` should now be moved to `web.service.workerGateway` and `web.service.api`. Any `labels` or `annotations` should be copied to all three sub-keys, `web`, `workerGateway`, and `prometheus`. 39 | 40 | # v12.0.1: 41 | 42 | - To configure Concourse to use containerd as a runtime, set `concourse.worker.runtime` to `containerd`. In past versions of the chart, this was set in `concourse.worker.garden.useContainerd`, which was removed. Any containerd configuration should now be set under `concourse.worker.containerd.*` rather than under `concourse.worker.garden.*`. The default value for `concourse.worker.runtime` is `guardian`. 43 | - Note: v12.0.0 has no changes from v11.0.0 - please use the patch version v12.0.1 instead 44 | 45 | # v13.0.0: 46 | 47 | - upgraded the PostgreSQL Chart (direct dependency of this Chart) from `6.5.5` to `9.2.0`. As the backward compatibility is not guarantee when upgrading the PostgreSQL chart to this major version, a major bump was needed. Please refer to [PostgreSQL Chart](https://github.com/bitnami/charts/tree/master/bitnami/postgresql#upgrade) for details. 48 | 49 | # v14.0.0: 50 | 51 | - The chart is now targeting Helm v3 and no longer supports Helm v2. Trying to deploy this version of the chart with Helm v2 will result an error such as `apiVersion 'v2' is not valid. The value must be "v1"`. 52 | 53 | # v15.0.0: 54 | 55 | - This chart version creates an init container where it will run the database migrations in. The migration command that it runs depends on a flag that is only added in concourse v7.0.0, making this a breaking change to anyone that tries to use this latest chart version with an older version of concourse. 56 | 57 | # v16.0.0: 58 | 59 | - For any users using Conjur for secret management, the field `secrets.conjurCertFile` changed to `secrets.conjurCACert`. It now takes the contents of a CA cert and creates a mount with a `ca.crt` file in the web deployment. 60 | 61 | # v17.0.0: 62 | 63 | - Upgrade the PostgreSQL Chart to v11. As the backward compatibility is not guarantee when upgrading the PostgreSQL chart to this major version, a major bump was needed. Please refer to [PostgreSQL Chart](https://docs.bitnami.com/kubernetes/infrastructure/postgresql/administration/upgrade#to-1100) for details. 64 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at concourse@pivotal.io . All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | -------------------------------------------------------------------------------- /Chart.lock: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - name: postgresql 3 | repository: https://charts.bitnami.com/bitnami 4 | version: 16.3.2 5 | digest: sha256:913828a3b53fb4f5a9730250296bc1fd159f5f7cb5dbb972e92d90958ed81ecb 6 | generated: "2024-12-18T14:48:15.95980588Z" 7 | -------------------------------------------------------------------------------- /Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: concourse 3 | type: application 4 | version: 18.1.1 5 | appVersion: 7.13.2 6 | description: Concourse is a simple and scalable CI system. 7 | icon: https://avatars1.githubusercontent.com/u/7809479 8 | keywords: 9 | - ci 10 | - concourse 11 | - concourse.ci 12 | home: https://concourse-ci.org/ 13 | sources: 14 | - https://github.com/concourse/concourse-chart 15 | - https://github.com/concourse/concourse 16 | dependencies: 17 | - name: postgresql 18 | version: 16.3.2 19 | repository: https://charts.bitnami.com/bitnami 20 | condition: postgresql.enabled 21 | maintainers: 22 | - name: concourse-team 23 | email: concourse@vmware.com 24 | engine: gotpl 25 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Concourse Helm Chart 2 | 3 | [Concourse](https://concourse-ci.org/) is a simple and scalable CI system. 4 | 5 | 6 | ## TL;DR; 7 | 8 | ```console 9 | $ helm repo add concourse https://concourse-charts.storage.googleapis.com/ 10 | $ helm install my-release concourse/concourse 11 | ``` 12 | 13 | 14 | ## Introduction 15 | 16 | This chart bootstraps a [Concourse](https://concourse-ci.org/) deployment on a [Kubernetes](https://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. 17 | 18 | 19 | ## Prerequisites Details 20 | 21 | * Kubernetes 1.6 (for [`pod affinity`](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity) support) 22 | * [`PersistentVolume`](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) support on underlying infrastructure (if persistence is required) 23 | * Helm v3.x 24 | 25 | 26 | ## Installing the Chart 27 | 28 | To install the chart with the release name `my-release`: 29 | 30 | ```console 31 | $ helm install my-release concourse/concourse 32 | ``` 33 | 34 | 35 | ## Uninstalling the Chart 36 | 37 | To uninstall/delete the `my-release` deployment: 38 | 39 | ```console 40 | $ helm delete my-release 41 | ``` 42 | 43 | The command removes nearly all the Kubernetes components associated with the chart and deletes the release. 44 | 45 | > ps: By default, a [namespace](https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/) is created for the `main` team named after `${RELEASE}-main` and is kept untouched after a `helm delete`. 46 | > See the [Configuration section](#configuration) for how to control the behavior. 47 | 48 | 49 | ### Cleanup orphaned Persistent Volumes 50 | 51 | This chart uses [`StatefulSets`](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/) for Concourse Workers. Deleting a `StatefulSet` does not delete associated `PersistentVolume`s. 52 | 53 | Do the following after deleting the chart release to clean up orphaned Persistent Volumes. 54 | 55 | ```console 56 | $ kubectl delete pvc -l app=${RELEASE-NAME}-worker 57 | ``` 58 | 59 | 60 | ### Restarting workers 61 | 62 | If a [Worker](https://concourse-ci.org/architecture.html#architecture-worker) isn't taking on work, you can recreate it with `kubectl delete pod`. This initiates a graceful shutdown by ["retiring"](https://concourse-ci.org/worker-internals.html#RETIRING-table) the worker, to ensure Concourse doesn't try looking for old volumes on the new worker. 63 | 64 | The value`worker.terminationGracePeriodSeconds` can be used to provide an upper limit on graceful shutdown time before forcefully terminating the container. 65 | 66 | Check the output of `fly workers`, and if a worker is [`stalled`](https://concourse-ci.org/worker-internals.html#STALLED-table), you'll also need to run [`fly prune-worker`](https://concourse-ci.org/administration.html#fly-prune-worker) to allow the new incarnation of the worker to start. 67 | 68 | > **TIP**: you can download `fly` either from https://concourse-ci.org/download.html or the home page of your Concourse installation. 69 | 70 | When using ephemeral workers with `worker.kind: Deployment` and spawning a lot of (new) workers, you might run into [issue 3091](https://github.com/concourse/concourse/issues/3091). 71 | As a workaround you could start a `worker.extraInitContainers` to cleanup unused loopback devices. 72 | 73 | ### Worker Liveness Probe 74 | 75 | By default, the worker's [`LivenessProbe`](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes) will trigger a restart of the worker container if it detects errors when trying to reach the worker's healthcheck endpoint which takes care of making sure that the [workers' components](https://concourse-ci.org/architecture.html#architecture) can properly serve their purpose. 76 | 77 | See [Configuration](#configuration) and [`values.yaml`](./values.yaml) for the configuration of both the `livenessProbe` (`worker.livenessProbe`) and the default healthchecking timeout (`concourse.worker.healthcheckTimeout`). 78 | 79 | 80 | ## Configuration 81 | 82 | The following table lists the configurable parameters of the Concourse chart and their default values. 83 | 84 | | Parameter | Description | Default | 85 | | ----------------------- | ---------------------------------- | ---------------------------------------------------------- | 86 | | `fullnameOverride` | Provide a name to substitute for the full names of resources | `nil` | 87 | | `imageDigest` | Specific image digest to use in place of a tag. | `nil` | 88 | | `imagePullPolicy` | Concourse image pull policy | `IfNotPresent` | 89 | | `imagePullSecrets` | Array of imagePullSecrets in the namespace for pulling images | `[]` | 90 | | `imageTag` | Concourse image version | `7.13.2` | 91 | | `image` | Concourse image | `concourse/concourse` | 92 | | `nameOverride` | Provide a name in place of `concourse` for `app:` labels | `nil` | 93 | | `persistence.enabled` | Enable Concourse persistence using Persistent Volume Claims | `true` | 94 | | `persistence.worker.accessMode` | Concourse Worker Persistent Volume Access Mode | `ReadWriteOnce` | 95 | | `persistence.worker.size` | Concourse Worker Persistent Volume Storage Size | `20Gi` | 96 | | `persistence.worker.storageClass` | Concourse Worker Persistent Volume Storage Class | `generic` | 97 | | `persistence.worker.labels` | Concourse Worker Persistent Volume Labels | `{}` | 98 | | `postgresql.enabled` | Enable PostgreSQL as a chart dependency | `true` | 99 | | `postgresql.persistence.accessModes` | Persistent Volume Access Mode | `["ReadWriteOnce"]` | 100 | | `postgresql.persistence.enabled` | Enable PostgreSQL persistence using Persistent Volume Claims | `true` | 101 | | `postgresql.persistence.size` | Persistent Volume Storage Size | `8Gi` | 102 | | `postgresql.persistence.storageClass` | Concourse data Persistent Volume Storage Class | `nil` | 103 | | `persistence.worker.selector` | Concourse Worker Persistent Volume selector | `nil` | 104 | | `postgresql.auth.database` | PostgreSQL Database to create | `concourse` | 105 | | `postgresql.auth.password` | PostgreSQL Password for the new user | `concourse` | 106 | | `postgresql.auth.username` | PostgreSQL User to create | `concourse` | 107 | | `rbac.apiVersion` | RBAC version | `v1beta1` | 108 | | `rbac.create` | Enables creation of RBAC resources | `true` | 109 | | `rbac.webServiceAccountName` | Name of the service account to use for web pods if `rbac.create` is `false` | `default` | 110 | | `rbac.webServiceAccountAnnotations` | Any annotations to be attached to the web service account | `{}` | 111 | | `rbac.workerServiceAccountName` | Name of the service account to use for workers if `rbac.create` is `false` | `default` | 112 | | `rbac.workerServiceAccountAnnotations` | Any annotations to be attached to the worker service account | `{}` | 113 | | `podSecurityPolicy.create` | Enables creation of podSecurityPolicy resources | `false` | 114 | | `podSecurityPolicy.allowedWorkerVolumes` | List of volumes allowed by the podSecurityPolicy for the worker pods | *See [values.yaml](values.yaml)* | 115 | | `podSecurityPolicy.allowedWebVolumes` | List of volumes allowed by the podSecurityPolicy for the web pods | *See [values.yaml](values.yaml)* | 116 | | `secrets.annotations`| Annotations to be added to the secrets | `{}` | 117 | | `secrets.awsSecretsmanagerAccessKey` | AWS Access Key ID for Secrets Manager access | `nil` | 118 | | `secrets.awsSecretsmanagerSecretKey` | AWS Secret Access Key ID for Secrets Manager access | `nil` | 119 | | `secrets.awsSecretsmanagerSessionToken` | AWS Session Token for Secrets Manager access | `nil` | 120 | | `secrets.awsSsmAccessKey` | AWS Access Key ID for SSM access | `nil` | 121 | | `secrets.awsSsmSecretKey` | AWS Secret Access Key ID for SSM access | `nil` | 122 | | `secrets.awsSsmSessionToken` | AWS Session Token for SSM access | `nil` | 123 | | `secrets.bitbucketCloudClientId` | Client ID for the BitbucketCloud OAuth | `nil` | 124 | | `secrets.bitbucketCloudClientSecret` | Client Secret for the BitbucketCloud OAuth | `nil` | 125 | | `secrets.cfCaCert` | CA certificate for cf auth provider | `nil` | 126 | | `secrets.cfClientId` | Client ID for cf auth provider | `nil` | 127 | | `secrets.cfClientSecret` | Client secret for cf auth provider | `nil` | 128 | | `secrets.conjurAccount` | Account for Conjur auth provider | `nil` | 129 | | `secrets.conjurAuthnLogin` | Host username for Conjur auth provider | `nil` | 130 | | `secrets.conjurAuthnApiKey` | API key for host used for Conjur auth provider. Either API key or token file can be used, but not both. | `nil` | 131 | | `secrets.conjurAuthnTokenFile` | Token file used for Conjur auth provider if running in Kubernetes or IAM. Either token file or API key can be used, but not both. | `nil` | 132 | | `secrets.conjurCACert` | CA Cert used if Conjur instance is deployed with a self-signed certificate | `nil` | 133 | | `secrets.create` | Create the secret resource from the following values. *See [Secrets](#secrets)* | `true` | 134 | | `secrets.credhubCaCert` | Value of PEM-encoded CA cert file to use to verify the CredHub server SSL cert. | `nil` | 135 | | `secrets.credhubClientId` | Client ID for CredHub authorization. | `nil` | 136 | | `secrets.credhubClientSecret` | Client secret for CredHub authorization. | `nil` | 137 | | `secrets.credhubClientKey` | Client key for Credhub authorization. | `nil` | 138 | | `secrets.credhubClientCert` | Client cert for Credhub authorization | `nil` | 139 | | `secrets.encryptionKey` | current encryption key | `nil` | 140 | | `secrets.githubCaCert` | CA certificate for Enterprise Github OAuth | `nil` | 141 | | `secrets.githubClientId` | Application client ID for GitHub OAuth | `nil` | 142 | | `secrets.githubClientSecret` | Application client secret for GitHub OAuth | `nil` | 143 | | `secrets.gitlabClientId` | Application client ID for GitLab OAuth | `nil` | 144 | | `secrets.gitlabClientSecret` | Application client secret for GitLab OAuth | `nil` | 145 | | `secrets.hostKeyPub` | Concourse Host Public Key | *See [values.yaml](values.yaml)* | 146 | | `secrets.hostKey` | Concourse Host Private Key | *See [values.yaml](values.yaml)* | 147 | | `secrets.influxdbPassword` | Password used to authenticate with influxdb | `nil` | 148 | | `secrets.ldapCaCert` | CA Certificate for LDAP | `nil` | 149 | | `secrets.localUsers` | Create concourse local users. Default username and password are `test:test` *See [values.yaml](values.yaml)* | 150 | | `secrets.microsoftClientId` | Client ID for Microsoft authorization. | `nil ` | 151 | | `secrets.microsoftClientSecret` | Client secret for Microsoft authorization. | `nil` | 152 | | `secrets.oauthCaCert` | CA certificate for Generic OAuth | `nil` | 153 | | `secrets.oauthClientId` | Application client ID for Generic OAuth | `nil` | 154 | | `secrets.oauthClientSecret` | Application client secret for Generic OAuth | `nil` | 155 | | `secrets.oidcCaCert` | CA certificate for OIDC Oauth | `nil` | 156 | | `secrets.oidcClientId` | Application client ID for OIDI OAuth | `nil` | 157 | | `secrets.oidcClientSecret` | Application client secret for OIDC OAuth | `nil` | 158 | | `secrets.oldEncryptionKey` | old encryption key, used for key rotation | `nil` | 159 | | `secrets.postgresCaCert` | PostgreSQL CA certificate | `nil` | 160 | | `secrets.postgresClientCert` | PostgreSQL Client certificate | `nil` | 161 | | `secrets.postgresClientKey` | PostgreSQL Client key | `nil` | 162 | | `secrets.postgresPassword` | PostgreSQL User Password | `nil` | 163 | | `secrets.postgresUser` | PostgreSQL User Name | `nil` | 164 | | `secrets.samlCaCert` | CA Certificate for SAML | `nil` | 165 | | `secrets.sessionSigningKey` | Concourse Session Signing Private Key | *See [values.yaml](values.yaml)* | 166 | | `secrets.syslogCaCert` | SSL certificate to verify Syslog server | `nil` | 167 | | `secrets.teamAuthorizedKeys` | Array of team names and worker public keys for external workers | `nil` | 168 | | `secrets.vaultAuthParam` | Paramter to pass when logging in via the backend | `nil` | 169 | | `secrets.vaultCaCert` | CA certificate use to verify the vault server SSL cert | `nil` | 170 | | `secrets.vaultClientCert` | Vault Client Certificate | `nil` | 171 | | `secrets.vaultClientKey` | Vault Client Key | `nil` | 172 | | `secrets.vaultClientToken` | Vault periodic client token | `nil` | 173 | | `secrets.webTlsCert` | TLS certificate for the web component to terminate TLS connections | `nil` | 174 | | `secrets.webTlsKey` | An RSA private key, used to encrypt HTTPS traffic | `nil` | 175 | | `secrets.webTlsCaCert` | TLS CA certificate for the web component to terminate TLS connections | `nil` | 176 | | `secrets.workerKeyPub` | Concourse Worker Public Key | *See [values.yaml](values.yaml)* | 177 | | `secrets.workerKey` | Concourse Worker Private Key | *See [values.yaml](values.yaml)* | 178 | | `secrets.workerAdditionalCerts` | Concourse Worker Additional Certificates | *See [values.yaml](values.yaml)* | 179 | | `web.additionalAffinities` | Additional affinities to apply to web pods. E.g: node affinity | `{}` | 180 | | `web.additionalVolumeMounts` | VolumeMounts to be added to the web pods | `nil` | 181 | | `web.additionalVolumes` | Volumes to be added to the web pods | `nil` | 182 | | `web.annotations`| Annotations to be added to the web pods | `{}` | 183 | | `web.authSecretsPath` | Specify the mount directory of the web auth secrets | `/concourse-auth` | 184 | | `web.credhubSecretsPath` | Specify the mount directory of the web credhub secrets | `/concourse-credhub` | 185 | | `web.datadog.agentHostUseHostIP` | Use IP of Pod's node overrides `agentHost` | `false` | 186 | | `web.datadog.agentHost` | Datadog Agent host | `127.0.0.1` | 187 | | `web.datadog.agentPort` | Datadog Agent port | `8125` | 188 | | `web.datadog.agentUdsFilepath` | Datadog agent unix domain socket (uds) filepath to expose dogstatsd metrics (ex. `/tmp/datadog.socket`) | `nil` | 189 | | `web.datadog.enabled` | Enable or disable Datadog metrics | `false` | 190 | | `web.datadog.prefix` | Prefix for emitted metrics | `"concourse.ci"` | 191 | | `web.enabled` | Enable or disable the web component | `true` | 192 | | `web.env` | Configure additional environment variables for the web containers | `[]` | 193 | | `web.command` | Override the docker image command | `nil` | 194 | | `web.args` | Docker image command arguments | `["web"]` | 195 | | `web.ingress.annotations` | Concourse Web Ingress annotations | `{}` | 196 | | `web.ingress.enabled` | Enable Concourse Web Ingress | `false` | 197 | | `web.ingress.hosts` | Concourse Web Ingress Hostnames | `[]` | 198 | | `web.ingress.ingressClassName` | IngressClass to register to | `nil` | 199 | | `web.ingress.rulesOverride` | Concourse Web Ingress rules (override) (alternate to `web.ingress.hosts`) | `[]` | 200 | | `web.ingress.tls` | Concourse Web Ingress TLS configuration | `[]` | 201 | | `web.keySecretsPath` | Specify the mount directory of the web keys secrets | `/concourse-keys` | 202 | | `web.labels`| Additional labels to be added to the web deployment `metadata.labels` | `{}` | 203 | | `web.deploymentAnnotations` | Additional annotations to be added to the web deployment `metadata.annotations` | `{}` | 204 | | `web.livenessProbe.failureThreshold` | Minimum consecutive failures for the probe to be considered failed after having succeeded | `5` | 205 | | `web.livenessProbe.httpGet.path` | Path to access on the HTTP server when performing the healthcheck | `/api/v1/info` | 206 | | `web.livenessProbe.httpGet.port` | Name or number of the port to access on the container | `atc` | 207 | | `web.livenessProbe.initialDelaySeconds` | Number of seconds after the container has started before liveness probes are initiated | `10` | 208 | | `web.livenessProbe.periodSeconds` | How often (in seconds) to perform the probe | `15` | 209 | | `web.livenessProbe.timeoutSeconds` | Number of seconds after which the probe times out | `3` | 210 | | `web.nameOverride` | Override the Concourse Web components name | `nil` | 211 | | `web.nodeSelector` | Node selector for web nodes | `{}` | 212 | | `web.podLabels`| Additional labels to be added to the web deployment `spec.template.metadata.labels`, setting pods `metadata.labels` | `{}` | 213 | | `web.postgresqlSecretsPath` | Specify the mount directory of the web postgresql secrets | `/concourse-postgresql` | 214 | | `web.prometheus.enabled` | Enable the Prometheus metrics endpoint | `false` | 215 | | `web.prometheus.bindIp` | IP to listen on to expose Prometheus metrics | `0.0.0.0` | 216 | | `web.prometheus.bindPort` | Port to listen on to expose Prometheus metrics | `9391` | 217 | | `web.prometheus.ServiceMonitor.enabled` | Enable the creation of a serviceMonitor object for the Prometheus operator | `false` | 218 | | `web.prometheus.ServiceMonitor.interval` | The interval the Prometheus endpoint is scraped | `30s` | 219 | | `web.prometheus.ServiceMonitor.namespace` | The namespace where the serviceMonitor object has to be created | `nil` | 220 | | `web.prometheus.ServiceMonitor.labels` | Additional lables for the serviceMonitor object | `nil` | 221 | | `web.prometheus.ServiceMonitor.metricRelabelings` | Relabel metrics as defined [here](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs) | `nil` | 222 | | `web.readinessProbe.httpGet.path` | Path to access on the HTTP server when performing the healthcheck | `/api/v1/info` | 223 | | `web.readinessProbe.httpGet.port` | Name or number of the port to access on the container | `atc` | 224 | | `web.replicas` | Number of Concourse Web replicas | `1` | 225 | | `web.resources.requests.cpu` | Minimum amount of cpu resources requested | `100m` | 226 | | `web.resources.requests.memory` | Minimum amount of memory resources requested | `128Mi` | 227 | | `web.service.api.annotations` | Concourse Web API Service annotations | `nil` | 228 | | `web.service.api.NodePort` | Sets the nodePort for api when using `NodePort` | `nil` | 229 | | `web.service.api.labels` | Additional concourse web api service labels | `nil` | 230 | | `web.service.api.loadBalancerIP` | The IP to use when web.service.api.type is LoadBalancer | `nil` | 231 | | `web.service.api.clusterIP` | The IP to use when web.service.api.type is ClusterIP | `nil` | 232 | | `web.service.api.loadBalancerSourceRanges` | Concourse Web API Service Load Balancer Source IP ranges | `nil` | 233 | | `web.service.api.tlsNodePort` | Sets the nodePort for api tls when using `NodePort` | `nil` | 234 | | `web.service.api.type` | Concourse Web API service type | `ClusterIP` | 235 | | `web.service.api.port.name` | Sets the port name for web service with `targetPort` `atc` | `atc` | 236 | | `web.service.api.tlsPort.name` | Sets the port name for web service with `targetPort` `atc-tls` | `atc-tls` | 237 | | `web.service.workerGateway.annotations` | Concourse Web workerGateway Service annotations | `nil` | 238 | | `web.service.workerGateway.labels` | Additional concourse web workerGateway service labels | `nil` | 239 | | `web.service.workerGateway.loadBalancerIP` | The IP to use when web.service.workerGateway.type is LoadBalancer | `nil` | 240 | | `web.service.workerGateway.clusterIP` | The IP to use when web.service.workerGateway.type is ClusterIP | `None` | 241 | | `web.service.workerGateway.loadBalancerSourceRanges` | Concourse Web workerGateway Service Load Balancer Source IP ranges | `nil` | 242 | | `web.service.workerGateway.NodePort` | Sets the nodePort for workerGateway when using `NodePort` | `nil` | 243 | | `web.service.workerGateway.type` | Concourse Web workerGateway service type | `ClusterIP` | 244 | | `web.service.prometheus.annotations` | Concourse Web Prometheus Service annotations | `nil` | 245 | | `web.service.prometheus.labels` | Additional concourse web prometheus service labels | `nil` | 246 | | `web.shareProcessNamespace` | Enable or disable the process namespace sharing for the web nodes | `false` | 247 | | `web.priorityClassName` | Sets a PriorityClass for the web pods | `nil` | 248 | | `web.sidecarContainers` | Array of extra containers to run alongside the Concourse web container | `nil` | 249 | | `web.databaseInitContainers` | Array of database init containers to run before the Concourse database migrations are applied | `nil` | 250 | | `web.extraInitContainers` | Array of extra init containers to run before the Concourse web container | `nil` | 251 | | `web.strategy` | Strategy for updates to deployment. | `{}` | 252 | | `web.syslogSecretsPath` | Specify the mount directory of the web syslog secrets | `/concourse-syslog` | 253 | | `web.tlsSecretsPath` | Where in the container the web TLS secrets should be mounted | `/concourse-web-tls` | 254 | | `web.tolerations` | Tolerations for the web nodes | `[]` | 255 | | `web.vaultSecretsPath` | Specify the mount directory of the web vault secrets | `/concourse-vault` | 256 | | `web.vault.tokenPath` | Specify the path to a file containing a vault client authentication token | `nil` | 257 | | `worker.additionalAffinities` | Additional affinities to apply to worker pods. E.g: node affinity | `{}` | 258 | | `worker.additionalVolumeMounts` | VolumeMounts to be added to the worker pods | `nil` | 259 | | `worker.additionalPorts` | Additional ports to be added to worker pods | `[]` | 260 | | `worker.additionalVolumes` | Volumes to be added to the worker pods | `nil` | 261 | | `worker.annotations` | Annotations to be added to the worker pods | `{}` | 262 | | `worker.autoscaling` | Enable and configure pod autoscaling | `{}` | 263 | | `worker.cleanUpWorkDirOnStart` | Removes any previous state created in `concourse.worker.workDir` | `true` | 264 | | `worker.emptyDirSize` | When persistance is disabled this value will be used to limit the emptyDir volume size | `nil` | 265 | | `worker.enabled` | Enable or disable the worker component. You should set postgres.enabled=false in order not to get an unnecessary Postgres chart deployed | `true` | 266 | | `worker.env` | Configure additional environment variables for the worker container(s) | `[]` | 267 | | `worker.hardAntiAffinity` | Should the workers be forced (as opposed to preferred) to be on different nodes? | `false` | 268 | | `worker.hardAntiAffinityLabels` | Set of labels used for hard anti affinity rule | `{}` | 269 | | `worker.keySecretsPath` | Specify the mount directory of the worker keys secrets | `/concourse-keys` | 270 | | `worker.deploymentAnnotations` | Additional annotations to be added to the worker deployment `metadata.annotations` | `{}` | 271 | | `worker.certsPath` | Specify the path for additional worker certificates | `/etc/ssl/certs` | 272 | | `worker.kind` | Choose between `StatefulSet` to preserve state or `Deployment` for ephemeral workers | `StatefulSet` | 273 | | `worker.livenessProbe.failureThreshold` | Minimum consecutive failures for the probe to be considered failed after having succeeded | `5` | 274 | | `worker.livenessProbe.httpGet.path` | Path to access on the HTTP server when performing the healthcheck | `/` | 275 | | `worker.livenessProbe.httpGet.port` | Name or number of the port to access on the container | `worker-hc` | 276 | | `worker.livenessProbe.initialDelaySeconds` | Number of seconds after the container has started before liveness probes are initiated | `10` | 277 | | `worker.livenessProbe.periodSeconds` | How often (in seconds) to perform the probe | `15` | 278 | | `worker.livenessProbe.timeoutSeconds` | Number of seconds after which the probe times out | `3` | 279 | | `worker.minAvailable` | Minimum number of workers available after an eviction | `1` | 280 | | `worker.nameOverride` | Override the Concourse Worker components name | `nil` | 281 | | `worker.nodeSelector` | Node selector for worker nodes | `{}` | 282 | | `worker.podManagementPolicy` | `OrderedReady` or `Parallel` (requires Kubernetes >= 1.7) | `Parallel` | 283 | | `worker.readinessProbe` | Periodic probe of container service readiness | `{}` | 284 | | `worker.replicas` | Number of Concourse Worker replicas | `2` | 285 | | `worker.resources.requests.cpu` | Minimum amount of cpu resources requested | `100m` | 286 | | `worker.resources.requests.memory` | Minimum amount of memory resources requested | `512Mi` | 287 | | `worker.sidecarContainers` | Array of extra containers to run alongside the Concourse worker container | `nil` | 288 | | `worker.extraInitContainers` | Array of extra init containers to run before the Concourse worker container | `nil` | 289 | | `worker.priorityClassName` | Sets a PriorityClass for the worker pods | `nil` | 290 | | `worker.terminationGracePeriodSeconds` | Upper bound for graceful shutdown to allow the worker to drain its tasks | `60` | 291 | | `worker.tolerations` | Tolerations for the worker nodes | `[]` | 292 | | `worker.updateStrategy` | `OnDelete` or `RollingUpdate` (requires Kubernetes >= 1.7) | `RollingUpdate` | 293 | 294 | For configurable Concourse parameters, refer to [`values.yaml`](values.yaml)' `concourse` section. All parameters under this section are strictly mapped from the `concourse` binary commands. 295 | 296 | For example if one needs to configure the Concourse external URL, the param `concourse` -> `web` -> `externalUrl` should be set, which is equivalent to running the `concourse` binary as `concourse web --external-url`. 297 | 298 | For those sub-sections that have `enabled`, one needs to set `enabled` to be `true` to use the following params within the section. 299 | 300 | Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. 301 | 302 | Alternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example, 303 | 304 | ```console 305 | $ helm install my-release -f values.yaml concourse/concourse 306 | ``` 307 | 308 | > **Tip**: You can use the default [values.yaml](values.yaml) 309 | 310 | 311 | ### Secrets 312 | 313 | For your convenience, this chart provides some default values for secrets, but it is recommended that you generate and manage these secrets outside the Helm chart. 314 | 315 | To do that, set `secrets.create` to `false`, create files for each secret value, and turn it all into a Kubernetes [Secret](https://kubernetes.io/docs/concepts/configuration/secret/). 316 | 317 | Be careful with introducing trailing newline characters; following the steps below ensures none end up in your secrets. First, perform the following to create the mandatory secret values: 318 | 319 | ```sh 320 | # Create a directory to host the set of secrets that are 321 | # required for a working Concourse installation and get 322 | # into it. 323 | # 324 | mkdir concourse-secrets 325 | cd concourse-secrets 326 | ``` 327 | 328 | Concourse needs three sets of key-pairs in order to work: 329 | - web key pair, 330 | - worker key pair, and 331 | - the session signing token. 332 | 333 | You can generate all three key-pairs by following either of these two methods: 334 | 335 | ##### Concourse Binary 336 | 337 | ```sh 338 | docker run -v $PWD:/keys --rm -it concourse/concourse generate-key -t rsa -f /keys/session-signing-key 339 | docker run -v $PWD:/keys --rm -it concourse/concourse generate-key -t ssh -f /keys/worker-key 340 | docker run -v $PWD:/keys --rm -it concourse/concourse generate-key -t ssh -f /keys/host-key 341 | rm session-signing-key.pub 342 | ``` 343 | 344 | ##### ssh-keygen 345 | 346 | ```sh 347 | ssh-keygen -t rsa -f host-key -N '' -m PEM 348 | ssh-keygen -t rsa -f worker-key -N '' -m PEM 349 | ssh-keygen -t rsa -f session-signing-key -N '' -m PEM 350 | rm session-signing-key.pub 351 | ``` 352 | 353 | #### Optional Features 354 | 355 | You'll also need to create/copy secret values for optional features. See [templates/web-secrets.yaml](templates/web-secrets.yaml) and [templates/worker-secrets.yaml](templates/worker-secrets.yaml) for possible values. 356 | 357 | In the example below, we are not using the [PostgreSQL](#postgresql) chart dependency, and so we must set `postgresql-user` and `postgresql-password` secrets. 358 | 359 | ```sh 360 | # Still within the directory where our secrets exist, 361 | # copy a postgres user to clipboard and paste it to file. 362 | # 363 | printf "%s" "$(pbpaste)" > postgresql-user 364 | 365 | # Copy a postgres password to clipboard and paste it to file 366 | # 367 | printf "%s" "$(pbpaste)" > postgresql-password 368 | 369 | # Copy Github client id and secrets to clipboard and paste to files 370 | # 371 | printf "%s" "$(pbpaste)" > github-client-id 372 | printf "%s" "$(pbpaste)" > github-client-secret 373 | 374 | # Set an encryption key for DB encryption at rest 375 | # 376 | printf "%s" "$(openssl rand -base64 24)" > encryption-key 377 | 378 | # Create a local user for concourse. 379 | # 380 | printf "%s:%s" "concourse" "$(openssl rand -base64 24)" > local-users 381 | ``` 382 | 383 | #### Creating the Secrets 384 | 385 | Make a directory for each secret and then move generated credentials into appropriate directories. 386 | ```console 387 | mkdir concourse web worker 388 | 389 | # worker secrets 390 | mv host-key.pub worker/host-key-pub 391 | mv worker-key.pub worker/worker-key-pub 392 | mv worker-key worker/worker-key 393 | 394 | # web secrets 395 | mv session-signing-key web/session-signing-key 396 | mv host-key web/host-key 397 | cp worker/worker-key-pub web/worker-key-pub 398 | mv local-users web/local-users 399 | 400 | # other concourse secrets (there may be more than the 3 listed below) 401 | mv encryption-key concourse/encryption-key 402 | mv postgresql-password concourse/postgresql-password 403 | mv postgresql-user concourse/postgresql-user 404 | ``` 405 | 406 | Then create the secrets from each of the 3 directories: 407 | 408 | ```console 409 | kubectl create secret generic [my-release]-worker --from-file=worker/ 410 | 411 | kubectl create secret generic [my-release]-web --from-file=web/ 412 | 413 | kubectl create secret generic [my-release]-concourse --from-file=concourse/ 414 | ``` 415 | 416 | Make sure you clean up after yourself. 417 | 418 | 419 | ### Persistence 420 | 421 | This chart mounts a Persistent Volume for each Concourse Worker. 422 | 423 | The volume is created using dynamic volume provisioning. 424 | 425 | If you want to disable it or change the persistence properties, update the `persistence` section of your custom `values.yaml` file: 426 | 427 | ```yaml 428 | ## Persistent Volume Storage configuration. 429 | ## ref: https://kubernetes.io/docs/user-guide/persistent-volumes 430 | ## 431 | persistence: 432 | ## Enable persistence using Persistent Volume Claims. 433 | ## 434 | enabled: true 435 | 436 | ## Worker Persistence configuration. 437 | ## 438 | worker: 439 | ## Persistent Volume Storage Class. 440 | ## 441 | storageClass: generic 442 | 443 | ## Persistent Volume Access Mode. 444 | ## 445 | accessMode: ReadWriteOnce 446 | 447 | ## Persistent Volume Storage Size. 448 | ## 449 | size: "20Gi" 450 | ``` 451 | 452 | It is highly recommended to use Persistent Volumes for Concourse Workers; otherwise, the Concourse volumes managed by the Worker are stored in an [`emptyDir`](https://kubernetes.io/docs/concepts/storage/volumes/#emptydir) volume on the Kubernetes node's disk. This will interfere with Kubernete's [ImageGC](https://kubernetes.io/docs/concepts/cluster-administration/kubelet-garbage-collection/#image-collection) and the node's disk will fill up as a result. 453 | 454 | 455 | ### Ingress TLS 456 | 457 | If your cluster allows automatic creation/retrieval of TLS certificates (e.g. [cert-manager](https://github.com/jetstack/cert-manager/)), please refer to the documentation for that mechanism. 458 | 459 | To manually configure TLS, first create/retrieve a key & certificate pair for the address(es) you wish to protect. Then create a TLS secret in the namespace: 460 | 461 | ```console 462 | kubectl create secret tls concourse-web-tls --cert=path/to/tls.cert --key=path/to/tls.key 463 | ``` 464 | 465 | Include the secret's name, along with the desired hostnames, in the `web.ingress.tls` section of your custom `values.yaml` file: 466 | 467 | ```yaml 468 | ## Configuration values for Concourse Web components. 469 | ## 470 | web: 471 | ## Ingress configuration. 472 | ## ref: https://kubernetes.io/docs/user-guide/ingress/ 473 | ## 474 | ingress: 475 | ## Enable ingress. 476 | ## 477 | enabled: true 478 | 479 | ## Hostnames. 480 | ## Either `hosts` or `rulesOverride` must be provided if Ingress is enabled. 481 | ## `hosts` sets up the Ingress with default rules per provided hostname. 482 | ## 483 | hosts: 484 | - concourse.domain.com 485 | 486 | ## Ingress rules override 487 | ## Either `hosts` or `rulesOverride` must be provided if Ingress is enabled. 488 | ## `rulesOverride` allows the user to define the full set of ingress rules, for more complex Ingress setups. 489 | ## 490 | ## 491 | rulesOverride: 492 | - host: concourse.domain.com 493 | http: 494 | paths: 495 | - path: '/*' 496 | backend: 497 | serviceName: "ssl-redirect" 498 | servicePort: "use-annotation" 499 | - path: '/*' 500 | backend: 501 | serviceName: "concourse-web" 502 | servicePort: atc 503 | 504 | ## TLS configuration. 505 | ## Secrets must be manually created in the namespace. 506 | ## 507 | tls: 508 | - secretName: concourse-web-tls 509 | hosts: 510 | - concourse.domain.com 511 | ``` 512 | 513 | ### PostgreSQL 514 | 515 | By default, this chart uses a PostgreSQL database deployed as a chart dependency (see the [PostgreSQL chart](https://github.com/bitnami/charts/blob/master/bitnami/postgresql/README.md)), with default values for username, password, and database name. These can be modified by setting the `postgresql.auth.*` values. 516 | 517 | You can also bring your own PostgreSQL. To do so, set `postgresql.enabled` to `false`, and then configure Concourse's `postgres` values (`concourse.web.postgres.*`) See [values.yaml](values.yaml). 518 | 519 | Note that Concourse (by default) will attempt to read in some values directly from secrets. Therefore, these values do not have to be explicitly passed into Concourse as individual arguments, or as members of lists or files. (e.g. Part of values.yaml, etc.) Some examples of these secret values are: `postgresql-user`, `postgresql-password` (in secret "[my-release]-concourse" or "[my-release]-web"), and others. See [templates/web-secrets.yaml](templates/web-secrets.yaml) for possible values and the [secrets section](#secrets) on this README for guidance on how to set those secrets. 520 | 521 | ### Credential Management 522 | 523 | Pipelines usually need credentials to do things. Concourse supports the use of a [Credential Manager](https://concourse-ci.org/creds.html) so your pipelines can contain references to secrets instead of the actual secret values. You can't use more than one credential manager at a time. 524 | 525 | #### Kubernetes Secrets 526 | 527 | By default, this chart uses Kubernetes Secrets as a credential manager. 528 | 529 | For a given Concourse *team*, a pipeline looks for secrets in a namespace named `[namespacePrefix][teamName]`. The namespace prefix is the release name followed by a hyphen by default, and can be overridden with the value `concourse.web.kubernetes.namespacePrefix`. Each team listed under `concourse.web.kubernetes.teams` will have a namespace created for it, and the namespace remains after deletion of the release unless you set `concourse.web.kubernetes.keepNamespace` to `false`. By default, a namespace will be created for the `main` team. 530 | 531 | The service account used by Concourse must have `get` access to secrets in that namespace. When `rbac.create` is true, this access is granted for each team listed under `concourse.web.kubernetes.teams`. 532 | 533 | Here are some examples of the lookup heuristics, given release name `concourse`: 534 | 535 | In team `accounting-dev`, pipeline `my-app`; the expression `((api-key))` resolves to: 536 | 537 | 1. the secret value in namespace: `concourse-accounting-dev` secret: `my-app.api-key`, key: `value` 538 | 2. and if not found, is the value in namespace: `concourse-accounting-dev` secret: `api-key`, key: `value` 539 | 540 | In team accounting-dev, pipeline `my-app`, the expression `((common-secrets.api-key))` resolves to: 541 | 542 | 1. the secret value in namespace: `concourse-accounting-dev` secret: `my-app.common-secrets`, key: `api-key` 543 | 2. and if not found, is the value in namespace: `concourse-accounting-dev` secret: `common-secrets`, key: `api-key` 544 | 545 | Be mindful of your team and pipeline names, to ensure they can be used in namespace and secret names, e.g. no underscores. 546 | 547 | To test, create a secret in namespace `concourse-main`: 548 | 549 | ```console 550 | kubectl create secret generic hello --from-literal 'value=Hello world!' 551 | ``` 552 | 553 | Then `fly set-pipeline` with the following pipeline, and trigger it: 554 | 555 | ```yaml 556 | jobs: 557 | - name: hello-world 558 | plan: 559 | - task: say-hello 560 | config: 561 | platform: linux 562 | image_resource: 563 | type: docker-image 564 | source: {repository: alpine} 565 | params: 566 | HELLO: ((hello)) 567 | run: 568 | path: /bin/sh 569 | args: ["-c", "echo $HELLO"] 570 | ``` 571 | 572 | #### Hashicorp Vault 573 | 574 | To use Vault, set `concourse.web.kubernetes.enabled` to false, and set the following values: 575 | 576 | 577 | ```yaml 578 | ## Configuration values for the Credential Manager. 579 | ## ref: https://concourse-ci.org/creds.html 580 | ## 581 | concourse: 582 | web: 583 | vault: 584 | ## Use Hashicorp Vault for the Credential Manager. 585 | ## 586 | enabled: true 587 | 588 | ## URL pointing to vault addr (i.e. http://vault:8200). 589 | ## 590 | url: 591 | 592 | ## vault path under which to namespace credential lookup, defaults to /concourse. 593 | ## 594 | pathPrefix: 595 | ``` 596 | 597 | #### Credhub 598 | 599 | To use Credhub, set `concourse.web.kubernetes.enabled` to false, and consider the following values: 600 | 601 | ```yaml 602 | ## Configuration for using Credhub as a credential manager. 603 | ## Ref: https://concourse-ci.org/credhub-credential-manager.html 604 | ## 605 | concourse: 606 | web: 607 | credhub: 608 | ## Enable the use of Credhub as a credential manager. 609 | ## 610 | enabled: true 611 | 612 | ## CredHub server address used to access secrets 613 | ## Example: https://credhub.example.com 614 | ## 615 | url: 616 | 617 | ## Path under which to namespace credential lookup. (default: /concourse) 618 | ## 619 | pathPrefix: 620 | 621 | ## Enables using a CA Certificate 622 | ## 623 | useCaCert: false 624 | 625 | ## Enables insecure SSL verification. 626 | ## 627 | insecureSkipVerify: false 628 | ``` 629 | 630 | #### Conjur 631 | 632 | To use Conjur, set `concourse.web.kubernetes.enabled` to false, and set the following values: 633 | 634 | ```yaml 635 | ## Configuration for using Conjur as a credential manager. 636 | ## Ref: https://concourse-ci.org/conjur-credential-manager.html 637 | ## 638 | concourse: 639 | web: 640 | conjur: 641 | ## Enable the use of Conjur as a credential manager. 642 | ## 643 | enabled: true 644 | 645 | ## Conjur server address used to access secrets 646 | ## Example: https://conjur.example.com 647 | ## 648 | applianceUrl: 649 | 650 | ## Base path used to locate a vault or safe-level secret 651 | ## Default: vaultName/{{.Secret}}) 652 | ## 653 | secretTemplate: 654 | 655 | ## Base path used to locate a team-level secret 656 | ## Default: concourse/{{.Team}}/{{.Secret}} 657 | ## 658 | teamSecretTemplate: 659 | 660 | ## Base path used to locate a pipeline-level secret 661 | ## Default: concourse/{{.Team}}/{{.Pipeline}}/{{.Secret}} 662 | ## 663 | pipelineSecretTemplate: 664 | secrets: 665 | # Org account. 666 | conjurAccount: 667 | 668 | # Host username. E.g host/concourse 669 | conjurAuthnLogin: 670 | 671 | # Api key related to the host. 672 | conjurAuthnApiKey: 673 | 674 | # Token file used if conjur instance is running in k8s or iam. E.g. /path/to/token_file 675 | conjurAuthnTokenFile: 676 | 677 | # CA Certificate to specify if conjur instance is deployed with a self-signed cert 678 | conjurCACert: 679 | ``` 680 | 681 | You can specify either `conjurAuthnApiKey` that corresponds to the Conjur host OR `conjurAuthnTokenFile` if running in K8s or IAM. 682 | 683 | If your Conjur instance is deployed with a self-signed SSL certifcate, you will need to set `conjurCACert` property in your `values.yaml`. 684 | 685 | #### AWS Systems Manager Parameter Store (SSM) 686 | 687 | To use SSM, set `concourse.web.kubernetes.enabled` to false, and set `concourse.web.awsSsm.enabled` to true. 688 | 689 | Authentication can be configured to use an access key and secret key as well as a session token. This is done by setting `concourse.web.awsSsm.keyAuth.enabled` to `true`. Alternatively, if it set to `false`, AWS IAM role based authentication (instance or pod credentials) is assumed. To use a session token, `concourse.web.awsSsm.useSessionToken` should be set to `true`. The secret values can be managed using the values specified in this helm chart or separately. For more details, see https://concourse-ci.org/creds.html#ssm. 690 | 691 | For a given Concourse *team*, a pipeline looks for secrets in SSM using either `/concourse/{team}/{secret}` or `/concourse/{team}/{pipeline}/{secret}`; the patterns can be overridden using the `concourse.web.awsSsm.teamSecretTemplate` and `concourse.web.awsSsm.pipelineSecretTemplate` settings. 692 | 693 | Concourse requires AWS credentials which are able to read from SSM for this feature to function. Credentials can be set in the `secrets.awsSsm*` settings; if your cluster is running in a different AWS region, you may also need to set `concourse.web.awsSsm.region`. 694 | 695 | The minimum IAM policy you need to use SSM with Concourse is: 696 | 697 | ```json 698 | { 699 | "Version": "2012-10-17", 700 | "Statement": [ 701 | { 702 | "Action": "kms:Decrypt", 703 | "Resource": "", 704 | "Effect": "Allow" 705 | }, 706 | { 707 | "Action": "ssm:GetParameter*", 708 | "Resource": "<...arn...>:parameter/concourse/*", 709 | "Effect": "Allow" 710 | } 711 | ] 712 | } 713 | ``` 714 | 715 | Where `` is the ARN of the KMS key used to encrypt the secrets in Parameter Store, and the `<...arn...>` should be replaced with a correct ARN for your account and region's Parameter Store. 716 | 717 | #### AWS Secrets Manager 718 | 719 | To use Secrets Manager, set `concourse.web.kubernetes.enabled` to false, and set `concourse.web.awsSecretsManager.enabled` to true. 720 | 721 | Authentication can be configured to use an access key and secret key as well as a session token. This is done by setting `concourse.web.awsSecretsManager.keyAuth.enabled` to `true`. Alternatively, if it set to `false`, AWS IAM role based authentication (instance or pod credentials) is assumed. To use a session token, `concourse.web.awsSecretsManger.useSessionToken` should be set to `true`. The secret values can be managed using the values specified in this helm chart or separately. For more details, see https://concourse-ci.org/creds.html#asm. 722 | 723 | For a given Concourse *team*, a pipeline looks for secrets in Secrets Manager using either `/concourse/{team}/{secret}` or `/concourse/{team}/{pipeline}/{secret}`; the patterns can be overridden using the `concourse.web.awsSecretsManager.teamSecretTemplate` and `concourse.web.awsSecretsManager.pipelineSecretTemplate` settings. 724 | 725 | Concourse requires AWS credentials which are able to read from Secrets Manager for this feature to function. Credentials can be set in the `secrets.awsSecretsmanager*` settings; if your cluster is running in a different AWS region, you may also need to set `concourse.web.awsSecretsManager.region`. 726 | 727 | The minimum IAM policy you need to use Secrets Manager with Concourse is: 728 | 729 | ```json 730 | { 731 | "Version": "2012-10-17", 732 | "Statement": [ 733 | { 734 | "Sid": "AllowAccessToSecretManagerParameters", 735 | "Effect": "Allow", 736 | "Action": [ 737 | "secretsmanager:ListSecrets" 738 | ], 739 | "Resource": "*" 740 | }, 741 | { 742 | "Sid": "AllowAccessGetSecret", 743 | "Effect": "Allow", 744 | "Action": [ 745 | "secretsmanager:GetSecretValue", 746 | "secretsmanager:DescribeSecret" 747 | ], 748 | "Resource": [ 749 | "arn:aws:secretsmanager:::secret:/concourse/*" 750 | ] 751 | } 752 | ] 753 | } 754 | ``` 755 | 756 | ## Developing 757 | 758 | When adding a new Concourse flag, don't assign a `default` value in the `values.yml` that mirrors a default set by the Concourse binary. 759 | 760 | Instead, you may add a comment specifying the default, such as 761 | 762 | ``` 763 | ## pipeline-specific template for SSM parameters, defaults to: /concourse/{{.Team}}/{{.Pipeline}}/{{.Secret}} 764 | ## 765 | pipelineSecretTemplate: 766 | 767 | ``` 768 | 769 | This prevents the behaviour drifting from that of the binary in case the binary's default values change. 770 | 771 | We understand that the comment stating the binary's default can become stale. The current solution is a suboptimal one. It may be improved in the future by generating a list of the default values from the binary. 772 | -------------------------------------------------------------------------------- /packaging-state/README.md: -------------------------------------------------------------------------------- 1 | The Concourse pipelines validate the flags exposed in the binary match the flags exposed in the chart. 2 | 3 | The `ignored-in-concourse` file is used to specify flags that are exposed in the binary, but not expected to be in the chart. 4 | 5 | The `ignored-in-distribution` file is used to specify flags that re exposed in the chart, but not expected to be in the binary. 6 | 7 | These files are referenced by the [check-distribution-env](https://github.com/concourse/ci/blob/master/tasks/check-distribution-env.yml) task. 8 | -------------------------------------------------------------------------------- /packaging-state/ignored-in-concourse: -------------------------------------------------------------------------------- 1 | CONCOURSE_ADD_CLIENT 2 | CONCOURSE_SYSTEM_CLAIM_KEY 3 | CONCOURSE_SYSTEM_CLAIM_VALUE 4 | CONCOURSE_DUMMY_CREDS_VAR 5 | CONCOURSE_TSA_CLUSTER_NAME 6 | CONCOURSE_TSA_LOG_CLUSTER_NAME 7 | CONCOURSE_TSA_PEER_ADDRESS 8 | CONCOURSE_TSA_TEAM_AUTHORIZED_KEYS_FILE 9 | CONCOURSE_TSA_SCOPE 10 | CONCOURSE_TSA_TOKEN_URL 11 | CONCOURSE_VERSION 12 | CONCOURSE_WEB_PUBLIC_DIR 13 | -------------------------------------------------------------------------------- /packaging-state/ignored-in-distribution: -------------------------------------------------------------------------------- 1 | LIVENESS_PROBE_FATAL_ERRORS 2 | POD_IP 3 | -------------------------------------------------------------------------------- /templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | 2 | * Concourse can be accessed: 3 | 4 | * Within your cluster, at the following DNS name at port {{ .Values.concourse.web.bindPort }}: 5 | 6 | {{ template "concourse.web.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local 7 | 8 | {{- if .Values.web.ingress.enabled }} 9 | 10 | * From outside the cluster, the URL(s) are: 11 | {{ range .Values.web.ingress.hosts }} 12 | http://{{ . }} 13 | {{- end }} 14 | {{- else }} 15 | 16 | * From outside the cluster, run these commands in the same shell: 17 | {{- if contains "NodePort" .Values.web.service.api.type }} 18 | 19 | export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "concourse.web.fullname" . }}) 20 | export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") 21 | echo http://$NODE_IP:$NODE_PORT 22 | {{- else if contains "LoadBalancer" .Values.web.service.api.type }} 23 | 24 | NOTE: It may take a few minutes for the LoadBalancer IP to be available. 25 | You can watch the status of by running 'kubectl get svc -w {{ template "concourse.web.fullname" . }}' 26 | 27 | export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "concourse.web.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') 28 | echo http://$SERVICE_IP:{{ .Values.concourse.web.bindPort }} 29 | {{- else if contains "ClusterIP" .Values.web.service.api.type }} 30 | 31 | export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "concourse.web.fullname" . }}" -o jsonpath="{.items[0].metadata.name}") 32 | echo "Visit http://127.0.0.1:8080 to use Concourse" 33 | kubectl port-forward --namespace {{ .Release.Namespace }} $POD_NAME 8080:{{ .Values.concourse.web.bindPort }} 34 | {{- end }} 35 | {{- end }} 36 | * If this is your first time using Concourse, follow the examples at https://concourse-ci.org/examples.html 37 | 38 | {{- if .Values.worker.enabled }} 39 | {{- if .Values.concourse.worker.baggageclaim.driver }} 40 | {{- if contains "naive" .Values.concourse.worker.baggageclaim.driver }} 41 | 42 | ******************* 43 | ******WARNING****** 44 | ******************* 45 | 46 | You are using the "naive" baggage claim driver, which is also the default value for this chart. 47 | 48 | This is the default for compatibility reasons, but is very space inefficient, and should be changed to either "btrfs" (recommended) or "overlay" depending on that filesystem's support in the Linux kernel your cluster is using. 49 | 50 | Please see https://github.com/concourse/concourse/issues/1230 and https://github.com/concourse/concourse/issues/1966 for background. 51 | 52 | {{- end }} 53 | {{- end }} 54 | {{- end }} 55 | 56 | 57 | 58 | {{- if .Values.concourse.web.localAuth.enabled }} 59 | {{- if contains "test:test" .Values.secrets.localUsers }} 60 | 61 | ******************* 62 | ******WARNING****** 63 | ******************* 64 | 65 | You're using the default "test" user with the default "test" password. 66 | 67 | Make sure you either disable local auth or change the combination to something more secure, preferably specifying a password in the bcrypted form. 68 | 69 | Please see `README.md` for examples. 70 | 71 | {{- end }} 72 | {{- end }} 73 | -------------------------------------------------------------------------------- /templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=mustache: */}} 2 | {{/* 3 | Expand the name of the chart. 4 | */}} 5 | {{- define "concourse.name" -}} 6 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} 7 | {{- end -}} 8 | 9 | {{/* 10 | Create a default fully qualified web node(s) name. 11 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 12 | */}} 13 | {{- define "concourse.web.fullname" -}} 14 | {{- $name := default "web" .Values.web.nameOverride -}} 15 | {{- if .Values.fullnameOverride -}} 16 | {{- printf "%s-%s" .Values.fullnameOverride $name | trunc 63 | trimSuffix "-" -}} 17 | {{- else -}} 18 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} 19 | {{- end -}} 20 | {{- end -}} 21 | 22 | {{/* 23 | Create a default fully qualified worker node(s) name. 24 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 25 | */}} 26 | {{- define "concourse.worker.fullname" -}} 27 | {{- $name := default "worker" .Values.worker.nameOverride -}} 28 | {{- if .Values.fullnameOverride -}} 29 | {{- printf "%s-%s" .Values.fullnameOverride $name | trunc 63 | trimSuffix "-" -}} 30 | {{- else -}} 31 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} 32 | {{- end -}} 33 | {{- end -}} 34 | 35 | {{/* 36 | Create a default fully qualified postgresql name. 37 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 38 | */}} 39 | {{- define "concourse.postgresql.fullname" -}} 40 | {{- $name := default "postgresql" .Values.postgresql.nameOverride -}} 41 | {{- if .Values.postgresql.fullnameOverride -}} 42 | {{- printf "%s" .Values.postgresql.fullnameOverride | trunc 63 | trimSuffix "-" -}} 43 | {{- else -}} 44 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} 45 | {{- end -}} 46 | {{- end -}} 47 | 48 | {{- define "concourse.secret.required" -}} 49 | {{- if .is }} 50 | {{- required (printf "secrets.%s is required because secrets.create is true and %s is true" .key .is) (index .root.Values.secrets .key ) | b64enc | quote }} 51 | {{- else -}} 52 | {{- required (printf "secrets.%s is required because secrets.create is true and %s isn't true" .key .isnt) (index .root.Values.secrets .key ) | b64enc | quote }} 53 | {{- end -}} 54 | {{- end -}} 55 | 56 | {{- define "concourse.namespacePrefix" -}} 57 | {{- default (printf "%s-" .Release.Name ) .Values.concourse.web.kubernetes.namespacePrefix -}} 58 | {{- end -}} 59 | 60 | {{- define "concourse.are-there-additional-volumes.with-the-name.concourse-work-dir" }} 61 | {{- range .Values.worker.additionalVolumes }} 62 | {{- if .name | eq "concourse-work-dir" }} 63 | {{- .name }} 64 | {{- end }} 65 | {{- end }} 66 | {{- end }} 67 | 68 | 69 | {{/* 70 | Creates the address of the TSA service. 71 | */}} 72 | {{- define "concourse.web.tsa.address" -}} 73 | {{- $port := .Values.concourse.web.tsa.bindPort -}} 74 | {{ template "concourse.web.fullname" . }}-worker-gateway:{{- print $port -}} 75 | {{- end -}} 76 | 77 | {{/* 78 | Determine version of Kubernetes cluster 79 | */}} 80 | {{- define "concourse.kubeVersion" -}} 81 | {{- print (.Capabilities.KubeVersion.Version | replace "v" "") -}} 82 | {{- end -}} 83 | 84 | {{/* 85 | Return the appropriate apiVersion for deployment. 86 | Sometimes GitVersion will contain a `v` so we need 87 | to strip that out. 88 | */}} 89 | {{- define "concourse.deployment.apiVersion" -}} 90 | {{- $version := include "concourse.kubeVersion" . -}} 91 | {{- if semverCompare "<1.9-0" $version -}} 92 | {{- print "extensions/v1beta1" -}} 93 | {{- else -}} 94 | {{- print "apps/v1" -}} 95 | {{- end -}} 96 | {{- end -}} 97 | 98 | {{/* 99 | Return the appropriate apiVersion for statefulset. 100 | */}} 101 | {{- define "concourse.statefulset.apiVersion" -}} 102 | {{- $version := include "concourse.kubeVersion" . -}} 103 | {{- if semverCompare "<1.9-0" $version -}} 104 | {{- print "apps/v1beta2" -}} 105 | {{- else -}} 106 | {{- print "apps/v1" -}} 107 | {{- end -}} 108 | {{- end -}} 109 | 110 | {{/* 111 | Return the appropriate apiVersion for ingress. 112 | */}} 113 | {{- define "concourse.ingress.apiVersion" -}} 114 | {{- $version := include "concourse.kubeVersion" . -}} 115 | {{- if semverCompare "<1.14-0" $version -}} 116 | {{- print "extensions/v1beta1" -}} 117 | {{- else if semverCompare "<1.20-0" $version -}} 118 | {{- print "networking.k8s.io/v1beta1" -}} 119 | {{- else -}} 120 | {{- print "networking.k8s.io/v1" -}} 121 | {{- end -}} 122 | {{- end -}} 123 | 124 | {{/* 125 | Return concourse environment variables for worker configuration 126 | */}} 127 | {{- define "concourse.worker.env" }} 128 | {{- if .Values.concourse.worker.rebalanceInterval }} 129 | - name: CONCOURSE_REBALANCE_INTERVAL 130 | value: {{ .Values.concourse.worker.rebalanceInterval | quote }} 131 | {{- end }} 132 | {{- if .Values.concourse.worker.sweepInterval }} 133 | - name: CONCOURSE_SWEEP_INTERVAL 134 | value: {{ .Values.concourse.worker.sweepInterval | quote }} 135 | {{- end }} 136 | {{- if .Values.concourse.worker.resourceTypes }} 137 | - name: CONCOURSE_RESOURCE_TYPES 138 | value: {{ .Values.concourse.worker.resourceTypes | quote }} 139 | {{- end }} 140 | {{- if .Values.concourse.worker.connectionDrainTimeout }} 141 | - name: CONCOURSE_CONNECTION_DRAIN_TIMEOUT 142 | value: {{ .Values.concourse.worker.connectionDrainTimeout | quote }} 143 | {{- end }} 144 | {{- if .Values.concourse.worker.healthcheckBindIp }} 145 | - name: CONCOURSE_HEALTHCHECK_BIND_IP 146 | value: {{ .Values.concourse.worker.healthcheckBindIp | quote }} 147 | {{- end }} 148 | {{- if .Values.concourse.worker.healthcheckBindPort }} 149 | - name: CONCOURSE_HEALTHCHECK_BIND_PORT 150 | value: {{ .Values.concourse.worker.healthcheckBindPort | quote }} 151 | {{- end }} 152 | {{- if .Values.concourse.worker.healthcheckTimeout }} 153 | - name: CONCOURSE_HEALTHCHECK_TIMEOUT 154 | value: {{ .Values.concourse.worker.healthcheckTimeout | quote }} 155 | {{- end }} 156 | {{- if .Values.concourse.worker.name }} 157 | - name: CONCOURSE_NAME 158 | value: {{ .Values.concourse.worker.name | quote }} 159 | {{- end }} 160 | {{- if .Values.concourse.worker.tag }} 161 | - name: CONCOURSE_TAG 162 | value: {{ .Values.concourse.worker.tag | quote }} 163 | {{- end }} 164 | {{- if .Values.concourse.worker.team }} 165 | - name: CONCOURSE_TEAM 166 | value: {{ .Values.concourse.worker.team | quote }} 167 | {{- end }} 168 | {{- if .Values.concourse.worker.http_proxy }} 169 | - name: http_proxy 170 | value: {{ .Values.concourse.worker.http_proxy | quote }} 171 | {{- end }} 172 | {{- if .Values.concourse.worker.https_proxy }} 173 | - name: https_proxy 174 | value: {{ .Values.concourse.worker.https_proxy | quote }} 175 | {{- end }} 176 | {{- if .Values.concourse.worker.no_proxy }} 177 | - name: no_proxy 178 | value: {{ .Values.concourse.worker.no_proxy | quote }} 179 | {{- end }} 180 | {{- if or .Values.concourse.worker.ephemeral ( eq .Values.worker.kind "Deployment") }} 181 | - name: CONCOURSE_EPHEMERAL 182 | value: "true" 183 | {{- end }} 184 | {{- if .Values.concourse.worker.debugBindIp }} 185 | - name: CONCOURSE_DEBUG_BIND_IP 186 | value: {{ .Values.concourse.worker.debugBindIp | quote }} 187 | {{- end }} 188 | {{- if .Values.concourse.worker.debugBindPort }} 189 | - name: CONCOURSE_DEBUG_BIND_PORT 190 | value: {{ .Values.concourse.worker.debugBindPort | quote }} 191 | {{- end }} 192 | {{- if .Values.concourse.worker.certsDir }} 193 | - name: CONCOURSE_CERTS_DIR 194 | value: {{ .Values.concourse.worker.certsDir | quote }} 195 | {{- end }} 196 | {{- if .Values.concourse.worker.workDir }} 197 | - name: CONCOURSE_WORK_DIR 198 | value: {{ .Values.concourse.worker.workDir | quote }} 199 | {{- end }} 200 | {{- if .Values.concourse.worker.bindIp }} 201 | - name: CONCOURSE_BIND_IP 202 | value: {{ .Values.concourse.worker.bindIp | quote }} 203 | {{- end }} 204 | {{- if .Values.concourse.worker.bindPort }} 205 | - name: CONCOURSE_BIND_PORT 206 | value: {{ .Values.concourse.worker.bindPort | quote }} 207 | {{- end }} 208 | {{- if .Values.concourse.worker.logLevel }} 209 | - name: CONCOURSE_LOG_LEVEL 210 | value: {{ .Values.concourse.worker.logLevel | quote }} 211 | {{- end }} 212 | {{- if not .Values.web.enabled }} 213 | - name: CONCOURSE_TSA_HOST 214 | value: "{{- range $i, $tsaHost := .Values.concourse.worker.tsa.hosts }}{{- if $i }},{{ end }}{{- $tsaHost }}{{- end -}}" 215 | {{- else }} 216 | - name: CONCOURSE_TSA_HOST 217 | value: "{{ template "concourse.web.tsa.address" . -}}" 218 | {{- end }} 219 | - name: CONCOURSE_TSA_PUBLIC_KEY 220 | value: "{{ .Values.worker.keySecretsPath }}/host_key.pub" 221 | - name: CONCOURSE_TSA_WORKER_PRIVATE_KEY 222 | value: "{{ .Values.worker.keySecretsPath }}/worker_key" 223 | {{- if .Values.concourse.worker.externalGardenUrl }} 224 | - name: CONCOURSE_EXTERNAL_GARDEN_URL 225 | value: {{ .Values.concourse.worker.externalGardenUrl | quote }} 226 | {{- end }} 227 | {{- if .Values.concourse.worker.runtime }} 228 | - name: CONCOURSE_RUNTIME 229 | value: {{ .Values.concourse.worker.runtime | quote }} 230 | {{- end }} 231 | {{- if .Values.concourse.worker.garden.bin }} 232 | - name: CONCOURSE_GARDEN_BIN 233 | value: {{ .Values.concourse.worker.garden.bin | quote }} 234 | {{- end }} 235 | {{- if .Values.concourse.worker.garden.config }} 236 | - name: CONCOURSE_GARDEN_CONFIG 237 | value: {{ .Values.concourse.worker.garden.config | quote }} 238 | {{- end }} 239 | {{- if not (kindIs "invalid" .Values.concourse.worker.garden.dnsProxyEnable) }} 240 | - name: CONCOURSE_GARDEN_DNS_PROXY_ENABLE 241 | value: {{ .Values.concourse.worker.garden.dnsProxyEnable | quote }} 242 | {{- end }} 243 | {{- if .Values.concourse.worker.garden.requestTimeout }} 244 | - name: CONCOURSE_GARDEN_REQUEST_TIMEOUT 245 | value: {{ .Values.concourse.worker.garden.requestTimeout | quote }} 246 | {{- end }} 247 | {{- if .Values.concourse.worker.garden.maxContainers | ne nil }} 248 | - name: CONCOURSE_GARDEN_MAX_CONTAINERS 249 | value: {{ .Values.concourse.worker.garden.maxContainers | quote }} 250 | {{- end }} 251 | {{- if .Values.concourse.worker.garden.networkPool }} 252 | - name: CONCOURSE_GARDEN_NETWORK_POOL 253 | value: {{ .Values.concourse.worker.garden.networkPool | quote }} 254 | {{- end }} 255 | {{- if .Values.concourse.worker.containerd.bin }} 256 | - name: CONCOURSE_CONTAINERD_BIN 257 | value: {{ .Values.concourse.worker.containerd.bin | quote }} 258 | {{- end }} 259 | {{- if .Values.concourse.worker.containerd.config }} 260 | - name: CONCOURSE_CONTAINERD_CONFIG 261 | value: {{ .Values.concourse.worker.containerd.config | quote }} 262 | {{- end }} 263 | {{- if .Values.concourse.worker.containerd.dnsProxyEnable }} 264 | - name: CONCOURSE_CONTAINERD_DNS_PROXY_ENABLE 265 | value: {{ .Values.concourse.worker.containerd.dnsProxyEnable | quote }} 266 | {{- end }} 267 | {{- if .Values.concourse.worker.containerd.mtu }} 268 | - name: CONCOURSE_CONTAINERD_MTU 269 | value: {{ .Values.concourse.worker.containerd.mtu | quote }} 270 | {{- end }} 271 | {{- if .Values.concourse.worker.containerd.externalIP }} 272 | - name: CONCOURSE_CONTAINERD_EXTERNAL_IP 273 | value: {{ .Values.concourse.worker.containerd.externalIP | quote }} 274 | {{- end }} 275 | {{- if .Values.concourse.worker.containerd.dnsServers }} 276 | {{- range .Values.concourse.worker.containerd.dnsServers }} 277 | - name: CONCOURSE_CONTAINERD_DNS_SERVER 278 | value: {{ . | title | quote }} 279 | {{- end }} 280 | {{- end }} 281 | {{- if .Values.concourse.worker.containerd.restrictedNetworks }} 282 | {{- range .Values.concourse.worker.containerd.restrictedNetworks }} 283 | - name: CONCOURSE_CONTAINERD_RESTRICTED_NETWORK 284 | value: {{ . | title | quote }} 285 | {{- end }} 286 | {{- end }} 287 | {{- if .Values.concourse.worker.containerd.allowHostAccess }} 288 | - name: CONCOURSE_CONTAINERD_ALLOW_HOST_ACCESS 289 | value: {{ .Values.concourse.worker.containerd.allowHostAccess | quote }} 290 | {{- end }} 291 | {{- if .Values.concourse.worker.containerd.maxContainers | ne nil }} 292 | - name: CONCOURSE_CONTAINERD_MAX_CONTAINERS 293 | value: {{ .Values.concourse.worker.containerd.maxContainers | quote }} 294 | {{- end }} 295 | {{- if .Values.concourse.worker.containerd.networkPool }} 296 | - name: CONCOURSE_CONTAINERD_NETWORK_POOL 297 | value: {{ .Values.concourse.worker.containerd.networkPool | quote }} 298 | {{- end }} 299 | {{- if .Values.concourse.worker.containerd.ipv6.enabled }} 300 | - name: CONCOURSE_CONTAINERD_V6_ENABLE 301 | value: {{ .Values.concourse.worker.containerd.ipv6.enabled | quote }} 302 | {{- end }} 303 | {{- if .Values.concourse.worker.containerd.ipv6.pool }} 304 | - name: CONCOURSE_CONTAINERD_V6_POOL 305 | value: {{ .Values.concourse.worker.containerd.ipv6.pool | quote }} 306 | {{- end }} 307 | {{- if .Values.concourse.worker.containerd.ipv6.disableMasquerade }} 308 | - name: CONCOURSE_CONTAINERD_V6_DISABLE_MASQUERADE 309 | value: {{ .Values.concourse.worker.containerd.ipv6.disableMasquerade | quote }} 310 | {{- end }} 311 | {{- if .Values.concourse.worker.containerd.requestTimeout }} 312 | - name: CONCOURSE_CONTAINERD_REQUEST_TIMEOUT 313 | value: {{ .Values.concourse.worker.containerd.requestTimeout | quote }} 314 | {{- end }} 315 | {{- if .Values.concourse.worker.containerd.initBin }} 316 | - name: CONCOURSE_CONTAINERD_INIT_BIN 317 | value: {{ .Values.concourse.worker.containerd.initBin | quote }} 318 | {{- end }} 319 | {{- if .Values.concourse.worker.containerd.ociHooksDir }} 320 | - name: CONCOURSE_CONTAINERD_OCI_HOOKS_DIR 321 | value: {{ .Values.concourse.worker.containerd.ociHooksDir | quote }} 322 | {{- end }} 323 | {{- if .Values.concourse.worker.containerd.seccompProfile }} 324 | - name: CONCOURSE_CONTAINERD_SECCOMP_PROFILE 325 | value: {{ .Values.concourse.worker.containerd.seccompProfile | quote }} 326 | {{- end }} 327 | {{- if .Values.concourse.worker.containerd.cniPluginsDir }} 328 | - name: CONCOURSE_CONTAINERD_CNI_PLUGINS_DIR 329 | value: {{ .Values.concourse.worker.containerd.cniPluginsDir | quote }} 330 | {{- end }} 331 | {{- if .Values.concourse.worker.containerd.privilegedMode }} 332 | - name: CONCOURSE_CONTAINERD_PRIVILEGED_MODE 333 | value: {{ .Values.concourse.worker.containerd.privilegedMode | quote }} 334 | {{- end }} 335 | {{- if .Values.concourse.worker.baggageclaim.logLevel }} 336 | - name: CONCOURSE_BAGGAGECLAIM_LOG_LEVEL 337 | value: {{ .Values.concourse.worker.baggageclaim.logLevel | quote }} 338 | {{- end }} 339 | {{- if .Values.concourse.worker.baggageclaim.bindIp }} 340 | - name: CONCOURSE_BAGGAGECLAIM_BIND_IP 341 | value: {{ .Values.concourse.worker.baggageclaim.bindIp | quote }} 342 | {{- end }} 343 | {{- if .Values.concourse.worker.baggageclaim.bindPort }} 344 | - name: CONCOURSE_BAGGAGECLAIM_BIND_PORT 345 | value: {{ .Values.concourse.worker.baggageclaim.bindPort | quote }} 346 | {{- end }} 347 | {{- if .Values.concourse.worker.baggageclaim.debugBindIp }} 348 | - name: CONCOURSE_BAGGAGECLAIM_DEBUG_BIND_IP 349 | value: {{ .Values.concourse.worker.baggageclaim.debugBindIp | quote }} 350 | {{- end }} 351 | {{- if .Values.concourse.worker.baggageclaim.debugBindPort }} 352 | - name: CONCOURSE_BAGGAGECLAIM_DEBUG_BIND_PORT 353 | value: {{ .Values.concourse.worker.baggageclaim.debugBindPort | quote }} 354 | {{- end }} 355 | {{- if .Values.concourse.worker.baggageclaim.volumes }} 356 | - name: CONCOURSE_BAGGAGECLAIM_VOLUMES 357 | value: {{ .Values.concourse.worker.baggageclaim.volumes | quote }} 358 | {{- end }} 359 | {{- if .Values.concourse.worker.baggageclaim.driver }} 360 | - name: CONCOURSE_BAGGAGECLAIM_DRIVER 361 | value: {{ .Values.concourse.worker.baggageclaim.driver | quote }} 362 | {{- end }} 363 | {{- if .Values.concourse.worker.baggageclaim.btrfsBin }} 364 | - name: CONCOURSE_BAGGAGECLAIM_BTRFS_BIN 365 | value: {{ .Values.concourse.worker.baggageclaim.btrfsBin | quote }} 366 | {{- end }} 367 | {{- if .Values.concourse.worker.baggageclaim.mkfsBin }} 368 | - name: CONCOURSE_BAGGAGECLAIM_MKFS_BIN 369 | value: {{ .Values.concourse.worker.baggageclaim.mkfsBin | quote }} 370 | {{- end }} 371 | {{- if .Values.concourse.worker.baggageclaim.overlaysDir }} 372 | - name: CONCOURSE_BAGGAGECLAIM_OVERLAYS_DIR 373 | value: {{ .Values.concourse.worker.baggageclaim.overlaysDir | quote }} 374 | {{- end }} 375 | {{- if .Values.concourse.worker.baggageclaim.disableUserNamespaces }} 376 | - name: CONCOURSE_BAGGAGECLAIM_DISABLE_USER_NAMESPACES 377 | value: {{ .Values.concourse.worker.baggageclaim.disableUserNamespaces | quote }} 378 | {{- end }} 379 | {{- if .Values.concourse.worker.volumeSweeperMaxInFlight }} 380 | - name: CONCOURSE_VOLUME_SWEEPER_MAX_IN_FLIGHT 381 | value: {{ .Values.concourse.worker.volumeSweeperMaxInFlight | quote }} 382 | {{- end }} 383 | {{- if .Values.concourse.worker.containerSweeperMaxInFlight }} 384 | - name: CONCOURSE_CONTAINER_SWEEPER_MAX_IN_FLIGHT 385 | value: {{ .Values.concourse.worker.containerSweeperMaxInFlight | quote }} 386 | {{- end }} 387 | {{- if .Values.concourse.worker.baggageclaim.p2pInterfaceFamily }} 388 | - name: CONCOURSE_BAGGAGECLAIM_P2P_INTERFACE_FAMILY 389 | value: {{ .Values.concourse.worker.baggageclaim.p2pInterfaceFamily | quote }} 390 | {{- end }} 391 | {{- if .Values.concourse.worker.baggageclaim.p2pInterfaceNamePattern }} 392 | - name: CONCOURSE_BAGGAGECLAIM_P2P_INTERFACE_NAME_PATTERN 393 | value: {{ .Values.concourse.worker.baggageclaim.p2pInterfaceNamePattern | quote }} 394 | {{- end -}} 395 | {{- if .Values.concourse.worker.tracing.serviceName }} 396 | - name: CONCOURSE_TRACING_SERVICE_NAME 397 | value: {{ .Values.concourse.worker.tracing.serviceName | quote }} 398 | {{- end }} 399 | {{- if .Values.concourse.worker.tracing.attributes }} 400 | - name: CONCOURSE_TRACING_ATTRIBUTE 401 | value: "{{- $local := dict "first" true -}}{{- range $k, $v := .Values.concourse.worker.tracing.attributes -}}{{- if not $local.first -}},{{- end -}}{{- $k -}}:{{- $v -}}{{- $_ := set $local "first" false -}}{{- end -}}" 402 | {{- end }} 403 | {{- if .Values.concourse.worker.tracing.jaegerEndpoint }} 404 | - name: CONCOURSE_TRACING_JAEGER_ENDPOINT 405 | value: {{ .Values.concourse.worker.tracing.jaegerEndpoint | quote }} 406 | {{- end }} 407 | {{- if .Values.concourse.worker.tracing.jaegerTags }} 408 | - name: CONCOURSE_TRACING_JAEGER_TAGS 409 | value: {{ .Values.concourse.worker.tracing.jaegerTags | quote }} 410 | {{- end }} 411 | {{- if .Values.concourse.worker.tracing.jaegerService }} 412 | - name: CONCOURSE_TRACING_JAEGER_SERVICE 413 | value: {{ .Values.concourse.worker.tracing.jaegerService | quote }} 414 | {{- end }} 415 | {{- if .Values.concourse.worker.tracing.stackdriverProjectId }} 416 | - name: CONCOURSE_TRACING_STACKDRIVER_PROJECTID 417 | value: {{ .Values.concourse.worker.tracing.stackdriverProjectId | quote }} 418 | {{- end }} 419 | {{- if .Values.concourse.worker.tracing.honeycombApiKey }} 420 | - name: CONCOURSE_TRACING_HONEYCOMB_API_KEY 421 | value: {{ .Values.concourse.worker.tracing.honeycombApiKey | quote }} 422 | {{- end }} 423 | {{- if .Values.concourse.worker.tracing.honeycombDataset }} 424 | - name: CONCOURSE_TRACING_HONEYCOMB_DATASET 425 | value: {{ .Values.concourse.worker.tracing.honeycombDataset | quote }} 426 | {{- end }} 427 | {{- if .Values.concourse.worker.tracing.otlpAddress }} 428 | - name: CONCOURSE_TRACING_OTLP_ADDRESS 429 | value: {{ .Values.concourse.worker.tracing.otlpAddress | quote }} 430 | {{- end }} 431 | {{- if .Values.concourse.worker.tracing.otlpHeaders }} 432 | - name: CONCOURSE_TRACING_OTLP_HEADER 433 | value: "{{- $local := dict "first" true -}}{{- range $k, $v := .Values.concourse.worker.tracing.otlpHeaders -}}{{- if not $local.first -}},{{- end -}}{{- $k -}}:{{- $v -}}{{- $_ := set $local "first" false -}}{{- end -}}" 434 | {{- end }} 435 | {{- if .Values.concourse.worker.tracing.otlpUseTls }} 436 | - name: CONCOURSE_TRACING_OTLP_USE_TLS 437 | value: {{ .Values.concourse.worker.tracing.otlpUseTls | quote }} 438 | {{- end }} 439 | {{- end -}} 440 | 441 | {{/* 442 | Return concourse environment variables for postgresql configuration 443 | */}} 444 | {{- define "concourse.postgresql.env" -}} 445 | {{- if .Values.postgresql.enabled }} 446 | - name: CONCOURSE_POSTGRES_HOST 447 | value: {{ template "concourse.postgresql.fullname" . }} 448 | - name: CONCOURSE_POSTGRES_USER 449 | value: {{ .Values.postgresql.auth.username | quote }} 450 | - name: CONCOURSE_POSTGRES_PASSWORD 451 | valueFrom: 452 | secretKeyRef: 453 | name: {{ template "concourse.postgresql.fullname" . }} 454 | key: password 455 | - name: CONCOURSE_POSTGRES_DATABASE 456 | value: {{ .Values.postgresql.auth.database | quote }} 457 | {{- else }} 458 | {{- if .Values.concourse.web.postgres.host }} 459 | - name: CONCOURSE_POSTGRES_HOST 460 | value: {{ .Values.concourse.web.postgres.host | quote }} 461 | {{- end }} 462 | {{- if .Values.concourse.web.postgres.port }} 463 | - name: CONCOURSE_POSTGRES_PORT 464 | value: {{ .Values.concourse.web.postgres.port | quote }} 465 | {{- end }} 466 | {{- if .Values.concourse.web.postgres.socket }} 467 | - name: CONCOURSE_POSTGRES_SOCKET 468 | value: {{ .Values.concourse.web.postgres.socket | quote }} 469 | {{- end }} 470 | - name: CONCOURSE_POSTGRES_USER 471 | valueFrom: 472 | secretKeyRef: 473 | name: {{ template "concourse.web.fullname" . }} 474 | key: postgresql-user 475 | - name: CONCOURSE_POSTGRES_PASSWORD 476 | valueFrom: 477 | secretKeyRef: 478 | name: {{ template "concourse.web.fullname" . }} 479 | key: postgresql-password 480 | {{- if .Values.concourse.web.postgres.sslmode }} 481 | - name: CONCOURSE_POSTGRES_SSLMODE 482 | value: {{ .Values.concourse.web.postgres.sslmode | quote }} 483 | {{- end }} 484 | {{- if .Values.secrets.postgresCaCert }} 485 | - name: CONCOURSE_POSTGRES_CA_CERT 486 | value: "{{ .Values.web.postgresqlSecretsPath }}/ca.cert" 487 | {{- end }} 488 | {{- if .Values.secrets.postgresClientCert }} 489 | - name: CONCOURSE_POSTGRES_CLIENT_CERT 490 | value: "{{ .Values.web.postgresqlSecretsPath }}/client.cert" 491 | {{- end }} 492 | {{- if .Values.secrets.postgresClientKey }} 493 | - name: CONCOURSE_POSTGRES_CLIENT_KEY 494 | value: "{{ .Values.web.postgresqlSecretsPath }}/client.key" 495 | {{- end }} 496 | {{- if .Values.concourse.web.postgres.connectTimeout }} 497 | - name: CONCOURSE_POSTGRES_CONNECT_TIMEOUT 498 | value: {{ .Values.concourse.web.postgres.connectTimeout | quote }} 499 | {{- end }} 500 | {{- if .Values.concourse.web.postgres.database }} 501 | - name: CONCOURSE_POSTGRES_DATABASE 502 | value: {{ .Values.concourse.web.postgres.database | quote }} 503 | {{- end }} 504 | {{- end -}} 505 | {{- end -}} 506 | -------------------------------------------------------------------------------- /templates/namespace.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.web.enabled -}} 2 | {{- if and .Values.concourse.web.kubernetes.enabled .Values.concourse.web.kubernetes.createTeamNamespaces -}} 3 | {{- range .Values.concourse.web.kubernetes.teams }} 4 | --- 5 | apiVersion: v1 6 | kind: Namespace 7 | metadata: 8 | {{- if $.Values.concourse.web.kubernetes.keepNamespaces }} 9 | annotations: 10 | "helm.sh/resource-policy": keep 11 | {{- end }} 12 | name: {{ template "concourse.namespacePrefix" $ }}{{ . }} 13 | labels: 14 | app: {{ template "concourse.web.fullname" $ }} 15 | chart: "{{ $.Chart.Name }}-{{ $.Chart.Version }}" 16 | release: "{{ $.Release.Name }}" 17 | heritage: "{{ $.Release.Service }}" 18 | {{- end }} 19 | {{- end }} 20 | {{- end -}} 21 | -------------------------------------------------------------------------------- /templates/required-check.yaml: -------------------------------------------------------------------------------- 1 | {{ if not (or .Values.web.enabled .Values.worker.enabled) }} 2 | {{- required "Must set either web.enabled or worker.enabled to create a concourse deployment" "" }} 3 | {{ end }} 4 | 5 | {{ if and (not .Values.concourse.worker.tsa.hosts) (and (not .Values.web.enabled) (.Values.worker.enabled)) }} 6 | {{- required "concourse.worker.tsa.hosts must be set in case of worker only deployment" "" }} 7 | {{ end }} 8 | 9 | {{ if and (.Values.web.ingress.enabled) (not (or .Values.web.ingress.hosts .Values.web.ingress.rulesOverride)) }} 10 | 11 | {{- required "When ingress is enabled, you must define either web.ingress.hosts or web.ingress.rulesOverride" "" }} 12 | {{ end }} 13 | -------------------------------------------------------------------------------- /templates/web-api-svc.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.web.enabled -}} 2 | {{- $root := . -}} 3 | apiVersion: v1 4 | kind: Service 5 | metadata: 6 | name: {{ template "concourse.web.fullname" . }} 7 | labels: 8 | app: {{ template "concourse.web.fullname" . }} 9 | chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 10 | release: "{{ .Release.Name }}" 11 | heritage: "{{ .Release.Service }}" 12 | {{- range $key, $value := .Values.web.service.api.labels }} 13 | {{ $key }}: {{ $value | quote }} 14 | {{- end }} 15 | {{- if .Values.web.service.api.annotations }} 16 | annotations: 17 | {{- range $key, $value := .Values.web.service.api.annotations }} 18 | {{ $key }}: {{ tpl $value $root | quote }} 19 | {{- end }} 20 | {{- end }} 21 | spec: 22 | type: {{ .Values.web.service.api.type }} 23 | {{- if .Values.web.service.api.loadBalancerSourceRanges }} 24 | loadBalancerSourceRanges: 25 | {{- range .Values.web.service.api.loadBalancerSourceRanges }} 26 | - {{ . }} 27 | {{- end }} 28 | {{- end }} 29 | {{- if and (eq "ClusterIP" .Values.web.service.api.type) .Values.web.service.api.clusterIP }} 30 | {{ with .Values.web.service.api.clusterIP }}clusterIP: {{quote . }}{{ end}} 31 | {{- end }} 32 | {{- if and (eq "LoadBalancer" .Values.web.service.api.type) .Values.web.service.api.loadBalancerIP }} 33 | loadBalancerIP: {{ .Values.web.service.api.loadBalancerIP }} 34 | {{- end }} 35 | ports: 36 | - name: {{ .Values.web.service.api.port.name }} 37 | port: {{ .Values.concourse.web.bindPort }} 38 | targetPort: atc 39 | {{- if and (eq "NodePort" .Values.web.service.api.type) .Values.web.service.api.NodePort }} 40 | nodePort: {{ .Values.web.service.api.NodePort}} 41 | {{- end }} 42 | {{- if .Values.concourse.web.tls.enabled }} 43 | - name: {{ .Values.web.service.api.tlsPort.name }} 44 | port: {{ .Values.concourse.web.tls.bindPort }} 45 | targetPort: atc-tls 46 | {{- if and (eq "NodePort" .Values.web.service.api.type) .Values.web.service.api.tlsNodePort }} 47 | nodePort: {{ .Values.web.service.api.tlsNodePort}} 48 | {{- end }} 49 | {{- end }} 50 | selector: 51 | app: {{ template "concourse.web.fullname" . }} 52 | {{- end }} 53 | -------------------------------------------------------------------------------- /templates/web-configmap.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.web.enabled -}} 2 | {{- if or .Values.concourse.web.auth.mainTeam.config (or .Values.concourse.web.configRBAC .Values.concourse.web.baseResourceTypeDefaults) -}} 3 | apiVersion: v1 4 | kind: ConfigMap 5 | metadata: 6 | name: {{ template "concourse.web.fullname" . }} 7 | labels: 8 | app: {{ template "concourse.web.fullname" . }} 9 | chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 10 | release: "{{ .Release.Name }}" 11 | heritage: "{{ .Release.Service }}" 12 | data: 13 | {{- if .Values.concourse.web.auth.mainTeam.config }} 14 | main-team.yml: {{ .Values.concourse.web.auth.mainTeam.config | quote }} 15 | {{- end -}} 16 | {{- if .Values.concourse.web.configRBAC }} 17 | config-rbac.yml: {{ .Values.concourse.web.configRBAC | quote }} 18 | {{- end -}} 19 | {{- if .Values.concourse.web.baseResourceTypeDefaults }} 20 | brt-defaults.yml: {{ .Values.concourse.web.baseResourceTypeDefaults | quote }} 21 | {{- end -}} 22 | {{- end -}} 23 | {{- end -}} 24 | -------------------------------------------------------------------------------- /templates/web-ingress.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.web.enabled -}} 2 | {{- if .Values.web.ingress.enabled -}} 3 | {{- $releaseName := .Release.Name -}} 4 | {{- $serviceName := include "concourse.web.fullname" . -}} 5 | {{- $servicePort := .Values.concourse.web.bindPort -}} 6 | {{- $apiVersion := include "concourse.ingress.apiVersion" . -}} 7 | apiVersion: {{ $apiVersion }} 8 | kind: Ingress 9 | metadata: 10 | name: {{ template "concourse.web.fullname" . }} 11 | labels: 12 | app: {{ template "concourse.web.fullname" . }} 13 | chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 14 | release: "{{ .Release.Name }}" 15 | heritage: "{{ .Release.Service }}" 16 | annotations: 17 | {{- range $key, $value := .Values.web.ingress.annotations }} 18 | {{ $key }}: {{ $value | quote }} 19 | {{- end }} 20 | spec: 21 | {{- if .Values.web.ingress.ingressClassName }} 22 | ingressClassName: {{ .Values.web.ingress.ingressClassName | quote }} 23 | {{- end }} 24 | rules: 25 | {{- if .Values.web.ingress.rulesOverride }} 26 | {{- toYaml .Values.web.ingress.rulesOverride | nindent 4 }} 27 | {{- else }} 28 | {{- range .Values.web.ingress.hosts }} 29 | - host: {{ . }} 30 | http: 31 | paths: 32 | {{- if or (eq $apiVersion "extensions/v1beta1") (eq $apiVersion "networking.k8s.io/v1beta1") }} 33 | - backend: 34 | serviceName: {{ $serviceName }} 35 | servicePort: {{ $servicePort }} 36 | {{- else }} 37 | - pathType: Prefix 38 | path: "/" 39 | backend: 40 | service: 41 | name: {{ $serviceName }} 42 | port: 43 | {{- if typeIs "string" $servicePort }} 44 | name: {{ $servicePort }} 45 | {{- else }} 46 | number: {{ $servicePort }} 47 | {{- end }} 48 | {{- end }} 49 | {{- end -}} 50 | {{- end }} 51 | {{- if .Values.web.ingress.tls }} 52 | tls: 53 | {{ toYaml .Values.web.ingress.tls | indent 4 }} 54 | {{- end -}} 55 | {{- end -}} 56 | {{- end -}} 57 | -------------------------------------------------------------------------------- /templates/web-podsecuritypolicy.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.web.enabled -}} 2 | {{- if .Values.podSecurityPolicy.create -}} 3 | apiVersion: policy/v1beta1 4 | kind: PodSecurityPolicy 5 | metadata: 6 | name: {{ template "concourse.web.fullname" . }} 7 | labels: 8 | app: {{ template "concourse.web.fullname" . }} 9 | chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 10 | release: "{{ .Release.Name }}" 11 | heritage: "{{ .Release.Service }}" 12 | spec: 13 | privileged: false 14 | allowPrivilegeEscalation: false 15 | requiredDropCapabilities: 16 | - ALL 17 | hostNetwork: false 18 | hostIPC: false 19 | hostPID: false 20 | volumes: 21 | {{ toYaml .Values.podSecurityPolicy.allowedWebVolumes | indent 4 }} 22 | runAsUser: 23 | rule: 'RunAsAny' 24 | seLinux: 25 | rule: 'RunAsAny' 26 | supplementalGroups: 27 | rule: 'MustRunAs' 28 | ranges: 29 | # Forbid adding the root group. 30 | - min: 1 31 | max: 65535 32 | fsGroup: 33 | rule: 'MustRunAs' 34 | ranges: 35 | # Forbid adding the root group. 36 | - min: 1 37 | max: 65535 38 | readOnlyRootFilesystem: true 39 | {{- end -}} 40 | {{- end }} 41 | -------------------------------------------------------------------------------- /templates/web-prometheus-svc.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.concourse.web.prometheus.enabled .Values.web.enabled}} 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: {{ template "concourse.web.fullname" . }}-prometheus 6 | labels: 7 | app: {{ template "concourse.web.fullname" . }} 8 | chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 9 | release: "{{ .Release.Name }}" 10 | heritage: "{{ .Release.Service }}" 11 | {{- range $key, $value := .Values.web.service.prometheus.labels }} 12 | {{ $key }}: {{ $value | quote }} 13 | {{- end }} 14 | annotations: 15 | prometheus.io/scrape: "true" 16 | prometheus.io/port: {{ .Values.concourse.web.prometheus.bindPort | quote }} 17 | {{- range $key, $value := .Values.web.service.prometheus.annotations }} 18 | {{ $key }}: {{ $value | quote }} 19 | {{- end }} 20 | spec: 21 | type: {{ .Values.web.service.prometheus.type }} 22 | {{- if .Values.web.service.prometheus.loadBalancerSourceRanges }} 23 | loadBalancerSourceRanges: 24 | {{- range .Values.web.service.prometheus.loadBalancerSourceRanges }} 25 | - {{ . }} 26 | {{- end }} 27 | {{- end }} 28 | {{- if and (eq "ClusterIP" .Values.web.service.prometheus.type) .Values.web.service.prometheus.clusterIP }} 29 | clusterIP: {{ .Values.web.service.prometheus.clusterIP }} 30 | {{- end }} 31 | {{- if and (eq "LoadBalancer" .Values.web.service.prometheus.type) .Values.web.service.prometheus.loadBalancerIP }} 32 | loadBalancerIP: {{ .Values.web.service.prometheus.loadBalancerIP }} 33 | {{- end }} 34 | ports: 35 | - name: prometheus 36 | port: {{ .Values.concourse.web.prometheus.bindPort }} 37 | targetPort: prometheus 38 | {{- if and (eq "NodePort" .Values.web.service.prometheus.type) .Values.web.service.prometheus.NodePort }} 39 | nodePort: {{ .Values.web.service.prometheus.NodePort}} 40 | {{- end }} 41 | selector: 42 | app: {{ template "concourse.web.fullname" . }} 43 | {{- end }} 44 | -------------------------------------------------------------------------------- /templates/web-role.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.web.enabled -}} 2 | {{- if .Values.rbac.create -}} 3 | {{- if .Values.concourse.web.kubernetes.enabled }} 4 | --- 5 | apiVersion: rbac.authorization.k8s.io/{{ .Values.rbac.apiVersion }} 6 | kind: ClusterRole 7 | metadata: 8 | name: {{ template "concourse.web.fullname" . }} 9 | labels: 10 | app: {{ template "concourse.web.fullname" . }} 11 | chart: {{ .Chart.Name }}-{{ .Chart.Version }} 12 | heritage: {{ .Release.Service }} 13 | release: {{ .Release.Name }} 14 | rules: 15 | - apiGroups: [""] 16 | resources: ["secrets"] 17 | verbs: ["get"] 18 | {{- end }} 19 | {{- if .Values.podSecurityPolicy.create }} 20 | --- 21 | apiVersion: rbac.authorization.k8s.io/{{ .Values.rbac.apiVersion }} 22 | kind: ClusterRole 23 | metadata: 24 | name: {{ template "concourse.web.fullname" . }}-psp 25 | labels: 26 | app: {{ template "concourse.web.fullname" . }} 27 | chart: {{ .Chart.Name }}-{{ .Chart.Version }} 28 | heritage: {{ .Release.Service }} 29 | release: {{ .Release.Name }} 30 | rules: 31 | - apiGroups: ['policy'] 32 | resources: ['podsecuritypolicies'] 33 | verbs: ['use'] 34 | resourceNames: 35 | - {{ template "concourse.web.fullname" . }} 36 | {{- end }} 37 | {{- end -}} 38 | {{- end -}} 39 | -------------------------------------------------------------------------------- /templates/web-rolebinding.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.web.enabled -}} 2 | {{- if .Values.rbac.create -}} 3 | {{- if and .Values.concourse.web.kubernetes.enabled .Values.concourse.web.kubernetes.createTeamNamespaces -}} 4 | {{- range .Values.concourse.web.kubernetes.teams }} 5 | --- 6 | apiVersion: rbac.authorization.k8s.io/{{ $.Values.rbac.apiVersion }} 7 | kind: RoleBinding 8 | metadata: 9 | name: {{ template "concourse.web.fullname" $ }}-{{ . }} 10 | namespace: {{ template "concourse.namespacePrefix" $ }}{{ . }} 11 | labels: 12 | app: {{ template "concourse.web.fullname" $ }} 13 | chart: {{ $.Chart.Name }}-{{ $.Chart.Version }} 14 | heritage: {{ $.Release.Service }} 15 | release: {{ $.Release.Name }} 16 | roleRef: 17 | apiGroup: rbac.authorization.k8s.io 18 | kind: ClusterRole 19 | name: {{ template "concourse.web.fullname" $ }} 20 | subjects: 21 | - kind: ServiceAccount 22 | name: {{ template "concourse.web.fullname" $ }} 23 | namespace: {{ $.Release.Namespace }} 24 | {{- end }} 25 | {{- end }} 26 | {{- if .Values.podSecurityPolicy.create }} 27 | --- 28 | apiVersion: rbac.authorization.k8s.io/{{ .Values.rbac.apiVersion }} 29 | kind: RoleBinding 30 | metadata: 31 | name: {{ template "concourse.web.fullname" . }}-psp 32 | labels: 33 | app: {{ template "concourse.web.fullname" . }} 34 | chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 35 | release: "{{ .Release.Name }}" 36 | heritage: "{{ .Release.Service }}" 37 | roleRef: 38 | apiGroup: rbac.authorization.k8s.io 39 | kind: ClusterRole 40 | name: {{ template "concourse.web.fullname" . }}-psp 41 | subjects: 42 | - kind: ServiceAccount 43 | name: {{ template "concourse.web.fullname" . }} 44 | namespace: {{ .Release.Namespace }} 45 | {{- end }} 46 | {{- end -}} 47 | {{- end -}} 48 | -------------------------------------------------------------------------------- /templates/web-secrets.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.web.enabled }} 2 | {{- if .Values.secrets.create }} 3 | apiVersion: v1 4 | kind: Secret 5 | metadata: 6 | name: {{ template "concourse.web.fullname" . }} 7 | labels: 8 | app: {{ template "concourse.web.fullname" . }} 9 | chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 10 | release: "{{ .Release.Name }}" 11 | heritage: "{{ .Release.Service }}" 12 | {{- if .Values.secrets.annotations }} 13 | annotations: 14 | {{ toYaml .Values.secrets.annotations | indent 4 }} 15 | {{- end }} 16 | type: Opaque 17 | data: 18 | host-key: {{ .Values.secrets.hostKey | b64enc | quote }} 19 | session-signing-key: {{ .Values.secrets.sessionSigningKey | b64enc | quote }} 20 | worker-key-pub: {{ .Values.secrets.workerKeyPub | b64enc | quote }} 21 | {{- if .Values.concourse.web.clientConfig.enabled }} 22 | client-id: {{ template "concourse.secret.required" dict "key" "clientId" "is" "concourse.web.clientConfig.enabled" "root" . }} 23 | client-secret: {{ template "concourse.secret.required" dict "key" "clientSecret" "is" "concourse.web.clientConfig.enabled" "root" . }} 24 | {{- end }} 25 | {{- if .Values.concourse.web.tsa.clientConfig.enabled }} 26 | tsa-client-id: {{ template "concourse.secret.required" dict "key" "tsaClientId" "is" "concourse.web.tsa.clientConfig.enabled" "root" . }} 27 | tsa-client-secret: {{ template "concourse.secret.required" dict "key" "tsaClientSecret" "is" "concourse.web.tsa.clientConfig.enabled" "root" . }} 28 | {{- end }} 29 | {{- if not .Values.postgresql.enabled }} 30 | postgresql-user: {{ template "concourse.secret.required" dict "key" "postgresUser" "isnt" "postgresql.enabled" "root" . }} 31 | postgresql-password: {{ template "concourse.secret.required" dict "key" "postgresPassword" "isnt" "postgresql.enabled" "root" . }} 32 | postgresql-ca-cert: {{ default "" .Values.secrets.postgresCaCert | b64enc | quote }} 33 | postgresql-client-cert: {{ default "" .Values.secrets.postgresClientCert | b64enc | quote }} 34 | postgresql-client-key: {{ default "" .Values.secrets.postgresClientKey | b64enc | quote }} 35 | {{- end }} 36 | {{- if .Values.concourse.web.encryption.enabled }} 37 | encryption-key: {{ template "concourse.secret.required" dict "key" "encryptionKey" "is" "concourse.encryption.enabled" "root" . }} 38 | old-encryption-key: {{ default "" .Values.secrets.oldEncryptionKey | b64enc | quote }} 39 | {{- end }} 40 | {{- if .Values.concourse.web.localAuth.enabled }} 41 | local-users: {{ .Values.secrets.localUsers | b64enc | quote }} 42 | {{- end }} 43 | {{- if .Values.concourse.web.auth.cf.enabled }} 44 | cf-client-id: {{ template "concourse.secret.required" dict "key" "cfClientId" "is" "concourse.web.auth.cf.enabled" "root" . }} 45 | cf-client-secret: {{ template "concourse.secret.required" dict "key" "cfClientSecret" "is" "concourse.web.auth.cf.enabled" "root" . }} 46 | cf-ca-cert: {{ default "" .Values.secrets.cfCaCert | b64enc | quote }} 47 | {{- end }} 48 | {{- if .Values.concourse.web.auth.bitbucketCloud.enabled }} 49 | bitbucket-cloud-client-id: {{ template "concourse.secret.required" dict "key" "bitbucketCloudClientId" "is" "concourse.web.auth.bitbucketCloud.enabled" "root" . }} 50 | bitbucket-cloud-client-secret: {{ template "concourse.secret.required" dict "key" "bitbucketCloudClientSecret" "is" "concourse.web.auth.bitbucketCloud.enabled" "root" . }} 51 | {{- end }} 52 | {{- if .Values.concourse.web.auth.github.enabled }} 53 | github-client-id: {{ template "concourse.secret.required" dict "key" "githubClientId" "is" "concourse.web.auth.github.enabled" "root" . }} 54 | github-client-secret: {{ template "concourse.secret.required" dict "key" "githubClientSecret" "is" "concourse.web.auth.github.enabled" "root" . }} 55 | github-ca-cert: {{ default "" .Values.secrets.githubCaCert | b64enc | quote }} 56 | {{- end }} 57 | {{- if .Values.concourse.web.auth.gitlab.enabled }} 58 | gitlab-client-id: {{ template "concourse.secret.required" dict "key" "gitlabClientId" "is" "concourse.web.auth.gitlab.enabled" "root" . }} 59 | gitlab-client-secret: {{ template "concourse.secret.required" dict "key" "gitlabClientSecret" "is" "concourse.web.auth.gitlab.enabled" "root" . }} 60 | {{- end }} 61 | {{- if .Values.concourse.web.auth.ldap.enabled }} 62 | ldap-ca-cert: {{ default "" .Values.secrets.ldapCaCert | b64enc | quote }} 63 | {{- end }} 64 | {{- if .Values.concourse.web.auth.saml.enabled }} 65 | {{- if not .Values.concourse.web.auth.saml.insecureSkipVerify }} 66 | saml-ca-cert: {{ default "" .Values.secrets.samlCaCert | b64enc | quote }} 67 | {{- end }} 68 | {{- end }} 69 | {{- if .Values.concourse.web.auth.oauth.enabled }} 70 | oauth-client-id: {{ template "concourse.secret.required" dict "key" "oauthClientId" "is" "concourse.web.auth.oauth.enabled" "root" . }} 71 | oauth-client-secret: {{ template "concourse.secret.required" dict "key" "oauthClientSecret" "is" "concourse.web.auth.oauth.enabled" "root" . }} 72 | oauth-ca-cert: {{ default "" .Values.secrets.oauthCaCert | b64enc | quote }} 73 | {{- end }} 74 | {{- if .Values.concourse.web.auth.oidc.enabled }} 75 | oidc-client-id: {{ template "concourse.secret.required" dict "key" "oidcClientId" "is" "concourse.web.auth.oidc.enabled" "root" . }} 76 | oidc-client-secret: {{ template "concourse.secret.required" dict "key" "oidcClientSecret" "is" "concourse.web.auth.oidc.enabled" "root" . }} 77 | oidc-ca-cert: {{ default "" .Values.secrets.oidcCaCert | b64enc | quote }} 78 | {{- end }} 79 | {{- if .Values.concourse.web.auth.microsoft.enabled }} 80 | microsoft-client-id: {{ template "concourse.secret.required" dict "key" "microsoftClientId" "is" "concourse.web.auth.microsoft.enabled" "root" . }} 81 | microsoft-client-secret: {{ template "concourse.secret.required" dict "key" "microsoftClientSecret" "is" "concourse.web.auth.microsoft.enabled" "root" . }} 82 | {{- end }} 83 | {{- if .Values.concourse.web.tls.enabled }} 84 | {{- if not .Values.concourse.web.letsEncrypt.enabled }} 85 | web-tls-cert: {{ template "concourse.secret.required" dict "key" "webTlsCert" "is" "concourse.web.tls.enabled" "root" . }} 86 | web-tls-key: {{ template "concourse.secret.required" dict "key" "webTlsKey" "is" "concourse.web.tls.enabled" "root" . }} 87 | {{- if .Values.secrets.webTlsCaCert }} 88 | web-tls-ca-cert: {{ template "concourse.secret.required" dict "key" "webTlsCaCert" "is" "concourse.web.tls.enabled" "root" . }} 89 | {{- end }} 90 | {{- end }} 91 | {{- end }} 92 | {{- if .Values.concourse.web.vault.enabled }} 93 | vault-ca-cert: {{ default "" .Values.secrets.vaultCaCert | b64enc | quote }} 94 | vault-client-token: {{ default "" .Values.secrets.vaultClientToken | b64enc | quote }} 95 | vault-client-cert: {{ default "" .Values.secrets.vaultClientCert | b64enc | quote }} 96 | vault-client-key: {{ default "" .Values.secrets.vaultClientKey | b64enc | quote }} 97 | vault-client-auth-param: {{ default "" .Values.secrets.vaultAuthParam | b64enc | quote }} 98 | {{- end }} 99 | {{- if .Values.concourse.web.credhub.enabled }} 100 | credhub-ca-cert: {{ default "" .Values.secrets.credhubCaCert | b64enc | quote }} 101 | {{- if eq .Values.concourse.web.credhub.authenticationMode "secrets" }} 102 | credhub-client-id: {{ template "concourse.secret.required" dict "key" "credhubClientId" "is" "authenticationMode set to 'secrets' with concourse.web.credhub.enabled" "root" . }} 103 | credhub-client-secret: {{ template "concourse.secret.required" dict "key" "credhubClientSecret" "is" "authenticationMode set to 'secrets' with concourse.web.credhub.enabled" "root" . }} 104 | {{- else if eq .Values.concourse.web.credhub.authenticationMode "mtls" }} 105 | credhub-client-cert: {{ template "concourse.secret.required" dict "key" "credhubClientCert" "is" "authenticationMode set to 'mtls' with concourse.web.credhub.enabled" "root" . }} 106 | credhub-client-key: {{ template "concourse.secret.required" dict "key" "credhubClientKey" "is" "authenticationMode set to 'mtls' with concourse.web.credhub.enabled" "root" . }} 107 | {{- else }} 108 | {{- required (printf "value %s is not recognized as an option for concourse.web.credhub.authenticationMode" .Values.concourse.web.credhub.authenticationMode) "" }} 109 | {{- end }} 110 | {{- end }} 111 | {{- if .Values.concourse.web.conjur.enabled }} 112 | conjur-account: {{ template "concourse.secret.required" dict "key" "conjurAccount" "is" "concourse.web.auth.conjur.enabled" "root" . }} 113 | conjur-authn-login: {{ template "concourse.secret.required" dict "key" "conjurAuthnLogin" "is" "concourse.web.auth.conjur.enabled" "root" . }} 114 | conjur-authn-api-key: {{ default "" .Values.secrets.conjurAuthnApiKey | b64enc | quote }} 115 | conjur-authn-token-file: {{ default "" .Values.secrets.conjurAuthnTokenFile | b64enc | quote }} 116 | conjur-ca-cert: {{ default "" .Values.secrets.conjurCACert | b64enc | quote }} 117 | {{- end }} 118 | {{- if .Values.concourse.web.awsSsm.enabled }} 119 | aws-ssm-access-key: {{ default "" .Values.secrets.awsSsmAccessKey | b64enc | quote }} 120 | aws-ssm-secret-key: {{ default "" .Values.secrets.awsSsmSecretKey | b64enc | quote }} 121 | {{- if .Values.secrets.awsSsmSessionToken }} 122 | aws-ssm-session-token: {{ .Values.secrets.awsSsmSessionToken | b64enc | quote }} 123 | {{- end }} 124 | {{- end }} 125 | {{- if .Values.concourse.web.awsSecretsManager.enabled }} 126 | aws-secretsmanager-access-key: {{ default "" .Values.secrets.awsSecretsmanagerAccessKey | b64enc | quote }} 127 | aws-secretsmanager-secret-key: {{ default "" .Values.secrets.awsSecretsmanagerSecretKey | b64enc | quote }} 128 | {{- if .Values.secrets.awsSecretsmanagerSessionToken }} 129 | aws-secretsmanager-session-token: {{ .Values.secrets.awsSecretsmanagerSessionToken | b64enc | quote }} 130 | {{- end }} 131 | {{- end }} 132 | {{- if .Values.concourse.web.influxdb.enabled }} 133 | influxdb-password: {{ default "" .Values.secrets.influxdbPassword | b64enc | quote }} 134 | {{- end }} 135 | {{- if .Values.concourse.web.syslog.enabled }} 136 | syslog-ca-cert: {{ default "" .Values.secrets.syslogCaCert | b64enc | quote }} 137 | {{- end }} 138 | {{- range .Values.secrets.teamAuthorizedKeys}} 139 | {{ .team }}-team-authorized-key: {{ .key | b64enc | quote }} 140 | {{- end}} 141 | {{- end }} 142 | {{- end }} 143 | -------------------------------------------------------------------------------- /templates/web-serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.web.enabled -}} 2 | {{- if .Values.rbac.create -}} 3 | apiVersion: v1 4 | kind: ServiceAccount 5 | metadata: 6 | name: {{ template "concourse.web.fullname" . }} 7 | labels: 8 | app: {{ template "concourse.web.fullname" . }} 9 | chart: {{ .Chart.Name }}-{{ .Chart.Version }} 10 | heritage: {{ .Release.Service }} 11 | release: {{ .Release.Name }} 12 | {{- if .Values.rbac.webServiceAccountAnnotations }} 13 | annotations: 14 | {{ toYaml .Values.rbac.webServiceAccountAnnotations | indent 4 }} 15 | {{- end -}} 16 | {{- end -}} 17 | {{- end -}} 18 | -------------------------------------------------------------------------------- /templates/web-servicemonitor.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.concourse.web.prometheus.serviceMonitor.enabled .Values.concourse.web.prometheus.enabled }} 2 | apiVersion: monitoring.coreos.com/v1 3 | kind: ServiceMonitor 4 | metadata: 5 | name: {{ template "concourse.web.fullname" . }} 6 | {{- if .Values.concourse.web.prometheus.serviceMonitor.namespace }} 7 | namespace: {{ .Values.concourse.web.prometheus.serviceMonitor.namespace }} 8 | {{- end }} 9 | labels: 10 | app: {{ template "concourse.web.fullname" . }} 11 | chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 12 | release: "{{ .Release.Name }}" 13 | heritage: "{{ .Release.Service }}" 14 | {{- with .Values.concourse.web.prometheus.serviceMonitor.labels }} 15 | {{ toYaml . | trim | indent 4 }} 16 | {{- end }} 17 | spec: 18 | endpoints: 19 | - interval: {{ .Values.concourse.web.prometheus.serviceMonitor.interval }} 20 | port: prometheus 21 | {{- if .Values.concourse.web.prometheus.serviceMonitor.metricRelabelings }} 22 | metricRelabelings: 23 | {{ toYaml .Values.concourse.web.prometheus.serviceMonitor.metricRelabelings | nindent 6 }} 24 | {{- end }} 25 | namespaceSelector: 26 | matchNames: 27 | - {{ .Release.Namespace }} 28 | selector: 29 | matchLabels: 30 | app: {{ template "concourse.web.fullname" . }} 31 | {{- end }} 32 | -------------------------------------------------------------------------------- /templates/web-worker-gateway-svc.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.web.enabled -}} 2 | {{- $root := . -}} 3 | apiVersion: v1 4 | kind: Service 5 | metadata: 6 | name: {{ template "concourse.web.fullname" . }}-worker-gateway 7 | labels: 8 | app: {{ template "concourse.web.fullname" . }} 9 | chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 10 | release: "{{ .Release.Name }}" 11 | heritage: "{{ .Release.Service }}" 12 | {{- range $key, $value := .Values.web.service.workerGateway.labels }} 13 | {{ $key }}: {{ $value | quote }} 14 | {{- end }} 15 | {{- if .Values.web.service.workerGateway.annotations }} 16 | annotations: 17 | {{- range $key, $value := .Values.web.service.workerGateway.annotations }} 18 | {{ $key }}: {{ tpl $value $root | quote }} 19 | {{- end }} 20 | {{- end }} 21 | spec: 22 | type: {{ .Values.web.service.workerGateway.type }} 23 | {{- if .Values.web.service.workerGateway.loadBalancerSourceRanges }} 24 | loadBalancerSourceRanges: 25 | {{- range .Values.web.service.workerGateway.loadBalancerSourceRanges }} 26 | - {{ . }} 27 | {{- end }} 28 | {{- end }} 29 | {{- if and (eq "ClusterIP" .Values.web.service.workerGateway.type) .Values.web.service.workerGateway.clusterIP }} 30 | {{ with .Values.web.service.workerGateway.clusterIP }}clusterIP: {{quote . }}{{ end}} 31 | {{- end }} 32 | {{- if and (eq "LoadBalancer" .Values.web.service.workerGateway.type) .Values.web.service.workerGateway.loadBalancerIP }} 33 | loadBalancerIP: {{ .Values.web.service.workerGateway.loadBalancerIP }} 34 | {{- end }} 35 | ports: 36 | - name: worker-gateway 37 | port: {{ .Values.concourse.web.tsa.bindPort }} 38 | targetPort: tsa 39 | {{- if and (eq "NodePort" .Values.web.service.workerGateway.type) .Values.web.service.workerGateway.NodePort }} 40 | nodePort: {{ .Values.web.service.workerGateway.NodePort}} 41 | {{- end }} 42 | selector: 43 | app: {{ template "concourse.web.fullname" . }} 44 | {{- end }} 45 | -------------------------------------------------------------------------------- /templates/worker-deployment.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.worker.enabled -}} 2 | {{- if eq .Values.worker.kind "Deployment" }} 3 | apiVersion: {{ template "concourse.deployment.apiVersion" . }} 4 | kind: Deployment 5 | metadata: 6 | name: {{ template "concourse.worker.fullname" . }} 7 | {{- if .Values.worker.deploymentAnnotations }} 8 | annotations: 9 | {{ toYaml .Values.worker.deploymentAnnotations | indent 4 }} 10 | {{- end }} 11 | labels: 12 | app: {{ template "concourse.worker.fullname" . }} 13 | chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 14 | release: "{{ .Release.Name }}" 15 | heritage: "{{ .Release.Service }}" 16 | spec: 17 | {{- if not .Values.concourse.worker.autoscaling.maxReplicas }} 18 | replicas: {{ .Values.worker.replicas }} 19 | {{- end }} 20 | selector: 21 | matchLabels: 22 | app: {{ template "concourse.worker.fullname" . }} 23 | release: "{{ .Release.Name }}" 24 | template: 25 | metadata: 26 | labels: 27 | app: {{ template "concourse.worker.fullname" . }} 28 | release: "{{ .Release.Name }}" 29 | {{- with .Values.worker.labels }} 30 | {{ toYaml . | trim | indent 8 }} 31 | {{- end }} 32 | {{- if .Values.worker.annotations }} 33 | annotations: 34 | {{ toYaml .Values.worker.annotations | indent 8 }} 35 | {{- end }} 36 | spec: 37 | {{- if .Values.worker.nodeSelector }} 38 | nodeSelector: 39 | {{ toYaml .Values.worker.nodeSelector | indent 8 }} 40 | {{- end }} 41 | serviceAccountName: {{ if .Values.rbac.create }}{{ template "concourse.worker.fullname" . }}{{ else }}{{ .Values.rbac.workerServiceAccountName }}{{ end }} 42 | {{- if .Values.worker.tolerations }} 43 | tolerations: 44 | {{ toYaml .Values.worker.tolerations | indent 8 }} 45 | {{- end }} 46 | {{- if .Values.imagePullSecrets }} 47 | imagePullSecrets: 48 | {{- range .Values.imagePullSecrets }} 49 | - name: {{ . }} 50 | {{- end }} 51 | {{- end }} 52 | {{- if .Values.worker.priorityClassName }} 53 | priorityClassName: {{ .Values.worker.priorityClassName }} 54 | {{- end }} 55 | {{- if .Values.worker.terminationGracePeriodSeconds }} 56 | terminationGracePeriodSeconds: {{ .Values.worker.terminationGracePeriodSeconds }} 57 | {{- end }} 58 | initContainers: 59 | {{- if .Values.worker.extraInitContainers }} 60 | {{- toYaml .Values.worker.extraInitContainers | nindent 8 }} 61 | {{- end }} 62 | containers: 63 | {{- if .Values.worker.sidecarContainers }} 64 | {{- toYaml .Values.worker.sidecarContainers | nindent 8 }} 65 | {{- end }} 66 | - name: {{ template "concourse.worker.fullname" . }} 67 | {{- if .Values.imageDigest }} 68 | image: "{{ .Values.image }}@{{ .Values.imageDigest }}" 69 | {{- else }} 70 | image: "{{ .Values.image }}:{{ .Values.imageTag }}" 71 | {{- end }} 72 | imagePullPolicy: {{ .Values.imagePullPolicy | quote }} 73 | args: 74 | - worker 75 | {{- if .Values.worker.livenessProbe }} 76 | livenessProbe: 77 | {{ toYaml .Values.worker.livenessProbe | indent 12 }} 78 | {{- end }} 79 | {{- if .Values.worker.readinessProbe }} 80 | readinessProbe: 81 | {{ toYaml .Values.worker.readinessProbe | indent 12 }} 82 | {{- end }} 83 | lifecycle: 84 | preStop: 85 | exec: 86 | command: 87 | - "/bin/bash" 88 | - "/pre-stop-hook.sh" 89 | env: 90 | {{- include "concourse.worker.env" . | indent 12 }} 91 | {{- if .Values.worker.env }} 92 | {{ toYaml .Values.worker.env | indent 12 }} 93 | {{- end }} 94 | ports: 95 | - name: worker-hc 96 | containerPort: {{ .Values.concourse.worker.healthcheckBindPort }} 97 | {{- if .Values.worker.additionalPorts }} 98 | {{ toYaml .Values.worker.additionalPorts | indent 12 }} 99 | {{- end }} 100 | {{- if .Values.worker.resources }} 101 | resources: 102 | {{ toYaml .Values.worker.resources | indent 12 }} 103 | {{- end }} 104 | securityContext: 105 | privileged: true 106 | volumeMounts: 107 | - name: concourse-keys 108 | mountPath: {{ .Values.worker.keySecretsPath | quote }} 109 | readOnly: true 110 | - name: pre-stop-hook 111 | mountPath: /pre-stop-hook.sh 112 | subPath: pre-stop-hook.sh 113 | {{- if and (not (kindIs "invalid" .Values.secrets.workerAdditionalCerts)) (.Values.secrets.workerAdditionalCerts | toString) }} 114 | - name: worker-additional-certs 115 | mountPath: "{{ .Values.worker.certsPath }}/worker-additional-certs.pem" 116 | subPath: worker-additional-certs.pem 117 | readOnly: true 118 | {{- end }} 119 | 120 | {{- if .Values.worker.additionalVolumeMounts }} 121 | {{ toYaml .Values.worker.additionalVolumeMounts | indent 12 }} 122 | {{- end }} 123 | affinity: 124 | {{- if .Values.worker.additionalAffinities }} 125 | {{ toYaml .Values.worker.additionalAffinities | indent 8 }} 126 | {{- end }} 127 | podAntiAffinity: 128 | {{- if .Values.worker.hardAntiAffinity }} 129 | requiredDuringSchedulingIgnoredDuringExecution: 130 | - labelSelector: 131 | matchLabels: 132 | {{- if .Values.worker.hardAntiAffinityLabels }} 133 | {{ toYaml .Values.worker.hardAntiAffinityLabels | indent 16 }} 134 | {{- else }} 135 | app: {{ template "concourse.worker.fullname" . }} 136 | release: {{ .Release.Name | quote }} 137 | {{- end }} 138 | topologyKey: kubernetes.io/hostname 139 | {{- else }} 140 | preferredDuringSchedulingIgnoredDuringExecution: 141 | - weight: 100 142 | podAffinityTerm: 143 | topologyKey: kubernetes.io/hostname 144 | labelSelector: 145 | matchLabels: 146 | app: {{ template "concourse.worker.fullname" . }} 147 | release: {{ .Release.Name | quote }} 148 | {{- end }} 149 | volumes: 150 | {{- if .Values.worker.additionalVolumes }} 151 | {{ toYaml .Values.worker.additionalVolumes | indent 8 }} 152 | {{- end }} 153 | - name: pre-stop-hook 154 | configMap: 155 | name: {{ template "concourse.worker.fullname" . }} 156 | - name: concourse-keys 157 | secret: 158 | secretName: {{ template "concourse.worker.fullname" . }} 159 | defaultMode: 0400 160 | items: 161 | - key: host-key-pub 162 | path: host_key.pub 163 | - key: worker-key 164 | path: worker_key 165 | {{- if and (not (kindIs "invalid" .Values.secrets.workerAdditionalCerts)) (.Values.secrets.workerAdditionalCerts | toString) }} 166 | - name: worker-additional-certs 167 | secret: 168 | secretName: {{ template "concourse.worker.fullname" . }} 169 | optional: true 170 | items: 171 | - key: worker-additional-certs 172 | path: worker-additional-certs.pem 173 | {{- end }} 174 | {{- if semverCompare "^1.7-0" .Capabilities.KubeVersion.Version }} 175 | strategy: 176 | {{ toYaml .Values.worker.updateStrategy | indent 4 }} 177 | {{- end }} 178 | {{- end }} 179 | {{- end }} 180 | -------------------------------------------------------------------------------- /templates/worker-horizontal-pod-autoscaler.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.concourse.worker.autoscaling }} 2 | {{- if .Values.concourse.worker.autoscaling.maxReplicas }} 3 | {{- if semverCompare ">=1.23-0" .Capabilities.KubeVersion.Version -}} 4 | apiVersion: autoscaling/v2 5 | {{- else -}} 6 | apiVersion: autoscaling/v2beta2 7 | {{- end }} 8 | kind: HorizontalPodAutoscaler 9 | metadata: 10 | name: {{ template "concourse.worker.fullname" . }} 11 | labels: 12 | app: {{ template "concourse.worker.fullname" . }} 13 | chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 14 | release: "{{ .Release.Name }}" 15 | heritage: "{{ .Release.Service }}" 16 | spec: 17 | minReplicas: {{ .Values.concourse.worker.autoscaling.minReplicas }} 18 | maxReplicas: {{ .Values.concourse.worker.autoscaling.maxReplicas }} 19 | {{- if .Values.concourse.worker.autoscaling.behavior }} 20 | behavior: 21 | {{ toYaml .Values.concourse.worker.autoscaling.behavior | indent 4 }} 22 | {{- end }} 23 | metrics: 24 | {{- if .Values.concourse.worker.autoscaling.builtInMetrics }} 25 | {{ toYaml .Values.concourse.worker.autoscaling.builtInMetrics | indent 4 }} 26 | {{- end }} 27 | {{- if .Values.concourse.worker.autoscaling.customMetrics }} 28 | {{ toYaml .Values.concourse.worker.autoscaling.customMetrics | indent 4 }} 29 | {{- end }} 30 | scaleTargetRef: 31 | apiVersion: {{ template "concourse.deployment.apiVersion" . }} 32 | kind: {{ .Values.worker.kind }} 33 | name: {{ template "concourse.worker.fullname" . }} 34 | {{- end }} 35 | {{- end }} 36 | -------------------------------------------------------------------------------- /templates/worker-podsecuritypolicy.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.worker.enabled -}} 2 | {{- if .Values.podSecurityPolicy.create -}} 3 | apiVersion: policy/v1beta1 4 | kind: PodSecurityPolicy 5 | metadata: 6 | name: {{ template "concourse.worker.fullname" . }} 7 | labels: 8 | app: {{ template "concourse.worker.fullname" . }} 9 | chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 10 | release: "{{ .Release.Name }}" 11 | heritage: "{{ .Release.Service }}" 12 | spec: 13 | privileged: true 14 | allowPrivilegeEscalation: true 15 | allowedCapabilities: 16 | - 'CAP_FOWNER' 17 | hostNetwork: false 18 | hostIPC: false 19 | hostPID: false 20 | volumes: 21 | {{ toYaml .Values.podSecurityPolicy.allowedWorkerVolumes | indent 4 }} 22 | runAsUser: 23 | rule: 'RunAsAny' 24 | runAsGroup: 25 | rule: 'RunAsAny' 26 | seLinux: 27 | rule: 'RunAsAny' 28 | supplementalGroups: 29 | rule: 'RunAsAny' 30 | fsGroup: 31 | rule: 'RunAsAny' 32 | readOnlyRootFilesystem: false 33 | {{- end -}} 34 | {{- end }} 35 | -------------------------------------------------------------------------------- /templates/worker-policy.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.worker.enabled -}} 2 | {{- if semverCompare ">=1.21-0" .Capabilities.KubeVersion.Version -}} 3 | apiVersion: policy/v1 4 | {{- else -}} 5 | apiVersion: policy/v1beta1 6 | {{- end }} 7 | kind: PodDisruptionBudget 8 | metadata: 9 | name: {{ template "concourse.worker.fullname" . }} 10 | labels: 11 | app: {{ template "concourse.worker.fullname" . }} 12 | chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 13 | release: "{{ .Release.Name }}" 14 | heritage: "{{ .Release.Service }}" 15 | spec: 16 | minAvailable: {{ .Values.worker.minAvailable }} 17 | selector: 18 | matchLabels: 19 | app: {{ template "concourse.worker.fullname" . }} 20 | {{- end }} 21 | -------------------------------------------------------------------------------- /templates/worker-prestop-configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: {{ template "concourse.worker.fullname" . }} 5 | labels: 6 | app: {{ template "concourse.worker.fullname" . }} 7 | chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 8 | release: "{{ .Release.Name }}" 9 | heritage: "{{ .Release.Service }}" 10 | data: 11 | pre-stop-hook.sh: | 12 | #!/bin/bash 13 | while true; do 14 | kill -s {{ .Values.concourse.worker.shutdownSignal }} 1 15 | for i in {0..60}; do 16 | sleep 1 17 | if ! [ -e /proc/1 ]; then 18 | exit 0 19 | fi 20 | done 21 | done 22 | -------------------------------------------------------------------------------- /templates/worker-role.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.worker.enabled -}} 2 | {{- if .Values.rbac.create -}} 3 | {{- if .Values.podSecurityPolicy.create -}} 4 | apiVersion: rbac.authorization.k8s.io/{{ .Values.rbac.apiVersion }} 5 | kind: Role 6 | metadata: 7 | name: {{ template "concourse.worker.fullname" . }} 8 | labels: 9 | app: {{ template "concourse.worker.fullname" . }} 10 | chart: {{ .Chart.Name }}-{{ .Chart.Version }} 11 | heritage: {{ .Release.Service }} 12 | release: {{ .Release.Name }} 13 | rules: 14 | - apiGroups: 15 | - extensions 16 | resources: 17 | - podsecuritypolicies 18 | resourceNames: 19 | - {{ template "concourse.worker.fullname" . }} 20 | verbs: 21 | - use 22 | {{- end -}} 23 | {{- end -}} 24 | {{- end }} 25 | -------------------------------------------------------------------------------- /templates/worker-rolebinding.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.worker.enabled -}} 2 | {{- if .Values.rbac.create -}} 3 | {{- if .Values.podSecurityPolicy.create -}} 4 | apiVersion: rbac.authorization.k8s.io/{{ .Values.rbac.apiVersion }} 5 | kind: RoleBinding 6 | metadata: 7 | name: {{ template "concourse.worker.fullname" . }} 8 | labels: 9 | app: {{ template "concourse.worker.fullname" . }} 10 | chart: {{ .Chart.Name }}-{{ .Chart.Version }} 11 | heritage: {{ .Release.Service }} 12 | release: {{ .Release.Name }} 13 | roleRef: 14 | apiGroup: rbac.authorization.k8s.io 15 | kind: Role 16 | name: {{ template "concourse.worker.fullname" . }} 17 | subjects: 18 | - kind: ServiceAccount 19 | name: {{ template "concourse.worker.fullname" . }} 20 | {{- end -}} 21 | {{- end -}} 22 | {{- end }} 23 | -------------------------------------------------------------------------------- /templates/worker-secrets.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.worker.enabled }} 2 | {{- if .Values.secrets.create }} 3 | apiVersion: v1 4 | kind: Secret 5 | metadata: 6 | name: {{ template "concourse.worker.fullname" . }} 7 | labels: 8 | app: {{ template "concourse.worker.fullname" . }} 9 | chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 10 | release: "{{ .Release.Name }}" 11 | heritage: "{{ .Release.Service }}" 12 | {{- if .Values.secrets.annotations }} 13 | annotations: 14 | {{ toYaml .Values.secrets.annotations | indent 4 }} 15 | {{- end }} 16 | type: Opaque 17 | data: 18 | host-key-pub: {{ .Values.secrets.hostKeyPub | b64enc | quote }} 19 | worker-key: {{ .Values.secrets.workerKey | b64enc | quote }} 20 | {{- if and (not (kindIs "invalid" .Values.secrets.workerAdditionalCerts)) (.Values.secrets.workerAdditionalCerts | toString) }} 21 | worker-additional-certs: {{ .Values.secrets.workerAdditionalCerts | b64enc | quote }} 22 | {{- end }} 23 | {{- end }} 24 | {{- end }} 25 | -------------------------------------------------------------------------------- /templates/worker-serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.worker.enabled -}} 2 | {{- if .Values.rbac.create -}} 3 | apiVersion: v1 4 | kind: ServiceAccount 5 | metadata: 6 | name: {{ template "concourse.worker.fullname" . }} 7 | labels: 8 | app: {{ template "concourse.worker.fullname" . }} 9 | chart: {{ .Chart.Name }}-{{ .Chart.Version }} 10 | heritage: {{ .Release.Service }} 11 | release: {{ .Release.Name }} 12 | {{- if .Values.rbac.workerServiceAccountAnnotations }} 13 | annotations: 14 | {{ toYaml .Values.rbac.workerServiceAccountAnnotations | indent 4 }} 15 | {{- end -}} 16 | {{- end -}} 17 | {{- end }} 18 | -------------------------------------------------------------------------------- /templates/worker-statefulset.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.worker.enabled -}} 2 | {{- if eq .Values.worker.kind "StatefulSet" }} 3 | apiVersion: {{ template "concourse.statefulset.apiVersion" . }} 4 | kind: StatefulSet 5 | metadata: 6 | name: {{ template "concourse.worker.fullname" . }} 7 | labels: 8 | app: {{ template "concourse.worker.fullname" . }} 9 | chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 10 | release: "{{ .Release.Name }}" 11 | heritage: "{{ .Release.Service }}" 12 | spec: 13 | serviceName: {{ template "concourse.worker.fullname" . }} 14 | {{- if not .Values.concourse.worker.autoscaling.maxReplicas }} 15 | replicas: {{ .Values.worker.replicas }} 16 | {{- end }} 17 | selector: 18 | matchLabels: 19 | app: {{ template "concourse.worker.fullname" . }} 20 | release: {{ .Release.Name }} 21 | template: 22 | metadata: 23 | labels: 24 | app: {{ template "concourse.worker.fullname" . }} 25 | release: "{{ .Release.Name }}" 26 | {{- with .Values.worker.labels }} 27 | {{ toYaml . | trim | indent 8 }} 28 | {{- end }} 29 | annotations: 30 | checksum/secrets: {{ include (print $.Template.BasePath "/worker-secrets.yaml") . | sha256sum }} 31 | {{- if .Values.worker.annotations }} 32 | {{ toYaml .Values.worker.annotations | indent 8 }} 33 | {{- end }} 34 | spec: 35 | {{- if .Values.worker.nodeSelector }} 36 | nodeSelector: 37 | {{ toYaml .Values.worker.nodeSelector | indent 8 }} 38 | {{- end }} 39 | serviceAccountName: {{ if .Values.rbac.create }}{{ template "concourse.worker.fullname" . }}{{ else }}{{ .Values.rbac.workerServiceAccountName }}{{ end }} 40 | {{- if .Values.worker.tolerations }} 41 | tolerations: 42 | {{ toYaml .Values.worker.tolerations | indent 8 }} 43 | {{- end }} 44 | {{- if .Values.imagePullSecrets }} 45 | imagePullSecrets: 46 | {{- range .Values.imagePullSecrets }} 47 | - name: {{ . }} 48 | {{- end }} 49 | {{- end }} 50 | {{- if .Values.worker.priorityClassName }} 51 | priorityClassName: {{ .Values.worker.priorityClassName }} 52 | {{- end }} 53 | {{- if .Values.worker.terminationGracePeriodSeconds }} 54 | terminationGracePeriodSeconds: {{ .Values.worker.terminationGracePeriodSeconds }} 55 | {{- end }} 56 | {{- if or .Values.worker.cleanUpWorkDirOnStart .Values.worker.extraInitContainers }} 57 | initContainers: 58 | {{- end }} 59 | {{- if .Values.worker.extraInitContainers }} 60 | {{- toYaml .Values.worker.extraInitContainers | nindent 8 }} 61 | {{- end }} 62 | {{- if .Values.worker.cleanUpWorkDirOnStart }} 63 | - name: {{ template "concourse.worker.fullname" . }}-init-rm 64 | {{- if .Values.imageDigest }} 65 | image: "{{ .Values.image }}@{{ .Values.imageDigest }}" 66 | {{- else }} 67 | image: "{{ .Values.image }}:{{ .Values.imageTag }}" 68 | {{- end }} 69 | imagePullPolicy: {{ .Values.imagePullPolicy | quote }} 70 | securityContext: 71 | privileged: true 72 | command: 73 | - /bin/bash 74 | args: 75 | - -ce 76 | - |- 77 | for v in $((btrfs subvolume list --sort=-ogen "{{ .Values.concourse.worker.workDir }}" || true) | awk '{print $9}'); do 78 | (btrfs subvolume show "{{ .Values.concourse.worker.workDir }}/$v" && btrfs subvolume delete "{{ .Values.concourse.worker.workDir }}/$v") || true 79 | done 80 | rm -rf "{{ .Values.concourse.worker.workDir }}"/* 81 | volumeMounts: 82 | - name: concourse-work-dir 83 | mountPath: {{ .Values.concourse.worker.workDir | quote }} 84 | {{- end }} 85 | containers: 86 | {{- if .Values.worker.sidecarContainers }} 87 | {{- toYaml .Values.worker.sidecarContainers | nindent 8 }} 88 | {{- end }} 89 | - name: {{ template "concourse.worker.fullname" . }} 90 | {{- if .Values.imageDigest }} 91 | image: "{{ .Values.image }}@{{ .Values.imageDigest }}" 92 | {{- else }} 93 | image: "{{ .Values.image }}:{{ .Values.imageTag }}" 94 | {{- end }} 95 | imagePullPolicy: {{ .Values.imagePullPolicy | quote }} 96 | args: 97 | - worker 98 | {{- if .Values.worker.livenessProbe }} 99 | livenessProbe: 100 | {{ toYaml .Values.worker.livenessProbe | indent 12 }} 101 | {{- end }} 102 | {{- if .Values.worker.readinessProbe }} 103 | readinessProbe: 104 | {{ toYaml .Values.worker.readinessProbe | indent 12 }} 105 | {{- end }} 106 | lifecycle: 107 | preStop: 108 | exec: 109 | command: 110 | - "/bin/bash" 111 | - "/pre-stop-hook.sh" 112 | env: 113 | {{- include "concourse.worker.env" . | indent 12 }} 114 | {{- if .Values.worker.env }} 115 | {{ toYaml .Values.worker.env | indent 12 }} 116 | {{- end }} 117 | ports: 118 | - name: worker-hc 119 | containerPort: {{ .Values.concourse.worker.healthcheckBindPort }} 120 | {{- if .Values.worker.additionalPorts }} 121 | {{ toYaml .Values.worker.additionalPorts | indent 12 }} 122 | {{- end }} 123 | {{- if .Values.worker.resources }} 124 | resources: 125 | {{ toYaml .Values.worker.resources | indent 12 }} 126 | {{- end }} 127 | securityContext: 128 | privileged: true 129 | volumeMounts: 130 | - name: concourse-keys 131 | mountPath: {{ .Values.worker.keySecretsPath | quote }} 132 | readOnly: true 133 | - name: concourse-work-dir 134 | mountPath: {{ .Values.concourse.worker.workDir | quote }} 135 | - name: pre-stop-hook 136 | mountPath: /pre-stop-hook.sh 137 | subPath: pre-stop-hook.sh 138 | {{- if and (not (kindIs "invalid" .Values.secrets.workerAdditionalCerts)) (.Values.secrets.workerAdditionalCerts | toString) }} 139 | - name: worker-additional-certs 140 | mountPath: "{{ .Values.worker.certsPath }}/worker-additional-certs.pem" 141 | subPath: worker-additional-certs.pem 142 | readOnly: true 143 | {{- end }} 144 | 145 | {{- if .Values.worker.additionalVolumeMounts }} 146 | {{ toYaml .Values.worker.additionalVolumeMounts | indent 12 }} 147 | {{- end }} 148 | affinity: 149 | {{- if .Values.worker.additionalAffinities }} 150 | {{ toYaml .Values.worker.additionalAffinities | indent 8 }} 151 | {{- end }} 152 | podAntiAffinity: 153 | {{- if .Values.worker.hardAntiAffinity }} 154 | requiredDuringSchedulingIgnoredDuringExecution: 155 | - labelSelector: 156 | matchLabels: 157 | {{- if .Values.worker.hardAntiAffinityLabels }} 158 | {{ toYaml .Values.worker.hardAntiAffinityLabels | indent 16 }} 159 | {{- else }} 160 | app: {{ template "concourse.worker.fullname" . }} 161 | release: {{ .Release.Name | quote }} 162 | {{- end }} 163 | topologyKey: kubernetes.io/hostname 164 | {{- else }} 165 | preferredDuringSchedulingIgnoredDuringExecution: 166 | - weight: 100 167 | podAffinityTerm: 168 | topologyKey: kubernetes.io/hostname 169 | labelSelector: 170 | matchLabels: 171 | app: {{ template "concourse.worker.fullname" . }} 172 | release: {{ .Release.Name | quote }} 173 | {{- end }} 174 | volumes: 175 | {{- if .Values.worker.additionalVolumes }} 176 | {{ toYaml .Values.worker.additionalVolumes | indent 8 }} 177 | {{- end }} 178 | - name: pre-stop-hook 179 | configMap: 180 | name: {{ template "concourse.worker.fullname" . }} 181 | - name: concourse-keys 182 | secret: 183 | secretName: {{ template "concourse.worker.fullname" . }} 184 | defaultMode: 0400 185 | items: 186 | - key: host-key-pub 187 | path: host_key.pub 188 | - key: worker-key 189 | path: worker_key 190 | {{- if and (not (kindIs "invalid" .Values.secrets.workerAdditionalCerts)) (.Values.secrets.workerAdditionalCerts | toString) }} 191 | - name: worker-additional-certs 192 | secret: 193 | secretName: {{ template "concourse.worker.fullname" . }} 194 | optional: true 195 | items: 196 | - key: worker-additional-certs 197 | path: worker-additional-certs.pem 198 | {{- end }} 199 | {{- if .Values.persistence.enabled }} 200 | volumeClaimTemplates: 201 | - metadata: 202 | name: concourse-work-dir 203 | {{- if .Values.persistence.worker.labels }} 204 | labels: 205 | {{- with .Values.persistence.worker.labels }} 206 | {{ toYaml . | trim | indent 10 }} 207 | {{- end }} 208 | {{- end }} 209 | spec: 210 | {{- if .Values.persistence.worker.selector }} 211 | selector: {{- .Values.persistence.worker.selector | toYaml | nindent 10 }} 212 | {{- end }} 213 | accessModes: 214 | - {{ .Values.persistence.worker.accessMode | quote }} 215 | resources: 216 | requests: 217 | storage: {{ .Values.persistence.worker.size | quote }} 218 | {{- if .Values.persistence.worker.storageClass }} 219 | {{- if (eq "-" .Values.persistence.worker.storageClass) }} 220 | storageClassName: "" 221 | {{- else }} 222 | storageClassName: "{{ .Values.persistence.worker.storageClass }}" 223 | {{- end }} 224 | {{- end }} 225 | {{- else }} 226 | {{ if include "concourse.are-there-additional-volumes.with-the-name.concourse-work-dir" . | not }} 227 | - name: concourse-work-dir 228 | emptyDir: 229 | {{- if .Values.worker.emptyDirSize }} 230 | sizeLimit: {{ .Values.worker.emptyDirSize | quote }} 231 | {{- end }} 232 | {{- end }} 233 | {{- end }} 234 | {{- if semverCompare "^1.7-0" .Capabilities.KubeVersion.Version }} 235 | updateStrategy: 236 | {{ toYaml .Values.worker.updateStrategy | indent 4 }} 237 | {{- end }} 238 | {{- if .Values.worker.podManagementPolicy }} 239 | podManagementPolicy: {{ .Values.worker.podManagementPolicy }} 240 | {{- end }} 241 | {{- end }} 242 | {{- end }} 243 | -------------------------------------------------------------------------------- /templates/worker-svc.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.worker.enabled -}} 2 | ## A Headless Service is required when using a StatefulSet 3 | ## ref: https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/ 4 | ## 5 | apiVersion: v1 6 | kind: Service 7 | metadata: 8 | name: {{ template "concourse.worker.fullname" . }} 9 | labels: 10 | app: {{ template "concourse.worker.fullname" . }} 11 | chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 12 | release: "{{ .Release.Name }}" 13 | heritage: "{{ .Release.Service }}" 14 | spec: 15 | type: ClusterIP 16 | clusterIP: None 17 | ## We do NOT expose any port as workers will forward connections with the ATC through a TSA reverse-tunnel 18 | ## ref: https://concourse-ci.org/architecture.html#architecture-worker 19 | ## 20 | ports: [] 21 | selector: 22 | app: {{ template "concourse.worker.fullname" . }} 23 | {{- end }} 24 | --------------------------------------------------------------------------------