Merge pull request #32 from pelotech/config-fixup
Clarify and improve internal/helm.Config
This commit is contained in:
commit
fc3bfc466a
|
@ -2,22 +2,21 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/kelseyhightower/envconfig"
|
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/pelotech/drone-helm3/internal/helm"
|
"github.com/pelotech/drone-helm3/internal/helm"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var c helm.Config
|
cfg, err := helm.NewConfig(os.Stdout, os.Stderr)
|
||||||
|
|
||||||
if err := envconfig.Process("plugin", &c); err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
|
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make the plan
|
// Make the plan
|
||||||
plan, err := helm.NewPlan(c)
|
plan, err := helm.NewPlan(*cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "%w\n", err)
|
fmt.Fprintf(os.Stderr, "%w\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|
|
@ -2,62 +2,76 @@ package helm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"github.com/kelseyhightower/envconfig"
|
||||||
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
// The Config struct captures the `settings` and `environment` blocks in the application's drone
|
// The Config struct captures the `settings` and `environment` blocks in the application's drone
|
||||||
// config. Configuration in drone's `settings` block arrives as uppercase env vars matching the
|
// config. Configuration in drone's `settings` block arrives as uppercase env vars matching the
|
||||||
// config key, prefixed with `PLUGIN_`. Config from the `environment` block is *not* prefixed; any
|
// config key, prefixed with `PLUGIN_`. Config from the `environment` block is uppercased, but does
|
||||||
// keys that are likely to be in that block (i.e. things that use `from_secret` need an explicit
|
// not have the `PLUGIN_` prefix. It may, however, be prefixed with the value in `$PLUGIN_PREFIX`.
|
||||||
// `envconfig:` tag so that envconfig will look for a non-prefixed env var.
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
// Configuration for drone-helm itself
|
// Configuration for drone-helm itself
|
||||||
Command helmCommand `envconfig:"HELM_COMMAND"` // Helm command to run
|
Command string `envconfig:"HELM_COMMAND"` // 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"` // Call `helm dependency update` before the main command
|
||||||
Repos []string `envconfig:"HELM_REPOS"` // call `helm repo add` before the main command
|
Repos []string `envconfig:"HELM_REPOS"` // Call `helm repo add` before the main command
|
||||||
Prefix string `` // Prefix to use when looking up secret env vars
|
Prefix string `` // Prefix to use when looking up secret env vars
|
||||||
|
Debug bool `` // Generate debug output and pass --debug to all helm commands
|
||||||
|
Values string `` // Argument to pass to --set 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
|
||||||
|
Namespace string `` // Kubernetes namespace for all helm commands
|
||||||
|
KubeToken string `envconfig:"KUBERNETES_TOKEN"` // Kubernetes authentication token to put in .kube/config
|
||||||
|
SkipTLSVerify bool `envconfig:"SKIP_TLS_VERIFY"` // Put insecure-skip-tls-verify in .kube/config
|
||||||
|
Certificate string `envconfig:"KUBERNETES_CERTIFICATE"` // The Kubernetes cluster CA's self-signed certificate (must be base64-encoded)
|
||||||
|
APIServer string `envconfig:"API_SERVER"` // The Kubernetes cluster's API endpoint
|
||||||
|
ServiceAccount string `split_words:"true"` // Account to use for connecting to the Kubernetes cluster
|
||||||
|
ChartVersion string `split_words:"true"` // Specific chart version to use in `helm upgrade`
|
||||||
|
DryRun bool `split_words:"true"` // Pass --dry-run to applicable helm commands
|
||||||
|
Wait bool `` // Pass --wait to applicable helm commands
|
||||||
|
ReuseValues bool `split_words:"true"` // Pass --reuse-values to `helm upgrade`
|
||||||
|
Timeout string `` // Argument to pass to --timeout in applicable helm commands
|
||||||
|
Chart string `` // Chart argument to use in applicable helm commands
|
||||||
|
Release string `` // Release argument to use in applicable helm commands
|
||||||
|
Force bool `` // Pass --force to applicable helm commands
|
||||||
|
|
||||||
// Global helm config
|
Stdout io.Writer `ignored:"true"`
|
||||||
Debug bool `` // global helm flag (also applies to drone-helm itself)
|
Stderr io.Writer `ignored:"true"`
|
||||||
KubeConfig string `split_words:"true" default:"/root/.kube/config"` // path to the kube config file
|
|
||||||
Values string ``
|
|
||||||
StringValues string `split_words:"true"`
|
|
||||||
ValuesFiles []string `split_words:"true"`
|
|
||||||
Namespace string ``
|
|
||||||
KubeToken string `envconfig:"KUBERNETES_TOKEN"`
|
|
||||||
SkipTLSVerify bool `envconfig:"SKIP_TLS_VERIFY"`
|
|
||||||
Certificate string `envconfig:"KUBERNETES_CERTIFICATE"`
|
|
||||||
APIServer string `envconfig:"API_SERVER"`
|
|
||||||
ServiceAccount string `envconfig:"SERVICE_ACCOUNT"` // Can't just use split_words; need envconfig to find the non-prefixed form
|
|
||||||
|
|
||||||
// Config specifically for `helm upgrade`
|
|
||||||
ChartVersion string `split_words:"true"` //
|
|
||||||
DryRun bool `split_words:"true"` // also available for `delete`
|
|
||||||
Wait bool `` //
|
|
||||||
ReuseValues bool `split_words:"true"` //
|
|
||||||
Timeout string `` //
|
|
||||||
Chart string `` // Also available for `lint`, in which case it must be a path to a chart directory
|
|
||||||
Release string ``
|
|
||||||
Force bool `` //
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type helmCommand string
|
// NewConfig creates a Config and reads environment variables into it, accounting for several possible formats.
|
||||||
|
func NewConfig(stdout, stderr io.Writer) (*Config, error) {
|
||||||
|
cfg := Config{
|
||||||
|
Stdout: stdout,
|
||||||
|
Stderr: stderr,
|
||||||
|
}
|
||||||
|
if err := envconfig.Process("plugin", &cfg); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// helmCommand.Decode checks the given value against the list of known commands and generates a helpful error if the command is unknown.
|
prefix := cfg.Prefix
|
||||||
func (cmd *helmCommand) Decode(value string) error {
|
|
||||||
known := []string{"upgrade", "delete", "lint", "help"}
|
if err := envconfig.Process("", &cfg); err != nil {
|
||||||
for _, c := range known {
|
return nil, err
|
||||||
if value == c {
|
}
|
||||||
*cmd = helmCommand(value)
|
|
||||||
return nil
|
if prefix != "" {
|
||||||
|
if err := envconfig.Process(cfg.Prefix, &cfg); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if value == "" {
|
if cfg.Debug && cfg.Stderr != nil {
|
||||||
return nil
|
cfg.logDebug()
|
||||||
}
|
}
|
||||||
known[len(known)-1] = fmt.Sprintf("or %s", known[len(known)-1])
|
|
||||||
return fmt.Errorf("unknown command '%s'. If specified, command must be %s",
|
return &cfg, nil
|
||||||
value, strings.Join(known, ", "))
|
}
|
||||||
|
|
||||||
|
func (cfg Config) logDebug() {
|
||||||
|
if cfg.KubeToken != "" {
|
||||||
|
cfg.KubeToken = "(redacted)"
|
||||||
|
}
|
||||||
|
fmt.Fprintf(cfg.Stderr, "Generated config: %+v\n", cfg)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,27 +2,179 @@ package helm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ConfigTestSuite struct {
|
type ConfigTestSuite struct {
|
||||||
suite.Suite
|
suite.Suite
|
||||||
|
// These tests need to mutate the environment, so the suite.setenv and .unsetenv functions store the original contents of the
|
||||||
|
// relevant variable in this map. Its use of *string is so they can distinguish between "not set" and "set to empty string"
|
||||||
|
envBackup map[string]*string
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConfigTestSuite(t *testing.T) {
|
func TestConfigTestSuite(t *testing.T) {
|
||||||
suite.Run(t, new(ConfigTestSuite))
|
suite.Run(t, new(ConfigTestSuite))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *ConfigTestSuite) TestHelmCommandDecodeSuccess() {
|
func (suite *ConfigTestSuite) TestNewConfigWithPluginPrefix() {
|
||||||
cmd := helmCommand("")
|
suite.unsetenv("PLUGIN_PREFIX")
|
||||||
err := cmd.Decode("upgrade")
|
suite.unsetenv("HELM_COMMAND")
|
||||||
suite.Require().Nil(err)
|
suite.unsetenv("UPDATE_DEPENDENCIES")
|
||||||
|
suite.unsetenv("DEBUG")
|
||||||
|
|
||||||
suite.EqualValues(cmd, "upgrade")
|
suite.setenv("PLUGIN_HELM_COMMAND", "execute order 66")
|
||||||
|
suite.setenv("PLUGIN_UPDATE_DEPENDENCIES", "true")
|
||||||
|
suite.setenv("PLUGIN_DEBUG", "true")
|
||||||
|
|
||||||
|
cfg, err := NewConfig(&strings.Builder{}, &strings.Builder{})
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
suite.Equal("execute order 66", cfg.Command)
|
||||||
|
suite.True(cfg.UpdateDependencies)
|
||||||
|
suite.True(cfg.Debug)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *ConfigTestSuite) TestHelmCommandDecodeFailure() {
|
func (suite *ConfigTestSuite) TestNewConfigWithNoPrefix() {
|
||||||
cmd := helmCommand("")
|
suite.unsetenv("PLUGIN_PREFIX")
|
||||||
err := cmd.Decode("execute order 66")
|
suite.unsetenv("PLUGIN_HELM_COMMAND")
|
||||||
suite.EqualError(err, "unknown command 'execute order 66'. If specified, command must be upgrade, delete, lint, or help")
|
suite.unsetenv("PLUGIN_UPDATE_DEPENDENCIES")
|
||||||
|
suite.unsetenv("PLUGIN_DEBUG")
|
||||||
|
|
||||||
|
suite.setenv("HELM_COMMAND", "execute order 66")
|
||||||
|
suite.setenv("UPDATE_DEPENDENCIES", "true")
|
||||||
|
suite.setenv("DEBUG", "true")
|
||||||
|
|
||||||
|
cfg, err := NewConfig(&strings.Builder{}, &strings.Builder{})
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
suite.Equal("execute order 66", cfg.Command)
|
||||||
|
suite.True(cfg.UpdateDependencies)
|
||||||
|
suite.True(cfg.Debug)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *ConfigTestSuite) TestNewConfigWithConfigurablePrefix() {
|
||||||
|
suite.unsetenv("API_SERVER")
|
||||||
|
suite.unsetenv("PLUGIN_API_SERVER")
|
||||||
|
|
||||||
|
suite.setenv("PLUGIN_PREFIX", "prix_fixe")
|
||||||
|
suite.setenv("PRIX_FIXE_API_SERVER", "your waiter this evening")
|
||||||
|
|
||||||
|
cfg, err := NewConfig(&strings.Builder{}, &strings.Builder{})
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
suite.Equal("prix_fixe", cfg.Prefix)
|
||||||
|
suite.Equal("your waiter this evening", cfg.APIServer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *ConfigTestSuite) TestPrefixSettingDoesNotAffectPluginPrefix() {
|
||||||
|
suite.setenv("PLUGIN_PREFIX", "IXFREP")
|
||||||
|
suite.setenv("PLUGIN_HELM_COMMAND", "wake me up")
|
||||||
|
suite.setenv("IXFREP_PLUGIN_HELM_COMMAND", "send me to sleep inside")
|
||||||
|
|
||||||
|
cfg, err := NewConfig(&strings.Builder{}, &strings.Builder{})
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
suite.Equal("wake me up", cfg.Command)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *ConfigTestSuite) TestPrefixSettingMustHavePluginPrefix() {
|
||||||
|
suite.unsetenv("PLUGIN_PREFIX")
|
||||||
|
suite.setenv("PREFIX", "refpix")
|
||||||
|
suite.setenv("HELM_COMMAND", "gimme more")
|
||||||
|
suite.setenv("REFPIX_HELM_COMMAND", "gimme less")
|
||||||
|
|
||||||
|
cfg, err := NewConfig(&strings.Builder{}, &strings.Builder{})
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
suite.Equal("gimme more", cfg.Command)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *ConfigTestSuite) TestNewConfigWithConflictingVariables() {
|
||||||
|
suite.setenv("PLUGIN_HELM_COMMAND", "execute order 66")
|
||||||
|
suite.setenv("HELM_COMMAND", "defend the jedi") // values from the `environment` block override those from `settings`
|
||||||
|
|
||||||
|
suite.setenv("PLUGIN_PREFIX", "prod")
|
||||||
|
suite.setenv("TIMEOUT", "5m0s")
|
||||||
|
suite.setenv("PROD_TIMEOUT", "2m30s") // values from prefixed env vars override those from non-prefixed ones
|
||||||
|
|
||||||
|
cfg, err := NewConfig(&strings.Builder{}, &strings.Builder{})
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
suite.Equal("defend the jedi", cfg.Command)
|
||||||
|
suite.Equal("2m30s", cfg.Timeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *ConfigTestSuite) TestNewConfigSetsWriters() {
|
||||||
|
stdout := &strings.Builder{}
|
||||||
|
stderr := &strings.Builder{}
|
||||||
|
cfg, err := NewConfig(stdout, stderr)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
suite.Equal(stdout, cfg.Stdout)
|
||||||
|
suite.Equal(stderr, cfg.Stderr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *ConfigTestSuite) TestLogDebug() {
|
||||||
|
suite.setenv("DEBUG", "true")
|
||||||
|
suite.setenv("HELM_COMMAND", "upgrade")
|
||||||
|
|
||||||
|
stderr := strings.Builder{}
|
||||||
|
stdout := strings.Builder{}
|
||||||
|
_, err := NewConfig(&stdout, &stderr)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
suite.Equal("", stdout.String())
|
||||||
|
|
||||||
|
suite.Regexp(`^Generated config: \{Command:upgrade.*\}`, stderr.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *ConfigTestSuite) TestLogDebugCensorsKubeToken() {
|
||||||
|
stderr := &strings.Builder{}
|
||||||
|
kubeToken := "I'm shy! Don't put me in your build logs!"
|
||||||
|
cfg := Config{
|
||||||
|
Debug: true,
|
||||||
|
KubeToken: kubeToken,
|
||||||
|
Stderr: stderr,
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg.logDebug()
|
||||||
|
|
||||||
|
suite.Contains(stderr.String(), "KubeToken:(redacted)")
|
||||||
|
suite.Equal(kubeToken, cfg.KubeToken) // The actual config value should be left unchanged
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *ConfigTestSuite) setenv(key, val string) {
|
||||||
|
orig, ok := os.LookupEnv(key)
|
||||||
|
if ok {
|
||||||
|
suite.envBackup[key] = &orig
|
||||||
|
} else {
|
||||||
|
suite.envBackup[key] = nil
|
||||||
|
}
|
||||||
|
os.Setenv(key, val)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *ConfigTestSuite) unsetenv(key string) {
|
||||||
|
orig, ok := os.LookupEnv(key)
|
||||||
|
if ok {
|
||||||
|
suite.envBackup[key] = &orig
|
||||||
|
} else {
|
||||||
|
suite.envBackup[key] = nil
|
||||||
|
}
|
||||||
|
os.Unsetenv(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *ConfigTestSuite) BeforeTest(_, _ string) {
|
||||||
|
suite.envBackup = make(map[string]*string)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *ConfigTestSuite) AfterTest(_, _ string) {
|
||||||
|
for key, val := range suite.envBackup {
|
||||||
|
if val == nil {
|
||||||
|
os.Unsetenv(key)
|
||||||
|
} else {
|
||||||
|
os.Setenv(key, *val)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,10 @@ import (
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
const kubeConfigTemplate = "/root/.kube/config.tpl"
|
const (
|
||||||
|
kubeConfigTemplate = "/root/.kube/config.tpl"
|
||||||
|
kubeConfigFile = "/root/.kube/config"
|
||||||
|
)
|
||||||
|
|
||||||
// A Step is one step in the plan.
|
// A Step is one step in the plan.
|
||||||
type Step interface {
|
type Step interface {
|
||||||
|
@ -27,13 +30,12 @@ func NewPlan(cfg Config) (*Plan, error) {
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
runCfg: run.Config{
|
runCfg: run.Config{
|
||||||
Debug: cfg.Debug,
|
Debug: cfg.Debug,
|
||||||
KubeConfig: cfg.KubeConfig,
|
|
||||||
Values: cfg.Values,
|
Values: cfg.Values,
|
||||||
StringValues: cfg.StringValues,
|
StringValues: cfg.StringValues,
|
||||||
ValuesFiles: cfg.ValuesFiles,
|
ValuesFiles: cfg.ValuesFiles,
|
||||||
Namespace: cfg.Namespace,
|
Namespace: cfg.Namespace,
|
||||||
Stdout: os.Stdout,
|
Stdout: cfg.Stdout,
|
||||||
Stderr: os.Stderr,
|
Stderr: cfg.Stderr,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +84,7 @@ func determineSteps(cfg Config) *func(Config) []Step {
|
||||||
func (p *Plan) Execute() error {
|
func (p *Plan) Execute() error {
|
||||||
for i, step := range p.steps {
|
for i, step := range p.steps {
|
||||||
if p.cfg.Debug {
|
if p.cfg.Debug {
|
||||||
fmt.Fprintf(os.Stderr, "calling %T.Execute (step %d)\n", step, i)
|
fmt.Fprintf(p.cfg.Stderr, "calling %T.Execute (step %d)\n", step, i)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := step.Execute(p.runCfg); err != nil {
|
if err := step.Execute(p.runCfg); err != nil {
|
||||||
|
@ -142,6 +144,7 @@ func initKube(cfg Config) []Step {
|
||||||
ServiceAccount: cfg.ServiceAccount,
|
ServiceAccount: cfg.ServiceAccount,
|
||||||
Token: cfg.KubeToken,
|
Token: cfg.KubeToken,
|
||||||
TemplateFile: kubeConfigTemplate,
|
TemplateFile: kubeConfigTemplate,
|
||||||
|
ConfigFile: kubeConfigFile,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
"os"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/pelotech/drone-helm3/internal/run"
|
"github.com/pelotech/drone-helm3/internal/run"
|
||||||
|
@ -29,25 +29,27 @@ func (suite *PlanTestSuite) TestNewPlan() {
|
||||||
}
|
}
|
||||||
defer func() { help = origHelp }()
|
defer func() { help = origHelp }()
|
||||||
|
|
||||||
|
stdout := strings.Builder{}
|
||||||
|
stderr := strings.Builder{}
|
||||||
cfg := Config{
|
cfg := Config{
|
||||||
Command: "help",
|
Command: "help",
|
||||||
Debug: false,
|
Debug: false,
|
||||||
KubeConfig: "/branch/.sfere/profig",
|
|
||||||
Values: "steadfastness,forthrightness",
|
Values: "steadfastness,forthrightness",
|
||||||
StringValues: "tensile_strength,flexibility",
|
StringValues: "tensile_strength,flexibility",
|
||||||
ValuesFiles: []string{"/root/price_inventory.yml"},
|
ValuesFiles: []string{"/root/price_inventory.yml"},
|
||||||
Namespace: "outer",
|
Namespace: "outer",
|
||||||
|
Stdout: &stdout,
|
||||||
|
Stderr: &stderr,
|
||||||
}
|
}
|
||||||
|
|
||||||
runCfg := run.Config{
|
runCfg := run.Config{
|
||||||
Debug: false,
|
Debug: false,
|
||||||
KubeConfig: "/branch/.sfere/profig",
|
|
||||||
Values: "steadfastness,forthrightness",
|
Values: "steadfastness,forthrightness",
|
||||||
StringValues: "tensile_strength,flexibility",
|
StringValues: "tensile_strength,flexibility",
|
||||||
ValuesFiles: []string{"/root/price_inventory.yml"},
|
ValuesFiles: []string{"/root/price_inventory.yml"},
|
||||||
Namespace: "outer",
|
Namespace: "outer",
|
||||||
Stdout: os.Stdout,
|
Stdout: &stdout,
|
||||||
Stderr: os.Stderr,
|
Stderr: &stderr,
|
||||||
}
|
}
|
||||||
|
|
||||||
stepOne.EXPECT().
|
stepOne.EXPECT().
|
||||||
|
@ -142,6 +144,7 @@ func (suite *PlanTestSuite) TestDel() {
|
||||||
ServiceAccount: "greathelm",
|
ServiceAccount: "greathelm",
|
||||||
Token: "b2YgbXkgYWZmZWN0aW9u",
|
Token: "b2YgbXkgYWZmZWN0aW9u",
|
||||||
TemplateFile: kubeConfigTemplate,
|
TemplateFile: kubeConfigTemplate,
|
||||||
|
ConfigFile: kubeConfigFile,
|
||||||
}
|
}
|
||||||
|
|
||||||
suite.Equal(expected, init)
|
suite.Equal(expected, init)
|
||||||
|
@ -176,6 +179,7 @@ func (suite *PlanTestSuite) TestInitKube() {
|
||||||
ServiceAccount: "helmet",
|
ServiceAccount: "helmet",
|
||||||
Token: "cXVlZXIgY2hhcmFjdGVyCg==",
|
Token: "cXVlZXIgY2hhcmFjdGVyCg==",
|
||||||
TemplateFile: kubeConfigTemplate,
|
TemplateFile: kubeConfigTemplate,
|
||||||
|
ConfigFile: kubeConfigFile,
|
||||||
}
|
}
|
||||||
suite.Equal(expected, init)
|
suite.Equal(expected, init)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
// Config contains configuration applicable to all helm commands
|
// Config contains configuration applicable to all helm commands
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Debug bool
|
Debug bool
|
||||||
KubeConfig string
|
|
||||||
Values string
|
Values string
|
||||||
StringValues string
|
StringValues string
|
||||||
ValuesFiles []string
|
ValuesFiles []string
|
||||||
|
|
|
@ -16,6 +16,7 @@ type InitKube struct {
|
||||||
ServiceAccount string
|
ServiceAccount string
|
||||||
Token string
|
Token string
|
||||||
TemplateFile string
|
TemplateFile string
|
||||||
|
ConfigFile string
|
||||||
|
|
||||||
template *template.Template
|
template *template.Template
|
||||||
configFile io.WriteCloser
|
configFile io.WriteCloser
|
||||||
|
@ -34,7 +35,7 @@ type kubeValues struct {
|
||||||
// Execute generates a kubernetes config file from drone-helm3's template.
|
// Execute generates a kubernetes config file from drone-helm3's template.
|
||||||
func (i *InitKube) Execute(cfg Config) error {
|
func (i *InitKube) Execute(cfg Config) error {
|
||||||
if cfg.Debug {
|
if cfg.Debug {
|
||||||
fmt.Fprintf(cfg.Stderr, "writing kubeconfig file to %s\n", cfg.KubeConfig)
|
fmt.Fprintf(cfg.Stderr, "writing kubeconfig file to %s\n", i.ConfigFile)
|
||||||
}
|
}
|
||||||
defer i.configFile.Close()
|
defer i.configFile.Close()
|
||||||
return i.template.Execute(i.configFile, i.values)
|
return i.template.Execute(i.configFile, i.values)
|
||||||
|
@ -73,16 +74,16 @@ func (i *InitKube) Prepare(cfg Config) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg.Debug {
|
if cfg.Debug {
|
||||||
if _, err := os.Stat(cfg.KubeConfig); err != nil {
|
if _, err := os.Stat(i.ConfigFile); err != nil {
|
||||||
// non-nil err here isn't an actual error state; the kubeconfig just doesn't exist
|
// non-nil err here isn't an actual error state; the kubeconfig just doesn't exist
|
||||||
fmt.Fprint(cfg.Stderr, "creating ")
|
fmt.Fprint(cfg.Stderr, "creating ")
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprint(cfg.Stderr, "truncating ")
|
fmt.Fprint(cfg.Stderr, "truncating ")
|
||||||
}
|
}
|
||||||
fmt.Fprintf(cfg.Stderr, "kubeconfig file at %s\n", cfg.KubeConfig)
|
fmt.Fprintf(cfg.Stderr, "kubeconfig file at %s\n", i.ConfigFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
i.configFile, err = os.Create(cfg.KubeConfig)
|
i.configFile, err = os.Create(i.ConfigFile)
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,10 +34,10 @@ namespace: {{ .Namespace }}
|
||||||
Certificate: "CCNA",
|
Certificate: "CCNA",
|
||||||
Token: "Aspire virtual currency",
|
Token: "Aspire virtual currency",
|
||||||
TemplateFile: templateFile.Name(),
|
TemplateFile: templateFile.Name(),
|
||||||
|
ConfigFile: configFile.Name(),
|
||||||
}
|
}
|
||||||
cfg := Config{
|
cfg := Config{
|
||||||
Namespace: "Cisco",
|
Namespace: "Cisco",
|
||||||
KubeConfig: configFile.Name(),
|
|
||||||
}
|
}
|
||||||
err = init.Prepare(cfg)
|
err = init.Prepare(cfg)
|
||||||
suite.Require().Nil(err)
|
suite.Require().Nil(err)
|
||||||
|
@ -95,11 +95,10 @@ func (suite *InitKubeTestSuite) TestPrepareCannotOpenDestinationFile() {
|
||||||
Certificate: "CCNA",
|
Certificate: "CCNA",
|
||||||
Token: "Aspire virtual currency",
|
Token: "Aspire virtual currency",
|
||||||
TemplateFile: templateFile.Name(),
|
TemplateFile: templateFile.Name(),
|
||||||
|
ConfigFile: "/usr/foreign/exclude/kubeprofig",
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg := Config{
|
cfg := Config{}
|
||||||
KubeConfig: "/usr/foreign/exclude/kubeprofig",
|
|
||||||
}
|
|
||||||
err = init.Prepare(cfg)
|
err = init.Prepare(cfg)
|
||||||
suite.Error(err)
|
suite.Error(err)
|
||||||
suite.Regexp("could not open .* for writing: .* no such file or directory", err)
|
suite.Regexp("could not open .* for writing: .* no such file or directory", err)
|
||||||
|
@ -120,11 +119,10 @@ func (suite *InitKubeTestSuite) TestPrepareRequiredConfig() {
|
||||||
Certificate: "CCNA",
|
Certificate: "CCNA",
|
||||||
Token: "Aspire virtual currency",
|
Token: "Aspire virtual currency",
|
||||||
TemplateFile: templateFile.Name(),
|
TemplateFile: templateFile.Name(),
|
||||||
|
ConfigFile: configFile.Name(),
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg := Config{
|
cfg := Config{}
|
||||||
KubeConfig: configFile.Name(),
|
|
||||||
}
|
|
||||||
|
|
||||||
suite.NoError(init.Prepare(cfg)) // consistency check; we should be starting in a happy state
|
suite.NoError(init.Prepare(cfg)) // consistency check; we should be starting in a happy state
|
||||||
|
|
||||||
|
@ -150,11 +148,10 @@ func (suite *InitKubeTestSuite) TestPrepareDefaultsServiceAccount() {
|
||||||
Certificate: "CCNA",
|
Certificate: "CCNA",
|
||||||
Token: "Aspire virtual currency",
|
Token: "Aspire virtual currency",
|
||||||
TemplateFile: templateFile.Name(),
|
TemplateFile: templateFile.Name(),
|
||||||
|
ConfigFile: configFile.Name(),
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg := Config{
|
cfg := Config{}
|
||||||
KubeConfig: configFile.Name(),
|
|
||||||
}
|
|
||||||
|
|
||||||
init.Prepare(cfg)
|
init.Prepare(cfg)
|
||||||
suite.Equal("helm", init.ServiceAccount)
|
suite.Equal("helm", init.ServiceAccount)
|
||||||
|
|
|
@ -22,7 +22,7 @@ func (u *Uninstall) Prepare(cfg Config) error {
|
||||||
return fmt.Errorf("release is required")
|
return fmt.Errorf("release is required")
|
||||||
}
|
}
|
||||||
|
|
||||||
args := []string{"--kubeconfig", cfg.KubeConfig}
|
args := make([]string, 0)
|
||||||
|
|
||||||
if cfg.Namespace != "" {
|
if cfg.Namespace != "" {
|
||||||
args = append(args, "--namespace", cfg.Namespace)
|
args = append(args, "--namespace", cfg.Namespace)
|
||||||
|
|
|
@ -58,11 +58,9 @@ func (suite *UninstallTestSuite) TestPrepareAndExecute() {
|
||||||
Run().
|
Run().
|
||||||
Times(1)
|
Times(1)
|
||||||
|
|
||||||
cfg := Config{
|
cfg := Config{}
|
||||||
KubeConfig: "/root/.kube/config",
|
|
||||||
}
|
|
||||||
suite.NoError(u.Prepare(cfg))
|
suite.NoError(u.Prepare(cfg))
|
||||||
expected := []string{"--kubeconfig", "/root/.kube/config", "uninstall", "zayde_wølf_king"}
|
expected := []string{"uninstall", "zayde_wølf_king"}
|
||||||
suite.Equal(expected, actual)
|
suite.Equal(expected, actual)
|
||||||
|
|
||||||
u.Execute(cfg)
|
u.Execute(cfg)
|
||||||
|
@ -73,15 +71,13 @@ func (suite *UninstallTestSuite) TestPrepareDryRunFlag() {
|
||||||
Release: "firefox_ak_wildfire",
|
Release: "firefox_ak_wildfire",
|
||||||
DryRun: true,
|
DryRun: true,
|
||||||
}
|
}
|
||||||
cfg := Config{
|
cfg := Config{}
|
||||||
KubeConfig: "/root/.kube/config",
|
|
||||||
}
|
|
||||||
|
|
||||||
suite.mockCmd.EXPECT().Stdout(gomock.Any()).AnyTimes()
|
suite.mockCmd.EXPECT().Stdout(gomock.Any()).AnyTimes()
|
||||||
suite.mockCmd.EXPECT().Stderr(gomock.Any()).AnyTimes()
|
suite.mockCmd.EXPECT().Stderr(gomock.Any()).AnyTimes()
|
||||||
|
|
||||||
suite.NoError(u.Prepare(cfg))
|
suite.NoError(u.Prepare(cfg))
|
||||||
expected := []string{"--kubeconfig", "/root/.kube/config", "uninstall", "--dry-run", "firefox_ak_wildfire"}
|
expected := []string{"uninstall", "--dry-run", "firefox_ak_wildfire"}
|
||||||
suite.Equal(expected, suite.actualArgs)
|
suite.Equal(expected, suite.actualArgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +86,6 @@ func (suite *UninstallTestSuite) TestPrepareNamespaceFlag() {
|
||||||
Release: "carly_simon_run_away_with_me",
|
Release: "carly_simon_run_away_with_me",
|
||||||
}
|
}
|
||||||
cfg := Config{
|
cfg := Config{
|
||||||
KubeConfig: "/root/.kube/config",
|
|
||||||
Namespace: "emotion",
|
Namespace: "emotion",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,8 +93,7 @@ func (suite *UninstallTestSuite) TestPrepareNamespaceFlag() {
|
||||||
suite.mockCmd.EXPECT().Stderr(gomock.Any()).AnyTimes()
|
suite.mockCmd.EXPECT().Stderr(gomock.Any()).AnyTimes()
|
||||||
|
|
||||||
suite.NoError(u.Prepare(cfg))
|
suite.NoError(u.Prepare(cfg))
|
||||||
expected := []string{"--kubeconfig", "/root/.kube/config",
|
expected := []string{"--namespace", "emotion", "uninstall", "carly_simon_run_away_with_me"}
|
||||||
"--namespace", "emotion", "uninstall", "carly_simon_run_away_with_me"}
|
|
||||||
suite.Equal(expected, suite.actualArgs)
|
suite.Equal(expected, suite.actualArgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,7 +103,6 @@ func (suite *UninstallTestSuite) TestPrepareDebugFlag() {
|
||||||
}
|
}
|
||||||
stderr := strings.Builder{}
|
stderr := strings.Builder{}
|
||||||
cfg := Config{
|
cfg := Config{
|
||||||
KubeConfig: "/root/.kube/config",
|
|
||||||
Debug: true,
|
Debug: true,
|
||||||
Stderr: &stderr,
|
Stderr: &stderr,
|
||||||
}
|
}
|
||||||
|
@ -126,8 +119,8 @@ func (suite *UninstallTestSuite) TestPrepareDebugFlag() {
|
||||||
suite.mockCmd.EXPECT().Stderr(&stderr).AnyTimes()
|
suite.mockCmd.EXPECT().Stderr(&stderr).AnyTimes()
|
||||||
|
|
||||||
suite.NoError(u.Prepare(cfg))
|
suite.NoError(u.Prepare(cfg))
|
||||||
suite.Equal(fmt.Sprintf("Generated command: '%s --kubeconfig /root/.kube/config "+
|
suite.Equal(fmt.Sprintf("Generated command: '%s --debug "+
|
||||||
"--debug uninstall just_a_band_huff_and_puff'\n", helmBin), stderr.String())
|
"uninstall just_a_band_huff_and_puff'\n", helmBin), stderr.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *UninstallTestSuite) TestPrepareRequiresRelease() {
|
func (suite *UninstallTestSuite) TestPrepareRequiresRelease() {
|
||||||
|
|
|
@ -35,7 +35,7 @@ func (u *Upgrade) Prepare(cfg Config) error {
|
||||||
return fmt.Errorf("release is required")
|
return fmt.Errorf("release is required")
|
||||||
}
|
}
|
||||||
|
|
||||||
args := []string{"--kubeconfig", cfg.KubeConfig}
|
args := make([]string, 0)
|
||||||
|
|
||||||
if cfg.Namespace != "" {
|
if cfg.Namespace != "" {
|
||||||
args = append(args, "--namespace", cfg.Namespace)
|
args = append(args, "--namespace", cfg.Namespace)
|
||||||
|
|
|
@ -41,8 +41,7 @@ func (suite *UpgradeTestSuite) TestPrepareAndExecute() {
|
||||||
|
|
||||||
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{"--kubeconfig", "/root/.kube/config", "upgrade", "--install",
|
suite.Equal([]string{"upgrade", "--install", "jonas_brothers_only_human", "at40"}, args)
|
||||||
"jonas_brothers_only_human", "at40"}, args)
|
|
||||||
|
|
||||||
return suite.mockCmd
|
return suite.mockCmd
|
||||||
}
|
}
|
||||||
|
@ -55,9 +54,7 @@ func (suite *UpgradeTestSuite) TestPrepareAndExecute() {
|
||||||
Run().
|
Run().
|
||||||
Times(1)
|
Times(1)
|
||||||
|
|
||||||
cfg := Config{
|
cfg := Config{}
|
||||||
KubeConfig: "/root/.kube/config",
|
|
||||||
}
|
|
||||||
err := u.Prepare(cfg)
|
err := u.Prepare(cfg)
|
||||||
suite.Require().Nil(err)
|
suite.Require().Nil(err)
|
||||||
u.Execute(cfg)
|
u.Execute(cfg)
|
||||||
|
@ -73,8 +70,7 @@ func (suite *UpgradeTestSuite) TestPrepareNamespaceFlag() {
|
||||||
|
|
||||||
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{"--kubeconfig", "/root/.kube/config", "--namespace", "melt", "upgrade",
|
suite.Equal([]string{"--namespace", "melt", "upgrade", "--install", "shaed_trampoline", "at40"}, args)
|
||||||
"--install", "shaed_trampoline", "at40"}, args)
|
|
||||||
|
|
||||||
return suite.mockCmd
|
return suite.mockCmd
|
||||||
}
|
}
|
||||||
|
@ -84,7 +80,6 @@ func (suite *UpgradeTestSuite) TestPrepareNamespaceFlag() {
|
||||||
|
|
||||||
cfg := Config{
|
cfg := Config{
|
||||||
Namespace: "melt",
|
Namespace: "melt",
|
||||||
KubeConfig: "/root/.kube/config",
|
|
||||||
}
|
}
|
||||||
err := u.Prepare(cfg)
|
err := u.Prepare(cfg)
|
||||||
suite.Require().Nil(err)
|
suite.Require().Nil(err)
|
||||||
|
@ -105,7 +100,6 @@ func (suite *UpgradeTestSuite) TestPrepareWithUpgradeFlags() {
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg := Config{
|
cfg := Config{
|
||||||
KubeConfig: "/root/.kube/config",
|
|
||||||
Values: "age=35",
|
Values: "age=35",
|
||||||
StringValues: "height=5ft10in",
|
StringValues: "height=5ft10in",
|
||||||
ValuesFiles: []string{"/usr/local/stats", "/usr/local/grades"},
|
ValuesFiles: []string{"/usr/local/stats", "/usr/local/grades"},
|
||||||
|
@ -113,7 +107,7 @@ func (suite *UpgradeTestSuite) TestPrepareWithUpgradeFlags() {
|
||||||
|
|
||||||
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{"--kubeconfig", "/root/.kube/config", "upgrade", "--install",
|
suite.Equal([]string{"upgrade", "--install",
|
||||||
"--version", "radio_edit",
|
"--version", "radio_edit",
|
||||||
"--dry-run",
|
"--dry-run",
|
||||||
"--wait",
|
"--wait",
|
||||||
|
@ -166,7 +160,6 @@ func (suite *UpgradeTestSuite) TestPrepareDebugFlag() {
|
||||||
stderr := strings.Builder{}
|
stderr := strings.Builder{}
|
||||||
cfg := Config{
|
cfg := Config{
|
||||||
Debug: true,
|
Debug: true,
|
||||||
KubeConfig: "/root/.kube/config",
|
|
||||||
Stdout: &stdout,
|
Stdout: &stdout,
|
||||||
Stderr: &stderr,
|
Stderr: &stderr,
|
||||||
}
|
}
|
||||||
|
@ -186,7 +179,7 @@ func (suite *UpgradeTestSuite) TestPrepareDebugFlag() {
|
||||||
|
|
||||||
u.Prepare(cfg)
|
u.Prepare(cfg)
|
||||||
|
|
||||||
want := fmt.Sprintf("Generated command: '%s --kubeconfig /root/.kube/config --debug upgrade "+
|
want := fmt.Sprintf("Generated command: '%s --debug upgrade "+
|
||||||
"--install lewis_capaldi_someone_you_loved at40'\n", helmBin)
|
"--install 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())
|
||||||
|
|
Loading…
Reference in a new issue