diff --git a/README.md b/README.md index 04f55a3..592baee 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,71 @@ # Drone plugin for Helm 3 -Dissatisfied with this empty README? Consider grabbing [the "put stuff in the README" issue](https://github.com/pelotech/drone-helm3/issues/8)! +This plugin provides an interface between [Drone](https://drone.io/) and [Helm 3](https://github.com/kubernetes/helm): + +* Lint your charts +* Deploy your service +* Delete your service + +The plugin is inpsired by [drone-helm](https://github.com/ipedrazas/drone-helm), which fills the same role for Helm 2. It provides a comparable feature-set and the configuration settings are backwards-compatible. + +## Example configuration + +The examples below give a minimal and sufficient configuration for each use-case. For a full description of each command's settings, see [docs/parameter_reference.md](docs/parameter_reference.md). + +### Linting + +```yaml +steps: + - name: lint + image: pelotech/drone-helm3 + settings: + helm_command: lint + chart: ./ +``` + +### Installation + +```yaml +steps: + - name: deploy + image: pelotech/drone-helm3 + settings: + helm_command: upgrade + chart: ./ + release: my-project + environment: + API_SERVER: https://my.kubernetes.installation/clusters/a-1234 + KUBERNETES_TOKEN: + from_secret: kubernetes_token +``` + +### Uninstallation + +```yaml +steps: + - name: uninstall + image: pelotech/drone-helm3 + settings: + helm_command: uninstall + release: my-project + environment: + API_SERVER: https://my.kubernetes.installation/clusters/a-1234 + KUBERNETES_TOKEN: + from_secret: kubernetes_token +``` + +## Upgrading from drone-helm + +drone-helm3 is largely backwards-compatible with drone-helm. There are some known differences: + +* `prefix` must be supplied via the `settings` block, not `environment`. +* Several settings no longer have any effect: + * `purge` -- this is the default behavior in Helm 3 + * `recreate_pods` + * `tiller_ns` + * `upgrade` + * `canary_image` + * `client_only` + * `stable_repo_url` + +Since helm 3 does not require Tiller, we also recommend switching to a service account with less-expansive permissions. diff --git a/assets/kubeconfig.tpl b/assets/kubeconfig.tpl index c7b2025..92ec2c7 100644 --- a/assets/kubeconfig.tpl +++ b/assets/kubeconfig.tpl @@ -3,7 +3,7 @@ clusters: - cluster: {{- if eq .SkipTLSVerify true }} insecure-skip-tls-verify: true -{{- else }} +{{- else if .Certificate }} certificate-authority-data: {{ .Certificate }} {{- end}} server: {{ .APIServer }} diff --git a/docs/parameter_reference.md b/docs/parameter_reference.md new file mode 100644 index 0000000..07d8107 --- /dev/null +++ b/docs/parameter_reference.md @@ -0,0 +1,129 @@ +# Parameter reference + +## Global +| Param name | Type | Purpose | +|---------------------|-----------------|---------| +| helm_command | string | Indicates the operation to perform. Recommended, but not required. Valid options are `upgrade`, `uninstall`, `lint`, and `help`. | +| update_dependencies | boolean | Calls `helm dependency update` before running the main command. **Not currently implemented**; see [#25](https://github.com/pelotech/drone-helm3/issues/25).| +| helm_repos | list\ | Calls `helm repo add $repo` before running the main command. Each string should be formatted as `repo_name=https://repo.url/`. **Not currently implemented**; see [#26](https://github.com/pelotech/drone-helm3/issues/26). | +| namespace | string | Kubernetes namespace to use for this operation. | +| prefix | string | Expect environment variables to be prefixed with the given string. For more details, see "Using the prefix setting" below. **Not currently implemented**; see [#19](https://github.com/pelotech/drone-helm3/issues/19). | +| debug | boolean | Generate debug output within drone-helm3 and pass `--debug` to all helm commands. Use with care, since the debug output may include secrets. | + +## Linting + +Linting is only triggered when the `helm_command` setting is "lint". + +| Param name | Type | Required | Purpose | +|---------------|----------------|----------|---------| +| chart | string | yes | The chart to be linted. Must be a local path. | +| values | list\ | | Chart values to use as the `--set` argument to `helm lint`. | +| string_values | list\ | | Chart values to use as the `--set-string` argument to `helm lint`. | +| values_files | list\ | | Values to use as `--values` arguments to `helm lint`. | + +## Installation + +Installations are triggered when the `helm_command` setting is "upgrade." They can also be triggered when the build was triggered by a `push`, `tag`, `deployment`, `pull_request`, `promote`, or `rollback` Drone event. + +| Param name | Type | Required | Purpose | +|------------------------|----------------|----------|---------| +| chart | string | yes | The chart to use for this installation. | +| release | string | yes | The release name for helm to use. | +| api_server | string | yes | API endpoint for the Kubernetes cluster. | +| kubernetes_token | string | yes | Token for authenticating to Kubernetes. | +| service_account | string | | Service account for authenticating to Kubernetes. Default is `helm`. | +| kubernetes_certificate | string | | Base64 encoded TLS certificate used by the Kubernetes cluster's certificate authority. | +| chart_version | string | | Specific chart version to install. | +| dry_run | boolean | | Pass `--dry-run` to `helm upgrade`. | +| wait | boolean | | Wait until kubernetes resources are in a ready state before marking the installation successful. | +| timeout | duration | | Timeout for any *individual* Kubernetes operation. The installation's full runtime may exceed this duration. | +| force | boolean | | Pass `--force` to `helm upgrade`. | +| values | list\ | | Chart values to use as the `--set` argument to `helm upgrade`. | +| string_values | list\ | | Chart values to use as the `--set-string` argument to `helm upgrade`. | +| values_files | list\ | | Values to use as `--values` arguments to `helm upgrade`. | +| reuse_values | boolean | | Reuse the values from a previous release. | +| skip_tls_verify | boolean | | Connect to the Kubernetes cluster without checking for a valid TLS certificate. Not recommended in production. | + +## Uninstallation + +Uninstallations are triggered when the `helm_command` setting is "uninstall" or "delete." They can also be triggered when the build was triggered by a `delete` Drone event. + +| Param name | Type | Required | Purpose | +|------------------------|----------|----------|---------| +| release | string | yes | The release name for helm to use. | +| api_server | string | yes | API endpoint for the Kubernetes cluster. | +| kubernetes_token | string | yes | Token for authenticating to Kubernetes. | +| service_account | string | | Service account for authenticating to Kubernetes. Default is `helm`. | +| kubernetes_certificate | string | | Base64 encoded TLS certificate used by the Kubernetes cluster's certificate authority. | +| dry_run | boolean | | Pass `--dry-run` to `helm uninstall`. | +| timeout | duration | | Timeout for any *individual* Kubernetes operation. The uninstallation's full runtime may exceed this duration. | +| skip_tls_verify | boolean | | Connect to the Kubernetes cluster without checking for a valid TLS certificate. Not recommended in production. | + +### Where to put settings + +Any setting (with the exception of `prefix`; [see below](#user-content-using-the-prefix-setting)), can go in either the `settings` or `environment` section. + +### Formatting non-string values + +* Booleans can be yaml's `true` and `false` literals or the strings `"true"` and `"false"`. +* Durations are strings formatted with the syntax accepted by [golang's ParseDuration function](https://golang.org/pkg/time/#ParseDuration) (e.g. 5m30s) +* List\s can be a yaml sequence or a comma-separated string. + +All of the following are equivalent: + +```yaml +values: "foo=1,bar=2" +values: ["foo=1", "bar=2"] +values: + - foo=1 + - bar=2 +``` + +Note that **list members must not contain commas**. Both of the following are equivalent: + +```yaml +values_files: [ "./over_9,000.yml" ] +values_files: [ "./over_9", "000.yml" ] +``` + +### Using the `prefix` setting + +Because the prefix setting is meta-configuration, it has some inherent edge-cases. Here is what it does in the cases we've thought of: + +Unlike the other settings, it must be declared in the `settings` block, not `environment`: + +```yaml +settings: + prefix: helm # drone-helm3 will look for environment variables called HELM_VARNAME +environment: + prefix: armet # no effect +``` + +It does not apply to configuration in the `settings` block, only in `environment`: + +```yaml +settings: + prefix: helm + helm_timeout: 5m # no effect +environment: + helm_timeout: 2m # timeout will be 2 minutes +``` + +If the environment contains a variable in non-prefixed form, it will still be applied: + +```yaml +settings: + prefix: helm +environment: + timeout: 2m # timeout will be 2 minutes +``` + +If the environment contains both the prefixed and non-prefixed forms, drone-helm3 will use the prefixed form: + +```yaml +settings: + prefix: helm +environment: + timeout: 5m # overridden + helm_timeout: 2m # timeout will be 2 minutes +``` diff --git a/internal/helm/plan.go b/internal/helm/plan.go index 1d4ced9..ffa3e52 100644 --- a/internal/helm/plan.go +++ b/internal/helm/plan.go @@ -67,6 +67,7 @@ func determineSteps(cfg Config) *func(Config) []Step { return &help default: switch cfg.DroneEvent { + // Note: These events are documented in docs/upgrade_settings.yml. Any changes here should be reflected there. case "push", "tag", "deployment", "pull_request", "promote", "rollback": return &upgrade case "delete": diff --git a/internal/run/initkube.go b/internal/run/initkube.go index 4af29af..a341dca 100644 --- a/internal/run/initkube.go +++ b/internal/run/initkube.go @@ -50,9 +50,6 @@ func (i *InitKube) Prepare(cfg Config) error { if i.Token == "" { return errors.New("token is needed to deploy") } - if i.Certificate == "" && !i.SkipTLSVerify { - return errors.New("certificate is needed to deploy") - } if i.ServiceAccount == "" { i.ServiceAccount = "helm" diff --git a/internal/run/initkube_test.go b/internal/run/initkube_test.go index 1d9d81f..479bf56 100644 --- a/internal/run/initkube_test.go +++ b/internal/run/initkube_test.go @@ -187,13 +187,6 @@ func (suite *InitKubeTestSuite) TestPrepareRequiredConfig() { init.APIServer = "Sysadmin" init.Token = "" suite.Error(init.Prepare(cfg), "Token should be required.") - - init.Token = "Aspire virtual currency" - init.Certificate = "" - suite.Error(init.Prepare(cfg), "Certificate should be required.") - - init.SkipTLSVerify = true - suite.NoError(init.Prepare(cfg), "Certificate should not be required if SkipTLSVerify is true") } func (suite *InitKubeTestSuite) TestPrepareDefaultsServiceAccount() { diff --git a/internal/run/lint.go b/internal/run/lint.go index e2843ca..1993b49 100644 --- a/internal/run/lint.go +++ b/internal/run/lint.go @@ -16,6 +16,8 @@ func (l *Lint) Execute(_ Config) error { } // Prepare gets the Lint ready to execute. +// Note: mandatory settings are documented in README.md, and the full list of settings is in docs/lint_settings.yml. +// Any additions or deletions here should be reflected there. func (l *Lint) Prepare(cfg Config) error { if l.Chart == "" { return fmt.Errorf("chart is required") diff --git a/internal/run/upgrade.go b/internal/run/upgrade.go index cff2c70..9f57e05 100644 --- a/internal/run/upgrade.go +++ b/internal/run/upgrade.go @@ -25,6 +25,8 @@ func (u *Upgrade) Execute(_ Config) error { } // Prepare gets the Upgrade ready to execute. +// Note: mandatory settings are documented in README.md, and the full list of settings is in docs/upgrade_settings.yml. +// Any additions or deletions here should be reflected there. func (u *Upgrade) Prepare(cfg Config) error { if u.Chart == "" { return fmt.Errorf("chart is required")