├── .circleci ├── config.yml └── test-deploy.yml ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── PULL_REQUEST_TEMPLATE.md ├── .yamllint ├── LICENSE ├── README.md ├── docs └── dev-notes.md └── src ├── @orb.yml ├── commands ├── delete_helm_release.yml ├── install_helm_chart.yml ├── install_helm_client.yml ├── install_helm_plugin.yml └── upgrade_helm_chart.yml ├── examples └── install_helm_chart_with_helm3.yml └── scripts ├── delete_helm_release.sh ├── install_helm_chart.sh ├── install_helm_client.sh ├── install_helm_plugin.sh └── upgrade_helm_chart.sh /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | setup: true 3 | orbs: 4 | orb-tools: circleci/orb-tools@12.0 5 | shellcheck: circleci/shellcheck@3.1 6 | 7 | filters: &filters 8 | tags: 9 | only: /.*/ 10 | 11 | workflows: 12 | lint-pack: 13 | jobs: 14 | - orb-tools/lint: 15 | filters: *filters 16 | - orb-tools/pack: 17 | filters: *filters 18 | - orb-tools/review: 19 | filters: *filters 20 | - shellcheck/check: 21 | exclude: SC2148,SC2038,SC2086,SC2002,SC2016 22 | filters: *filters 23 | - orb-tools/continue: 24 | orb_name: helm 25 | pipeline_number: << pipeline.number >> 26 | vcs_type: << pipeline.project.type >> 27 | requires: [orb-tools/lint, orb-tools/review, orb-tools/pack, shellcheck/check] 28 | filters: *filters 29 | -------------------------------------------------------------------------------- /.circleci/test-deploy.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | orbs: 3 | aws-eks: circleci/aws-eks@2.2 4 | orb-tools: circleci/orb-tools@12.0 5 | helm: {} 6 | filters: &filters 7 | tags: 8 | only: /.*/ 9 | release-filters: &release-filters 10 | branches: 11 | ignore: /.*/ 12 | tags: 13 | only: /^v[0-9]+\.[0-9]+\.[0-9]+$/ 14 | jobs: 15 | helm-client-install-test: 16 | docker: 17 | - image: cimg/python:3.10 18 | parameters: 19 | version: 20 | type: string 21 | description: version to install 22 | default: "" 23 | steps: 24 | - helm/install_helm_client: 25 | version: << parameters.version >> 26 | helm-plugin-install-test: 27 | docker: 28 | - image: cimg/base:current 29 | parameters: 30 | helm_plugin_url: 31 | type: string 32 | steps: 33 | - helm/install_helm_plugin: 34 | helm_plugin_url: << parameters.helm_plugin_url >> 35 | install-helm-on-eks-cluster: 36 | docker: 37 | - image: cimg/python:3.10 38 | parameters: 39 | cluster-name: 40 | type: string 41 | description: Cluster name 42 | steps: 43 | - aws-eks/update-kubeconfig-with-authenticator: 44 | cluster-name: << parameters.cluster-name >> 45 | install-kubectl: true 46 | install-helm-chart-on-eks-cluster: 47 | docker: 48 | - image: cimg/python:3.10 49 | parameters: 50 | release_name: 51 | type: string 52 | default: "prometheus-community" 53 | cluster-name: 54 | type: string 55 | description: Cluster name 56 | helm_version: 57 | type: string 58 | default: "v3.8.2" 59 | description: the helm client version to install. e.g. v3.0.0 60 | add_repo: 61 | type: string 62 | default: "" 63 | description: the helm chart repository url to use 64 | chart: 65 | type: string 66 | default: "prometheus-community/prometheus" 67 | description: the helm chart to install 68 | debug: 69 | description: | 70 | Enable debug mode 71 | type: boolean 72 | default: false 73 | steps: 74 | - aws-eks/update-kubeconfig-with-authenticator: 75 | cluster-name: << parameters.cluster-name >> 76 | install-kubectl: true 77 | aws-region: us-west-2 78 | - helm/install_helm_client: 79 | version: << parameters.helm_version >> 80 | - run: 81 | name: Install cncf stable repo 82 | command: | 83 | helm repo add stable http://cncf.gitlab.io/stable 84 | - helm/install_helm_chart: 85 | chart: << parameters.chart >> 86 | add_repo: << parameters.add_repo >> 87 | release_name: << parameters.release_name >> 88 | helm_version: << parameters.helm_version >> 89 | debug: << parameters.debug >> 90 | upgrade-helm-chart-on-eks-cluster: 91 | docker: 92 | - image: cimg/python:3.10 93 | parameters: 94 | release_name: 95 | type: string 96 | default: "prometheus-community" 97 | add_repo: 98 | type: string 99 | default: "https://prometheus-community.github.io/helm-charts" 100 | description: the helm chart repository url to use 101 | cluster-name: 102 | type: string 103 | description: Cluster name 104 | helm_version: 105 | type: string 106 | default: "v3.8.2" 107 | description: the helm client version to install. e.g. v3.0.0 108 | chart: 109 | type: string 110 | default: "prometheus-community/prometheus" 111 | description: the helm chart to install 112 | debug: 113 | description: | 114 | Enable debug mode 115 | type: boolean 116 | default: false 117 | steps: 118 | - aws-eks/update-kubeconfig-with-authenticator: 119 | cluster-name: << parameters.cluster-name >> 120 | install-kubectl: true 121 | aws-region: us-west-2 122 | - helm/install_helm_client: 123 | version: << parameters.helm_version >> 124 | - run: 125 | name: Install cncf stable repo 126 | command: | 127 | helm repo add stable http://cncf.gitlab.io/stable 128 | - helm/upgrade_helm_chart: 129 | add_repo: << parameters.add_repo >> 130 | chart: << parameters.chart >> 131 | release_name: << parameters.release_name >> 132 | helm_version: << parameters.helm_version >> # test specifying no_output_timeout 133 | debug: << parameters.debug >> 134 | # test specifying no_output_timeout 135 | no_output_timeout: 25m 136 | delete-helm-release-on-eks-cluster: 137 | docker: 138 | - image: cimg/python:3.10 139 | parameters: 140 | cluster-name: 141 | type: string 142 | description: Cluster name 143 | helm_version: 144 | type: string 145 | default: "v3.8.2" 146 | description: the helm client version to install. e.g. v3.0.0 147 | timeout: 148 | type: string 149 | default: "" 150 | steps: 151 | - aws-eks/update-kubeconfig-with-authenticator: 152 | cluster-name: << parameters.cluster-name >> 153 | install-kubectl: true 154 | aws-region: us-west-2 155 | - helm/install_helm_client: 156 | version: << parameters.helm_version >> 157 | - run: 158 | name: Install cncf stable repo 159 | command: | 160 | helm repo add stable http://cncf.gitlab.io/stable 161 | - helm/delete_helm_release: 162 | release_name: prometheus-community 163 | purge: true 164 | timeout: << parameters.timeout >> 165 | helm_version: << parameters.helm_version >> 166 | workflows: 167 | test-deploy: 168 | jobs: 169 | - helm-client-install-test: 170 | name: helm-client-install-latest 171 | filters: *filters 172 | - helm-client-install-test: 173 | name: helm-client-install-specific-version 174 | version: v3.0.0 175 | filters: *filters 176 | - helm-plugin-install-test: 177 | name: helm-plugin-install-env 178 | helm_plugin_url: https://github.com/adamreese/helm-env 179 | filters: *filters 180 | - aws-eks/create-cluster: 181 | name: create-cluster-helm4 182 | cluster-name: ${AWS_RESOURCE_NAME_PREFIX}-helm4-eks 183 | filters: *filters 184 | context: CPE_ORBS_AWS 185 | - install-helm-chart-on-eks-cluster: 186 | name: install-helm-chart-on-eks-cluster-helm4 187 | helm_version: v3.8.2 188 | # test repo update 189 | cluster-name: ${AWS_RESOURCE_NAME_PREFIX}-helm4-eks 190 | add_repo: https://prometheus-community.github.io/helm-charts 191 | chart: prometheus-community/prometheus 192 | debug: true 193 | context: CPE_ORBS_AWS 194 | filters: *filters 195 | requires: 196 | - create-cluster-helm4 197 | - upgrade-helm-chart-on-eks-cluster: 198 | name: upgrade-helm-chart-on-eks-cluster-helm4 199 | helm_version: v3.8.2 200 | cluster-name: ${AWS_RESOURCE_NAME_PREFIX}-helm4-eks 201 | debug: true 202 | context: CPE_ORBS_AWS 203 | filters: *filters 204 | requires: 205 | - install-helm-chart-on-eks-cluster-helm4 206 | - delete-helm-release-on-eks-cluster: 207 | name: delete-helm-release-on-eks-cluster-helm4 208 | helm_version: v3.8.2 209 | cluster-name: ${AWS_RESOURCE_NAME_PREFIX}-helm4-eks 210 | context: CPE_ORBS_AWS 211 | filters: *filters 212 | requires: 213 | - upgrade-helm-chart-on-eks-cluster-helm4 214 | - install-helm-chart-on-eks-cluster: 215 | name: reinstall-helm-chart-on-eks-cluster-helm4 216 | helm_version: v3.8.2 217 | # Test auto-generated release name 218 | release_name: prometheus-community 219 | add_repo: https://prometheus-community.github.io/helm-charts 220 | cluster-name: ${AWS_RESOURCE_NAME_PREFIX}-helm4-eks 221 | context: CPE_ORBS_AWS 222 | filters: *filters 223 | requires: 224 | - delete-helm-release-on-eks-cluster-helm4 225 | - delete-helm-release-on-eks-cluster: 226 | name: delete-helm-release-on-eks-cluster-again-helm4 227 | helm_version: v3.8.2 228 | cluster-name: ${AWS_RESOURCE_NAME_PREFIX}-helm4-eks 229 | # test timeout 230 | timeout: "600s" 231 | context: CPE_ORBS_AWS 232 | filters: *filters 233 | requires: 234 | - reinstall-helm-chart-on-eks-cluster-helm4 235 | - aws-eks/delete-cluster: 236 | name: delete-cluster-helm4 237 | cluster-name: ${AWS_RESOURCE_NAME_PREFIX}-helm4-eks 238 | aws-region: us-west-2 239 | wait: true 240 | context: CPE_ORBS_AWS 241 | filters: *filters 242 | requires: 243 | - delete-helm-release-on-eks-cluster-again-helm4 244 | # Make sure to include "filters: *filters" in every test job you want to run as part of your deployment. 245 | - orb-tools/pack: 246 | filters: *release-filters 247 | - orb-tools/publish: 248 | orb_name: circleci/helm 249 | vcs_type: << pipeline.project.type >> 250 | pub_type: production 251 | enable_pr_comment: true 252 | requires: 253 | - orb-tools/pack 254 | - helm-client-install-latest 255 | - helm-client-install-specific-version 256 | - helm-client-install-latest 257 | - create-cluster-helm4 258 | - install-helm-chart-on-eks-cluster-helm4 259 | - upgrade-helm-chart-on-eks-cluster-helm4 260 | - delete-helm-release-on-eks-cluster-helm4 261 | - reinstall-helm-chart-on-eks-cluster-helm4 262 | - delete-helm-release-on-eks-cluster-again-helm4 263 | - delete-cluster-helm4 264 | context: orb-publisher 265 | filters: *release-filters 266 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Ping these folks when changes are made to this repository 2 | * @CircleCI-Public/orb-publishers 3 | 4 | # We can also add orb-specifc codeowners at some point if desirable 5 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "Bug report" 3 | about: Create a report to help improve the project 4 | labels: bug 5 | 6 | --- 7 | 8 | ### Orb version 9 | 10 | 17 | 18 | ### What happened 19 | 20 | 24 | 25 | ### Expected behavior 26 | 27 | 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "Feature request" 3 | about: Suggest an idea that will improve the project 4 | labels: enhancement 5 | 6 | --- 7 | 8 | ## What would you like to be added 9 | 10 | 13 | 14 | ## Why is this needed 15 | 16 | 19 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Checklist 2 | 3 | 8 | 9 | - [ ] All new jobs, commands, executors, parameters have descriptions 10 | - [ ] Examples have been added for any significant new features 11 | - [ ] README has been updated, if necessary 12 | 13 | ### Motivation, issues 14 | 15 | 20 | 21 | ### Description 22 | 23 | 27 | -------------------------------------------------------------------------------- /.yamllint: -------------------------------------------------------------------------------- 1 | extends: relaxed 2 | 3 | rules: 4 | line-length: 5 | max: 200 6 | allow-non-breakable-inline-mappings: true 7 | 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 CircleCI Public 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # helm Orb [![CircleCI status](https://circleci.com/gh/CircleCI-Public/helm-orb.svg "CircleCI status")](https://circleci.com/gh/CircleCI-Public/helm-orb) [![CircleCI Orb Version](https://badges.circleci.com/orbs/circleci/helm.svg)](https://circleci.com/orbs/registry/orb/circleci/helm) [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/CircleCI-Public/helm-orb/blob/master/LICENSE) [![CircleCI Community](https://img.shields.io/badge/community-CircleCI%20Discuss-343434.svg)](https://discuss.circleci.com/c/ecosystem/orbs) 2 | 3 | A CircleCI Orb to simplify deployments to Kubernetes using Helm. 4 | 5 | Here are the features that the Helm orb provides: 6 | 7 | - Installing the helm client (`install_helm_client`) 8 | - Installing helm charts (`install_helm_chart`) and deleting releases (`delete_helm_release`) 9 | - Installing helm plugin (`install_helm_plugin`) 10 | 11 | Table of Contents 12 | ================= 13 | * [Usage](#usage) 14 | * [Requirements](#requirements) 15 | * [Examples](#examples) 16 | * [Contributing](#contributing) 17 | 18 | ## Usage 19 | 20 | See the [orb registry listing](https://circleci.com/developer/orbs/orb/circleci/helm) for usage guidelines. 21 | 22 | ## Requirements 23 | 24 | - `curl` should be present in `PATH`. 25 | 26 | ## Examples 27 | 28 | Refer to the usage examples [here](https://circleci.com/developer/orbs/orb/circleci/helm#usage-install-helm-chart-with-helm3). 29 | 30 | ## Contributing 31 | 32 | Development notes for building, testing and orb publishing are located [here](docs/dev-notes.md). 33 | 34 | We welcome [issues](https://github.com/CircleCI-Public/helm-orb/issues) to and [pull requests](https://github.com/CircleCI-Public/helm-orb/pulls) against this repository! 35 | 36 | For further questions/comments about this or other orbs, visit [CircleCI's orbs discussion forum](https://discuss.circleci.com/c/orbs). 37 | -------------------------------------------------------------------------------- /docs/dev-notes.md: -------------------------------------------------------------------------------- 1 | # Notes for Internal Contributors 2 | 3 | The notes here are primarily targeted at internal (CircleCI) contributors to the orb but could be of reference to fork owners who wish to run the tests with their own AWS account. 4 | 5 | ## Building 6 | 7 | ### Required Project Environment Variables 8 | 9 | The following [project environment variables](https://circleci.com/docs/2.0/env-vars/#setting-an-environment-variable-in-a-project) must be set for the project on CircleCI via the project settings page, before the project can be built successfully. 10 | 11 | | Variable | Description | 12 | | -------------------------------| ---------------------------------| 13 | | `AWS_ACCESS_KEY_ID` | Picked up by the AWS CLI | 14 | | `AWS_SECRET_ACCESS_KEY` | Picked up by the AWS CLI | 15 | | `AWS_DEFAULT_REGION` | Picked up by the AWS CLI | 16 | | `AWS_RESOURCE_NAME_PREFIX` | Prefix for some AWS resources created in tests. This is used just to make the project more portable. | 17 | | `CIRCLECI_API_KEY` | Used by the `queue` orb | 18 | 19 | ### Required Context and Context Environment Variables 20 | 21 | The `orb-publishing` context is referenced in the build. In particular, the following [context environment variables](https://circleci.com/docs/2.0/env-vars/#setting-an-environment-variable-in-a-context) must be set in the `orb-publishing` context, before the project can be built successfully. 22 | 23 | | Variable | Description | 24 | | -------------------------------| ---------------------------------| 25 | | `CIRCLE_TOKEN` | CircleCI API token used to publish the orb | 26 | 27 | 28 | ### AWS Resource Cleanup 29 | 30 | The tests configured in `.circleci/config.yml` have been tested to be able to successfully clean up the AWS resources used, via the `delete-cluster` command. 31 | 32 | However, when adding new tests, depending on the type of AWS resources involved (e.g. AWS Elastic Load Balancers), you may encounter situations where if the resources deployed onto the EKS cluster are not deleted before running `delete-cluster`, `delete-cluster` may fail to remove all of the deployed AWS resources, e.g. the VPC. 33 | 34 | When that happens, in order to properly clean up the AWS resources, first try to delete the CloudFormation stacks (there are 2 for each deployed cluster - one that has `nodegroup` in its name and one that ends with the `-cluster` suffix) by deleting the nodegroup stack first and then the the other stack, for each cluster and region under test. 35 | 36 | If a CloudFormation stack cannot be deleted, check on the status of the CloudFormation stack corresponding to the EKS cluster used in the test. If the status is `DELETE_FAILED`, check the events for a hint of which AWS resources could not be deleted. Usually it is a Load Balancer that is preventing the VPC (that was created by `create-cluster`) from being deleted. Once that resource has been deleted, you should be able to delete the entire VPC from the `VPC` section of the AWS Console. 37 | 38 | ## Orb Publishing 39 | The orb is promoted into publishing by triggering the `production-orb-publishing` workflow. This workflow is meant to be manually triggered by tagging a `master` branch commit, after (manually) verifying that it has successfully completed the `integration-tests` workflow. The `production-orb-publishing` workflow will promote into production a dev orb that was published with a version that corresponds to the shortened SHA-1 hash of the tagged commit. 40 | 41 | **NOTE**: The workflow has a manual approval step before it can proceed to promotion of the orb. Please locate the `production-orb-publishing` workflow from the Workflows listing to execute the approval. 42 | 43 | ### Patch release tag example: 44 | 45 | ``` 46 | git tag patch-release-v0.0.1 47 | git push origin patch-release-v0.0.1 48 | ``` 49 | 50 | ### Minor release tag example: 51 | 52 | ``` 53 | git tag minor-release-v0.1.0 54 | git push origin minor-release-v0.1.0 55 | ``` 56 | 57 | ### Major release tag example: 58 | 59 | ``` 60 | git tag major-release-v1.0.0 61 | git push origin major-release-v1.0.0 62 | ``` 63 | -------------------------------------------------------------------------------- /src/@orb.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | description: | 4 | An orb for working with helm for Kubernetes deployments. Currently supports helm3 versions. 5 | 6 | display: 7 | home_url: https://helm.sh/ 8 | source_url: https://github.com/CircleCI-Public/helm-orb 9 | 10 | -------------------------------------------------------------------------------- /src/commands/delete_helm_release.yml: -------------------------------------------------------------------------------- 1 | description: | 2 | Deletes a helm release. 3 | Requirements: helm should be installed on the cluster 4 | and kubeconfig should be configured to connect to the cluster. 5 | 6 | parameters: 7 | release_name: 8 | description: | 9 | Specify the release to be deleted. 10 | type: string 11 | purge: 12 | description: | 13 | Effective for helm 2 commands only (purging is the default in helm 3) 14 | Whether to remove the release from the store and make its name free for 15 | later use 16 | type: boolean 17 | default: false 18 | keep_history: 19 | description: | 20 | Effective for helm 3 commands only. 21 | Retains release history. 22 | type: boolean 23 | default: false 24 | timeout: 25 | description: | 26 | Specify a timeout value that will be passed as a --timeout argument 27 | to the helm command. For helm 3, the unit of the duration must 28 | be specified e.g. '300s'. 29 | type: string 30 | default: "" 31 | namespace: 32 | description: | 33 | The kubernetes namespace that should be used. 34 | type: string 35 | default: "" 36 | tls: 37 | description: | 38 | Enable TLS for the request 39 | type: boolean 40 | default: false 41 | tls_ca_cert: 42 | description: | 43 | Path to TLS CA certificate file 44 | type: string 45 | default: "" 46 | tls_cert: 47 | description: | 48 | Path to TLS certificate file 49 | type: string 50 | default: "" 51 | tls_hostname: 52 | description: | 53 | The server name used to verify the hostname on the returned 54 | certificates from the server 55 | type: string 56 | default: "" 57 | tls_key: 58 | description: | 59 | Path to TLS key file 60 | type: string 61 | default: "" 62 | tls_verify: 63 | description: | 64 | Enable TLS for request and verify remote 65 | type: boolean 66 | default: false 67 | tiller_namespace: 68 | description: | 69 | Specify the namespace of Tiller 70 | type: string 71 | default: "" 72 | helm_version: 73 | type: string 74 | default: "v3.8.2" 75 | description: the helm client version to install. e.g. v3.0.0. 76 | no_output_timeout: 77 | description: | 78 | Elapsed time that the helm command can run on CircleCI without output. 79 | The string is a decimal with unit suffix, such as “20m”, “1.25h”, “5s” 80 | type: string 81 | default: "30m" 82 | 83 | steps: 84 | - install_helm_client: 85 | version: << parameters.helm_version >> 86 | - run: 87 | name: Delete helm release 88 | environment: 89 | HELM_STR_RELEASE_NAME: << parameters.release_name >> 90 | HELM_BOOL_PURGE: << parameters.purge >> 91 | HELM_BOOL_KEEP_HISTORY: << parameters.keep_history >> 92 | HELM_STR_TIMEOUT: << parameters.timeout >> 93 | HELM_STR_NAMESPACE: << parameters.namespace >> 94 | HELM_BOOL_TLS: << parameters.tls >> 95 | HELM_STR_TLS_CA_CERT: << parameters.tls_ca_cert >> 96 | HELM_STR_TLS_CERT: << parameters.tls_cert >> 97 | HELM_STR_TLS_HOSTNAME: << parameters.tls_hostname >> 98 | HELM_STR_TLS_KEY: << parameters.tls_key >> 99 | HELM_BOOL_TLS_VERIFY: << parameters.tls_verify >> 100 | HELM_STR_TILLER_NAMESPACE: << parameters.tiller_namespace >> 101 | command: <> 102 | no_output_timeout: << parameters.no_output_timeout >> 103 | -------------------------------------------------------------------------------- /src/commands/install_helm_chart.yml: -------------------------------------------------------------------------------- 1 | description: | 2 | Installs a helm chart. 3 | Requirements: helm should be installed on the cluster 4 | and kubeconfig should be configured to connect to the cluster. 5 | 6 | parameters: 7 | chart: 8 | description: | 9 | Specify for installation a chart reference (e.g. stable/mariadb), 10 | or a path to a packaged chart (e.g. ./nginx-1.2.3.tgz), 11 | or a path to an unpacked chart directory (e.g. ./nginx) 12 | or an absolute URL (e.g. https://example.com/charts/nginx-1.2.3.tgz) 13 | type: string 14 | add_repo: 15 | description: | 16 | The url for the helm chart repository used as part of helm repo add 17 | command. Required when update_repositories is true. 18 | type: string 19 | default: "" 20 | release_name: 21 | description: | 22 | Specify a name for the release. 23 | type: string 24 | default: "" 25 | values_to_override: 26 | description: | 27 | Override values in a chart using the --set flag of the helm install 28 | command. Format: key1=val1,key2=val2 29 | type: string 30 | default: "" 31 | namespace: 32 | description: | 33 | The kubernetes namespace that should be used. 34 | type: string 35 | default: "" 36 | create_namespace: 37 | description: | 38 | This parameter creates the kubernetes namespace if the one provided does not exist. 39 | type: boolean 40 | default: false 41 | wait: 42 | description: | 43 | Whether to wait for the installation or upgrade to be complete 44 | type: boolean 45 | default: false 46 | wait_for_jobs: 47 | description: | 48 | Whether to wait for all jobs associated with deployment to be complete before marking the release as successful. 49 | type: boolean 50 | default: false 51 | update_repositories: 52 | description: | 53 | Choose to update repositories by running helm repo update. 54 | type: boolean 55 | default: true 56 | helm_version: 57 | type: string 58 | default: "v3.8.2" 59 | description: the helm client version to install. e.g. v3.0.0 60 | no_output_timeout: 61 | description: | 62 | Elapsed time that the helm command can run on CircleCI without output. 63 | The string is a decimal with unit suffix, such as “20m”, “1.25h”, “5s” 64 | type: string 65 | default: "30m" 66 | debug: 67 | description: | 68 | Enable debug mode by adding --debug to helm command. Defaults to false. 69 | type: boolean 70 | default: false 71 | steps: 72 | - install_helm_client: 73 | version: << parameters.helm_version >> 74 | - when: 75 | condition: << parameters.update_repositories >> 76 | steps: 77 | - run: 78 | name: Update repositories 79 | command: | 80 | helm repo add <> <> && \ 81 | helm repo update 82 | - run: 83 | name: Install chart 84 | environment: 85 | HELM_STR_RELEASE_NAME: << parameters.release_name >> 86 | HELM_STR_VALUES_TO_OVERRIDE: << parameters.values_to_override >> 87 | HELM_STR_NAMESPACE: << parameters.namespace >> 88 | HELM_BOOL_WAIT: << parameters.wait >> 89 | HELM_BOOL_CREATE_NAMESPACE: << parameters.create_namespace >> 90 | HELM_STR_CHART: << parameters.chart >> 91 | HELM_BOOL_WAIT_FOR_JOBS: << parameters.wait_for_jobs >> 92 | HELM_BOOL_DEBUG: << parameters.debug >> 93 | command: <> 94 | no_output_timeout: << parameters.no_output_timeout >> 95 | -------------------------------------------------------------------------------- /src/commands/install_helm_client.yml: -------------------------------------------------------------------------------- 1 | description: | 2 | Install the helm client. 3 | Defaults to the latest version of Helm 3. You can specify a specific version e.g v3.0.0. 4 | Requirements: curl 5 | 6 | parameters: 7 | version: 8 | type: string 9 | default: "v3.8.2" 10 | description: the helm client version to install. e.g. v3.8.0 11 | retries: 12 | type: integer 13 | default: 2 14 | description: The amount of retries when downloading the helm client, in case it fails. 15 | 16 | steps: 17 | - run: 18 | name: Install and init the helm client (if necessary) 19 | environment: 20 | HELM_RETRIES: <> 21 | HELM_STR_VERSION: << parameters.version >> 22 | command: <> 23 | -------------------------------------------------------------------------------- /src/commands/install_helm_plugin.yml: -------------------------------------------------------------------------------- 1 | description: | 2 | Installs a helm plugin. 3 | Requirements: helm should be installed on the cluster 4 | 5 | parameters: 6 | helm_plugin_url: 7 | description: | 8 | absolute URL to helm plugin to install 9 | (e.g. https://example.com/helm-plugin/helm-plugin-1.2.3.tgz) 10 | type: string 11 | helm_version: 12 | type: string 13 | default: "v3.8.2" 14 | description: the helm client version to install. e.g. v3.0.0 15 | no_output_timeout: 16 | description: | 17 | Elapsed time that the helm command can run on CircleCI without output. 18 | The string is a decimal with unit suffix, such as “20m”, “1.25h”, “5s” 19 | type: string 20 | default: "30m" 21 | 22 | steps: 23 | - install_helm_client: 24 | version: << parameters.helm_version >> 25 | - run: 26 | name: Install helm plugin 27 | environment: 28 | HELM_STR_PLUGIN_URL: << parameters.helm_plugin_url >> 29 | command: <> 30 | no_output_timeout: << parameters.no_output_timeout >> 31 | -------------------------------------------------------------------------------- /src/commands/upgrade_helm_chart.yml: -------------------------------------------------------------------------------- 1 | description: | 2 | Upgrades an existing helm chart 3 | Requirements: helm should be installed on the cluster 4 | and kubeconfig should be configured to connect to the cluster. 5 | 6 | parameters: 7 | chart: 8 | description: | 9 | Specify for upgrade a chart reference (e.g. stable/mariadb), 10 | or a path to a packaged chart (e.g. ./nginx-1.2.3.tgz), 11 | or a path to an unpacked chart directory (e.g. ./nginx) 12 | or an absolute URL (e.g. https://example.com/charts/nginx-1.2.3.tgz) 13 | type: string 14 | default: "" 15 | add_repo: 16 | description: | 17 | The url for the helm chart repository used as part of helm repo add 18 | command 19 | type: string 20 | default: "" 21 | release_name: 22 | description: | 23 | Specify a name for the release. 24 | type: string 25 | default: "" 26 | namespace: 27 | description: | 28 | The kubernetes namespace that should be used. 29 | type: string 30 | default: "" 31 | create_namespace: 32 | description: | 33 | This parameter creates the kubernetes namespace if the one provided does not exist. 34 | type: boolean 35 | default: false 36 | wait: 37 | description: | 38 | Whether to wait for the installation to be complete. 39 | type: boolean 40 | default: false 41 | wait_for_jobs: 42 | description: | 43 | Whether to wait for all jobs associated with deployment to be complete before marking the release as successful. 44 | type: boolean 45 | default: false 46 | timeout: 47 | description: | 48 | If timeout is reached, the release will be marked as FAILED. 49 | type: string 50 | default: "" 51 | no_hooks: 52 | description: | 53 | This skips running hooks for the command 54 | type: boolean 55 | default: false 56 | devel: 57 | description: | 58 | Use development versions, too. Equivalent to version '>0.0.0-0'. If --version is set, this is ignored. 59 | type: string 60 | default: "" 61 | dry_run: 62 | description: | 63 | simulate an upgrade 64 | type: boolean 65 | default: false 66 | force: 67 | description: | 68 | Use development versions, too. Equivalent to version '>0.0.0-0'. If --version is set, this is ignored. 69 | type: boolean 70 | default: false 71 | reset_values: 72 | description: | 73 | when upgrading, reset the values to the ones built into the chart 74 | type: boolean 75 | default: false 76 | reuse_values: 77 | description: | 78 | when upgrading, reuse the last release's values and merge in any overrides from the command line via --set and -f. If '--reset_values' is specified, this is ignored. 79 | type: boolean 80 | default: false 81 | values: 82 | description: | 83 | specify values in a YAML file or a URL 84 | type: string 85 | default: "" 86 | version: 87 | description: | 88 | specify the exact chart version to use. If this is not specified, the latest version is used 89 | type: string 90 | default: "" 91 | recreate_pods: 92 | description: | 93 | performs pods restart for the resource if applicable 94 | type: boolean 95 | default: false 96 | values_to_override: 97 | description: | 98 | Override values in a chart using the --set flag of the helm upgrade 99 | command. Format: key1=val1,key2=val2 100 | type: string 101 | default: "" 102 | history_max: 103 | description: | 104 | limit the maximum number of revisions saved per release. Use 0 for no limit (default 10) 105 | type: integer 106 | default: 10 107 | helm_version: 108 | type: string 109 | default: "v3.8.2" 110 | description: the helm client version to install. e.g. v3.0.0 111 | no_output_timeout: 112 | description: | 113 | Elapsed time that the helm command can run on CircleCI without output. 114 | The string is a decimal with unit suffix, such as “20m”, “1.25h”, “5s” 115 | type: string 116 | default: "30m" 117 | atomic: 118 | description: | 119 | if set, upgrade process rolls back changes made in case of failed upgrade. 120 | The --wait flag will be set automatically if --atomic is used 121 | type: boolean 122 | default: false 123 | debug: 124 | description: | 125 | Enable debug mode by adding --debug to helm command. Defaults to false. 126 | type: boolean 127 | default: false 128 | steps: 129 | - install_helm_client: 130 | version: << parameters.helm_version >> 131 | - run: 132 | name: Upgrade, update, or install chart 133 | environment: 134 | HELM_STR_TIMEOUT: << parameters.timeout >> 135 | HELM_BOOL_ATOMIC: << parameters.atomic >> 136 | HELM_BOOL_WAIT: << parameters.wait >> 137 | HELM_BOOL_NO_HOOKS: << parameters.no_hooks >> 138 | HELM_BOOL_RECREATE_PODS: << parameters.recreate_pods >> 139 | HELM_STR_NAMESPACE: << parameters.namespace >> 140 | HELM_BOOL_CREATE_NAMESPACE: << parameters.create_namespace >> 141 | HELM_STR_DEVEL: << parameters.devel >> 142 | HELM_BOOL_DRY_RUN: << parameters.dry_run >> 143 | HELM_BOOL_RESET_VALUES: << parameters.reset_values >> 144 | HELM_BOOL_REUSE_VALUES: << parameters.reuse_values >> 145 | HELM_STR_VALUES: << parameters.values >> 146 | HELM_STR_VERSION: << parameters.version >> 147 | HELM_STR_VALUES_TO_OVERRIDE: << parameters.values_to_override >> 148 | HELM_INT_HISTORY_MAX: << parameters.history_max >> 149 | HELM_STR_CHART: << parameters.chart >> 150 | HELM_STR_RELEASE_NAME: << parameters.release_name >> 151 | HELM_STR_ADD_REPO: << parameters.add_repo >> 152 | HELM_BOOL_WAIT_FOR_JOBS: << parameters.wait_for_jobs >> 153 | HELM_BOOL_FORCE: << parameters.force >> 154 | HELM_BOOL_DEBUG: << parameters.debug >> 155 | command: <> 156 | no_output_timeout: << parameters.no_output_timeout >> 157 | -------------------------------------------------------------------------------- /src/examples/install_helm_chart_with_helm3.yml: -------------------------------------------------------------------------------- 1 | description: | 2 | Demonstrate installing a helm chart on a Kubernetes cluster, with 3 | helm 3. 4 | 5 | usage: 6 | version: 2.1 7 | 8 | orbs: 9 | aws-eks: circleci/aws-eks@2.1.2 10 | helm: circleci/helm@1.0 11 | 12 | jobs: 13 | install_helm_chart: 14 | executor: aws-eks/python 15 | parameters: 16 | cluster-name: 17 | type: string 18 | description: Cluster name 19 | steps: 20 | - aws-eks/update-kubeconfig-with-authenticator: 21 | cluster-name: << parameters.cluster-name >> 22 | - helm/install_helm_chart: 23 | helm_version: v3.2.4 24 | chart: stable/grafana 25 | release_name: grafana-release 26 | delete_helm_release: 27 | executor: aws-eks/python 28 | parameters: 29 | cluster-name: 30 | type: string 31 | description: Cluster name 32 | steps: 33 | - aws-eks/update-kubeconfig-with-authenticator: 34 | cluster-name: << parameters.cluster-name >> 35 | - helm/delete_helm_release: 36 | helm_version: v3.2.4 37 | release_name: grafana-release 38 | timeout: 600s 39 | 40 | workflows: 41 | deployment: 42 | jobs: 43 | - aws-eks/create-cluster: 44 | cluster-name: test-cluster 45 | - install_helm_chart: 46 | cluster-name: test-cluster 47 | requires: 48 | - aws-eks/create-cluster 49 | - delete_helm_release: 50 | cluster-name: test-cluster 51 | requires: 52 | - install_helm_chart 53 | - aws-eks/delete-cluster: 54 | cluster-name: test-cluster 55 | wait: true 56 | requires: 57 | - delete_helm_release 58 | -------------------------------------------------------------------------------- /src/scripts/delete_helm_release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | HELM_STR_TIMEOUT="$(echo "${HELM_STR_TIMEOUT}" | circleci env subst)" 3 | HELM_STR_NAMESPACE="$(echo "${HELM_STR_NAMESPACE}" | circleci env subst)" 4 | HELM_STR_TLS_CA_CERT="$(echo "${HELM_STR_TLS_CA_CERT}" | circleci env subst)" 5 | HELM_STR_TLS_CERT="$(echo "${HELM_STR_TLS_CERT}" | circleci env subst)" 6 | HELM_STR_TLS_HOSTNAME="$(echo "${HELM_STR_TLS_HOSTNAME}" | circleci env subst)" 7 | HELM_STR_TLS_KEY="$(echo "${HELM_STR_TLS_KEY}" | circleci env subst)" 8 | HELM_STR_RELEASE_NAME="$(echo "${HELM_STR_RELEASE_NAME}" | circleci env subst)" 9 | HELM_STR_TILLER_NAMESPACE="$(echo "${HELM_STR_TILLER_NAMESPACE}" | circleci env subst)" 10 | 11 | set -x 12 | if [ -n "${HELM_STR_TIMEOUT}" ]; then 13 | set -- "$@" --timeout="${HELM_STR_TIMEOUT}" 14 | fi 15 | if [ -n "${HELM_STR_NAMESPACE}" ]; then 16 | set -- "$@" --namespace="${HELM_STR_NAMESPACE}" 17 | fi 18 | if [ "${HELM_BOOL_TLS}" -eq 1 ]; then 19 | set -- "$@" --tls 20 | fi 21 | if [ -n "${HELM_STR_TLS_CA_CERT}" ]; then 22 | set -- "$@" --tls-ca-cert="${HELM_STR_TLS_CA_CERT}" 23 | fi 24 | if [ -n "${HELM_STR_TLS_CERT}" ]; then 25 | set -- "$@" --tls-cert="${HELM_STR_TLS_CERT}" 26 | fi 27 | if [ -n "${HELM_STR_TLS_HOSTNAME}" ]; then 28 | set -- "$@" --tls-hostname="${HELM_STR_TLS_HOSTNAME}" 29 | fi 30 | if [ -n "${HELM_STR_TLS_KEY}" ]; then 31 | set -- "$@" --tls-key="${HELM_STR_TLS_KEY}" 32 | fi 33 | if [ "${HELM_BOOL_TLS_VERIFY}" -eq 1 ]; then 34 | set -- "$@" --tls-verify 35 | fi 36 | if [ -n "${HELM_STR_TILLER_NAMESPACE}" ]; then 37 | set -- "$@" --tiller-namespace "${HELM_STR_TILLER_NAMESPACE}" 38 | fi 39 | 40 | VERSION_2_MATCH="$(helm version --short -c | grep 'Client: v2' || true)" 41 | if [ -n "${VERSION_2_MATCH}" ]; then 42 | if [ "${HELM_BOOL_PURGE}" -eq 1 ]; then 43 | set -- "$@" --purge 44 | fi 45 | else 46 | if [ "${HELM_BOOL_KEEP_HISTORY}" -eq 1 ]; then 47 | set -- "$@" --keep-history 48 | fi 49 | fi 50 | helm delete "$@" "${HELM_STR_RELEASE_NAME}" 51 | set +x -------------------------------------------------------------------------------- /src/scripts/install_helm_chart.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | HELM_STR_VALUES_TO_OVERRIDE="$(echo "${HELM_STR_VALUES_TO_OVERRIDE}" | circleci env subst)" 3 | HELM_STR_NAMESPACE="$(echo "${HELM_STR_NAMESPACE}" | circleci env subst)" 4 | HELM_STR_RELEASE_NAME="$(echo "${HELM_STR_RELEASE_NAME}" | circleci env subst)" 5 | HELM_STR_CHART="$(echo "${HELM_STR_CHART}" | circleci env subst)" 6 | 7 | set -x 8 | if [ -n "${HELM_STR_VALUES_TO_OVERRIDE}" ]; then 9 | set -- "$@" --set "${HELM_STR_VALUES_TO_OVERRIDE}" 10 | fi 11 | if [ "${HELM_BOOL_WAIT_FOR_JOBS}" -eq 1 ]; then 12 | set -- "$@" --wait-for-jobs 13 | fi 14 | if [ -n "${HELM_STR_NAMESPACE}" ]; then 15 | if [ "${HELM_BOOL_CREATE_NAMESPACE}" -eq "1" ]; then 16 | set -- "$@" --create-namespace --namespace="${HELM_STR_NAMESPACE}" 17 | else 18 | set -- "$@" --namespace="${HELM_STR_NAMESPACE}" 19 | fi 20 | fi 21 | if [ "${HELM_BOOL_WAIT}" -eq 1 ]; then 22 | set -- "$@" --wait 23 | fi 24 | if [ "${HELM_BOOL_DEBUG}" -eq 1 ]; then 25 | set -- "$@" --debug 26 | fi 27 | if [ -n "${HELM_STR_RELEASE_NAME}" ]; then 28 | helm install "${HELM_STR_RELEASE_NAME}" "${HELM_STR_CHART}" "$@" 29 | else 30 | set -- "$@" --generate-name 31 | helm install "${HELM_STR_CHART}" "$@" 32 | fi 33 | set +x -------------------------------------------------------------------------------- /src/scripts/install_helm_client.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | HELM_STR_VERSION="$(echo "${HELM_STR_VERSION}" | circleci env subst)" 3 | 4 | set -x 5 | if command -v helm &> /dev/null; then 6 | echo "helm is already installed" 7 | exit 0 8 | fi 9 | 10 | if [ -n "${HELM_STR_VERSION}" ]; then 11 | set -- "$@" --version "${HELM_STR_VERSION}" 12 | fi 13 | 14 | INSTALL_SCRIPT="https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3" 15 | 16 | success_helm_download=false 17 | retry_count=0 18 | while [ "$retry_count" -lt "$HELM_RETRIES" ]; do 19 | 20 | if curl -sSf "${INSTALL_SCRIPT}" -o get_helm.sh; then 21 | echo "Script downloaded succesfully" 22 | success_helm_download=true 23 | break 24 | else 25 | echo "Error downloading. Retying..." 26 | retry_count=$((retry_count + 1)) 27 | sleep 5 28 | fi 29 | done 30 | if [ "$success_helm_download" = false ]; then 31 | echo "Max retries reached" 32 | exit 1 33 | fi 34 | chmod 700 get_helm.sh 35 | ./get_helm.sh "$@" 36 | 37 | rm -rf get_helm.sh 38 | set +x 39 | -------------------------------------------------------------------------------- /src/scripts/install_helm_plugin.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | HELM_STR_PLUGIN_URL="$(echo "${HELM_STR_PLUGIN_URL}" | circleci env subst)" 3 | 4 | STATUS="$(helm plugin install "${HELM_STR_PLUGIN_URL}")" 5 | 6 | if echo "${STATUS}" | grep "Installed plugin:"; then 7 | echo "Installation successful" 8 | exit 0 9 | else 10 | echo "Installation failed. Please check the Helm plugin URL" 11 | exit 1 12 | fi 13 | -------------------------------------------------------------------------------- /src/scripts/upgrade_helm_chart.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | HELM_STR_TIMEOUT="$(echo "${HELM_STR_TIMEOUT}" | circleci env subst)" 3 | HELM_STR_NAMESPACE="$(echo "${HELM_STR_NAMESPACE}" | circleci env subst)" 4 | HELM_STR_DEVEL="$(echo "${HELM_STR_DEVEL}" | circleci env subst)" 5 | HELM_STR_VALUES="$(echo "${HELM_STR_VALUES}" | circleci env subst)" 6 | HELM_STR_VERSION="$(echo "${HELM_STR_VERSION}" | circleci env subst)" 7 | HELM_STR_VALUES_TO_OVERRIDE="$(echo "${HELM_STR_VALUES_TO_OVERRIDE}" | circleci env subst)" 8 | HELM_STR_CHART="$(echo "${HELM_STR_CHART}" | circleci env subst)" 9 | HELM_STR_RELEASE_NAME="$(echo "${HELM_STR_RELEASE_NAME}" | circleci env subst)" 10 | HELM_STR_ADD_REPO="$(echo "${HELM_STR_ADD_REPO}" | circleci env subst)" 11 | 12 | set -x 13 | if [ -n "${HELM_STR_NAMESPACE}" ]; then 14 | if [ "${HELM_BOOL_CREATE_NAMESPACE}" -eq "1" ]; then 15 | set -- "$@" --create-namespace --namespace="${HELM_STR_NAMESPACE}" 16 | else 17 | set -- "$@" --namespace="${HELM_STR_NAMESPACE}" 18 | fi 19 | fi 20 | if [ -n "${HELM_STR_TIMEOUT}" ]; then 21 | set -- "$@" --timeout "${HELM_STR_TIMEOUT}" 22 | fi 23 | if [ "${HELM_BOOL_NO_HOOKS}" = "1" ]; then 24 | set -- "$@" --no-hooks 25 | fi 26 | if [ "${HELM_BOOL_RECREATE_PODS}" -eq 1 ]; then 27 | set -- "$@" --recreate-pods 28 | fi 29 | if [ "${HELM_BOOL_ATOMIC}" -eq 1 ]; then 30 | set -- "$@" --atomic 31 | fi 32 | if [ "${HELM_BOOL_WAIT}" -eq 1 ]; then 33 | set -- "$@" --wait 34 | fi 35 | if [ -n "${HELM_STR_DEVEL}" ]; then 36 | set -- "$@" --devel "${HELM_STR_DEVEL}" 37 | fi 38 | if [ "${HELM_BOOL_DRY_RUN}" -eq 1 ]; then 39 | set -- "$@" --dry-run 40 | fi 41 | if [ "${HELM_BOOL_RESET_VALUES}" -eq 1 ]; then 42 | set -- "$@" --reset-values 43 | fi 44 | if [ "${HELM_BOOL_REUSE_VALUES}" -eq 1 ]; then 45 | set -- "$@" --reuse-values 46 | fi 47 | if [ -n "${HELM_STR_VALUES}" ]; then 48 | set -- "$@" --values "${HELM_STR_VALUES}" 49 | fi 50 | if [ -n "${HELM_STR_VALUES_TO_OVERRIDE}" ]; then 51 | set -- "$@" --set "${HELM_STR_VALUES_TO_OVERRIDE}" 52 | fi 53 | if [ -n "${HELM_INT_HISTORY_MAX}" ]; then 54 | set -- "$@" --history-max "${HELM_INT_HISTORY_MAX}" 55 | fi 56 | if [ -n "${HELM_STR_VERSION}" ]; then 57 | set -- "$@" --version="${HELM_STR_VERSION}" 58 | fi 59 | if [ "${HELM_BOOL_WAIT_FOR_JOBS}" -eq 1 ]; then 60 | set -- "$@" --wait-for-jobs 61 | fi 62 | if [ "${HELM_BOOL_FORCE}" -eq 1 ]; then 63 | set -- "$@" --force 64 | fi 65 | if [ "${HELM_BOOL_DEBUG}" -eq 1 ]; then 66 | set -- "$@" --debug 67 | fi 68 | 69 | if [ -n "${HELM_STR_ADD_REPO}" ]; then 70 | helm repo add "${HELM_STR_RELEASE_NAME}" "${HELM_STR_ADD_REPO}" 71 | helm repo update 72 | fi 73 | 74 | helm upgrade --install "${HELM_STR_RELEASE_NAME}" "${HELM_STR_CHART}" "$@" 75 | set +x --------------------------------------------------------------------------------