parent
72c43a2f46
commit
1acd07fa7e
1
Makefile
1
Makefile
|
|
@ -42,6 +42,7 @@ clean:
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
|
|
||||||
pristine: generate fmt
|
pristine: generate fmt
|
||||||
|
git diff | cat
|
||||||
git ls-files --exclude-standard --modified --deleted --others | diff /dev/null -
|
git ls-files --exclude-standard --modified --deleted --others | diff /dev/null -
|
||||||
.PHONY: pristine
|
.PHONY: pristine
|
||||||
|
|
||||||
|
|
|
||||||
15
README.md
15
README.md
|
|
@ -43,6 +43,7 @@ repositories:
|
||||||
#default values to set for args along with dedicated keys that can be set by contributers, cli args take precedence over these
|
#default values to set for args along with dedicated keys that can be set by contributers, cli args take precedence over these
|
||||||
helmDefaults:
|
helmDefaults:
|
||||||
tillerNamespace: tiller-namespace #dedicated default key for tiller-namespace
|
tillerNamespace: tiller-namespace #dedicated default key for tiller-namespace
|
||||||
|
tillerless: false #dedicated default key for tillerless
|
||||||
kubeContext: kube-context #dedicated default key for kube-context (--kube-context)
|
kubeContext: kube-context #dedicated default key for kube-context (--kube-context)
|
||||||
# additional and global args passed to helm
|
# additional and global args passed to helm
|
||||||
args:
|
args:
|
||||||
|
|
@ -110,6 +111,10 @@ releases:
|
||||||
installed: true
|
installed: true
|
||||||
# restores previous state in case of failed release
|
# restores previous state in case of failed release
|
||||||
atomic: true
|
atomic: true
|
||||||
|
# name of the tiller namespace
|
||||||
|
tillerNamespace: vault
|
||||||
|
# if true, will use the helm-tiller plugin
|
||||||
|
tillerless: false
|
||||||
# enable TLS for request to Tiller
|
# enable TLS for request to Tiller
|
||||||
tls: true
|
tls: true
|
||||||
# path to TLS CA certificate file (default "$HELM_HOME/ca.pem")
|
# path to TLS CA certificate file (default "$HELM_HOME/ca.pem")
|
||||||
|
|
@ -557,6 +562,16 @@ Then the environment secret `foo.bar` can be referenced by the below template ex
|
||||||
{{ .Environment.Values.foo.bar }}
|
{{ .Environment.Values.foo.bar }}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Tillerless
|
||||||
|
|
||||||
|
With the [helm-tiller](https://github.com/rimusz/helm-tiller) plugin installed, you can work without tiller installed.
|
||||||
|
|
||||||
|
To enable this mode, you need to define `tillerless: true` and set the `tillerNamespace` in the `helmDefaults` section
|
||||||
|
or in the `releases` entries.
|
||||||
|
|
||||||
|
Since every commands is run with `helm tiller run ...`, you have to disable concurrency. Otherwise you'll get
|
||||||
|
mysterious errors about the tiller daemon.
|
||||||
|
|
||||||
## Separating helmfile.yaml into multiple independent files
|
## Separating helmfile.yaml into multiple independent files
|
||||||
|
|
||||||
Once your `helmfile.yaml` got to contain too many releases,
|
Once your `helmfile.yaml` got to contain too many releases,
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ func (bus *Bus) Trigger(evt string, context map[string]interface{}) (bool, error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes, err := bus.Runner.Execute(command, args)
|
bytes, err := bus.Runner.Execute(command, args, map[string]string{})
|
||||||
bus.Logger.Debugf("hook[%s]: %s\n", name, string(bytes))
|
bus.Logger.Debugf("hook[%s]: %s\n", name, string(bytes))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ var logger = helmexec.NewLogger(os.Stdout, "warn")
|
||||||
type runner struct {
|
type runner struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *runner) Execute(cmd string, args []string) ([]byte, error) {
|
func (r *runner) Execute(cmd string, args []string, env map[string]string) ([]byte, error) {
|
||||||
if cmd == "ng" {
|
if cmd == "ng" {
|
||||||
return nil, fmt.Errorf("cmd failed due to invalid cmd: %s", cmd)
|
return nil, fmt.Errorf("cmd failed due to invalid cmd: %s", cmd)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
package helmexec
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HelmContext struct {
|
||||||
|
Tillerless bool
|
||||||
|
TillerNamespace string
|
||||||
|
WorkerIndex int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (context *HelmContext) GetTillerlessArgs(helmBinary string) []string {
|
||||||
|
if context.Tillerless {
|
||||||
|
if context.TillerNamespace != "" {
|
||||||
|
return []string{"tiller", "run", context.TillerNamespace, "--", helmBinary}
|
||||||
|
} else {
|
||||||
|
return []string{"tiller", "run", "--", helmBinary}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (context *HelmContext) getTillerlessEnv() map[string]string {
|
||||||
|
if context.Tillerless {
|
||||||
|
result := map[string]string{
|
||||||
|
"HELM_TILLER_SILENT": "true",
|
||||||
|
// Changing the TILLER port doesn't really work: https://github.com/helm/helm/issues/3159
|
||||||
|
// So this is not used for the moment.
|
||||||
|
// "HELM_TILLER_PORT": strconv.Itoa(44134 + context.WorkerIndex),
|
||||||
|
}
|
||||||
|
if config := os.Getenv("KUBECONFIG"); config != "" {
|
||||||
|
absConfig, err := filepath.Abs(config)
|
||||||
|
if err == nil {
|
||||||
|
result["KUBECONFIG"] = absConfig
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
} else {
|
||||||
|
return map[string]string{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -70,60 +70,68 @@ func (helm *execer) AddRepo(name, repository, certfile, keyfile, username, passw
|
||||||
args = append(args, "--username", username, "--password", password)
|
args = append(args, "--username", username, "--password", password)
|
||||||
}
|
}
|
||||||
helm.logger.Infof("Adding repo %v %v", name, repository)
|
helm.logger.Infof("Adding repo %v %v", name, repository)
|
||||||
out, err := helm.exec(args...)
|
out, err := helm.exec(args, map[string]string{})
|
||||||
helm.write(out)
|
helm.write(out)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (helm *execer) UpdateRepo() error {
|
func (helm *execer) UpdateRepo() error {
|
||||||
helm.logger.Info("Updating repo")
|
helm.logger.Info("Updating repo")
|
||||||
out, err := helm.exec("repo", "update")
|
out, err := helm.exec([]string{"repo", "update"}, map[string]string{})
|
||||||
helm.write(out)
|
helm.write(out)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (helm *execer) UpdateDeps(chart string) error {
|
func (helm *execer) UpdateDeps(chart string) error {
|
||||||
helm.logger.Infof("Updating dependency %v", chart)
|
helm.logger.Infof("Updating dependency %v", chart)
|
||||||
out, err := helm.exec("dependency", "update", chart)
|
out, err := helm.exec([]string{"dependency", "update", chart}, map[string]string{})
|
||||||
helm.write(out)
|
helm.write(out)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (helm *execer) BuildDeps(chart string) error {
|
func (helm *execer) BuildDeps(chart string) error {
|
||||||
helm.logger.Infof("Building dependency %v", chart)
|
helm.logger.Infof("Building dependency %v", chart)
|
||||||
out, err := helm.exec("dependency", "build", chart)
|
out, err := helm.exec([]string{"dependency", "build", chart}, map[string]string{})
|
||||||
helm.write(out)
|
helm.write(out)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (helm *execer) SyncRelease(name, chart string, flags ...string) error {
|
func (helm *execer) SyncRelease(context HelmContext, name, chart string, flags ...string) error {
|
||||||
helm.logger.Infof("Upgrading %v", chart)
|
helm.logger.Infof("Upgrading %v", chart)
|
||||||
out, err := helm.exec(append([]string{"upgrade", "--install", "--reset-values", name, chart}, flags...)...)
|
preArgs := context.GetTillerlessArgs(helm.helmBinary)
|
||||||
|
env := context.getTillerlessEnv()
|
||||||
|
out, err := helm.exec(append(append(preArgs, "upgrade", "--install", "--reset-values", name, chart), flags...), env)
|
||||||
helm.write(out)
|
helm.write(out)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (helm *execer) ReleaseStatus(name string, flags ...string) error {
|
func (helm *execer) ReleaseStatus(context HelmContext, name string, flags ...string) error {
|
||||||
helm.logger.Infof("Getting status %v", name)
|
helm.logger.Infof("Getting status %v", name)
|
||||||
out, err := helm.exec(append([]string{"status", name}, flags...)...)
|
preArgs := context.GetTillerlessArgs(helm.helmBinary)
|
||||||
|
env := context.getTillerlessEnv()
|
||||||
|
out, err := helm.exec(append(append(preArgs, "status", name), flags...), env)
|
||||||
helm.write(out)
|
helm.write(out)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (helm *execer) List(filter string, flags ...string) (string, error) {
|
func (helm *execer) List(context HelmContext, filter string, flags ...string) (string, error) {
|
||||||
helm.logger.Infof("Listing releases matching %v", filter)
|
helm.logger.Infof("Listing releases matching %v", filter)
|
||||||
out, err := helm.exec(append([]string{"list", filter}, flags...)...)
|
preArgs := context.GetTillerlessArgs(helm.helmBinary)
|
||||||
|
env := context.getTillerlessEnv()
|
||||||
|
out, err := helm.exec(append(append(preArgs, "list", filter), flags...), env)
|
||||||
helm.write(out)
|
helm.write(out)
|
||||||
return string(out), err
|
return string(out), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (helm *execer) DecryptSecret(name string) (string, error) {
|
func (helm *execer) DecryptSecret(context HelmContext, name string, flags ...string) (string, error) {
|
||||||
// Prevents https://github.com/roboll/helmfile/issues/258
|
// Prevents https://github.com/roboll/helmfile/issues/258
|
||||||
helm.decryptionMutex.Lock()
|
helm.decryptionMutex.Lock()
|
||||||
defer helm.decryptionMutex.Unlock()
|
defer helm.decryptionMutex.Unlock()
|
||||||
|
|
||||||
helm.logger.Infof("Decrypting secret %v", name)
|
helm.logger.Infof("Decrypting secret %v", name)
|
||||||
out, err := helm.exec(append([]string{"secrets", "dec", name})...)
|
preArgs := context.GetTillerlessArgs(helm.helmBinary)
|
||||||
|
env := context.getTillerlessEnv()
|
||||||
|
out, err := helm.exec(append(append(preArgs, "secrets", "dec", name), flags...), env)
|
||||||
helm.write(out)
|
helm.write(out)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
|
@ -162,47 +170,53 @@ func (helm *execer) DecryptSecret(name string) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (helm *execer) TemplateRelease(chart string, flags ...string) error {
|
func (helm *execer) TemplateRelease(chart string, flags ...string) error {
|
||||||
out, err := helm.exec(append([]string{"template", chart}, flags...)...)
|
out, err := helm.exec(append([]string{"template", chart}, flags...), map[string]string{})
|
||||||
helm.write(out)
|
helm.write(out)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (helm *execer) DiffRelease(name, chart string, flags ...string) error {
|
func (helm *execer) DiffRelease(context HelmContext, name, chart string, flags ...string) error {
|
||||||
helm.logger.Infof("Comparing %v %v", name, chart)
|
helm.logger.Infof("Comparing %v %v", name, chart)
|
||||||
out, err := helm.exec(append([]string{"diff", "upgrade", "--allow-unreleased", name, chart}, flags...)...)
|
preArgs := context.GetTillerlessArgs(helm.helmBinary)
|
||||||
|
env := context.getTillerlessEnv()
|
||||||
|
out, err := helm.exec(append(append(preArgs, "diff", "upgrade", "--allow-unreleased", name, chart), flags...), env)
|
||||||
helm.write(out)
|
helm.write(out)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (helm *execer) Lint(chart string, flags ...string) error {
|
func (helm *execer) Lint(chart string, flags ...string) error {
|
||||||
helm.logger.Infof("Linting %v", chart)
|
helm.logger.Infof("Linting %v", chart)
|
||||||
out, err := helm.exec(append([]string{"lint", chart}, flags...)...)
|
out, err := helm.exec(append([]string{"lint", chart}, flags...), map[string]string{})
|
||||||
helm.write(out)
|
helm.write(out)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (helm *execer) Fetch(chart string, flags ...string) error {
|
func (helm *execer) Fetch(chart string, flags ...string) error {
|
||||||
helm.logger.Infof("Fetching %v", chart)
|
helm.logger.Infof("Fetching %v", chart)
|
||||||
out, err := helm.exec(append([]string{"fetch", chart}, flags...)...)
|
out, err := helm.exec(append([]string{"fetch", chart}, flags...), map[string]string{})
|
||||||
helm.write(out)
|
helm.write(out)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (helm *execer) DeleteRelease(name string, flags ...string) error {
|
func (helm *execer) DeleteRelease(context HelmContext, name string, flags ...string) error {
|
||||||
helm.logger.Infof("Deleting %v", name)
|
helm.logger.Infof("Deleting %v", name)
|
||||||
out, err := helm.exec(append([]string{"delete", name}, flags...)...)
|
preArgs := context.GetTillerlessArgs(helm.helmBinary)
|
||||||
|
env := context.getTillerlessEnv()
|
||||||
|
out, err := helm.exec(append(append(preArgs, "delete", name), flags...), env)
|
||||||
helm.write(out)
|
helm.write(out)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (helm *execer) TestRelease(name string, flags ...string) error {
|
func (helm *execer) TestRelease(context HelmContext, name string, flags ...string) error {
|
||||||
helm.logger.Infof("Testing %v", name)
|
helm.logger.Infof("Testing %v", name)
|
||||||
out, err := helm.exec(append([]string{"test", name}, flags...)...)
|
preArgs := context.GetTillerlessArgs(helm.helmBinary)
|
||||||
|
env := context.getTillerlessEnv()
|
||||||
|
out, err := helm.exec(append(append(preArgs, "test", name), flags...), env)
|
||||||
helm.write(out)
|
helm.write(out)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (helm *execer) exec(args ...string) ([]byte, error) {
|
func (helm *execer) exec(args []string, env map[string]string) ([]byte, error) {
|
||||||
cmdargs := args
|
cmdargs := args
|
||||||
if len(helm.extra) > 0 {
|
if len(helm.extra) > 0 {
|
||||||
cmdargs = append(cmdargs, helm.extra...)
|
cmdargs = append(cmdargs, helm.extra...)
|
||||||
|
|
@ -211,7 +225,7 @@ func (helm *execer) exec(args ...string) ([]byte, error) {
|
||||||
cmdargs = append(cmdargs, "--kube-context", helm.kubeContext)
|
cmdargs = append(cmdargs, "--kube-context", helm.kubeContext)
|
||||||
}
|
}
|
||||||
helm.logger.Debugf("exec: %s %s", helm.helmBinary, strings.Join(cmdargs, " "))
|
helm.logger.Debugf("exec: %s %s", helm.helmBinary, strings.Join(cmdargs, " "))
|
||||||
return helm.runner.Execute(helm.helmBinary, cmdargs)
|
return helm.runner.Execute(helm.helmBinary, cmdargs, env)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (helm *execer) write(out []byte) {
|
func (helm *execer) write(out []byte) {
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package helmexec
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
|
@ -16,7 +17,7 @@ type mockRunner struct {
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mock *mockRunner) Execute(cmd string, args []string) ([]byte, error) {
|
func (mock *mockRunner) Execute(cmd string, args []string, env map[string]string) ([]byte, error) {
|
||||||
return []byte{}, nil
|
return []byte{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -118,7 +119,7 @@ func Test_SyncRelease(t *testing.T) {
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
logger := NewLogger(&buffer, "debug")
|
logger := NewLogger(&buffer, "debug")
|
||||||
helm := MockExecer(logger, "dev")
|
helm := MockExecer(logger, "dev")
|
||||||
helm.SyncRelease("release", "chart", "--timeout 10", "--wait")
|
helm.SyncRelease(HelmContext{}, "release", "chart", "--timeout 10", "--wait")
|
||||||
expected := `Upgrading chart
|
expected := `Upgrading chart
|
||||||
exec: helm upgrade --install --reset-values release chart --timeout 10 --wait --kube-context dev
|
exec: helm upgrade --install --reset-values release chart --timeout 10 --wait --kube-context dev
|
||||||
`
|
`
|
||||||
|
|
@ -127,7 +128,7 @@ exec: helm upgrade --install --reset-values release chart --timeout 10 --wait --
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.Reset()
|
buffer.Reset()
|
||||||
helm.SyncRelease("release", "chart")
|
helm.SyncRelease(HelmContext{}, "release", "chart")
|
||||||
expected = `Upgrading chart
|
expected = `Upgrading chart
|
||||||
exec: helm upgrade --install --reset-values release chart --kube-context dev
|
exec: helm upgrade --install --reset-values release chart --kube-context dev
|
||||||
`
|
`
|
||||||
|
|
@ -136,6 +137,20 @@ exec: helm upgrade --install --reset-values release chart --kube-context dev
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_SyncReleaseTillerless(t *testing.T) {
|
||||||
|
var buffer bytes.Buffer
|
||||||
|
logger := NewLogger(&buffer, "debug")
|
||||||
|
helm := MockExecer(logger, "dev")
|
||||||
|
helm.SyncRelease(HelmContext{Tillerless: true, TillerNamespace: "foo"}, "release", "chart",
|
||||||
|
"--timeout 10", "--wait")
|
||||||
|
expected := `Upgrading chart
|
||||||
|
exec: helm tiller run foo -- helm upgrade --install --reset-values release chart --timeout 10 --wait --kube-context dev
|
||||||
|
`
|
||||||
|
if buffer.String() != expected {
|
||||||
|
t.Errorf("helmexec.SyncRelease()\nactual = %v\nexpect = %v", buffer.String(), expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func Test_UpdateDeps(t *testing.T) {
|
func Test_UpdateDeps(t *testing.T) {
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
logger := NewLogger(&buffer, "debug")
|
logger := NewLogger(&buffer, "debug")
|
||||||
|
|
@ -186,7 +201,7 @@ func Test_DecryptSecret(t *testing.T) {
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
logger := NewLogger(&buffer, "debug")
|
logger := NewLogger(&buffer, "debug")
|
||||||
helm := MockExecer(logger, "dev")
|
helm := MockExecer(logger, "dev")
|
||||||
helm.DecryptSecret("secretName")
|
helm.DecryptSecret(HelmContext{}, "secretName")
|
||||||
expected := `Decrypting secret secretName
|
expected := `Decrypting secret secretName
|
||||||
exec: helm secrets dec secretName --kube-context dev
|
exec: helm secrets dec secretName --kube-context dev
|
||||||
`
|
`
|
||||||
|
|
@ -199,7 +214,7 @@ func Test_DiffRelease(t *testing.T) {
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
logger := NewLogger(&buffer, "debug")
|
logger := NewLogger(&buffer, "debug")
|
||||||
helm := MockExecer(logger, "dev")
|
helm := MockExecer(logger, "dev")
|
||||||
helm.DiffRelease("release", "chart", "--timeout 10", "--wait")
|
helm.DiffRelease(HelmContext{}, "release", "chart", "--timeout 10", "--wait")
|
||||||
expected := `Comparing release chart
|
expected := `Comparing release chart
|
||||||
exec: helm diff upgrade --allow-unreleased release chart --timeout 10 --wait --kube-context dev
|
exec: helm diff upgrade --allow-unreleased release chart --timeout 10 --wait --kube-context dev
|
||||||
`
|
`
|
||||||
|
|
@ -208,7 +223,7 @@ exec: helm diff upgrade --allow-unreleased release chart --timeout 10 --wait --k
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.Reset()
|
buffer.Reset()
|
||||||
helm.DiffRelease("release", "chart")
|
helm.DiffRelease(HelmContext{}, "release", "chart")
|
||||||
expected = `Comparing release chart
|
expected = `Comparing release chart
|
||||||
exec: helm diff upgrade --allow-unreleased release chart --kube-context dev
|
exec: helm diff upgrade --allow-unreleased release chart --kube-context dev
|
||||||
`
|
`
|
||||||
|
|
@ -217,11 +232,24 @@ exec: helm diff upgrade --allow-unreleased release chart --kube-context dev
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_DiffReleaseTillerless(t *testing.T) {
|
||||||
|
var buffer bytes.Buffer
|
||||||
|
logger := NewLogger(&buffer, "debug")
|
||||||
|
helm := MockExecer(logger, "dev")
|
||||||
|
helm.DiffRelease(HelmContext{Tillerless: true}, "release", "chart", "--timeout 10", "--wait")
|
||||||
|
expected := `Comparing release chart
|
||||||
|
exec: helm tiller run -- helm diff upgrade --allow-unreleased release chart --timeout 10 --wait --kube-context dev
|
||||||
|
`
|
||||||
|
if buffer.String() != expected {
|
||||||
|
t.Errorf("helmexec.DiffRelease()\nactual = %v\nexpect = %v", buffer.String(), expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func Test_DeleteRelease(t *testing.T) {
|
func Test_DeleteRelease(t *testing.T) {
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
logger := NewLogger(&buffer, "debug")
|
logger := NewLogger(&buffer, "debug")
|
||||||
helm := MockExecer(logger, "dev")
|
helm := MockExecer(logger, "dev")
|
||||||
helm.DeleteRelease("release")
|
helm.DeleteRelease(HelmContext{}, "release")
|
||||||
expected := `Deleting release
|
expected := `Deleting release
|
||||||
exec: helm delete release --kube-context dev
|
exec: helm delete release --kube-context dev
|
||||||
`
|
`
|
||||||
|
|
@ -233,7 +261,7 @@ func Test_DeleteRelease_Flags(t *testing.T) {
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
logger := NewLogger(&buffer, "debug")
|
logger := NewLogger(&buffer, "debug")
|
||||||
helm := MockExecer(logger, "dev")
|
helm := MockExecer(logger, "dev")
|
||||||
helm.DeleteRelease("release", "--purge")
|
helm.DeleteRelease(HelmContext{}, "release", "--purge")
|
||||||
expected := `Deleting release
|
expected := `Deleting release
|
||||||
exec: helm delete release --purge --kube-context dev
|
exec: helm delete release --purge --kube-context dev
|
||||||
`
|
`
|
||||||
|
|
@ -246,7 +274,7 @@ func Test_TestRelease(t *testing.T) {
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
logger := NewLogger(&buffer, "debug")
|
logger := NewLogger(&buffer, "debug")
|
||||||
helm := MockExecer(logger, "dev")
|
helm := MockExecer(logger, "dev")
|
||||||
helm.TestRelease("release")
|
helm.TestRelease(HelmContext{}, "release")
|
||||||
expected := `Testing release
|
expected := `Testing release
|
||||||
exec: helm test release --kube-context dev
|
exec: helm test release --kube-context dev
|
||||||
`
|
`
|
||||||
|
|
@ -258,7 +286,7 @@ func Test_TestRelease_Flags(t *testing.T) {
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
logger := NewLogger(&buffer, "debug")
|
logger := NewLogger(&buffer, "debug")
|
||||||
helm := MockExecer(logger, "dev")
|
helm := MockExecer(logger, "dev")
|
||||||
helm.TestRelease("release", "--cleanup", "--timeout", "60")
|
helm.TestRelease(HelmContext{}, "release", "--cleanup", "--timeout", "60")
|
||||||
expected := `Testing release
|
expected := `Testing release
|
||||||
exec: helm test release --cleanup --timeout 60 --kube-context dev
|
exec: helm test release --cleanup --timeout 60 --kube-context dev
|
||||||
`
|
`
|
||||||
|
|
@ -271,7 +299,7 @@ func Test_ReleaseStatus(t *testing.T) {
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
logger := NewLogger(&buffer, "debug")
|
logger := NewLogger(&buffer, "debug")
|
||||||
helm := MockExecer(logger, "dev")
|
helm := MockExecer(logger, "dev")
|
||||||
helm.ReleaseStatus("myRelease")
|
helm.ReleaseStatus(HelmContext{}, "myRelease")
|
||||||
expected := `Getting status myRelease
|
expected := `Getting status myRelease
|
||||||
exec: helm status myRelease --kube-context dev
|
exec: helm status myRelease --kube-context dev
|
||||||
`
|
`
|
||||||
|
|
@ -284,28 +312,29 @@ func Test_exec(t *testing.T) {
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
logger := NewLogger(&buffer, "debug")
|
logger := NewLogger(&buffer, "debug")
|
||||||
helm := MockExecer(logger, "")
|
helm := MockExecer(logger, "")
|
||||||
helm.exec("version")
|
env := map[string]string{}
|
||||||
|
helm.exec([]string{"version"}, env)
|
||||||
expected := "exec: helm version\n"
|
expected := "exec: helm version\n"
|
||||||
if buffer.String() != expected {
|
if buffer.String() != expected {
|
||||||
t.Errorf("helmexec.exec()\nactual = %v\nexpect = %v", buffer.String(), expected)
|
t.Errorf("helmexec.exec()\nactual = %v\nexpect = %v", buffer.String(), expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
helm = MockExecer(logger, "dev")
|
helm = MockExecer(logger, "dev")
|
||||||
ret, _ := helm.exec("diff")
|
ret, _ := helm.exec([]string{"diff"}, env)
|
||||||
if len(ret) != 0 {
|
if len(ret) != 0 {
|
||||||
t.Error("helmexec.exec() - expected empty return value")
|
t.Error("helmexec.exec() - expected empty return value")
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.Reset()
|
buffer.Reset()
|
||||||
helm = MockExecer(logger, "dev")
|
helm = MockExecer(logger, "dev")
|
||||||
helm.exec("diff", "release", "chart", "--timeout 10", "--wait")
|
helm.exec([]string{"diff", "release", "chart", "--timeout 10", "--wait"}, env)
|
||||||
expected = "exec: helm diff release chart --timeout 10 --wait --kube-context dev\n"
|
expected = "exec: helm diff release chart --timeout 10 --wait --kube-context dev\n"
|
||||||
if buffer.String() != expected {
|
if buffer.String() != expected {
|
||||||
t.Errorf("helmexec.exec()\nactual = %v\nexpect = %v", buffer.String(), expected)
|
t.Errorf("helmexec.exec()\nactual = %v\nexpect = %v", buffer.String(), expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.Reset()
|
buffer.Reset()
|
||||||
helm.exec("version")
|
helm.exec([]string{"version"}, env)
|
||||||
expected = "exec: helm version --kube-context dev\n"
|
expected = "exec: helm version --kube-context dev\n"
|
||||||
if buffer.String() != expected {
|
if buffer.String() != expected {
|
||||||
t.Errorf("helmexec.exec()\nactual = %v\nexpect = %v", buffer.String(), expected)
|
t.Errorf("helmexec.exec()\nactual = %v\nexpect = %v", buffer.String(), expected)
|
||||||
|
|
@ -313,7 +342,7 @@ func Test_exec(t *testing.T) {
|
||||||
|
|
||||||
buffer.Reset()
|
buffer.Reset()
|
||||||
helm.SetExtraArgs("foo")
|
helm.SetExtraArgs("foo")
|
||||||
helm.exec("version")
|
helm.exec([]string{"version"}, env)
|
||||||
expected = "exec: helm version foo --kube-context dev\n"
|
expected = "exec: helm version foo --kube-context dev\n"
|
||||||
if buffer.String() != expected {
|
if buffer.String() != expected {
|
||||||
t.Errorf("helmexec.exec()\nactual = %v\nexpect = %v", buffer.String(), expected)
|
t.Errorf("helmexec.exec()\nactual = %v\nexpect = %v", buffer.String(), expected)
|
||||||
|
|
@ -322,7 +351,7 @@ func Test_exec(t *testing.T) {
|
||||||
buffer.Reset()
|
buffer.Reset()
|
||||||
helm = MockExecer(logger, "")
|
helm = MockExecer(logger, "")
|
||||||
helm.SetHelmBinary("overwritten")
|
helm.SetHelmBinary("overwritten")
|
||||||
helm.exec("version")
|
helm.exec([]string{"version"}, env)
|
||||||
expected = "exec: overwritten version\n"
|
expected = "exec: overwritten version\n"
|
||||||
if buffer.String() != expected {
|
if buffer.String() != expected {
|
||||||
t.Errorf("helmexec.exec()\nactual = %v\nexpect = %v", buffer.String(), expected)
|
t.Errorf("helmexec.exec()\nactual = %v\nexpect = %v", buffer.String(), expected)
|
||||||
|
|
@ -376,3 +405,37 @@ func Test_LogLevels(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_getTillerlessEnv(t *testing.T) {
|
||||||
|
context := HelmContext{Tillerless: true, TillerNamespace: "foo", WorkerIndex: 1}
|
||||||
|
|
||||||
|
os.Unsetenv("KUBECONFIG")
|
||||||
|
actual := context.getTillerlessEnv()
|
||||||
|
if val, found := actual["HELM_TILLER_SILENT"]; !found || val != "true" {
|
||||||
|
t.Errorf("getTillerlessEnv() HELM_TILLER_SILENT\nactual = %s\nexpect = true", val)
|
||||||
|
}
|
||||||
|
// This feature is disabled until it is fixed in helm
|
||||||
|
/*if val, found := actual["HELM_TILLER_PORT"]; !found || val != "44135" {
|
||||||
|
t.Errorf("getTillerlessEnv() HELM_TILLER_PORT\nactual = %s\nexpect = 44135", val)
|
||||||
|
}*/
|
||||||
|
if val, found := actual["KUBECONFIG"]; found {
|
||||||
|
t.Errorf("getTillerlessEnv() KUBECONFIG\nactual = %s\nexpect = nil", val)
|
||||||
|
}
|
||||||
|
|
||||||
|
os.Setenv("KUBECONFIG", "toto")
|
||||||
|
actual = context.getTillerlessEnv()
|
||||||
|
cwd, _ := os.Getwd()
|
||||||
|
expected := path.Join(cwd, "toto")
|
||||||
|
if val, found := actual["KUBECONFIG"]; !found || val != expected {
|
||||||
|
t.Errorf("getTillerlessEnv() KUBECONFIG\nactual = %s\nexpect = %s", val, expected)
|
||||||
|
}
|
||||||
|
os.Unsetenv("KUBECONFIG")
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_mergeEnv(t *testing.T) {
|
||||||
|
actual := env2map(mergeEnv([]string{"A=1", "B=c=d", "E=2"}, map[string]string{"B": "3", "F": "4"}))
|
||||||
|
expected := map[string]string{"A": "1", "B": "3", "E": "2", "F": "4"}
|
||||||
|
if !reflect.DeepEqual(actual, expected) {
|
||||||
|
t.Errorf("mergeEnv()\nactual = %v\nexpect = %v", actual, expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,14 +9,14 @@ type Interface interface {
|
||||||
UpdateRepo() error
|
UpdateRepo() error
|
||||||
BuildDeps(chart string) error
|
BuildDeps(chart string) error
|
||||||
UpdateDeps(chart string) error
|
UpdateDeps(chart string) error
|
||||||
SyncRelease(name, chart string, flags ...string) error
|
SyncRelease(context HelmContext, name, chart string, flags ...string) error
|
||||||
DiffRelease(name, chart string, flags ...string) error
|
DiffRelease(context HelmContext, name, chart string, flags ...string) error
|
||||||
TemplateRelease(chart string, flags ...string) error
|
TemplateRelease(chart string, flags ...string) error
|
||||||
Fetch(chart string, flags ...string) error
|
Fetch(chart string, flags ...string) error
|
||||||
Lint(chart string, flags ...string) error
|
Lint(chart string, flags ...string) error
|
||||||
ReleaseStatus(name string, flags ...string) error
|
ReleaseStatus(context HelmContext, name string, flags ...string) error
|
||||||
DeleteRelease(name string, flags ...string) error
|
DeleteRelease(context HelmContext, name string, flags ...string) error
|
||||||
TestRelease(name string, flags ...string) error
|
TestRelease(context HelmContext, name string, flags ...string) error
|
||||||
List(filter string, flags ...string) (string, error)
|
List(context HelmContext, filter string, flags ...string) (string, error)
|
||||||
DecryptSecret(name string) (string, error)
|
DecryptSecret(context HelmContext, name string, flags ...string) (string, error)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
package helmexec
|
package helmexec
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -11,7 +13,7 @@ const (
|
||||||
|
|
||||||
// Runner interface for shell commands
|
// Runner interface for shell commands
|
||||||
type Runner interface {
|
type Runner interface {
|
||||||
Execute(cmd string, args []string) ([]byte, error)
|
Execute(cmd string, args []string, env map[string]string) ([]byte, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ShellRunner implemention for shell commands
|
// ShellRunner implemention for shell commands
|
||||||
|
|
@ -20,8 +22,34 @@ type ShellRunner struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute a shell command
|
// Execute a shell command
|
||||||
func (shell ShellRunner) Execute(cmd string, args []string) ([]byte, error) {
|
func (shell ShellRunner) Execute(cmd string, args []string, env map[string]string) ([]byte, error) {
|
||||||
preparedCmd := exec.Command(cmd, args...)
|
preparedCmd := exec.Command(cmd, args...)
|
||||||
preparedCmd.Dir = shell.Dir
|
preparedCmd.Dir = shell.Dir
|
||||||
|
preparedCmd.Env = mergeEnv(os.Environ(), env)
|
||||||
return preparedCmd.CombinedOutput()
|
return preparedCmd.CombinedOutput()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mergeEnv(orig []string, new map[string]string) []string {
|
||||||
|
wanted := env2map(orig)
|
||||||
|
for k, v := range new {
|
||||||
|
wanted[k] = v
|
||||||
|
}
|
||||||
|
return map2env(wanted)
|
||||||
|
}
|
||||||
|
|
||||||
|
func map2env(wanted map[string]string) []string {
|
||||||
|
result := []string{}
|
||||||
|
for k, v := range wanted {
|
||||||
|
result = append(result, k+"="+v)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func env2map(env []string) map[string]string {
|
||||||
|
wanted := map[string]string{}
|
||||||
|
for _, cur := range env {
|
||||||
|
pair := strings.SplitN(cur, "=", 2)
|
||||||
|
wanted[pair[0]] = pair[1]
|
||||||
|
}
|
||||||
|
return wanted
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -158,8 +158,9 @@ func (st *HelmState) loadEnv(name string, readFile func(string) ([]byte, error))
|
||||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
release := &st.Releases[0]
|
||||||
decFile, err := helm.DecryptSecret(path)
|
flags := st.appendTillerFlags([]string{}, release)
|
||||||
|
decFile, err := helm.DecryptSecret(st.createHelmContext(release, 0), path, flags...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@ type HelmState struct {
|
||||||
type HelmSpec struct {
|
type HelmSpec struct {
|
||||||
KubeContext string `yaml:"kubeContext"`
|
KubeContext string `yaml:"kubeContext"`
|
||||||
TillerNamespace string `yaml:"tillerNamespace"`
|
TillerNamespace string `yaml:"tillerNamespace"`
|
||||||
|
Tillerless bool `yaml:"tillerless"`
|
||||||
Args []string `yaml:"args"`
|
Args []string `yaml:"args"`
|
||||||
Verify bool `yaml:"verify"`
|
Verify bool `yaml:"verify"`
|
||||||
// Devel, when set to true, use development versions, too. Equivalent to version '>0.0.0-0'
|
// Devel, when set to true, use development versions, too. Equivalent to version '>0.0.0-0'
|
||||||
|
|
@ -130,6 +131,7 @@ type ReleaseSpec struct {
|
||||||
ValuesPathPrefix string `yaml:"valuesPathPrefix"`
|
ValuesPathPrefix string `yaml:"valuesPathPrefix"`
|
||||||
|
|
||||||
TillerNamespace string `yaml:"tillerNamespace"`
|
TillerNamespace string `yaml:"tillerNamespace"`
|
||||||
|
Tillerless *bool `yaml:"tillerless"`
|
||||||
|
|
||||||
TLS *bool `yaml:"tls"`
|
TLS *bool `yaml:"tls"`
|
||||||
TLSCACert string `yaml:"tlsCACert"`
|
TLSCACert string `yaml:"tlsCACert"`
|
||||||
|
|
@ -226,11 +228,11 @@ func (st *HelmState) prepareSyncReleases(helm helmexec.Interface, additionalValu
|
||||||
}
|
}
|
||||||
close(jobs)
|
close(jobs)
|
||||||
},
|
},
|
||||||
func(_ int) {
|
func(workerIndex int) {
|
||||||
for release := range jobs {
|
for release := range jobs {
|
||||||
st.applyDefaultsTo(release)
|
st.applyDefaultsTo(release)
|
||||||
|
|
||||||
flags, flagsErr := st.flagsForUpgrade(helm, release)
|
flags, flagsErr := st.flagsForUpgrade(helm, release, workerIndex)
|
||||||
if flagsErr != nil {
|
if flagsErr != nil {
|
||||||
results <- syncPrepareResult{errors: []*ReleaseError{&ReleaseError{release, flagsErr}}}
|
results <- syncPrepareResult{errors: []*ReleaseError{&ReleaseError{release, flagsErr}}}
|
||||||
continue
|
continue
|
||||||
|
|
@ -277,8 +279,8 @@ func (st *HelmState) prepareSyncReleases(helm helmexec.Interface, additionalValu
|
||||||
return res, errs
|
return res, errs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *HelmState) isReleaseInstalled(helm helmexec.Interface, release ReleaseSpec) (bool, error) {
|
func (st *HelmState) isReleaseInstalled(context helmexec.HelmContext, helm helmexec.Interface, release ReleaseSpec) (bool, error) {
|
||||||
out, err := helm.List("^"+release.Name+"$", st.tillerFlags(&release)...)
|
out, err := helm.List(context, "^"+release.Name+"$", st.tillerFlags(&release)...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
} else if out != "" {
|
} else if out != "" {
|
||||||
|
|
@ -289,10 +291,9 @@ func (st *HelmState) isReleaseInstalled(helm helmexec.Interface, release Release
|
||||||
|
|
||||||
func (st *HelmState) DetectReleasesToBeDeleted(helm helmexec.Interface) ([]*ReleaseSpec, error) {
|
func (st *HelmState) DetectReleasesToBeDeleted(helm helmexec.Interface) ([]*ReleaseSpec, error) {
|
||||||
detected := []*ReleaseSpec{}
|
detected := []*ReleaseSpec{}
|
||||||
for i, _ := range st.Releases {
|
for _, release := range st.Releases {
|
||||||
release := st.Releases[i]
|
|
||||||
if !release.Desired() {
|
if !release.Desired() {
|
||||||
installed, err := st.isReleaseInstalled(helm, release)
|
installed, err := st.isReleaseInstalled(st.createHelmContext(&release, 0), helm, release)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if installed {
|
} else if installed {
|
||||||
|
|
@ -323,22 +324,23 @@ func (st *HelmState) SyncReleases(helm helmexec.Interface, additionalValues []st
|
||||||
}
|
}
|
||||||
close(jobQueue)
|
close(jobQueue)
|
||||||
},
|
},
|
||||||
func(_ int) {
|
func(workerIndex int) {
|
||||||
for prep := range jobQueue {
|
for prep := range jobQueue {
|
||||||
release := prep.release
|
release := prep.release
|
||||||
flags := prep.flags
|
flags := prep.flags
|
||||||
chart := normalizeChart(st.basePath, release.Chart)
|
chart := normalizeChart(st.basePath, release.Chart)
|
||||||
var relErr *ReleaseError
|
var relErr *ReleaseError
|
||||||
|
context := st.createHelmContext(release, workerIndex)
|
||||||
if !release.Desired() {
|
if !release.Desired() {
|
||||||
installed, err := st.isReleaseInstalled(helm, *release)
|
installed, err := st.isReleaseInstalled(context, helm, *release)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
relErr = &ReleaseError{release, err}
|
relErr = &ReleaseError{release, err}
|
||||||
} else if installed {
|
} else if installed {
|
||||||
if err := helm.DeleteRelease(release.Name, "--purge"); err != nil {
|
if err := helm.DeleteRelease(context, release.Name, "--purge"); err != nil {
|
||||||
relErr = &ReleaseError{release, err}
|
relErr = &ReleaseError{release, err}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if err := helm.SyncRelease(release.Name, chart, flags...); err != nil {
|
} else if err := helm.SyncRelease(context, release.Name, chart, flags...); err != nil {
|
||||||
relErr = &ReleaseError{release, err}
|
relErr = &ReleaseError{release, err}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -468,7 +470,7 @@ func (st *HelmState) TemplateReleases(helm helmexec.Interface, additionalValues
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
flags, err := st.flagsForTemplate(helm, &release)
|
flags, err := st.flagsForTemplate(helm, &release, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs = append(errs, err)
|
errs = append(errs, err)
|
||||||
}
|
}
|
||||||
|
|
@ -528,7 +530,7 @@ func (st *HelmState) LintReleases(helm helmexec.Interface, additionalValues []st
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
flags, err := st.flagsForLint(helm, &release)
|
flags, err := st.flagsForLint(helm, &release, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs = append(errs, err)
|
errs = append(errs, err)
|
||||||
}
|
}
|
||||||
|
|
@ -607,13 +609,13 @@ func (st *HelmState) prepareDiffReleases(helm helmexec.Interface, additionalValu
|
||||||
}
|
}
|
||||||
close(jobs)
|
close(jobs)
|
||||||
},
|
},
|
||||||
func(_ int) {
|
func(workerIndex int) {
|
||||||
for release := range jobs {
|
for release := range jobs {
|
||||||
errs := []error{}
|
errs := []error{}
|
||||||
|
|
||||||
st.applyDefaultsTo(release)
|
st.applyDefaultsTo(release)
|
||||||
|
|
||||||
flags, err := st.flagsForDiff(helm, release)
|
flags, err := st.flagsForDiff(helm, release, workerIndex)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs = append(errs, err)
|
errs = append(errs, err)
|
||||||
}
|
}
|
||||||
|
|
@ -666,6 +668,23 @@ func (st *HelmState) prepareDiffReleases(helm helmexec.Interface, additionalValu
|
||||||
return rs, errs
|
return rs, errs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (st *HelmState) createHelmContext(spec *ReleaseSpec, workerIndex int) helmexec.HelmContext {
|
||||||
|
namespace := st.HelmDefaults.TillerNamespace
|
||||||
|
if spec.TillerNamespace != "" {
|
||||||
|
namespace = spec.TillerNamespace
|
||||||
|
}
|
||||||
|
tillerless := st.HelmDefaults.Tillerless
|
||||||
|
if spec.Tillerless != nil {
|
||||||
|
tillerless = *spec.Tillerless
|
||||||
|
}
|
||||||
|
|
||||||
|
return helmexec.HelmContext{
|
||||||
|
Tillerless: tillerless,
|
||||||
|
TillerNamespace: namespace,
|
||||||
|
WorkerIndex: workerIndex,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// DiffReleases wrapper for executing helm diff on the releases
|
// DiffReleases wrapper for executing helm diff on the releases
|
||||||
// It returns releases that had any changes
|
// It returns releases that had any changes
|
||||||
func (st *HelmState) DiffReleases(helm helmexec.Interface, additionalValues []string, workerLimit int, detailedExitCode, suppressSecrets bool, triggerCleanupEvents bool) ([]*ReleaseSpec, []error) {
|
func (st *HelmState) DiffReleases(helm helmexec.Interface, additionalValues []string, workerLimit int, detailedExitCode, suppressSecrets bool, triggerCleanupEvents bool) ([]*ReleaseSpec, []error) {
|
||||||
|
|
@ -689,11 +708,11 @@ func (st *HelmState) DiffReleases(helm helmexec.Interface, additionalValues []st
|
||||||
}
|
}
|
||||||
close(jobQueue)
|
close(jobQueue)
|
||||||
},
|
},
|
||||||
func(_ int) {
|
func(workerIndex int) {
|
||||||
for prep := range jobQueue {
|
for prep := range jobQueue {
|
||||||
flags := prep.flags
|
flags := prep.flags
|
||||||
release := prep.release
|
release := prep.release
|
||||||
if err := helm.DiffRelease(release.Name, normalizeChart(st.basePath, release.Chart), flags...); err != nil {
|
if err := helm.DiffRelease(st.createHelmContext(release, workerIndex), release.Name, normalizeChart(st.basePath, release.Chart), flags...); err != nil {
|
||||||
switch e := err.(type) {
|
switch e := err.(type) {
|
||||||
case *exec.ExitError:
|
case *exec.ExitError:
|
||||||
// Propagate any non-zero exit status from the external command like `helm` that is failed under the hood
|
// Propagate any non-zero exit status from the external command like `helm` that is failed under the hood
|
||||||
|
|
@ -731,7 +750,7 @@ func (st *HelmState) DiffReleases(helm helmexec.Interface, additionalValues []st
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *HelmState) ReleaseStatuses(helm helmexec.Interface, workerLimit int) []error {
|
func (st *HelmState) ReleaseStatuses(helm helmexec.Interface, workerLimit int) []error {
|
||||||
return st.scatterGatherReleases(helm, workerLimit, func(release ReleaseSpec) error {
|
return st.scatterGatherReleases(helm, workerLimit, func(release ReleaseSpec, workerIndex int) error {
|
||||||
if !release.Desired() {
|
if !release.Desired() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -739,13 +758,13 @@ func (st *HelmState) ReleaseStatuses(helm helmexec.Interface, workerLimit int) [
|
||||||
flags := []string{}
|
flags := []string{}
|
||||||
flags = st.appendTillerFlags(flags, &release)
|
flags = st.appendTillerFlags(flags, &release)
|
||||||
|
|
||||||
return helm.ReleaseStatus(release.Name, flags...)
|
return helm.ReleaseStatus(st.createHelmContext(&release, workerIndex), release.Name, flags...)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteReleases wrapper for executing helm delete on the releases
|
// DeleteReleases wrapper for executing helm delete on the releases
|
||||||
func (st *HelmState) DeleteReleases(helm helmexec.Interface, purge bool) []error {
|
func (st *HelmState) DeleteReleases(helm helmexec.Interface, purge bool) []error {
|
||||||
return st.scatterGatherReleases(helm, len(st.Releases), func(release ReleaseSpec) error {
|
return st.scatterGatherReleases(helm, len(st.Releases), func(release ReleaseSpec, workerIndex int) error {
|
||||||
if !release.Desired() {
|
if !release.Desired() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -755,13 +774,14 @@ func (st *HelmState) DeleteReleases(helm helmexec.Interface, purge bool) []error
|
||||||
flags = append(flags, "--purge")
|
flags = append(flags, "--purge")
|
||||||
}
|
}
|
||||||
flags = st.appendTillerFlags(flags, &release)
|
flags = st.appendTillerFlags(flags, &release)
|
||||||
|
context := st.createHelmContext(&release, workerIndex)
|
||||||
|
|
||||||
installed, err := st.isReleaseInstalled(helm, release)
|
installed, err := st.isReleaseInstalled(context, helm, release)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if installed {
|
if installed {
|
||||||
return helm.DeleteRelease(release.Name, flags...)
|
return helm.DeleteRelease(context, release.Name, flags...)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
@ -769,7 +789,7 @@ func (st *HelmState) DeleteReleases(helm helmexec.Interface, purge bool) []error
|
||||||
|
|
||||||
// TestReleases wrapper for executing helm test on the releases
|
// TestReleases wrapper for executing helm test on the releases
|
||||||
func (st *HelmState) TestReleases(helm helmexec.Interface, cleanup bool, timeout int, concurrency int) []error {
|
func (st *HelmState) TestReleases(helm helmexec.Interface, cleanup bool, timeout int, concurrency int) []error {
|
||||||
return st.scatterGatherReleases(helm, concurrency, func(release ReleaseSpec) error {
|
return st.scatterGatherReleases(helm, concurrency, func(release ReleaseSpec, workerIndex int) error {
|
||||||
if !release.Desired() {
|
if !release.Desired() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -781,7 +801,7 @@ func (st *HelmState) TestReleases(helm helmexec.Interface, cleanup bool, timeout
|
||||||
flags = append(flags, "--timeout", strconv.Itoa(timeout))
|
flags = append(flags, "--timeout", strconv.Itoa(timeout))
|
||||||
flags = st.appendTillerFlags(flags, &release)
|
flags = st.appendTillerFlags(flags, &release)
|
||||||
|
|
||||||
return helm.TestRelease(release.Name, flags...)
|
return helm.TestRelease(st.createHelmContext(&release, workerIndex), release.Name, flags...)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -993,6 +1013,11 @@ func (st *HelmState) appendTillerFlags(flags []string, release *ReleaseSpec) []s
|
||||||
|
|
||||||
func (st *HelmState) tillerFlags(release *ReleaseSpec) []string {
|
func (st *HelmState) tillerFlags(release *ReleaseSpec) []string {
|
||||||
flags := []string{}
|
flags := []string{}
|
||||||
|
tillerless := st.HelmDefaults.Tillerless
|
||||||
|
if release.Tillerless != nil {
|
||||||
|
tillerless = *release.Tillerless
|
||||||
|
}
|
||||||
|
if !tillerless {
|
||||||
if release.TillerNamespace != "" {
|
if release.TillerNamespace != "" {
|
||||||
flags = append(flags, "--tiller-namespace", release.TillerNamespace)
|
flags = append(flags, "--tiller-namespace", release.TillerNamespace)
|
||||||
} else if st.HelmDefaults.TillerNamespace != "" {
|
} else if st.HelmDefaults.TillerNamespace != "" {
|
||||||
|
|
@ -1020,11 +1045,12 @@ func (st *HelmState) tillerFlags(release *ReleaseSpec) []string {
|
||||||
} else if st.HelmDefaults.TLSCACert != "" {
|
} else if st.HelmDefaults.TLSCACert != "" {
|
||||||
flags = append(flags, "--tls-ca-cert", st.HelmDefaults.TLSCACert)
|
flags = append(flags, "--tls-ca-cert", st.HelmDefaults.TLSCACert)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return flags
|
return flags
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *HelmState) flagsForUpgrade(helm helmexec.Interface, release *ReleaseSpec) ([]string, error) {
|
func (st *HelmState) flagsForUpgrade(helm helmexec.Interface, release *ReleaseSpec, workerIndex int) ([]string, error) {
|
||||||
flags := []string{}
|
flags := []string{}
|
||||||
if release.Version != "" {
|
if release.Version != "" {
|
||||||
flags = append(flags, "--version", release.Version)
|
flags = append(flags, "--version", release.Version)
|
||||||
|
|
@ -1064,25 +1090,25 @@ func (st *HelmState) flagsForUpgrade(helm helmexec.Interface, release *ReleaseSp
|
||||||
|
|
||||||
flags = st.appendTillerFlags(flags, release)
|
flags = st.appendTillerFlags(flags, release)
|
||||||
|
|
||||||
common, err := st.namespaceAndValuesFlags(helm, release)
|
common, err := st.namespaceAndValuesFlags(helm, release, workerIndex)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return append(flags, common...), nil
|
return append(flags, common...), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *HelmState) flagsForTemplate(helm helmexec.Interface, release *ReleaseSpec) ([]string, error) {
|
func (st *HelmState) flagsForTemplate(helm helmexec.Interface, release *ReleaseSpec, workerIndex int) ([]string, error) {
|
||||||
flags := []string{
|
flags := []string{
|
||||||
"--name", release.Name,
|
"--name", release.Name,
|
||||||
}
|
}
|
||||||
common, err := st.namespaceAndValuesFlags(helm, release)
|
common, err := st.namespaceAndValuesFlags(helm, release, workerIndex)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return append(flags, common...), nil
|
return append(flags, common...), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *HelmState) flagsForDiff(helm helmexec.Interface, release *ReleaseSpec) ([]string, error) {
|
func (st *HelmState) flagsForDiff(helm helmexec.Interface, release *ReleaseSpec, workerIndex int) ([]string, error) {
|
||||||
flags := []string{}
|
flags := []string{}
|
||||||
if release.Version != "" {
|
if release.Version != "" {
|
||||||
flags = append(flags, "--version", release.Version)
|
flags = append(flags, "--version", release.Version)
|
||||||
|
|
@ -1094,7 +1120,7 @@ func (st *HelmState) flagsForDiff(helm helmexec.Interface, release *ReleaseSpec)
|
||||||
|
|
||||||
flags = st.appendTillerFlags(flags, release)
|
flags = st.appendTillerFlags(flags, release)
|
||||||
|
|
||||||
common, err := st.namespaceAndValuesFlags(helm, release)
|
common, err := st.namespaceAndValuesFlags(helm, release, workerIndex)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -1110,8 +1136,8 @@ func (st *HelmState) isDevelopment(release *ReleaseSpec) bool {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *HelmState) flagsForLint(helm helmexec.Interface, release *ReleaseSpec) ([]string, error) {
|
func (st *HelmState) flagsForLint(helm helmexec.Interface, release *ReleaseSpec, workerIndex int) ([]string, error) {
|
||||||
return st.namespaceAndValuesFlags(helm, release)
|
return st.namespaceAndValuesFlags(helm, release, workerIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *HelmState) RenderValuesFileToBytes(path string) ([]byte, error) {
|
func (st *HelmState) RenderValuesFileToBytes(path string) ([]byte, error) {
|
||||||
|
|
@ -1181,7 +1207,7 @@ func (st *HelmState) generateTemporaryValuesFiles(values []interface{}, missingF
|
||||||
return generatedFiles, nil
|
return generatedFiles, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *HelmState) namespaceAndValuesFlags(helm helmexec.Interface, release *ReleaseSpec) ([]string, error) {
|
func (st *HelmState) namespaceAndValuesFlags(helm helmexec.Interface, release *ReleaseSpec, workerIndex int) ([]string, error) {
|
||||||
flags := []string{}
|
flags := []string{}
|
||||||
if release.Namespace != "" {
|
if release.Namespace != "" {
|
||||||
flags = append(flags, "--namespace", release.Namespace)
|
flags = append(flags, "--namespace", release.Namespace)
|
||||||
|
|
@ -1230,7 +1256,8 @@ func (st *HelmState) namespaceAndValuesFlags(helm helmexec.Interface, release *R
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
valfile, err := helm.DecryptSecret(path)
|
decryptFlags := st.appendTillerFlags([]string{}, release)
|
||||||
|
valfile, err := helm.DecryptSecret(st.createHelmContext(release, workerIndex), path, decryptFlags...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,8 @@ func (st *HelmState) scatterGather(concurrency int, items int, produceInputs fun
|
||||||
waitGroup.Wait()
|
waitGroup.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *HelmState) scatterGatherReleases(helm helmexec.Interface, concurrency int, do func(ReleaseSpec) error) []error {
|
func (st *HelmState) scatterGatherReleases(helm helmexec.Interface, concurrency int,
|
||||||
|
do func(ReleaseSpec, int) error) []error {
|
||||||
var errs []error
|
var errs []error
|
||||||
|
|
||||||
inputs := st.Releases
|
inputs := st.Releases
|
||||||
|
|
@ -60,7 +61,7 @@ func (st *HelmState) scatterGatherReleases(helm helmexec.Interface, concurrency
|
||||||
},
|
},
|
||||||
func(id int) {
|
func(id int) {
|
||||||
for release := range releases {
|
for release := range releases {
|
||||||
err := do(release)
|
err := do(release, id)
|
||||||
st.logger.Debugf("sending result for release: %s\n", release.Name)
|
st.logger.Debugf("sending result for release: %s\n", release.Name)
|
||||||
results <- result{release: release, err: err}
|
results <- result{release: release, err: err}
|
||||||
st.logger.Debugf("sent result for release: %s\n", release.Name)
|
st.logger.Debugf("sent result for release: %s\n", release.Name)
|
||||||
|
|
|
||||||
|
|
@ -512,7 +512,7 @@ func TestHelmState_flagsForUpgrade(t *testing.T) {
|
||||||
HelmDefaults: tt.defaults,
|
HelmDefaults: tt.defaults,
|
||||||
}
|
}
|
||||||
helm := helmexec.New(logger, "default")
|
helm := helmexec.New(logger, "default")
|
||||||
args, err := state.flagsForUpgrade(helm, tt.release)
|
args, err := state.flagsForUpgrade(helm, tt.release, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error flagsForUpgade: %v", err)
|
t.Errorf("unexpected error flagsForUpgade: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -679,7 +679,7 @@ func (helm *mockHelmExec) AddRepo(name, repository, certfile, keyfile, username,
|
||||||
func (helm *mockHelmExec) UpdateRepo() error {
|
func (helm *mockHelmExec) UpdateRepo() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (helm *mockHelmExec) SyncRelease(name, chart string, flags ...string) error {
|
func (helm *mockHelmExec) SyncRelease(context helmexec.HelmContext, name, chart string, flags ...string) error {
|
||||||
if strings.Contains(name, "error") {
|
if strings.Contains(name, "error") {
|
||||||
return errors.New("error")
|
return errors.New("error")
|
||||||
}
|
}
|
||||||
|
|
@ -687,28 +687,28 @@ func (helm *mockHelmExec) SyncRelease(name, chart string, flags ...string) error
|
||||||
helm.charts = append(helm.charts, chart)
|
helm.charts = append(helm.charts, chart)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (helm *mockHelmExec) DiffRelease(name, chart string, flags ...string) error {
|
func (helm *mockHelmExec) DiffRelease(context helmexec.HelmContext, name, chart string, flags ...string) error {
|
||||||
helm.diffed = append(helm.diffed, mockRelease{name: name, flags: flags})
|
helm.diffed = append(helm.diffed, mockRelease{name: name, flags: flags})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (helm *mockHelmExec) ReleaseStatus(release string, flags ...string) error {
|
func (helm *mockHelmExec) ReleaseStatus(context helmexec.HelmContext, release string, flags ...string) error {
|
||||||
if strings.Contains(release, "error") {
|
if strings.Contains(release, "error") {
|
||||||
return errors.New("error")
|
return errors.New("error")
|
||||||
}
|
}
|
||||||
helm.releases = append(helm.releases, mockRelease{name: release, flags: flags})
|
helm.releases = append(helm.releases, mockRelease{name: release, flags: flags})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (helm *mockHelmExec) DeleteRelease(name string, flags ...string) error {
|
func (helm *mockHelmExec) DeleteRelease(context helmexec.HelmContext, name string, flags ...string) error {
|
||||||
helm.deleted = append(helm.deleted, mockRelease{name: name, flags: flags})
|
helm.deleted = append(helm.deleted, mockRelease{name: name, flags: flags})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (helm *mockHelmExec) List(filter string, flags ...string) (string, error) {
|
func (helm *mockHelmExec) List(context helmexec.HelmContext, filter string, flags ...string) (string, error) {
|
||||||
return helm.lists[listKey{filter: filter, flags: strings.Join(flags, "")}], nil
|
return helm.lists[listKey{filter: filter, flags: strings.Join(flags, "")}], nil
|
||||||
}
|
}
|
||||||
func (helm *mockHelmExec) DecryptSecret(name string) (string, error) {
|
func (helm *mockHelmExec) DecryptSecret(context helmexec.HelmContext, name string, flags ...string) (string, error) {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
func (helm *mockHelmExec) TestRelease(name string, flags ...string) error {
|
func (helm *mockHelmExec) TestRelease(context helmexec.HelmContext, name string, flags ...string) error {
|
||||||
if strings.Contains(name, "error") {
|
if strings.Contains(name, "error") {
|
||||||
return errors.New("error")
|
return errors.New("error")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue