56 Commits

Author SHA1 Message Date
c017a87c4c Update Dockerfile
All checks were successful
continuous-integration/drone/push Build is passing
2025-08-23 18:53:35 +03:00
f21e5bede0 Update Dockerfile
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/promote/production Build was killed
2025-08-23 18:50:38 +03:00
4896617402 Update .drone.yml
Some checks failed
continuous-integration/drone/push Build is failing
2025-08-23 18:49:56 +03:00
5b9ebfb2d8 Update Dockerfile
Some checks failed
continuous-integration/drone/push Build is failing
2025-08-23 18:49:21 +03:00
628f9d3ef6 upd
All checks were successful
continuous-integration/drone/push Build is passing
2025-06-26 21:20:53 +03:00
5a95211c2f Update Dockerfile
All checks were successful
continuous-integration/drone/push Build is passing
2025-06-26 21:18:22 +03:00
b926404924 3.17
All checks were successful
continuous-integration/drone/push Build is passing
2025-04-09 16:02:07 +03:00
53104347c2 Update Dockerfile
All checks were successful
continuous-integration/drone/push Build is passing
2024-12-23 18:36:49 +03:00
123c331889 Update Dockerfile
All checks were successful
continuous-integration/drone/push Build is passing
2024-12-23 18:35:02 +03:00
9ce383cf2c upd
All checks were successful
continuous-integration/drone/push Build is passing
2024-11-21 20:54:41 +03:00
06bf1b863c Update Dockerfile
All checks were successful
continuous-integration/drone/push Build is passing
2024-02-20 19:50:00 +03:00
e656306216 Update Dockerfile
Some checks failed
continuous-integration/drone/push Build is failing
2024-02-20 19:48:58 +03:00
82ed33b180 Update .drone.yml
All checks were successful
continuous-integration/drone/push Build is passing
2024-02-20 19:46:38 +03:00
e4a1fa89fa Update .drone.yml
Some checks failed
continuous-integration/drone/push Build is failing
2024-02-20 19:43:22 +03:00
66e8afd9a4 Update .drone.yml
Some checks failed
continuous-integration/drone/push Build encountered an error
2024-02-20 19:40:31 +03:00
b1e18abf75 Update .drone.yml
Some checks failed
continuous-integration/drone/push Build encountered an error
2024-02-20 19:39:28 +03:00
5a725fd5c6 Update .drone.yml 2024-02-20 19:39:18 +03:00
cda07939db new helm 2024-02-20 19:37:18 +03:00
Joachim Hill-Grannec
7533ed95ad update for CGO 2022-08-23 10:11:21 -06:00
Joachim Hill-Grannec
98bb4e4ba4 explicitly target linux amd64 2022-08-23 09:31:37 -06:00
Joachim Hill-Grannec
e07eb1399b Merge pull request #112 from navi86/fix-folder-issue
fix issue
2022-08-23 08:07:59 -06:00
Ivan Krylov
9a9987eeb2 fix issue 2022-08-23 12:41:12 +01:00
Joachim Hill-Grannec
fed0a769f2 Update container maintainer 2022-08-22 09:58:59 -06:00
Joachim Hill-Grannec
48473bd9d8 Merge pull request #110 from mongodb-forks/contribute_historymax
Add `history_max` setting
2022-08-22 09:54:03 -06:00
Colin Hoglund
64045fadfb add comment 2022-08-16 11:44:57 -07:00
Colin Hoglund
c5a7551da8 unexport 2022-08-16 11:43:37 -07:00
Colin Hoglund
eeccfdd143 fix test 2022-08-16 11:42:02 -07:00
Colin Hoglund
8d450bbf7d DEVOPS-2496 add max history setting (#12)
* add history_max setting

* update docs

* use suite for env test
2022-08-16 11:37:13 -07:00
Joachim Hill-Grannec
a566ea0cf7 Merge pull request #108 from hobbypunk90/master
Update to helm 3.8.1
2022-07-08 00:48:40 -06:00
Marcel Hoppe
24f10ce1b9 Update to helm 3.8.1 2022-04-04 11:51:54 +02:00
Joachim Hill-Grannec
7c033a8b0a Merge pull request #104 from georgekaz/add-skip-crds
add skip-crds flag support
2021-07-21 08:10:35 -06:00
George Kaz
e482a144c1 add skip-crds flag support
Signed-off-by: George Kaz <egeorgekaz@gmail.com>
2021-07-20 19:26:00 +01:00
Joachim Hill-Grannec
8dba329407 Merge pull request #101 from jeessy2/master
fix: Add a new parameter "create_namespace"
2020-08-28 12:09:17 -07:00
Joachim Hill-Grannec
4462307983 Merge branch 'master' into master 2020-08-26 10:15:24 -07:00
Erin Call
cfc59a46ef Merge pull request #102 from minhdanh/skip-kube-init
Support skipping kubeconfig creation
2020-08-25 22:20:05 -07:00
minhdanh
5b4e3ab2ea Rename kube_init_skip to skip_kubeconfig 2020-08-25 09:59:06 +07:00
minhdanh
0e58dde591 Support skipping kubeconfig creation 2020-08-24 13:03:36 +07:00
jie
1809d7b133 upgrade helm to 3.2.4, kubernetes needs 1.8+ 2020-08-19 13:36:30 +08:00
jie
70b2a2d0b4 Add a parameter "create_namespace" 2020-08-19 11:11:11 +08:00
Joachim Hill-Grannec
03b066bfd7 Merge pull request #94 from pelotech/no-binary
Remove the built binary
2020-05-22 17:24:15 -07:00
Erin Call
fe0c874815 Merge branch 'master' into no-binary 2020-05-22 17:17:18 -07:00
Erin Call
91d4506b37 Ignore build/* [#93]
I definitely thought this rule was already in effect--I had a
`build/.gitignore` that contained just `*`. Unfortunately, that makes
git ignore the .gitignore file itself, so it was never added to the
repo...
2020-05-22 17:15:24 -07:00
Joachim Hill-Grannec
0ab0a7fee4 Merge pull request #96 from pelotech/explain-setting-aliases
Document the purpose of settingAliases
2020-05-22 17:04:28 -07:00
Erin Call
0b17d929a7 Document the purpose of settingAliases [#95] 2020-05-22 15:35:43 -07:00
Erin Call
3fea592040 Remove the built binary [#93]
It was never supposed to be part of the repo, and currently accounts for
at least half of the .git directory's size. We need to nip it in the bud
before `git clone` times become unmanageable!
2020-05-22 14:43:33 -07:00
Joachim Hill-Grannec
d7a9eccb13 Merge pull request #86 from obukhov/add-dependecies-action
Add dependecies action
2020-04-07 14:06:48 -06:00
Alex Obukhov
9e3a424a36 Add configuration option to docs 2020-04-05 14:30:44 +02:00
Alex Obukhov
774bbb74db Add dependencies_action configuration option 2020-04-05 14:22:46 +02:00
Joachim Hill-Grannec
e0157d9bc2 Merge pull request #84 from BnMcG/noissue-repos-environment-interpolation
Allow environment variable interpolation in Helm repository configuration
2020-03-31 22:29:47 -06:00
Ben Magee
1f2da68bbb Remove built binary 2020-03-31 23:39:02 +01:00
Ben Magee
7e2f982af7 Update docs 2020-03-31 23:33:54 +01:00
Ben Magee
0502d76c63 Interpolate environment variables in the AddRepos configuration parameter 2020-03-31 23:07:28 +01:00
Joachim Hill-Grannec
591b084970 upgrading image to helm 3.1.1 2020-03-06 13:25:35 -06:00
Erin Call
f24a8e44ca Merge pull request #79 from pelotech/versions-in-bugs
Ask for version information in the bug template
2020-01-22 11:24:10 -08:00
Erin Call
8cb8a5d95d Merge branch 'master' into versions-in-bugs 2020-01-22 11:21:37 -08:00
Erin Call
8b6a8fdd4b Ask for version information in the bug template [#78] 2020-01-22 10:06:57 -08:00
16 changed files with 482 additions and 135 deletions

View File

@@ -1,32 +1,36 @@
---
kind: pipeline kind: pipeline
type: docker type: kubernetes
name: default name: build
trigger:
branch:
- master
clone:
# disable: true
depth: 1
image_pull_secrets:
- dockerconfig
steps: steps:
- name: test
image: golang:1.13
commands:
- go test ./cmd/... ./internal/...
- go vet ./cmd/... ./internal/...
- name: lint
image: cytopia/golint
commands:
- golint -set_exit_status ./cmd/... ./internal/...
- name: build
image: golang:1.13
commands:
- go build -o build/drone-helm cmd/drone-helm/main.go
- name: publish_linux_amd64 - name: publish_linux_amd64
image: plugins/docker image: harbor.1sept.ru/drone/drone-kaniko
settings: settings:
auto_tag: true registry: harbor.1sept.ru
username: repo: drone/drone-helm3
from_secret: docker_username cache: false
password: tags:
from_secret: docker_password - git-${DRONE_COMMIT_SHA:0:7}
repo: - latest
from_secret: plugin_repo username:
dockerfile: Dockerfile from_secret: harbor-username
when: password:
event: [ tag, push ] from_secret: harbor-password
---
kind: signature
hmac: ab275b41f1621072152d6e85b5f94289be8dda38debd2a177e0f666960491c6e
...

View File

@@ -7,6 +7,9 @@ assignees: ''
--- ---
**My drone-helm3 and drone versions:**
<!-- e.g. drone-helm3 0.9.0, drone 1.6.0-->
**What I tried to do:** **What I tried to do:**
<!-- e.g. run a helm installation --> <!-- e.g. run a helm installation -->

4
.gitignore vendored
View File

@@ -4,6 +4,7 @@
*.dll *.dll
*.so *.so
*.dylib *.dylib
*.swp
.idea .idea
@@ -17,3 +18,6 @@
# vendor/ # vendor/
.env .env
.secrets .secrets
build/*
**/.DS_Store

View File

@@ -1,10 +1,19 @@
FROM alpine/helm:3.0.2 FROM golang:1.24-alpine3.21 AS builder
MAINTAINER Erin Call <erin@liffft.com>
COPY build/drone-helm /bin/drone-helm ENV GO111MODULE=on
COPY assets/kubeconfig.tpl /root/.kube/config.tpl WORKDIR /app
LABEL description="Helm 3 plugin for Drone 3" COPY --link go.mod .
LABEL base="alpine/helm" COPY --link go.sum .
RUN go mod download
COPY --link . .
ENTRYPOINT [ "/bin/drone-helm" ] RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /go/bin/drone-helm ./cmd/drone-helm
# --- Copy the cli to an image with helm already installed ---
FROM alpine/helm:3.18.5
COPY --link --from=builder /go/bin/drone-helm /bin/drone-helm
COPY --link ./assets/kubeconfig.tpl /root/.kube/config.tpl
ENTRYPOINT [ "/bin/drone-helm" ]

9
Makefile Normal file
View File

@@ -0,0 +1,9 @@
help:
@echo "make check - Check Dockerfile syntax"
@echo "make drone-sign - Sign Drone config file"
check:
docker build --check .
drone-sign: ## Envs DRONE_SERVER & DRONE_TOKEN needed
drone sign --save 1sept/drone-helm3

View File

@@ -31,22 +31,27 @@ Installations are triggered when the `mode` setting is "upgrade." They can also
|------------------------|----------------|----------|------------------------|---------| |------------------------|----------------|----------|------------------------|---------|
| chart | string | yes | | The chart to use for this installation. | | chart | string | yes | | The chart to use for this installation. |
| release | string | yes | | The release name for helm to use. | | release | string | yes | | The release name for helm to use. |
| kube_api_server | string | yes | api_server | API endpoint for the Kubernetes cluster. | | skip_kubeconfig | boolean | | | Whether to skip kubeconfig file creation. |
| kube_token | string | yes | kubernetes_token | Token for authenticating to Kubernetes. | | kube_api_server | string | yes | api_server | API endpoint for the Kubernetes cluster. This is ignored if `skip_kubeconfig` is `true`. |
| kube_service_account | string | | service_account | Service account for authenticating to Kubernetes. Default is `helm`. | | kube_token | string | yes | kubernetes_token | Token for authenticating to Kubernetes. This is ignored if `skip_kubeconfig` is `true`. |
| kube_certificate | string | | kubernetes_certificate | Base64 encoded TLS certificate used by the Kubernetes cluster's certificate authority. | | kube_service_account | string | | service_account | Service account for authenticating to Kubernetes. Default is `helm`. This is ignored if `skip_kubeconfig` is `true`. |
| kube_certificate | string | | kubernetes_certificate | Base64 encoded TLS certificate used by the Kubernetes cluster's certificate authority. This is ignored if `skip_kubeconfig` is `true`. |
| chart_version | string | | | Specific chart version to install. | | chart_version | string | | | Specific chart version to install. |
| dry_run | boolean | | | Pass `--dry-run` to `helm upgrade`. | | dry_run | boolean | | | Pass `--dry-run` to `helm upgrade`. |
| dependencies_action | string | | | Calls `helm dependency build` OR `helm dependency update` before running the main command. Possible values: `build`, `update`. |
| wait_for_upgrade | boolean | | wait | Wait until kubernetes resources are in a ready state before marking the installation successful. | | wait_for_upgrade | boolean | | wait | 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. | | timeout | duration | | | Timeout for any *individual* Kubernetes operation. The installation's full runtime may exceed this duration. |
| force_upgrade | boolean | | force | Pass `--force` to `helm upgrade`. | | force_upgrade | boolean | | force | Pass `--force` to `helm upgrade`. |
| atomic_upgrade | boolean | | | Pass `--atomic` to `helm upgrade`. | | atomic_upgrade | boolean | | | Pass `--atomic` to `helm upgrade`. |
| cleanup_failed_upgrade | boolean | | | Pass `--cleanup-on-fail` to `helm upgrade`. | | cleanup_failed_upgrade | boolean | | | Pass `--cleanup-on-fail` to `helm upgrade`. |
| history_max | int | | | Pass `--history-max` to `helm upgrade`. |
| values | list\<string\> | | | Chart values to use as the `--set` argument to `helm upgrade`. | | values | list\<string\> | | | Chart values to use as the `--set` argument to `helm upgrade`. |
| string_values | list\<string\> | | | Chart values to use as the `--set-string` argument to `helm upgrade`. | | string_values | list\<string\> | | | Chart values to use as the `--set-string` argument to `helm upgrade`. |
| values_files | list\<string\> | | | Values to use as `--values` arguments to `helm upgrade`. | | values_files | list\<string\> | | | Values to use as `--values` arguments to `helm upgrade`. |
| reuse_values | boolean | | | Reuse the values from a previous release. | | 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. | | skip_tls_verify | boolean | | | Connect to the Kubernetes cluster without checking for a valid TLS certificate. Not recommended in production. This is ignored if `skip_kubeconfig` is `true`. |
| create_namespace | boolean | | | Pass --create-namespace to `helm upgrade`. |
| skip_crds | boolean | | | Pass --skip-crds to `helm upgrade`. |
## Uninstallation ## Uninstallation
@@ -55,14 +60,15 @@ Uninstallations are triggered when the `mode` setting is "uninstall" or "delete.
| Param name | Type | Required | Alias | Purpose | | Param name | Type | Required | Alias | Purpose |
|------------------------|----------|----------|------------------------|---------| |------------------------|----------|----------|------------------------|---------|
| release | string | yes | | The release name for helm to use. | | release | string | yes | | The release name for helm to use. |
| kube_api_server | string | yes | api_server | API endpoint for the Kubernetes cluster. | | skip_kubeconfig | boolean | | | Whether to skip kubeconfig file creation. |
| kube_token | string | yes | kubernetes_token | Token for authenticating to Kubernetes. | | kube_api_server | string | yes | api_server | API endpoint for the Kubernetes cluster. This is ignored if `skip_kubeconfig` is `true`. |
| kube_service_account | string | | service_account | Service account for authenticating to Kubernetes. Default is `helm`. | | kube_token | string | yes | kubernetes_token | Token for authenticating to Kubernetes. This is ignored if `skip_kubeconfig` is `true`. |
| kube_certificate | string | | kubernetes_certificate | Base64 encoded TLS certificate used by the Kubernetes cluster's certificate authority. | | kube_service_account | string | | service_account | Service account for authenticating to Kubernetes. Default is `helm`. This is ignored if `skip_kubeconfig` is `true`. |
| kube_certificate | string | | kubernetes_certificate | Base64 encoded TLS certificate used by the Kubernetes cluster's certificate authority. This is ignored if `skip_kubeconfig` is `true`. |
| keep_history | boolean | | | Pass `--keep-history` to `helm uninstall`, to retain the release history. | | keep_history | boolean | | | Pass `--keep-history` to `helm uninstall`, to retain the release history. |
| dry_run | boolean | | | Pass `--dry-run` to `helm uninstall`. | | 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. | | 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. | | skip_tls_verify | boolean | | | Connect to the Kubernetes cluster without checking for a valid TLS certificate. Not recommended in production. This is ignored if `skip_kubeconfig` is `true`. |
| chart | string | | | Required when the global `update_dependencies` parameter is true. No effect otherwise. | | chart | string | | | Required when the global `update_dependencies` parameter is true. No effect otherwise. |
### Where to put settings ### Where to put settings
@@ -95,7 +101,7 @@ values_files: [ "./over_9,000.yml" ]
values_files: [ "./over_9", "000.yml" ] values_files: [ "./over_9", "000.yml" ]
``` ```
### Interpolating secrets into the `values` and `string_values` settings ### Interpolating secrets into the `values`, `string_values` and `add_repos` settings
If you want to send secrets to your charts, you can use syntax similar to shell variable interpolation--either `$VARNAME` or `$${VARNAME}`. The double dollar-sign is necessary when using curly brackets; using curly brackets with a single dollar-sign will trigger Drone's string substitution (which can't use arbitrary environment variables). If an environment variable is not set, it will be treated as if it were set to the empty string. If you want to send secrets to your charts, you can use syntax similar to shell variable interpolation--either `$VARNAME` or `$${VARNAME}`. The double dollar-sign is necessary when using curly brackets; using curly brackets with a single dollar-sign will trigger Drone's string substitution (which can't use arbitrary environment variables). If an environment variable is not set, it will be treated as if it were set to the empty string.

