DEVOPS-2496 add max history setting (#12)

* add history_max setting

* update docs

* use suite for env test
This commit is contained in:
Colin Hoglund 2021-05-19 13:16:43 -04:00 committed by Colin Hoglund
parent a566ea0cf7
commit 8d450bbf7d
6 changed files with 98 additions and 55 deletions

View file

@ -44,6 +44,7 @@ Installations are triggered when the `mode` setting is "upgrade." They can also
| 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`. |

View file

@ -10,6 +10,10 @@ import (
"github.com/kelseyhightower/envconfig" "github.com/kelseyhightower/envconfig"
) )
const (
DefaultHistoryMax = 10
)
var ( var (
justNumbers = regexp.MustCompile(`^\d+$`) justNumbers = regexp.MustCompile(`^\d+$`)
deprecatedVars = []string{"PURGE", "RECREATE_PODS", "TILLER_NS", "UPGRADE", "CANARY_IMAGE", "CLIENT_ONLY", "STABLE_REPO_URL"} deprecatedVars = []string{"PURGE", "RECREATE_PODS", "TILLER_NS", "UPGRADE", "CANARY_IMAGE", "CLIENT_ONLY", "STABLE_REPO_URL"}
@ -45,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
@ -79,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,
} }

View file

@ -217,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 {

15
internal/env/testing.go vendored Normal file
View file

@ -0,0 +1,15 @@
package env
import (
"os"
"testing"
"github.com/stretchr/testify/require"
)
func NewTestConfig(t *testing.T) *Config {
conf, err := NewConfig(os.Stdout, os.Stderr)
require.NoError(t, err)
return conf
}

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"
) )
@ -22,6 +23,7 @@ type Upgrade struct {
force bool force bool
atomic bool atomic bool
cleanupOnFail bool cleanupOnFail bool
historyMax int
certs *repoCerts certs *repoCerts
createNamespace bool createNamespace bool
skipCrds bool skipCrds bool
@ -46,6 +48,7 @@ func NewUpgrade(cfg env.Config) *Upgrade {
force: cfg.Force, force: cfg.Force,
atomic: cfg.AtomicUpgrade, atomic: cfg.AtomicUpgrade,
cleanupOnFail: cfg.CleanupOnFail, cleanupOnFail: cfg.CleanupOnFail,
historyMax: cfg.HistoryMax,
certs: newRepoCerts(cfg), certs: newRepoCerts(cfg),
createNamespace: cfg.CreateNamespace, createNamespace: cfg.CreateNamespace,
skipCrds: cfg.SkipCrds, skipCrds: cfg.SkipCrds,
@ -110,6 +113,9 @@ func (u *Upgrade) Prepare() error {
} }
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

@ -33,23 +33,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 +70,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 +99,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 +123,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 +158,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 +192,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 +217,10 @@ 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())
} }