├── .dockerignore ├── .gitignore ├── Dockerfile ├── LICENSE ├── README.md ├── assets ├── check ├── common.sh ├── in └── out └── test ├── .gitignore ├── name ├── nginx-0.1.0.tgz └── payload.json.template /.dockerignore: -------------------------------------------------------------------------------- 1 | test 2 | wait-for-helm-deployment/node_modules 3 | wait-for-helm-deployment/**/*.js 4 | wait-for-helm-deployment/**/*.js.map 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkyard/concourse-helm-resource/b5c6786036a6a3671734e0252b3d6539af0b0359/.gitignore -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM linkyard/alpine-helm:2.17.0 2 | LABEL maintainer "mario.siegenthaler@linkyard.ch" 3 | 4 | RUN apk add --update --upgrade --no-cache jq bash curl git gettext libintl 5 | 6 | ENV KUBERNETES_VERSION 1.19.6 7 | RUN curl -L -o /usr/local/bin/kubectl https://storage.googleapis.com/kubernetes-release/release/v${KUBERNETES_VERSION}/bin/linux/amd64/kubectl; \ 8 | chmod +x /usr/local/bin/kubectl 9 | 10 | ADD assets /opt/resource 11 | RUN chmod +x /opt/resource/* 12 | 13 | RUN mkdir -p "$(helm home)/plugins" 14 | RUN helm plugin install https://github.com/databus23/helm-diff && \ 15 | helm plugin install https://github.com/rimusz/helm-tiller 16 | 17 | ENTRYPOINT [ "/bin/bash" ] 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Helm Resource for Concourse 2 | 3 | Deploy to [Kubernetes Helm](https://github.com/kubernetes/helm) from [Concourse](https://concourse.ci/). 4 | 5 | ## Installing 6 | 7 | Add the resource type to your pipeline: 8 | 9 | ```yaml 10 | resource_types: 11 | - name: helm 12 | type: docker-image 13 | source: 14 | repository: linkyard/concourse-helm-resource 15 | ``` 16 | 17 | ## Source Configuration 18 | 19 | * `cluster_url`: *Optional.* URL to Kubernetes Master API service. Do not set when using the `kubeconfig_path` parameter, otherwise required. 20 | * `cluster_ca`: *Optional.* Base64 encoded PEM. Required if `cluster_url` is https. 21 | * `insecure_skip_tls_verify`: *Optional* Skips verifying the `cluster_ca`. (Default: false). Ignored unless `cluster_url` is https. Useful for self-signed certificates. It is not recommended to use blindly. 22 | * `token`: *Optional.* Bearer token for Kubernetes. This, 'token_path' or `admin_key`/`admin_cert` are required if `cluster_url` is https. 23 | * `token_path`: *Optional.* Path to file containing the bearer token for Kubernetes. This, 'token' or `admin_key`/`admin_cert` are required if `cluster_url` is https. 24 | * `admin_key`: *Optional.* Base64 encoded PEM. Required if `cluster_url` is https and no `token` or 'token_path' is provided. 25 | * `admin_cert`: *Optional.* Base64 encoded PEM. Required if `cluster_url` is https and no `token` or 'token_path' is provided. 26 | * `release`: *Optional.* Name of the release (not a file, a string). (Default: autogenerated by helm) 27 | * `namespace`: *Optional.* Kubernetes namespace the chart will be installed into. (Default: default) 28 | * `tillerless`: *Optional.* Set to true to use tiller-less mode (Default: false). See . 29 | * `tillerless_silent`: *Optional.* Set to `true` to make tiller-less mode silent (Default: true). Activating tillerless helm without making it silent **will make credentials to leak in the build output** when using `override_values` parameter with `hide: true`. 30 | * `helm_init_server`: *Optional.* Installs helm into the cluster if not already installed. (Default: false). Not supported when using tillerless. 31 | * `tiller_namespace`: *Optional.* Kubernetes namespace where tiller is running (or will be installed to). (Default: kube-system) 32 | * `tiller_cert`: *Optional* Certificate for Tiller (only applies if tls_enabled and helm_init_server are true). 33 | * `tiller_key`: *Optional* Key created for Tiller when doing a secure Tiller install (only applies if tls_enabled and helm_init_server are true). 34 | * `tiller_service_account`: *Optional* Name of the service account that tiller will use (only applies if helm_init_server is true). 35 | * `helm_ca`: *Optional* Private CA that is used to issue certificates for Tiller clients and servers (only applies if tls_enabled is true). 36 | * `helm_cert`: *Optional* Certificate for Client (only applies if tls_enabled is true). 37 | * `helm_key`: *Optional* Key created for Client when doing a secure Tiller install (only applies if tls_enabled is true). 38 | * `tls_enabled`: *Optional* Uses TLS for all interactions with Tiller. (Default: false). Not supported when using tillerless. 39 | * `helm_history_max`: *Optional.* Limits the maximum number of revisions. (Default: 0 = no limit) 40 | * `helm_host`: *Optional* Address of Tiller. Skips helm discovery process. (only applies if `helm_init_server` is false). 41 | * `repos`: *Optional.* Array of Helm repositories to initialize, each repository is defined as an object with properties `name`, `url` (required) username and password (optional). 42 | * `plugins`: *Optional.* Array of Helm plugins to install, each defined as an object with properties `url` (required), `version` (optional). 43 | * `stable_repo`: *Optional* Override default Helm stable repo . Useful if running helm deploys without internet access. 44 | * `kubeconfig_namespace`: *Optional.* Use the kubeconfig context namespace as the helm namespace. (Default: false) 45 | * `kubeconfig_tiller_namespace`: *Optional.* Use the kubeconfig context namespace as the tiller namespace. (Default: false) 46 | * `tracing_enabled`: *Optional.* Enable extremely verbose tracing for this resource. Useful when developing the resource itself. May allow secrets to be displayed. (Default: false) 47 | * `helm_init_wait`: *Optional.* When initializing the helm server, use the `--wait` option. (Default: false) 48 | * `helm_setup_purge_all`: *Optional.* Delete and purge every helm release. Use with extreme caution. (Default: false) 49 | 50 | ## Behavior 51 | 52 | ### `check`: Check for new releases 53 | 54 | Any new revisions to the release are returned, no matter their current state. The release and cluster url must be specified in the 55 | source for `check` to work. 56 | 57 | ### `in`: Not Supported 58 | 59 | ### `out`: Deploy the helm chart 60 | 61 | Deploys a Helm chart onto the Kubernetes cluster. Tiller must be already installed 62 | on the cluster. 63 | 64 | #### Parameters 65 | 66 | * `chart`: *Required.* Either the file containing the helm chart to deploy (ends with .tgz), the path to a local directory containing the chart or the name of the chart from a repo (e.g. `stable/mysql`). 67 | * `namespace`: *Optional.* Either a file containing the name of the namespace or the name of the namespace. (Default: taken from source configuration). 68 | * `release`: *Optional.* Either a file containing the name of the release or the name of the release. (Default: taken from source configuration). 69 | * `values`: *Optional.* File containing the values.yaml for the deployment. Supports setting multiple value files using an array. 70 | * `override_values`: *Optional.* Array of values that can override those defined in values.yaml. Each entry in 71 | the array is a map containing a key and a value or path. Value is set directly while path reads the contents of 72 | the file in that path. A `hide: true` parameter ensures that the value is not logged and instead replaced with `***HIDDEN***`. 73 | A `type: string` parameter makes sure Helm always treats the value as a string (uses the `--set-string` option to Helm; useful if the value varies 74 | and may look like a number, eg. if it's a Git commit hash). 75 | A `verbatim: true` parameter escapes backslashes so the value is passed as-is to the Helm chart (useful for `((credentials))`). 76 | The default behaviour of backslashes in `--set` is to quote the next character so `val\ue` is treated as `value` by Helm. 77 | * `token_path`: *Optional.* Path to file containing the bearer token for Kubernetes. This, 'token' or `admin_key`/`admin_cert` are required if `cluster_url` is https. 78 | * `version`: *Optional* Chart version to deploy, can be a file or a value. Only applies if `chart` is not a file. 79 | * `delete`: *Optional.* Deletes the release instead of installing it. Requires the `name`. (Default: false) 80 | * `test`: *Optional.* Test the release instead of installing it. Requires the `release`. (Default: false) 81 | * `purge`: *Optional.* Purge the release on delete. (Default: false) 82 | * `replace`: *Optional.* Replace deleted release with same name. (Default: false) 83 | * `force`: *Optional.* Force resource update through delete/recreate if needed. (Default: false) 84 | * `devel`: *Optional.* Allow development versions of chart to be installed. This is useful when wanting to install pre-release 85 | charts (i.e. 1.0.2-rc1) without having to specify a version. (Default: false) 86 | * `debug`: *Optional.* Dry run the helm install with the debug flag which logs interpolated chart templates. (Default: false) 87 | * `wait_until_ready`: *Optional.* Set to the number of seconds it should wait until all the resources in 88 | the chart are ready. (Default: `0` which means don't wait). 89 | * `check_is_ready`: *Optional.* Requires that `wait_until_ready` is set to Default. Applies --wait without timeout. (Default: false) 90 | * `atomic`: *Optional.* This flag will cause failed installs to purge the release, and failed upgrades to rollback to the previous release. (Default: false) 91 | * `recreate_pods`: *Optional.* This flag will cause all pods to be recreated when upgrading. (Default: false) 92 | * `show_diff`: *Optional.* Show the diff that is applied if upgrading an existing successful release. Will not be used when `devel` is set. (Default: false) 93 | * `exit_after_diff`: *Optional.* Show the diff but don't actually install/upgrade. (Default: false) 94 | * `reuse_values`: *Optional.* When upgrading, reuse the last release's values. (Default: false) 95 | * `reset_values`: *Optional.* When upgrading, reset the values to the ones built into the chart. (Default: false) 96 | * `wait`: *Optional.* Allows deploy task to sleep for X seconds before continuing to next task. Allows pods to restart and become stable, useful where dependency between pods exists. (Default: 0) 97 | * `kubeconfig_path`: *Optional.* File containing a kubeconfig. Overrides source configuration for cluster, token, and admin config. 98 | 99 | ## Example 100 | 101 | ### Out 102 | 103 | Define the resource: 104 | 105 | ```yaml 106 | resources: 107 | - name: myapp-helm 108 | type: helm 109 | source: 110 | cluster_url: https://kube-master.domain.example 111 | cluster_ca: _base64 encoded CA pem_ 112 | admin_key: _base64 encoded key pem_ 113 | admin_cert: _base64 encoded certificate pem_ 114 | repos: 115 | - name: some_repo 116 | url: https://somerepo.github.io/charts 117 | ``` 118 | 119 | Add to job: 120 | 121 | ```yaml 122 | jobs: 123 | # ... 124 | plan: 125 | - put: myapp-helm 126 | params: 127 | chart: source-repo/chart-0.0.1.tgz 128 | values: source-repo/values.yaml 129 | override_values: 130 | - key: replicas 131 | value: 2 132 | - key: version 133 | path: version/number # Read value from version/number 134 | - key: secret 135 | value: ((my-top-secret-value)) # Pulled from a credentials backend like Vault 136 | hide: true # Hides value in output 137 | - key: image.tag 138 | path: version/image_tag # Read value from version/number 139 | type: string # Make sure it's interpreted as a string by Helm (not a number) 140 | ``` 141 | -------------------------------------------------------------------------------- /assets/check: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | set -o pipefail 5 | 6 | exec 3>&1 # make stdout available as fd 3 for the result 7 | exec 1>&2 # redirect all output to stderr for logging 8 | 9 | source /opt/resource/common.sh 10 | 11 | # Read inputs 12 | payload=$(mktemp $TMPDIR/helm-resource-request.XXXXXX) 13 | cat > $payload <&0 14 | 15 | # Parse parameters 16 | namespace=$(jq -r '.source.namespace // "default"' < $payload) 17 | release=$(jq -r '.source.release // ""' < $payload) 18 | tiller_namespace=$(jq -r '.source.tiller_namespace // "kube-system"' < $payload) 19 | cluster_url=$(jq -r '.source.cluster_url // ""' < $payload) 20 | 21 | tillerless=$(jq -r '.source.tillerless // "false"' < $payload) 22 | if [ "$tillerless" = true ]; then 23 | helm_bin="helm tiller run ${tiller_namespace} -- helm" 24 | else 25 | helm_bin="helm" 26 | fi 27 | 28 | current_release=$(jq -r '.version.release' < $payload || true) 29 | if [ -z "$release" ]; then 30 | release="$current_release" 31 | fi 32 | 33 | tls_enabled=$(jq -r '.source.tls_enabled // "false"' < $payload) 34 | if [ "$tls_enabled" = true ]; then 35 | tls_flag="--tls" 36 | fi 37 | 38 | current_rev=$(jq -r '.version.revision // "0"' < $payload || true) 39 | 40 | if [ -z "$cluster_url" ]; then 41 | # Since the resource was configured to use a dynamic namespace, 42 | # check does not make any sense since it is impossible to know which 43 | # tiller and which release name should be checked. 44 | # The resource is in "put" only mode. 45 | if [ $current_rev -eq 0 ]; then 46 | # When there was no `version` passed in, return an empty list 47 | echo '[]' >&3 48 | else 49 | # When the `version` was passed in, parrot it back 50 | printf '[{"revision":"%s","release":"%s"}]\n' "$current_rev" "$release" | jq -M . >&3 51 | fi 52 | 53 | # Check has successfully finished so exit with success. 54 | exit 0 55 | fi 56 | 57 | # Prepare 58 | setup_resource $payload 59 | echo "Resource setup successful." 60 | 61 | if [ "$current_rev" -eq "0" ]; then 62 | # Empty => return the current 63 | $helm_bin history $tls_flag --tiller-namespace $tiller_namespace --max 20 $release | tail -n 1 | while read -r line; do 64 | revision=$(echo $line | awk '{ print $1 }') 65 | echo "$revision" 66 | done | jq -R '.' | jq -s "map({\"revision\": ., \"release\": \"$release\"})" >&3 67 | else 68 | # All versions equal and newer 69 | $helm_bin history $tls_flag --tiller-namespace $tiller_namespace --max 20 $release | tail -n +2 | while read -r line; do 70 | revision=$(echo $line | awk '{ print $1 }') 71 | if [ -z "$current_rev" ] || [ "$revision" -ge "$current_rev" ]; then 72 | echo "$revision" 73 | fi 74 | done | jq -R '.' | jq -s "map({\"revision\": ., \"release\": \"$release\"})" >&3 75 | fi 76 | -------------------------------------------------------------------------------- /assets/common.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | setup_kubernetes() { 5 | payload=$1 6 | source=$2 7 | 8 | mkdir -p /root/.kube 9 | kubeconfig_path=$(jq -r '.params.kubeconfig_path // ""' < $payload) 10 | absolute_kubeconfig_path="${source}/${kubeconfig_path}" 11 | if [ -f "$absolute_kubeconfig_path" ]; then 12 | cp "$absolute_kubeconfig_path" "/root/.kube/config" 13 | else 14 | # Setup kubectl 15 | cluster_url=$(jq -r '.source.cluster_url // ""' < $payload) 16 | if [ -z "$cluster_url" ]; then 17 | echo "invalid payload (missing cluster_url)" 18 | exit 1 19 | fi 20 | if [[ "$cluster_url" =~ https.* ]]; then 21 | 22 | cluster_ca=$(jq -r '.source.cluster_ca // ""' < $payload) 23 | admin_key=$(jq -r '.source.admin_key // ""' < $payload) 24 | admin_cert=$(jq -r '.source.admin_cert // ""' < $payload) 25 | token=$(jq -r '.source.token // ""' < $payload) 26 | token_path=$(jq -r '.params.token_path // ""' < $payload) 27 | insecure_skip_tls_verify=$(jq -r '.source.insecure_skip_tls_verify // "false"' < $payload) 28 | 29 | if [ "$insecure_skip_tls_verify" = true ]; then 30 | kubectl config set-cluster default --server=$cluster_url --insecure-skip-tls-verify 31 | else 32 | ca_path="/root/.kube/ca.pem" 33 | echo "$cluster_ca" | base64 -d > $ca_path 34 | kubectl config set-cluster default --server=$cluster_url --certificate-authority=$ca_path 35 | fi 36 | 37 | if [ -f "$source/$token_path" ]; then 38 | kubectl config set-credentials admin --token=$(cat $source/$token_path) 39 | elif [ ! -z "$token" ]; then 40 | kubectl config set-credentials admin --token=$token 41 | else 42 | mkdir -p /root/.kube 43 | key_path="/root/.kube/key.pem" 44 | cert_path="/root/.kube/cert.pem" 45 | echo "$admin_key" | base64 -d > $key_path 46 | echo "$admin_cert" | base64 -d > $cert_path 47 | kubectl config set-credentials admin --client-certificate=$cert_path --client-key=$key_path 48 | fi 49 | 50 | kubectl config set-context default --cluster=default --user=admin 51 | else 52 | kubectl config set-cluster default --server=$cluster_url 53 | kubectl config set-context default --cluster=default 54 | fi 55 | 56 | kubectl config use-context default 57 | fi 58 | 59 | kubectl version 60 | } 61 | 62 | setup_tls() { 63 | tls_enabled=$(jq -r '.source.tls_enabled // "false"' < $payload) 64 | tillerless=$(jq -r '.source.tillerless // "false"' < $payload) 65 | if [ "$tls_enabled" = true ]; then 66 | if [ "$tillerless" = true ]; then 67 | echo "Setting both tls_enabled and tillerless is not supported" 68 | exit 1 69 | fi 70 | 71 | helm_ca=$(jq -r '.source.helm_ca // ""' < $payload) 72 | helm_key=$(jq -r '.source.helm_key // ""' < $payload) 73 | helm_cert=$(jq -r '.source.helm_cert // ""' < $payload) 74 | if [ -z "$helm_ca" ]; then 75 | echo "invalid payload (missing helm_ca)" 76 | exit 1 77 | fi 78 | if [ -z "$helm_key" ]; then 79 | echo "invalid payload (missing helm_key)" 80 | exit 1 81 | fi 82 | if [ -z "$helm_cert" ]; then 83 | echo "invalid payload (missing helm_cert)" 84 | exit 1 85 | fi 86 | helm_ca_cert_path="/root/.helm/ca.pem" 87 | helm_key_path="/root/.helm/key.pem" 88 | helm_cert_path="/root/.helm/cert.pem" 89 | echo "$helm_ca" > $helm_ca_cert_path 90 | echo "$helm_key" > $helm_key_path 91 | echo "$helm_cert" > $helm_cert_path 92 | fi 93 | } 94 | 95 | setup_helm() { 96 | # $1 is the name of the payload file 97 | # $2 is the name of the source directory 98 | init_server=$(jq -r '.source.helm_init_server // "false"' < $1) 99 | 100 | # Compute tiller_namespace as follows: 101 | # If kubeconfig_tiller_namespace is set, then tiller_namespace is the namespace from the kubeconfig 102 | # If tiller_namespace is set and it is the name of a file, then tiller_namespace is the contents of the file 103 | # If tiller_namespace is set and it is not the name of a file, then tiller_namespace is the literal 104 | # Otherwise tiller_namespace defaults to kube-system 105 | kubeconfig_tiller_namespace=$(jq -r '.source.kubeconfig_tiller_namespace // "false"' <$1) 106 | if [ "$kubeconfig_tiller_namespace" = "true" ] 107 | then 108 | tiller_namespace=$(kubectl config view --minify -ojson | jq -r .contexts[].context.namespace) 109 | else 110 | tiller_namespace=$(jq -r '.source.tiller_namespace // "kube-system"' < $1) 111 | if [ "$tiller_namespace" != "kube-system" -a -f "$2/$tiller_namespace" ] 112 | then 113 | tiller_namespace=$(cat "$2/$tiller_namespace") 114 | fi 115 | fi 116 | 117 | tillerless=$(jq -r '.source.tillerless // "false"' < $payload) 118 | tls_enabled=$(jq -r '.source.tls_enabled // "false"' < $payload) 119 | history_max=$(jq -r '.source.helm_history_max // "0"' < $1) 120 | stable_repo=$(jq -r '.source.stable_repo // ""' < $payload) 121 | 122 | if [ "$tillerless" = true ]; then 123 | echo "Using tillerless helm" 124 | helm_bin="helm tiller run ${tiller_namespace} -- helm" 125 | else 126 | helm_bin="helm" 127 | fi 128 | 129 | if [ -n "$stable_repo" ]; then 130 | echo "Stable Repo URL : ${stable_repo}" 131 | stable_repo="--stable-repo-url=${stable_repo}" 132 | fi 133 | 134 | if [ "$init_server" = true ]; then 135 | if [ "$tillerless" = true ]; then 136 | echo "Setting both init_server and tillerless is not supported" 137 | exit 1 138 | fi 139 | tiller_service_account=$(jq -r '.source.tiller_service_account // "default"' < $1) 140 | 141 | helm_init_wait=$(jq -r '.source.helm_init_wait // "false"' <$1) 142 | helm_init_wait_arg="" 143 | if [ "$helm_init_wait" = "true" ]; then 144 | helm_init_wait_arg="--wait" 145 | fi 146 | 147 | if [ "$tls_enabled" = true ]; then 148 | tiller_key=$(jq -r '.source.tiller_key // ""' < $payload) 149 | tiller_cert=$(jq -r '.source.tiller_cert // ""' < $payload) 150 | if [ -z "$tiller_key" ]; then 151 | echo "invalid payload (missing tiller_key)" 152 | exit 1 153 | fi 154 | if [ -z "$tiller_cert" ]; then 155 | echo "invalid payload (missing tiller_cert)" 156 | exit 1 157 | fi 158 | tiller_key_path="/root/.helm/tiller_key.pem" 159 | tiller_cert_path="/root/.helm/tiller_cert.pem" 160 | helm_ca_cert_path="/root/.helm/ca.pem" 161 | echo "$tiller_key" > $tiller_key_path 162 | echo "$tiller_cert" > $tiller_cert_path 163 | $helm_bin init --tiller-tls --tiller-tls-cert $tiller_cert_path --tiller-tls-key $tiller_key_path --tiller-tls-verify --tls-ca-cert $tiller_key_path --tiller-namespace=$tiller_namespace --service-account=$tiller_service_account --history-max=$history_max $stable_repo --upgrade $helm_init_wait_arg 164 | else 165 | $helm_bin init --tiller-namespace=$tiller_namespace --service-account=$tiller_service_account --history-max=$history_max $stable_repo --upgrade $helm_init_wait_arg 166 | fi 167 | wait_for_service_up tiller-deploy 10 168 | else 169 | export HELM_HOST=$(jq -r '.source.helm_host // ""' < $1) 170 | $helm_bin init -c --tiller-namespace $tiller_namespace $stable_repo > /dev/null 171 | fi 172 | 173 | tls_enabled_arg="" 174 | if [ "$tls_enabled" = true ]; then 175 | tls_enabled_arg="--tls" 176 | fi 177 | $helm_bin version $tls_enabled_arg --tiller-namespace $tiller_namespace 178 | 179 | helm_setup_purge_all=$(jq -r '.source.helm_setup_purge_all // "false"' <$1) 180 | if [ "$helm_setup_purge_all" = "true" ]; then 181 | local release 182 | for release in $(helm ls -aq --tiller-namespace $tiller_namespace ) 183 | do 184 | helm delete $tls_enabled_arg --purge "$release" --tiller-namespace $tiller_namespace 185 | done 186 | fi 187 | } 188 | 189 | wait_for_service_up() { 190 | SERVICE=$1 191 | TIMEOUT=$2 192 | if [ "$TIMEOUT" -le "0" ]; then 193 | echo "Service $SERVICE was not ready in time" 194 | exit 1 195 | fi 196 | RESULT=`kubectl get endpoints --namespace=$tiller_namespace $SERVICE -o jsonpath={.subsets[].addresses[].targetRef.name} 2> /dev/null || true` 197 | if [ -z "$RESULT" ]; then 198 | sleep 1 199 | wait_for_service_up $SERVICE $((--TIMEOUT)) 200 | fi 201 | } 202 | 203 | setup_repos() { 204 | repos=$(jq -c '(try .source.repos[] catch [][])' < $1) 205 | plugins=$(jq -c '(try .source.plugins[] catch [][])' < $1) 206 | 207 | kubeconfig_tiller_namespace=$(jq -r '.source.kubeconfig_tiller_namespace // "false"' <$1) 208 | if [ "$kubeconfig_tiller_namespace" = "true" ] 209 | then 210 | tiller_namespace=$(kubectl config view --minify -ojson | jq -r .contexts[].context.namespace) 211 | else 212 | tiller_namespace=$(jq -r '.source.tiller_namespace // "kube-system"' < $1) 213 | fi 214 | 215 | local IFS=$'\n' 216 | 217 | for pl in $plugins; do 218 | plurl=$(echo $pl | jq -cr '.url') 219 | plversion=$(echo $pl | jq -cr '.version // ""') 220 | if [ -n "$plversion" ]; then 221 | plversionflag="--version $plversion" 222 | fi 223 | helm plugin install $plurl $plversionflag 224 | done 225 | 226 | for r in $repos; do 227 | name=$(echo $r | jq -r '.name') 228 | url=$(echo $r | jq -r '.url') 229 | username=$(echo $r | jq -r '.username // ""') 230 | password=$(echo $r | jq -r '.password // ""') 231 | 232 | echo Installing helm repository $name $url 233 | if [[ -n "$username" && -n "$password" ]]; then 234 | helm repo add $name $url --tiller-namespace $tiller_namespace --username $username --password $password 235 | else 236 | helm repo add $name $url --tiller-namespace $tiller_namespace 237 | fi 238 | done 239 | 240 | helm repo update 241 | } 242 | 243 | setup_resource() { 244 | tracing_enabled=$(jq -r '.source.tracing_enabled // "false"' < $1) 245 | if [ "$tracing_enabled" = "true" ]; then 246 | set -x 247 | fi 248 | 249 | echo "Initializing kubectl..." 250 | setup_kubernetes $1 $2 251 | echo "Initializing helm..." 252 | setup_tls $1 253 | setup_helm $1 $2 254 | setup_repos $1 255 | } 256 | -------------------------------------------------------------------------------- /assets/in: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo '{"version":{"ref":"none"}}' -------------------------------------------------------------------------------- /assets/out: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | set -o pipefail 5 | 6 | exec 3>&1 # make stdout available as fd 3 for the result 7 | exec 1>&2 # redirect all output to stderr for logging 8 | 9 | source /opt/resource/common.sh 10 | 11 | # Read inputs 12 | source=$1 13 | payload=$(mktemp helm-resource-request.XXXXXX) 14 | cat > $payload <&0 15 | 16 | # Prepare 17 | setup_resource $payload $source 18 | echo "Resource setup successful." 19 | 20 | # Parse parameters 21 | tillerless=$(jq -r '.source.tillerless // "false"' < $payload) 22 | tillerless_silent=$(jq -r '.source.tillerless_silent // "true"' < $payload) 23 | namespace=$(jq -r '.source.namespace // "default"' < $payload) 24 | # tiller_namespace is computed in a more robust manner in common.sh via setup_resource. Don't override it here! 25 | # tiller_namespace=$(jq -r '.params.tiller_namespace // ""' < $payload) 26 | chart=$(jq -r '.params.chart // ""' < $payload) 27 | version=$(jq -r '.params.version // ""' < $payload) 28 | namespace_file=$(jq -r '.params.namespace // ""' < $payload) 29 | release_file=$(jq -r '.params.release // ""' < $payload) 30 | values=$(jq -r '.params.values // "" | if type == "array" then .[] else . end' < $payload) 31 | wait_until_ready=$(jq -r '.params.wait_until_ready // 0' < $payload) 32 | debug=$(jq -r '.params.debug // "false"' < $payload) 33 | replace=$(jq -r '.params.replace // "false"' < $payload) 34 | delete=$(jq -r '.params.delete // "false"' < $payload) 35 | test=$(jq -r '.params.test // "false"' < $payload) 36 | purge=$(jq -r '.params.purge // "false"' < $payload) 37 | devel=$(jq -r '.params.devel // "false"' < $payload) 38 | atomic=$(jq -r '.params.atomic // "false"' < $payload) 39 | cleanup_on_fail=$(jq -r '.params.cleanup_on_fail // "false"' < $payload) 40 | recreate_pods=$(jq -r '.params.recreate_pods // "false"' < $payload) 41 | force=$(jq -r '.params.force // "false"' < $payload) 42 | show_diff=$(jq -r '.params.show_diff // "false"' < $payload) 43 | recreate_pods=$(jq -r '.params.recreate_pods // "false"' < $payload) 44 | tls_enabled=$(jq -r '.source.tls_enabled // "false"' < $payload) 45 | exit_after_diff=$(jq -r '.params.exit_after_diff // "false"' < $payload) 46 | reuse_values=$(jq -r '.params.reuse_values // "false"' < $payload) 47 | reset_values=$(jq -r '.params.reset_values // "false"' < $payload) 48 | wait=$(jq -r '.params.wait // 0' < $payload) 49 | check_is_ready=$(jq -r '.params.check_is_ready // "false"' < $payload) 50 | kubeconfig_namespace=$(jq -r '.source.kubeconfig_namespace // "false"' < $payload) 51 | 52 | if [ -z "$chart" ]; then 53 | if [[ "$test" == "false" && "$delete" == "false" ]]; then 54 | echo "invalid payload (missing chart)" 55 | exit 1 56 | fi 57 | fi 58 | if [ -f "$source/$namespace_file" ]; then 59 | namespace=`cat $source/$namespace_file` 60 | elif [ -n "$namespace_file" ]; then 61 | namespace=$namespace_file 62 | fi 63 | 64 | if [ "$kubeconfig_namespace" = "true" ] ; then 65 | namespace=$(kubectl config view --minify -ojson | jq -r .contexts[].context.namespace) 66 | fi 67 | 68 | if [ -n "$release_file" ]; then 69 | if [ -f "$source/$release_file" ]; then 70 | release=`cat $source/$release_file` 71 | else 72 | release=$release_file 73 | fi 74 | else 75 | release=$(jq -r '.source.release // ""' < $payload) 76 | fi 77 | 78 | # Expand env variables such as resource metadata (see https://concourse-ci.org/implementing-resource-types.html#resource-metadata) 79 | release=$(echo -n "$release" | envsubst) 80 | 81 | if [[ "$chart" == *.tgz ]] || [[ -d "$source/$chart" ]]; then 82 | # it's a file/directory 83 | chart_full="$source/$chart" 84 | version="" 85 | else 86 | # get from a repo 87 | chart_full="$chart" 88 | fi 89 | 90 | if [ "$tls_enabled" = true ]; then 91 | tls_flag="--tls" 92 | fi 93 | 94 | if [ "$tillerless" = true ]; then 95 | if [ "$tillerless_silent" = true ]; then 96 | export HELM_TILLER_SILENT=true 97 | fi 98 | helm_bin="helm tiller run ${tiller_namespace} -- helm" 99 | else 100 | helm_bin="helm" 101 | fi 102 | 103 | set_overridden_values() { 104 | while read -r -d '' key && read -r -d '' value && read -r -d '' path && read -r -d '' hidden && read -r -d '' type && read -r -d '' verbatim; do 105 | if [ -n "$path" ]; then 106 | value="$(< "$source/$path")" 107 | fi 108 | 109 | if [ "$verbatim" != 'false' ]; then 110 | value="${value/\\/\\\\}" 111 | fi 112 | 113 | scrubbed_value="$value" 114 | if [ "$hidden" != 'false' ]; then 115 | scrubbed_value='***HIDDEN***' 116 | fi 117 | 118 | helm_set_opt='--set' 119 | if [ "$type" == 'string' ]; then 120 | helm_set_opt='--set-string' 121 | fi 122 | 123 | overridden_args+=("$helm_set_opt" "$key=$value") 124 | scrubbed_overridden_args+=("$helm_set_opt" "$key=$scrubbed_value") 125 | done < <(jq -j '.params.override_values[]? | if .key and (.value or .path) then (.key, .value // "", .path // "", .hide // false, .type, .verbatim // false) else empty end | tostring + "\u0000"' < $payload) 126 | } 127 | 128 | # Find the current revision of a helm release 129 | current_deployed() { 130 | local release="$1" 131 | $helm_bin history $tls_flag --tiller-namespace $tiller_namespace --max 1 $release | grep "DEPLOYED" 132 | } 133 | 134 | helm_upgrade() { 135 | non_diff_args=("--namespace" "$namespace") 136 | if [ "$release" = "" ]; then 137 | upgrade_args=("install" $chart_full "--tiller-namespace=$tiller_namespace") 138 | else 139 | upgrade_args=("upgrade" "$release" $chart_full "--tiller-namespace=$tiller_namespace") 140 | non_diff_args+=("--install") 141 | 142 | # --cleanup-on-fail is only present on the upgrade command (not install) 143 | if [ "$cleanup_on_fail" = true ]; then 144 | non_diff_args+=("--cleanup-on-fail") 145 | fi 146 | fi 147 | 148 | if [ -n "$values" ]; then 149 | for value in $values; do 150 | upgrade_args+=("-f" "$source/"$value) 151 | done 152 | fi 153 | overridden_args=() 154 | scrubbed_overridden_args=() 155 | set_overridden_values 156 | if [ -n "$wait_until_ready" ] && [ "$wait_until_ready" -gt "0" ]; then 157 | non_diff_args+=("--wait" "--timeout" "$wait_until_ready") 158 | fi 159 | 160 | if [ "$check_is_ready" = true ] && [ "$wait_until_ready" -lt "1" ]; then 161 | non_diff_args+=("--wait") 162 | fi 163 | 164 | if [ "$debug" = true ]; then 165 | upgrade_args+=("--debug") 166 | non_diff_args+=("--dry-run") 167 | fi 168 | if [ "$devel" = true ]; then 169 | non_diff_args+=("--devel") 170 | fi 171 | if [ -n "$version" ]; then 172 | if [ -f "$source/$version" ]; then 173 | version=$(cat $source/$version) 174 | fi 175 | upgrade_args+=("--version" "$version") 176 | fi 177 | if [ "$atomic" = true ]; then 178 | non_diff_args+=("--atomic") 179 | fi 180 | if [ "$recreate_pods" = true ]; then 181 | non_diff_args+=("--recreate-pods") 182 | fi 183 | if [ "$force" = true ]; then 184 | non_diff_args+=("--force") 185 | fi 186 | if [ "$reuse_values" = true ]; then 187 | upgrade_args+=("--reuse-values") 188 | non_diff_args+=("--reuse-values") 189 | fi 190 | if [ "$reset_values" = true ]; then 191 | upgrade_args+=("--reset-values") 192 | non_diff_args+=("--reset-values") 193 | fi 194 | 195 | logfile="/tmp/log" 196 | mkdir -p /tmp 197 | 198 | helm_args=("${upgrade_args[@]}" "${overridden_args[@]}" "${non_diff_args[@]}") 199 | helm_echo_args=("${upgrade_args[@]}" "${scrubbed_overridden_args[@]}" "${non_diff_args[@]}") 200 | helm_diff_args=("${upgrade_args[@]}" "${overridden_args[@]}" "--suppress-secrets" "--allow-unreleased") 201 | 202 | if [[ -d "$chart_full" ]]; then 203 | helm_depup_args=("dependency" "update" "$chart_full") 204 | helm_depup_echo_args=("dependency" "update" "$chart_full") 205 | echo "Running command helm ${helm_depup_echo_args[@]}" 206 | $helm_bin "${helm_depup_args[@]}" | tee "$logfile" 207 | fi 208 | 209 | if [ "$show_diff" = true ] && current_deployed "$release"> /dev/null && [ "$devel" != true ]; then 210 | if [ "$tls_enabled" = true ]; then 211 | echo "helm diff does not support TLS at the present moment." 212 | else 213 | echo "Release diff:" 214 | $helm_bin diff "${helm_diff_args[@]}" | tee "$logfile" 215 | fi 216 | fi 217 | 218 | if [ "$exit_after_diff" = true ]; then 219 | echo "Exiting after diff" 220 | else 221 | echo "Running command helm ${helm_echo_args[@]} | tee $logfile" 222 | $helm_bin "${helm_args[@]}" $tls_flag | tee "$logfile" 223 | fi 224 | 225 | if [ -n "$wait" ] && [ "$wait" -gt "0" ]; then 226 | echo "Waiting for $wait Seconds" 227 | sleep $wait 228 | fi 229 | } 230 | 231 | helm_delete() { 232 | if [ -z "$release" ]; then 233 | echo "invalid payload (missing release if delete=true)" 234 | exit 1 235 | fi 236 | echo "Deleting the release $release..." 237 | delete_args=("delete" "--tiller-namespace=$tiller_namespace") 238 | if [ "$debug" = true ]; then 239 | delete_args+=("--dry-run" "--debug") 240 | fi 241 | 242 | if [ "$purge" = true ]; then 243 | delete_args+=("--purge") 244 | fi 245 | 246 | delete_args+=("$release") 247 | logfile="/tmp/log" 248 | mkdir -p /tmp 249 | echo "Running command helm ${delete_args[@]} | tee $logfile" 250 | $helm_bin "${delete_args[@]}" $tls_flag | tee $logfile 251 | } 252 | 253 | helm_test() { 254 | if [ -z "$release" ]; then 255 | echo "invalid payload (missing release if test=true)" 256 | exit 1 257 | fi 258 | echo "Testing the release $release..." 259 | test_args=("test" "--tiller-namespace=$tiller_namespace") 260 | if [ "$debug" = true ]; then 261 | test_args+=("--dry-run" "--debug") 262 | fi 263 | test_args+=("$release") 264 | logfile="/tmp/log" 265 | mkdir -p /tmp 266 | echo "Running command helm ${test_args[@]} | tee $logfile" 267 | result=$(${helm_bin} "${test_args[@]}" $tls_flag || true) 268 | 269 | if [[ $result = *"FAILED"* ]]; then 270 | _cmd=$(echo $result | awk -F '`' '{print $2};') 271 | 272 | echo "" 273 | echo "#### FAILED TEST OUTPUT ####" | tee $logfile 274 | $_cmd | tee $logfile 275 | echo "#### FAILED TEST OUTPUT ####" | tee $logfile 276 | echo "" 277 | 278 | cleanup=$(echo $_cmd | sed 's/logs/delete pod/g') 279 | $cleanup | tee $logfile 280 | 281 | exit 1 282 | elif [[ $result = *"ERROR"* ]]; then 283 | echo $result | tee $logfile 284 | exit 1 285 | elif [[ $result = *"PASSED"* ]]; then 286 | echo $result | tee $logfile 287 | TEST_PODS=$(echo $result | awk '{for(i=1;i<=NF;i++)if($i=="RUNNING:")print $(i+1)}' | sed 's/^/ /' ) 288 | kubectl delete pod $TEST_PODS -n $namespace | tee $logfile 289 | else 290 | echo "Unhandled" 291 | exit 1 292 | fi 293 | } 294 | 295 | wait_ready_notice() { 296 | if [ -n "$wait_until_ready" ] && [ "$wait_until_ready" -gt "0" ]; then 297 | echo "Waiting until deployment of $release is ready... (up to $wait_until_ready seconds)" 298 | fi 299 | } 300 | 301 | 302 | if [ "$delete" = true ]; then 303 | helm_delete 304 | result="$(jq -n "{version:{release:\"$release\", deleted: \"true\"}, metadata: [{name: \"release\", value: \"$release\"}]}")" 305 | echo "$result" | jq -s add >&3 306 | elif [ "$test" = true ]; then 307 | helm_test 308 | result="$(jq -n "{version:{release:\"$release\", tested: \"true\"}, metadata: [{name: \"release\", value: \"$release\"}]}")" 309 | echo "$result" | jq -s add >&3 310 | else 311 | echo "Installing $release" 312 | helm_upgrade 313 | 314 | if [ "$release" = "" ]; then 315 | release=$(helm ls -qrd --tiller-namespace $tiller_namespace --max 1 | head -1) 316 | fi 317 | deployed=$(current_deployed "$release") 318 | revision=$(echo $deployed | awk '{ print $1 }') 319 | chart=$(echo $deployed | awk '{ print $8 }') 320 | echo "Deployed revision $revision of $release" 321 | wait_ready_notice 322 | result="$(jq -n "{version:{release:\"$release\", revision:\"$revision\"}, metadata: [{name: \"release\", value: \"$release\"},{name: \"revision\", value: \"$revision\"},{name: \"chart\", value: \"$chart\"}]}")" 323 | echo "$result" | jq -s add >&3 324 | fi 325 | -------------------------------------------------------------------------------- /test/.gitignore: -------------------------------------------------------------------------------- 1 | payload.json 2 | -------------------------------------------------------------------------------- /test/name: -------------------------------------------------------------------------------- 1 | cit -------------------------------------------------------------------------------- /test/nginx-0.1.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkyard/concourse-helm-resource/b5c6786036a6a3671734e0252b3d6539af0b0359/test/nginx-0.1.0.tgz -------------------------------------------------------------------------------- /test/payload.json.template: -------------------------------------------------------------------------------- 1 | { 2 | "source": { 3 | "cluster_url": "https://my.kubenetes-cluster.test:8443", 4 | "cluster_ca": "...", 5 | "admin_key": "...", 6 | "admin_cert": "..." 7 | }, 8 | "params": { 9 | "chart": "nginx-0.1.0.tgz", 10 | "release": "name", 11 | "replace": "true", 12 | "delete": "false", 13 | "debug": "false", 14 | "devel": "false", 15 | "wait_until_ready": "10" 16 | } 17 | } 18 | --------------------------------------------------------------------------------