View File

@@ -2,11 +2,16 @@ package env
import ( import (
"fmt" "fmt"
"github.com/kelseyhightower/envconfig"
"io" "io"
"os" "os"
"regexp" "regexp"
"strings" "strings"
"github.com/kelseyhightower/envconfig"
)
const (
defaultHistoryMax = 10
) )
var ( var (
@@ -22,7 +27,8 @@ type Config struct {
// Configuration for drone-helm itself // Configuration for drone-helm itself
Command string `envconfig:"mode"` // Helm command to run Command string `envconfig:"mode"` // Helm command to run
DroneEvent string `envconfig:"drone_build_event"` // Drone event that invoked this plugin. DroneEvent string `envconfig:"drone_build_event"` // Drone event that invoked this plugin.
UpdateDependencies bool `split_words:"true"` // Call `helm dependency update` before the main command UpdateDependencies bool `split_words:"true"` // [Deprecated] Call `helm dependency update` before the main command (deprecated, use dependencies_action: update instead)
DependenciesAction string `split_words:"true"` // Call `helm dependency build` or `helm dependency update` before the main command
AddRepos []string `split_words:"true"` // Call `helm repo add` before the main command AddRepos []string `split_words:"true"` // Call `helm repo add` before the main command
RepoCertificate string `envconfig:"repo_certificate"` // The Helm chart repository's self-signed certificate (must be base64-encoded) RepoCertificate string `envconfig:"repo_certificate"` // The Helm chart repository's self-signed certificate (must be base64-encoded)
RepoCACertificate string `envconfig:"repo_ca_certificate"` // The Helm chart repository CA's self-signed certificate (must be base64-encoded) RepoCACertificate string `envconfig:"repo_ca_certificate"` // The Helm chart repository CA's self-signed certificate (must be base64-encoded)
@@ -31,7 +37,9 @@ type Config struct {
StringValues string `split_words:"true"` // Argument to pass to --set-string in applicable helm commands StringValues string `split_words:"true"` // Argument to pass to --set-string in applicable helm commands
ValuesFiles []string `split_words:"true"` // Arguments to pass to --values in applicable helm commands ValuesFiles []string `split_words:"true"` // Arguments to pass to --values in applicable helm commands
Namespace string `` // Kubernetes namespace for all helm commands Namespace string `` // Kubernetes namespace for all helm commands
CreateNamespace bool `split_words:"true"` // Pass --create-namespace to `helm upgrade`
KubeToken string `split_words:"true"` // Kubernetes authentication token to put in .kube/config KubeToken string `split_words:"true"` // Kubernetes authentication token to put in .kube/config
SkipKubeconfig bool `envconfig:"skip_kubeconfig"` // Skip kubeconfig creation
SkipTLSVerify bool `envconfig:"skip_tls_verify"` // Put insecure-skip-tls-verify in .kube/config SkipTLSVerify bool `envconfig:"skip_tls_verify"` // Put insecure-skip-tls-verify in .kube/config
Certificate string `envconfig:"kube_certificate"` // The Kubernetes cluster CA's self-signed certificate (must be base64-encoded) Certificate string `envconfig:"kube_certificate"` // The Kubernetes cluster CA's self-signed certificate (must be base64-encoded)
APIServer string `envconfig:"kube_api_server"` // The Kubernetes cluster's API endpoint APIServer string `envconfig:"kube_api_server"` // The Kubernetes cluster's API endpoint
@@ -41,6 +49,7 @@ type Config struct {
Wait bool `envconfig:"wait_for_upgrade"` // Pass --wait to applicable helm commands Wait bool `envconfig:"wait_for_upgrade"` // Pass --wait to applicable helm commands
ReuseValues bool `split_words:"true"` // Pass --reuse-values to `helm upgrade` ReuseValues bool `split_words:"true"` // Pass --reuse-values to `helm upgrade`
KeepHistory bool `split_words:"true"` // Pass --keep-history to `helm uninstall` KeepHistory bool `split_words:"true"` // Pass --keep-history to `helm uninstall`
HistoryMax int `split_words:"true"` // Pass --history-max option
Timeout string `` // Argument to pass to --timeout in applicable helm commands Timeout string `` // Argument to pass to --timeout in applicable helm commands
Chart string `` // Chart argument to use in applicable helm commands Chart string `` // Chart argument to use in applicable helm commands
Release string `` // Release argument to use in applicable helm commands Release string `` // Release argument to use in applicable helm commands
@@ -48,6 +57,7 @@ type Config struct {
AtomicUpgrade bool `split_words:"true"` // Pass --atomic to `helm upgrade` AtomicUpgrade bool `split_words:"true"` // Pass --atomic to `helm upgrade`
CleanupOnFail bool `envconfig:"cleanup_failed_upgrade"` // Pass --cleanup-on-fail to `helm upgrade` CleanupOnFail bool `envconfig:"cleanup_failed_upgrade"` // Pass --cleanup-on-fail to `helm upgrade`
LintStrictly bool `split_words:"true"` // Pass --strict to `helm lint` LintStrictly bool `split_words:"true"` // Pass --strict to `helm lint`
SkipCrds bool `split_words:"true"` // Pass --skip-crds to `helm upgrade`
Stdout io.Writer `ignored:"true"` Stdout io.Writer `ignored:"true"`
Stderr io.Writer `ignored:"true"` Stderr io.Writer `ignored:"true"`
@@ -74,6 +84,9 @@ func NewConfig(stdout, stderr io.Writer) (*Config, error) {
KubeToken: aliases.KubeToken, KubeToken: aliases.KubeToken,
Certificate: aliases.Certificate, Certificate: aliases.Certificate,
// set to same default as helm CLI
HistoryMax: defaultHistoryMax,
Stdout: stdout, Stdout: stdout,
Stderr: stderr, Stderr: stderr,
} }
@@ -85,6 +98,12 @@ func NewConfig(stdout, stderr io.Writer) (*Config, error) {
return nil, err return nil, err
} }
if cfg.SkipKubeconfig {
if cfg.KubeToken != "" || cfg.Certificate != "" || cfg.APIServer != "" || cfg.ServiceAccount != "" || cfg.SkipTLSVerify {
fmt.Fprintf(cfg.Stderr, "Warning: skip_kubeconfig is set. The following kubeconfig-related settings will be ignored: kube_config, kube_certificate, kube_api_server, kube_service_account, skip_tls_verify.")
}
}
if justNumbers.MatchString(cfg.Timeout) { if justNumbers.MatchString(cfg.Timeout) {
cfg.Timeout = fmt.Sprintf("%ss", cfg.Timeout) cfg.Timeout = fmt.Sprintf("%ss", cfg.Timeout)
} }
@@ -119,6 +138,10 @@ func (cfg *Config) loadValuesSecrets() {
cfg.Values = findVar.ReplaceAllStringFunc(cfg.Values, replacer) cfg.Values = findVar.ReplaceAllStringFunc(cfg.Values, replacer)
cfg.StringValues = findVar.ReplaceAllStringFunc(cfg.StringValues, replacer) cfg.StringValues = findVar.ReplaceAllStringFunc(cfg.StringValues, replacer)
for i := 0; i < len(cfg.AddRepos); i++ {
cfg.AddRepos[i] = findVar.ReplaceAllStringFunc(cfg.AddRepos[i], replacer)
}
} }
func (cfg Config) logDebug() { func (cfg Config) logDebug() {
@@ -138,6 +161,10 @@ func (cfg *Config) deprecationWarn() {
} }
} }
// settingAliases provides alternate environment variable names for certain settings, either because
// they were renamed during drone-helm3's lifetime or for backward-compatibility with the original
// drone-helm. Most config options don't need to be included here; adding them to the main Config
// struct is sufficient.
type settingAliases struct { type settingAliases struct {
Command string `envconfig:"helm_command"` Command string `envconfig:"helm_command"`
AddRepos []string `envconfig:"helm_repos"` AddRepos []string `envconfig:"helm_repos"`

View File

@@ -2,10 +2,11 @@ package env
import ( import (
"fmt" "fmt"
"github.com/stretchr/testify/suite"
"os" "os"
"strings" "strings"
"testing" "testing"
"github.com/stretchr/testify/suite"
) )
type ConfigTestSuite struct { type ConfigTestSuite struct {
@@ -191,12 +192,14 @@ func (suite *ConfigTestSuite) TestNewConfigWithValuesSecrets() {
suite.setenv("SECRET_RINGS", "1") suite.setenv("SECRET_RINGS", "1")
suite.setenv("PLUGIN_VALUES", "fire=$SECRET_FIRE,water=${SECRET_WATER}") suite.setenv("PLUGIN_VALUES", "fire=$SECRET_FIRE,water=${SECRET_WATER}")
suite.setenv("PLUGIN_STRING_VALUES", "rings=${SECRET_RINGS}") suite.setenv("PLUGIN_STRING_VALUES", "rings=${SECRET_RINGS}")
suite.setenv("PLUGIN_ADD_REPOS", "testrepo=https://user:${SECRET_FIRE}@testrepo.test")
cfg, err := NewConfig(&strings.Builder{}, &strings.Builder{}) cfg, err := NewConfig(&strings.Builder{}, &strings.Builder{})
suite.Require().NoError(err) suite.Require().NoError(err)
suite.Equal("fire=Eru_Ilúvatar,water=", cfg.Values) suite.Equal("fire=Eru_Ilúvatar,water=", cfg.Values)
suite.Equal("rings=1", cfg.StringValues) suite.Equal("rings=1", cfg.StringValues)
suite.Equal(fmt.Sprintf("testrepo=https://user:%s@testrepo.test", os.Getenv("SECRET_FIRE")), cfg.AddRepos[0])
} }
func (suite *ConfigTestSuite) TestValuesSecretsWithDebugLogging() { func (suite *ConfigTestSuite) TestValuesSecretsWithDebugLogging() {
@@ -214,6 +217,15 @@ func (suite *ConfigTestSuite) TestValuesSecretsWithDebugLogging() {
suite.Contains(stderr.String(), `$SECRET_WATER not present in environment, replaced with ""`) suite.Contains(stderr.String(), `$SECRET_WATER not present in environment, replaced with ""`)
} }
func (suite *ConfigTestSuite) TestHistoryMax() {
conf := NewTestConfig(suite.T())
suite.Assert().Equal(10, conf.HistoryMax)
suite.setenv("PLUGIN_HISTORY_MAX", "0")
conf = NewTestConfig(suite.T())
suite.Assert().Equal(0, conf.HistoryMax)
}
func (suite *ConfigTestSuite) setenv(key, val string) { func (suite *ConfigTestSuite) setenv(key, val string) {
orig, ok := os.LookupEnv(key) orig, ok := os.LookupEnv(key)
if ok { if ok {

16
internal/env/testing.go vendored Normal file
View File

@@ -0,0 +1,16 @@
package env
import (
"os"
"testing"
"github.com/stretchr/testify/require"
)
// NewTestConfig is a helper for setting up a Config object and error checking
func NewTestConfig(t *testing.T) *Config {
conf, err := NewConfig(os.Stdout, os.Stderr)
require.NoError(t, err)
return conf
}

View File

@@ -1,6 +1,7 @@
package helm package helm
import ( import (
"errors"
"fmt" "fmt"
"github.com/pelotech/drone-helm3/internal/env" "github.com/pelotech/drone-helm3/internal/env"
"github.com/pelotech/drone-helm3/internal/run" "github.com/pelotech/drone-helm3/internal/run"
@@ -30,6 +31,10 @@ func NewPlan(cfg env.Config) (*Plan, error) {
cfg: cfg, cfg: cfg,
} }
if cfg.UpdateDependencies && cfg.DependenciesAction != "" {
return nil, errors.New("update_dependencies is deprecated and cannot be provided together with dependencies_action")
}
p.steps = (*determineSteps(cfg))(cfg) p.steps = (*determineSteps(cfg))(cfg)
for i, step := range p.steps { for i, step := range p.steps {
@@ -87,13 +92,21 @@ func (p *Plan) Execute() error {
var upgrade = func(cfg env.Config) []Step { var upgrade = func(cfg env.Config) []Step {
var steps []Step var steps []Step
steps = append(steps, run.NewInitKube(cfg, kubeConfigTemplate, kubeConfigFile)) if !cfg.SkipKubeconfig {
steps = append(steps, run.NewInitKube(cfg, kubeConfigTemplate, kubeConfigFile))
}
for _, repo := range cfg.AddRepos { for _, repo := range cfg.AddRepos {
steps = append(steps, run.NewAddRepo(cfg, repo)) steps = append(steps, run.NewAddRepo(cfg, repo))
} }
if cfg.DependenciesAction != "" {
steps = append(steps, run.NewDepAction(cfg))
}
if cfg.UpdateDependencies { if cfg.UpdateDependencies {
steps = append(steps, run.NewDepUpdate(cfg)) steps = append(steps, run.NewDepUpdate(cfg))
} }
steps = append(steps, run.NewUpgrade(cfg)) steps = append(steps, run.NewUpgrade(cfg))
return steps return steps
@@ -101,7 +114,9 @@ var upgrade = func(cfg env.Config) []Step {
var uninstall = func(cfg env.Config) []Step { var uninstall = func(cfg env.Config) []Step {
var steps []Step var steps []Step
steps = append(steps, run.NewInitKube(cfg, kubeConfigTemplate, kubeConfigFile)) if !cfg.SkipKubeconfig {
steps = append(steps, run.NewInitKube(cfg, kubeConfigTemplate, kubeConfigFile))
}
if cfg.UpdateDependencies { if cfg.UpdateDependencies {
steps = append(steps, run.NewDepUpdate(cfg)) steps = append(steps, run.NewDepUpdate(cfg))
} }

View File

@@ -122,6 +122,12 @@ func (suite *PlanTestSuite) TestUpgrade() {
suite.IsType(&run.Upgrade{}, steps[1]) suite.IsType(&run.Upgrade{}, steps[1])
} }
func (suite *PlanTestSuite) TestUpgradeWithSkipKubeconfig() {
steps := upgrade(env.Config{SkipKubeconfig: true})
suite.Require().Equal(1, len(steps), "upgrade should return 1 step")
suite.IsType(&run.Upgrade{}, steps[0])
}
func (suite *PlanTestSuite) TestUpgradeWithUpdateDependencies() { func (suite *PlanTestSuite) TestUpgradeWithUpdateDependencies() {
cfg := env.Config{ cfg := env.Config{
UpdateDependencies: true, UpdateDependencies: true,

59
internal/run/depaction.go Normal file
View File

@@ -0,0 +1,59 @@
package run
import (
"errors"
"fmt"
"github.com/pelotech/drone-helm3/internal/env"
)
const (
actionBuild = "build"
actionUpdate = "update"
)
// DepAction is an execution step that calls `helm dependency update` or `helm dependency build` when executed.
type DepAction struct {
*config
chart string
cmd cmd
action string
}
// NewDepAction creates a DepAction using fields from the given Config. No validation is performed at this time.
func NewDepAction(cfg env.Config) *DepAction {
return &DepAction{
config: newConfig(cfg),
chart: cfg.Chart,
action: cfg.DependenciesAction,
}
}
// Execute executes the `helm upgrade` command.
func (d *DepAction) Execute() error {
return d.cmd.Run()
}
// Prepare gets the DepAction ready to execute.
func (d *DepAction) Prepare() error {
if d.chart == "" {
return fmt.Errorf("chart is required")
}
args := d.globalFlags()
if d.action != actionBuild && d.action != actionUpdate {
return errors.New("unknown dependency_action: " + d.action)
}
args = append(args, "dependency", d.action, d.chart)
d.cmd = command(helmBin, args...)
d.cmd.Stdout(d.stdout)
d.cmd.Stderr(d.stderr)
if d.debug {
fmt.Fprintf(d.stderr, "Generated command: '%s'\n", d.cmd.String())
}
return nil
}

View File

@@ -0,0 +1,131 @@
package run
import (
"errors"
"github.com/golang/mock/gomock"
"github.com/pelotech/drone-helm3/internal/env"
"github.com/stretchr/testify/suite"
"strings"
"testing"
)
type DepActionTestSuite struct {
suite.Suite
ctrl *gomock.Controller
mockCmd *Mockcmd
originalCommand func(string, ...string) cmd
}
func (suite *DepActionTestSuite) BeforeTest(_, _ string) {
suite.ctrl = gomock.NewController(suite.T())
suite.mockCmd = NewMockcmd(suite.ctrl)
suite.originalCommand = command
command = func(path string, args ...string) cmd { return suite.mockCmd }
}
func (suite *DepActionTestSuite) AfterTest(_, _ string) {
command = suite.originalCommand
}
func TestDepActionTestSuite(t *testing.T) {
suite.Run(t, new(DepActionTestSuite))
}
func (suite *DepActionTestSuite) TestNewDepAction() {
cfg := env.Config{
Chart: "scatterplot",
}
d := NewDepAction(cfg)
suite.Equal("scatterplot", d.chart)
}
func (suite *DepActionTestSuite) TestPrepareAndExecuteBuild() {
defer suite.ctrl.Finish()
stdout := strings.Builder{}
stderr := strings.Builder{}
cfg := env.Config{
Chart: "your_top_songs_2019",
Stdout: &stdout,
Stderr: &stderr,
DependenciesAction: "build",
}
command = func(path string, args ...string) cmd {
suite.Equal(helmBin, path)
suite.Equal([]string{"dependency", "build", "your_top_songs_2019"}, args)
return suite.mockCmd
}
suite.mockCmd.EXPECT().
Stdout(&stdout)
suite.mockCmd.EXPECT().
Stderr(&stderr)
suite.mockCmd.EXPECT().
Run().
Times(1)
d := NewDepAction(cfg)
suite.Require().NoError(d.Prepare())
suite.NoError(d.Execute())
}
func (suite *DepActionTestSuite) TestPrepareAndExecuteUpdate() {
defer suite.ctrl.Finish()
stdout := strings.Builder{}
stderr := strings.Builder{}
cfg := env.Config{
Chart: "your_top_songs_2019",
Stdout: &stdout,
Stderr: &stderr,
DependenciesAction: "update",
}
command = func(path string, args ...string) cmd {
suite.Equal(helmBin, path)
suite.Equal([]string{"dependency", "update", "your_top_songs_2019"}, args)
return suite.mockCmd
}
suite.mockCmd.EXPECT().
Stdout(&stdout)
suite.mockCmd.EXPECT().
Stderr(&stderr)
suite.mockCmd.EXPECT().
Run().
Times(1)
d := NewDepAction(cfg)
suite.Require().NoError(d.Prepare())
suite.NoError(d.Execute())
}
func (suite *DepActionTestSuite) TestPrepareAndExecuteUnknown() {
defer suite.ctrl.Finish()
stdout := strings.Builder{}
stderr := strings.Builder{}
cfg := env.Config{
Chart: "your_top_songs_2019",
Stdout: &stdout,
Stderr: &stderr,
DependenciesAction: "downgrade",
}
d := NewDepAction(cfg)
suite.Require().Equal(errors.New("unknown dependency_action: downgrade"), d.Prepare())
}
func (suite *DepActionTestSuite) TestPrepareChartRequired() {
d := NewDepAction(env.Config{})
suite.mockCmd.EXPECT().Stdout(gomock.Any()).AnyTimes()
suite.mockCmd.EXPECT().Stderr(gomock.Any()).AnyTimes()
err := d.Prepare()
suite.EqualError(err, "chart is required")
}

View File

@@ -3,10 +3,11 @@ package run
import ( import (
"errors" "errors"
"fmt" "fmt"
"github.com/pelotech/drone-helm3/internal/env"
"io" "io"
"os" "os"
"text/template" "text/template"
"github.com/pelotech/drone-helm3/internal/env"
) )
// InitKube is a step in a helm Plan that initializes the kubernetes config file. // InitKube is a step in a helm Plan that initializes the kubernetes config file.
@@ -87,7 +88,7 @@ func (i *InitKube) Prepare() error {
fmt.Fprintf(i.stderr, "kubeconfig file at %s\n", i.configFilename) fmt.Fprintf(i.stderr, "kubeconfig file at %s\n", i.configFilename)
} }
i.configFile, err = os.Create(i.configFilename) i.configFile, err = os.OpenFile(i.configFilename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil { if err != nil {
return fmt.Errorf("could not open kubeconfig file for writing: %w", err) return fmt.Errorf("could not open kubeconfig file for writing: %w", err)
} }

View File

@@ -2,6 +2,7 @@ package run
import ( import (
"fmt" "fmt"
"github.com/pelotech/drone-helm3/internal/env" "github.com/pelotech/drone-helm3/internal/env"
) )
@@ -11,18 +12,21 @@ type Upgrade struct {
chart string chart string
release string release string
chartVersion string chartVersion string
dryRun bool dryRun bool
wait bool wait bool
values string values string
stringValues string stringValues string
valuesFiles []string valuesFiles []string
reuseValues bool reuseValues bool
timeout string timeout string
force bool force bool
atomic bool atomic bool
cleanupOnFail bool cleanupOnFail bool
certs *repoCerts historyMax int
certs *repoCerts
createNamespace bool
skipCrds bool
cmd cmd cmd cmd
} }
@@ -30,21 +34,24 @@ type Upgrade struct {
// NewUpgrade creates an Upgrade using fields from the given Config. No validation is performed at this time. // NewUpgrade creates an Upgrade using fields from the given Config. No validation is performed at this time.
func NewUpgrade(cfg env.Config) *Upgrade { func NewUpgrade(cfg env.Config) *Upgrade {
return &Upgrade{ return &Upgrade{
config: newConfig(cfg), config: newConfig(cfg),
chart: cfg.Chart, chart: cfg.Chart,
release: cfg.Release, release: cfg.Release,
chartVersion: cfg.ChartVersion, chartVersion: cfg.ChartVersion,
dryRun: cfg.DryRun, dryRun: cfg.DryRun,
wait: cfg.Wait, wait: cfg.Wait,
values: cfg.Values, values: cfg.Values,
stringValues: cfg.StringValues, stringValues: cfg.StringValues,
valuesFiles: cfg.ValuesFiles, valuesFiles: cfg.ValuesFiles,
reuseValues: cfg.ReuseValues, reuseValues: cfg.ReuseValues,
timeout: cfg.Timeout, timeout: cfg.Timeout,
force: cfg.Force, force: cfg.Force,
atomic: cfg.AtomicUpgrade, atomic: cfg.AtomicUpgrade,
cleanupOnFail: cfg.CleanupOnFail, cleanupOnFail: cfg.CleanupOnFail,
certs: newRepoCerts(cfg), historyMax: cfg.HistoryMax,
certs: newRepoCerts(cfg),
createNamespace: cfg.CreateNamespace,
skipCrds: cfg.SkipCrds,
} }
} }
@@ -95,11 +102,20 @@ func (u *Upgrade) Prepare() error {
if u.stringValues != "" { if u.stringValues != "" {
args = append(args, "--set-string", u.stringValues) args = append(args, "--set-string", u.stringValues)
} }
if u.createNamespace {
args = append(args, "--create-namespace")
}
if u.skipCrds {
args = append(args, "--skip-crds")
}
for _, vFile := range u.valuesFiles { for _, vFile := range u.valuesFiles {
args = append(args, "--values", vFile) args = append(args, "--values", vFile)
} }
args = append(args, u.certs.flags()...) args = append(args, u.certs.flags()...)
// always set --history-max since it defaults to non-zero value
args = append(args, fmt.Sprintf("--history-max=%d", u.historyMax))
args = append(args, u.release, u.chart) args = append(args, u.release, u.chart)
u.cmd = command(helmBin, args...) u.cmd = command(helmBin, args...)
u.cmd.Stdout(u.stdout) u.cmd.Stdout(u.stdout)

View File

@@ -2,11 +2,12 @@ package run
import ( import (
"fmt" "fmt"
"strings"
"testing"
"github.com/golang/mock/gomock" "github.com/golang/mock/gomock"
"github.com/pelotech/drone-helm3/internal/env" "github.com/pelotech/drone-helm3/internal/env"
"github.com/stretchr/testify/suite" "github.com/stretchr/testify/suite"
"strings"
"testing"
) )
type UpgradeTestSuite struct { type UpgradeTestSuite struct {
@@ -33,23 +34,23 @@ func TestUpgradeTestSuite(t *testing.T) {
} }
func (suite *UpgradeTestSuite) TestNewUpgrade() { func (suite *UpgradeTestSuite) TestNewUpgrade() {
cfg := env.Config{ cfg := env.NewTestConfig(suite.T())
ChartVersion: "seventeen", cfg.ChartVersion = "seventeen"
DryRun: true, cfg.DryRun = true
Wait: true, cfg.Wait = true
Values: "steadfastness,forthrightness", cfg.Values = "steadfastness,forthrightness"
StringValues: "tensile_strength,flexibility", cfg.StringValues = "tensile_strength,flexibility"
ValuesFiles: []string{"/root/price_inventory.yml"}, cfg.ValuesFiles = []string{"/root/price_inventory.yml"}
ReuseValues: true, cfg.ReuseValues = true
Timeout: "go sit in the corner", cfg.Timeout = "go sit in the corner"
Chart: "billboard_top_100", cfg.Chart = "billboard_top_100"
Release: "post_malone_circles", cfg.Release = "post_malone_circles"
Force: true, cfg.Force = true
AtomicUpgrade: true, cfg.AtomicUpgrade = true
CleanupOnFail: true, cfg.CleanupOnFail = true
}
up := NewUpgrade(*cfg)
up := NewUpgrade(cfg)
suite.Equal(cfg.Chart, up.chart) suite.Equal(cfg.Chart, up.chart)
suite.Equal(cfg.Release, up.release) suite.Equal(cfg.Release, up.release)
suite.Equal(cfg.ChartVersion, up.chartVersion) suite.Equal(cfg.ChartVersion, up.chartVersion)
@@ -70,15 +71,15 @@ func (suite *UpgradeTestSuite) TestNewUpgrade() {
func (suite *UpgradeTestSuite) TestPrepareAndExecute() { func (suite *UpgradeTestSuite) TestPrepareAndExecute() {
defer suite.ctrl.Finish() defer suite.ctrl.Finish()
cfg := env.Config{ cfg := env.NewTestConfig(suite.T())
Chart: "at40", cfg.Chart = "at40"
Release: "jonas_brothers_only_human", cfg.Release = "jonas_brothers_only_human"
}
u := NewUpgrade(cfg) u := NewUpgrade(*cfg)
command = func(path string, args ...string) cmd { command = func(path string, args ...string) cmd {
suite.Equal(helmBin, path) suite.Equal(helmBin, path)
suite.Equal([]string{"upgrade", "--install", "jonas_brothers_only_human", "at40"}, args) suite.Equal([]string{"upgrade", "--install", "--history-max=10", "jonas_brothers_only_human", "at40"}, args)
return suite.mockCmd return suite.mockCmd
} }
@@ -99,16 +100,16 @@ func (suite *UpgradeTestSuite) TestPrepareAndExecute() {
func (suite *UpgradeTestSuite) TestPrepareNamespaceFlag() { func (suite *UpgradeTestSuite) TestPrepareNamespaceFlag() {
defer suite.ctrl.Finish() defer suite.ctrl.Finish()
cfg := env.Config{ cfg := env.NewTestConfig(suite.T())
Namespace: "melt", cfg.Namespace = "melt"
Chart: "at40", cfg.Chart = "at40"
Release: "shaed_trampoline", cfg.Release = "shaed_trampoline"
}
u := NewUpgrade(cfg) u := NewUpgrade(*cfg)
command = func(path string, args ...string) cmd { command = func(path string, args ...string) cmd {
suite.Equal(helmBin, path) suite.Equal(helmBin, path)
suite.Equal([]string{"--namespace", "melt", "upgrade", "--install", "shaed_trampoline", "at40"}, args) suite.Equal([]string{"--namespace", "melt", "upgrade", "--install", "--history-max=10", "shaed_trampoline", "at40"}, args)
return suite.mockCmd return suite.mockCmd
} }
@@ -123,22 +124,22 @@ func (suite *UpgradeTestSuite) TestPrepareNamespaceFlag() {
func (suite *UpgradeTestSuite) TestPrepareWithUpgradeFlags() { func (suite *UpgradeTestSuite) TestPrepareWithUpgradeFlags() {
defer suite.ctrl.Finish() defer suite.ctrl.Finish()
cfg := env.Config{ cfg := env.NewTestConfig(suite.T())
Chart: "hot_ac", cfg.Chart = "hot_ac"
Release: "maroon_5_memories", cfg.Release = "maroon_5_memories"
ChartVersion: "radio_edit", cfg.ChartVersion = "radio_edit"
DryRun: true, cfg.DryRun = true
Wait: true, cfg.Wait = true
Values: "age=35", cfg.Values = "age=35"
StringValues: "height=5ft10in", cfg.StringValues = "height=5ft10in"
ValuesFiles: []string{"/usr/local/stats", "/usr/local/grades"}, cfg.ValuesFiles = []string{"/usr/local/stats", "/usr/local/grades"}
ReuseValues: true, cfg.ReuseValues = true
Timeout: "sit_in_the_corner", cfg.Timeout = "sit_in_the_corner"
Force: true, cfg.Force = true
AtomicUpgrade: true, cfg.AtomicUpgrade = true
CleanupOnFail: true, cfg.CleanupOnFail = true
}
u := NewUpgrade(cfg) u := NewUpgrade(*cfg)
// inject a ca cert filename so repoCerts won't create any files that we'd have to clean up // inject a ca cert filename so repoCerts won't create any files that we'd have to clean up
u.certs.caCertFilename = "local_ca.cert" u.certs.caCertFilename = "local_ca.cert"
@@ -158,6 +159,7 @@ func (suite *UpgradeTestSuite) TestPrepareWithUpgradeFlags() {
"--values", "/usr/local/stats", "--values", "/usr/local/stats",
"--values", "/usr/local/grades", "--values", "/usr/local/grades",
"--ca-file", "local_ca.cert", "--ca-file", "local_ca.cert",
"--history-max=10",
"maroon_5_memories", "hot_ac"}, args) "maroon_5_memories", "hot_ac"}, args)
return suite.mockCmd return suite.mockCmd
@@ -191,14 +193,15 @@ func (suite *UpgradeTestSuite) TestRequiresChartAndRelease() {
func (suite *UpgradeTestSuite) TestPrepareDebugFlag() { func (suite *UpgradeTestSuite) TestPrepareDebugFlag() {
stdout := strings.Builder{} stdout := strings.Builder{}
stderr := strings.Builder{} stderr := strings.Builder{}
cfg := env.Config{
Chart: "at40", cfg := env.NewTestConfig(suite.T())
Release: "lewis_capaldi_someone_you_loved", cfg.Chart = "at40"
Debug: true, cfg.Release = "lewis_capaldi_someone_you_loved"
Stdout: &stdout, cfg.Debug = true
Stderr: &stderr, cfg.Stdout = &stdout
} cfg.Stderr = &stderr
u := NewUpgrade(cfg)
u := NewUpgrade(*cfg)
command = func(path string, args ...string) cmd { command = func(path string, args ...string) cmd {
suite.mockCmd.EXPECT(). suite.mockCmd.EXPECT().
@@ -215,8 +218,34 @@ func (suite *UpgradeTestSuite) TestPrepareDebugFlag() {
u.Prepare() u.Prepare()
want := fmt.Sprintf("Generated command: '%s --debug upgrade "+ want := fmt.Sprintf(
"--install lewis_capaldi_someone_you_loved at40'\n", helmBin) "Generated command: '%s --debug upgrade --install --history-max=10 lewis_capaldi_someone_you_loved at40'\n",
helmBin,
)
suite.Equal(want, stderr.String()) suite.Equal(want, stderr.String())
suite.Equal("", stdout.String()) suite.Equal("", stdout.String())
} }
func (suite *UpgradeTestSuite) TestPrepareSkipCrdsFlag() {
defer suite.ctrl.Finish()
cfg := env.NewTestConfig(suite.T())
cfg.Chart = "at40"
cfg.Release = "cabbages_smell_great"
cfg.SkipCrds = true
u := NewUpgrade(*cfg)
command = func(path string, args ...string) cmd {
suite.Equal(helmBin, path)
suite.Equal([]string{"upgrade", "--install", "--skip-crds", "--history-max=10", "cabbages_smell_great", "at40"}, args)
return suite.mockCmd
}
suite.mockCmd.EXPECT().Stdout(gomock.Any())
suite.mockCmd.EXPECT().Stderr(gomock.Any())
err := u.Prepare()
suite.Require().Nil(err)
}