fix: unexpected `no releases found for any helmfiles` on `helmfiles:` config (#318)
Fixes #315 Fixes #316
This commit is contained in:
parent
595c70f85b
commit
7c65b2ed2c
|
|
@ -0,0 +1,108 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/roboll/helmfile/helmexec"
|
||||||
|
"github.com/roboll/helmfile/state"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// See https://github.com/roboll/helmfile/issues/193
|
||||||
|
func TestFindAndIterateOverDesiredStates(t *testing.T) {
|
||||||
|
absPaths := map[string]string{
|
||||||
|
".": "/path/to",
|
||||||
|
"/path/to/helmfile.d": "/path/to/helmfile.d",
|
||||||
|
}
|
||||||
|
dirs := map[string]bool{
|
||||||
|
"helmfile.d": true,
|
||||||
|
}
|
||||||
|
files := map[string]string{
|
||||||
|
"helmfile.yaml": `
|
||||||
|
helmfiles:
|
||||||
|
- helmfile.d/a*.yaml
|
||||||
|
- helmfile.d/b*.yaml
|
||||||
|
`,
|
||||||
|
"/path/to/helmfile.d/a1.yaml": `
|
||||||
|
releases:
|
||||||
|
- name: zipkin
|
||||||
|
chart: stable/zipkin
|
||||||
|
`,
|
||||||
|
"/path/to/helmfile.d/a2.yaml": `
|
||||||
|
releases:
|
||||||
|
- name: prometheus
|
||||||
|
chart: stable/prometheus
|
||||||
|
`,
|
||||||
|
"/path/to/helmfile.d/b.yaml": `
|
||||||
|
releases:
|
||||||
|
- name: grafana
|
||||||
|
chart: stable/grafana
|
||||||
|
`,
|
||||||
|
}
|
||||||
|
globMatches := map[string][]string{
|
||||||
|
"/path/to/helmfile.d/a*.yaml": []string{"/path/to/helmfile.d/a1.yaml", "/path/to/helmfile.d/a2.yaml"},
|
||||||
|
"/path/to/helmfile.d/b*.yaml": []string{"/path/to/helmfile.d/b.yaml"},
|
||||||
|
}
|
||||||
|
fileExistsAt := func(path string) bool {
|
||||||
|
_, ok := files[path]
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
directoryExistsAt := func(path string) bool {
|
||||||
|
_, ok := dirs[path]
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
readFile := func(filename string) ([]byte, error) {
|
||||||
|
str, ok := files[filename]
|
||||||
|
if !ok {
|
||||||
|
return []byte(nil), fmt.Errorf("no file found: %s", filename)
|
||||||
|
}
|
||||||
|
return []byte(str), nil
|
||||||
|
}
|
||||||
|
glob := func(pattern string) ([]string, error) {
|
||||||
|
matches, ok := globMatches[pattern]
|
||||||
|
if !ok {
|
||||||
|
return []string(nil), fmt.Errorf("no file matched: %s", pattern)
|
||||||
|
}
|
||||||
|
return matches, nil
|
||||||
|
}
|
||||||
|
abs := func(path string) (string, error) {
|
||||||
|
a, ok := absPaths[path]
|
||||||
|
if !ok {
|
||||||
|
return "", fmt.Errorf("abs: unexpected path: %s", path)
|
||||||
|
}
|
||||||
|
return a, nil
|
||||||
|
}
|
||||||
|
app := &app{
|
||||||
|
readFile: readFile,
|
||||||
|
glob: glob,
|
||||||
|
abs: abs,
|
||||||
|
fileExistsAt: fileExistsAt,
|
||||||
|
directoryExistsAt: directoryExistsAt,
|
||||||
|
kubeContext: "default",
|
||||||
|
logger: helmexec.NewLogger(os.Stderr, "debug"),
|
||||||
|
}
|
||||||
|
noop := func(st *state.HelmState, helm helmexec.Interface) []error {
|
||||||
|
return []error{}
|
||||||
|
}
|
||||||
|
|
||||||
|
testcases := []struct {
|
||||||
|
name string
|
||||||
|
expectErr bool
|
||||||
|
}{
|
||||||
|
{name: "prometheus", expectErr: false},
|
||||||
|
{name: "zipkin", expectErr: false},
|
||||||
|
{name: "grafana", expectErr: false},
|
||||||
|
{name: "elasticsearch", expectErr: true},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testcase := range testcases {
|
||||||
|
err := app.FindAndIterateOverDesiredStates(
|
||||||
|
"helmfile.yaml", noop, "", []string{fmt.Sprintf("name=%s", testcase.name)}, "default",
|
||||||
|
)
|
||||||
|
if testcase.expectErr && err == nil {
|
||||||
|
t.Errorf("error expected but not happened for name=%s", testcase.name)
|
||||||
|
} else if !testcase.expectErr && err != nil {
|
||||||
|
t.Errorf("unexpected error for name=%s: %v", testcase.name, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
137
main.go
137
main.go
|
|
@ -534,6 +534,16 @@ func executeDiffCommand(c *cli.Context, st *state.HelmState, helm helmexec.Inter
|
||||||
return st.DiffReleases(helm, values, workers, detailedExitCode, suppressSecrets)
|
return st.DiffReleases(helm, values, workers, detailedExitCode, suppressSecrets)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type app struct {
|
||||||
|
kubeContext string
|
||||||
|
logger *zap.SugaredLogger
|
||||||
|
readFile func(string) ([]byte, error)
|
||||||
|
glob func(string) ([]string, error)
|
||||||
|
abs func(string) (string, error)
|
||||||
|
fileExistsAt func(string) bool
|
||||||
|
directoryExistsAt func(string) bool
|
||||||
|
}
|
||||||
|
|
||||||
func findAndIterateOverDesiredStatesUsingFlags(c *cli.Context, converge func(*state.HelmState, helmexec.Interface) []error) error {
|
func findAndIterateOverDesiredStatesUsingFlags(c *cli.Context, converge func(*state.HelmState, helmexec.Interface) []error) error {
|
||||||
fileOrDir := c.GlobalString("file")
|
fileOrDir := c.GlobalString("file")
|
||||||
kubeContext := c.GlobalString("kube-context")
|
kubeContext := c.GlobalString("kube-context")
|
||||||
|
|
@ -546,101 +556,134 @@ func findAndIterateOverDesiredStatesUsingFlags(c *cli.Context, converge func(*st
|
||||||
env = state.DefaultEnv
|
env = state.DefaultEnv
|
||||||
}
|
}
|
||||||
|
|
||||||
return findAndIterateOverDesiredStates(fileOrDir, converge, kubeContext, namespace, selectors, env, logger)
|
app := &app{
|
||||||
|
readFile: ioutil.ReadFile,
|
||||||
|
glob: filepath.Glob,
|
||||||
|
abs: filepath.Abs,
|
||||||
|
fileExistsAt: fileExistsAt,
|
||||||
|
directoryExistsAt: directoryExistsAt,
|
||||||
|
kubeContext: kubeContext,
|
||||||
|
logger: logger,
|
||||||
|
}
|
||||||
|
if err := app.FindAndIterateOverDesiredStates(fileOrDir, converge, namespace, selectors, env); err != nil {
|
||||||
|
switch e := err.(type) {
|
||||||
|
case *noMatchingHelmfileError:
|
||||||
|
return cli.NewExitError(e.Error(), 2)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func findAndIterateOverDesiredStates(fileOrDir string, converge func(*state.HelmState, helmexec.Interface) []error, kubeContext, namespace string, selectors []string, env string, logger *zap.SugaredLogger) error {
|
type noMatchingHelmfileError struct {
|
||||||
desiredStateFiles, err := findDesiredStateFiles(fileOrDir)
|
selectors []string
|
||||||
|
env string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *noMatchingHelmfileError) Error() string {
|
||||||
|
return fmt.Sprintf(
|
||||||
|
"err: no releases found that matches specified selector(%s) and environment(%s), in any helmfile",
|
||||||
|
strings.Join(e.selectors, ", "),
|
||||||
|
e.env,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *app) FindAndIterateOverDesiredStates(fileOrDir string, converge func(*state.HelmState, helmexec.Interface) []error, namespace string, selectors []string, env string) error {
|
||||||
|
desiredStateFiles, err := a.findDesiredStateFiles(fileOrDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
noTargetFoundForAllHelmfiles := true
|
noMatchInHelmfiles := true
|
||||||
for _, f := range desiredStateFiles {
|
for _, f := range desiredStateFiles {
|
||||||
logger.Debugf("Processing %s", f)
|
a.logger.Debugf("Processing %s", f)
|
||||||
yamlBuf, err := tmpl.NewFileRenderer(ioutil.ReadFile, "", environment.Environment{Name: env, Values: map[string]interface{}(nil)}).RenderTemplateFileToBuffer(f)
|
yamlBuf, err := tmpl.NewFileRenderer(a.readFile, "", environment.Environment{Name: env, Values: map[string]interface{}(nil)}).RenderTemplateFileToBuffer(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
st, helm, noReleasesMatchingSelector, err := loadDesiredStateFromFile(
|
st, noMatchInThisHelmfile, err := a.loadDesiredStateFromYaml(
|
||||||
yamlBuf.Bytes(),
|
yamlBuf.Bytes(),
|
||||||
f,
|
f,
|
||||||
kubeContext,
|
|
||||||
namespace,
|
namespace,
|
||||||
selectors,
|
selectors,
|
||||||
env,
|
env,
|
||||||
logger,
|
|
||||||
)
|
)
|
||||||
|
helm := helmexec.New(a.logger, a.kubeContext)
|
||||||
|
|
||||||
var noTarget bool
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
switch stateLoadErr := err.(type) {
|
switch stateLoadErr := err.(type) {
|
||||||
// Addresses https://github.com/roboll/helmfile/issues/279
|
// Addresses https://github.com/roboll/helmfile/issues/279
|
||||||
case *state.StateLoadError:
|
case *state.StateLoadError:
|
||||||
switch stateLoadErr.Cause.(type) {
|
switch stateLoadErr.Cause.(type) {
|
||||||
case *state.UndefinedEnvError:
|
case *state.UndefinedEnvError:
|
||||||
noTarget = true
|
noMatchInThisHelmfile = true
|
||||||
default:
|
default:
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else if len(st.Helmfiles) > 0 {
|
}
|
||||||
|
|
||||||
|
errs := []error{}
|
||||||
|
|
||||||
|
if len(st.Helmfiles) > 0 {
|
||||||
|
noMatchInSubHelmfiles := true
|
||||||
for _, globPattern := range st.Helmfiles {
|
for _, globPattern := range st.Helmfiles {
|
||||||
helmfileRelativePattern := st.JoinBase(globPattern)
|
helmfileRelativePattern := st.JoinBase(globPattern)
|
||||||
matches, err := filepath.Glob(helmfileRelativePattern)
|
matches, err := a.glob(helmfileRelativePattern)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed processing %s: %v", globPattern, err)
|
return fmt.Errorf("failed processing %s: %v", globPattern, err)
|
||||||
}
|
}
|
||||||
sort.Strings(matches)
|
sort.Strings(matches)
|
||||||
|
|
||||||
for _, m := range matches {
|
for _, m := range matches {
|
||||||
if err := findAndIterateOverDesiredStates(m, converge, kubeContext, namespace, selectors, env, logger); err != nil {
|
if err := a.FindAndIterateOverDesiredStates(m, converge, namespace, selectors, env); err != nil {
|
||||||
return fmt.Errorf("failed processing %s: %v", globPattern, err)
|
switch err.(type) {
|
||||||
|
case *noMatchingHelmfileError:
|
||||||
|
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("failed processing %s: %v", globPattern, err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
noMatchInSubHelmfiles = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
noMatchInHelmfiles = noMatchInHelmfiles && noMatchInSubHelmfiles
|
||||||
} else {
|
} else {
|
||||||
noTarget = noReleasesMatchingSelector
|
noMatchInHelmfiles = noMatchInHelmfiles && noMatchInThisHelmfile
|
||||||
|
if noMatchInThisHelmfile {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
errs = converge(st, helm)
|
||||||
}
|
}
|
||||||
|
|
||||||
noTargetFoundForAllHelmfiles = noTargetFoundForAllHelmfiles && noTarget
|
|
||||||
if noTarget {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
errs := converge(st, helm)
|
|
||||||
if err := clean(st, errs); err != nil {
|
if err := clean(st, errs); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if noTargetFoundForAllHelmfiles {
|
if noMatchInHelmfiles {
|
||||||
logger.Errorf(
|
return &noMatchingHelmfileError{selectors, env}
|
||||||
"err: no releases found that matches specified selector(%s) and environment(%s), in any helmfile",
|
|
||||||
strings.Join(selectors, ", "),
|
|
||||||
env,
|
|
||||||
)
|
|
||||||
os.Exit(2)
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func findDesiredStateFiles(specifiedPath string) ([]string, error) {
|
func (a *app) findDesiredStateFiles(specifiedPath string) ([]string, error) {
|
||||||
var helmfileDir string
|
var helmfileDir string
|
||||||
if specifiedPath != "" {
|
if specifiedPath != "" {
|
||||||
if fileExistsAt(specifiedPath) {
|
if a.fileExistsAt(specifiedPath) {
|
||||||
return []string{specifiedPath}, nil
|
return []string{specifiedPath}, nil
|
||||||
} else if directoryExistsAt(specifiedPath) {
|
} else if a.directoryExistsAt(specifiedPath) {
|
||||||
helmfileDir = specifiedPath
|
helmfileDir = specifiedPath
|
||||||
} else {
|
} else {
|
||||||
return []string{}, fmt.Errorf("specified state file %s is not found", specifiedPath)
|
return []string{}, fmt.Errorf("specified state file %s is not found", specifiedPath)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var defaultFile string
|
var defaultFile string
|
||||||
if fileExistsAt(DefaultHelmfile) {
|
if a.fileExistsAt(DefaultHelmfile) {
|
||||||
defaultFile = DefaultHelmfile
|
defaultFile = DefaultHelmfile
|
||||||
} else if fileExistsAt(DeprecatedHelmfile) {
|
} else if a.fileExistsAt(DeprecatedHelmfile) {
|
||||||
log.Printf(
|
log.Printf(
|
||||||
"warn: %s is being loaded: %s is deprecated in favor of %s. See https://github.com/roboll/helmfile/issues/25 for more information",
|
"warn: %s is being loaded: %s is deprecated in favor of %s. See https://github.com/roboll/helmfile/issues/25 for more information",
|
||||||
DeprecatedHelmfile,
|
DeprecatedHelmfile,
|
||||||
|
|
@ -650,7 +693,7 @@ func findDesiredStateFiles(specifiedPath string) ([]string, error) {
|
||||||
defaultFile = DeprecatedHelmfile
|
defaultFile = DeprecatedHelmfile
|
||||||
}
|
}
|
||||||
|
|
||||||
if directoryExistsAt(DefaultHelmfileDirectory) {
|
if a.directoryExistsAt(DefaultHelmfileDirectory) {
|
||||||
if defaultFile != "" {
|
if defaultFile != "" {
|
||||||
return []string{}, fmt.Errorf("configuration conlict error: you can have either %s or %s, but not both", defaultFile, DefaultHelmfileDirectory)
|
return []string{}, fmt.Errorf("configuration conlict error: you can have either %s or %s, but not both", defaultFile, DefaultHelmfileDirectory)
|
||||||
}
|
}
|
||||||
|
|
@ -663,7 +706,7 @@ func findDesiredStateFiles(specifiedPath string) ([]string, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
files, err := filepath.Glob(filepath.Join(helmfileDir, "*.yaml"))
|
files, err := a.glob(filepath.Join(helmfileDir, "*.yaml"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []string{}, err
|
return []string{}, err
|
||||||
}
|
}
|
||||||
|
|
@ -683,19 +726,19 @@ func directoryExistsAt(path string) bool {
|
||||||
return err == nil && fileInfo.Mode().IsDir()
|
return err == nil && fileInfo.Mode().IsDir()
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadDesiredStateFromFile(yaml []byte, file string, kubeContext, namespace string, labels []string, env string, logger *zap.SugaredLogger) (*state.HelmState, helmexec.Interface, bool, error) {
|
func (a *app) loadDesiredStateFromYaml(yaml []byte, file string, namespace string, labels []string, env string) (*state.HelmState, bool, error) {
|
||||||
st, err := state.CreateFromYaml(yaml, file, env, logger)
|
c := state.NewCreator(a.logger, a.readFile, a.abs)
|
||||||
|
st, err := c.CreateFromYaml(yaml, file, env)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if st.Context != "" {
|
if a.kubeContext != "" {
|
||||||
if kubeContext != "" {
|
if st.Context != "" {
|
||||||
log.Printf("err: Cannot use option --kube-context and set attribute context.")
|
log.Printf("err: Cannot use option --kube-context and set attribute context.")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
st.Context = a.kubeContext
|
||||||
kubeContext = st.Context
|
|
||||||
}
|
}
|
||||||
if namespace != "" {
|
if namespace != "" {
|
||||||
if st.Namespace != "" {
|
if st.Namespace != "" {
|
||||||
|
|
@ -709,7 +752,7 @@ func loadDesiredStateFromFile(yaml []byte, file string, kubeContext, namespace s
|
||||||
err = st.FilterReleases(labels)
|
err = st.FilterReleases(labels)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
return nil, nil, true, nil
|
return nil, true, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -719,7 +762,7 @@ func loadDesiredStateFromFile(yaml []byte, file string, kubeContext, namespace s
|
||||||
}
|
}
|
||||||
for name, c := range releaseNameCounts {
|
for name, c := range releaseNameCounts {
|
||||||
if c > 1 {
|
if c > 1 {
|
||||||
return nil, nil, false, fmt.Errorf("duplicate release \"%s\" found: there were %d releases named \"%s\" matching specified selector", name, c, name)
|
return nil, false, fmt.Errorf("duplicate release \"%s\" found: there were %d releases named \"%s\" matching specified selector", name, c, name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -732,7 +775,7 @@ func loadDesiredStateFromFile(yaml []byte, file string, kubeContext, namespace s
|
||||||
clean(st, errs)
|
clean(st, errs)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return st, helmexec.New(logger, kubeContext), len(st.Releases) == 0, nil
|
return st, len(st.Releases) == 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func clean(st *state.HelmState, errs []error) error {
|
func clean(st *state.HelmState, errs []error) error {
|
||||||
|
|
|
||||||
15
main_test.go
15
main_test.go
|
|
@ -1,6 +1,10 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import "testing"
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
// See https://github.com/roboll/helmfile/issues/193
|
// See https://github.com/roboll/helmfile/issues/193
|
||||||
func TestReadFromYaml_DuplicateReleaseName(t *testing.T) {
|
func TestReadFromYaml_DuplicateReleaseName(t *testing.T) {
|
||||||
|
|
@ -16,7 +20,14 @@ func TestReadFromYaml_DuplicateReleaseName(t *testing.T) {
|
||||||
labels:
|
labels:
|
||||||
stage: post
|
stage: post
|
||||||
`)
|
`)
|
||||||
_, _, _, err := loadDesiredStateFromFile(yamlContent, yamlFile, "default", "default", []string{}, "default", logger)
|
app := &app{
|
||||||
|
readFile: ioutil.ReadFile,
|
||||||
|
glob: filepath.Glob,
|
||||||
|
abs: filepath.Abs,
|
||||||
|
kubeContext: "default",
|
||||||
|
logger: logger,
|
||||||
|
}
|
||||||
|
_, _, err := app.loadDesiredStateFromYaml(yamlContent, yamlFile, "default", []string{}, "default")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("error expected but not happened")
|
t.Error("error expected but not happened")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,14 +30,38 @@ func (e *UndefinedEnvError) Error() string {
|
||||||
return e.msg
|
return e.msg
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateFromYaml(content []byte, file string, env string, logger *zap.SugaredLogger) (*HelmState, error) {
|
func createFromYaml(content []byte, file string, env string, logger *zap.SugaredLogger) (*HelmState, error) {
|
||||||
return createFromYamlWithFileReader(content, file, env, logger, ioutil.ReadFile)
|
c := &creator{
|
||||||
|
logger,
|
||||||
|
ioutil.ReadFile,
|
||||||
|
filepath.Abs,
|
||||||
|
}
|
||||||
|
return c.CreateFromYaml(content, file, env)
|
||||||
}
|
}
|
||||||
|
|
||||||
func createFromYamlWithFileReader(content []byte, file string, env string, logger *zap.SugaredLogger, readFile func(string) ([]byte, error)) (*HelmState, error) {
|
type creator struct {
|
||||||
|
logger *zap.SugaredLogger
|
||||||
|
readFile func(string) ([]byte, error)
|
||||||
|
abs func(string) (string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCreator(logger *zap.SugaredLogger, readFile func(string) ([]byte, error), abs func(string) (string, error)) *creator {
|
||||||
|
return &creator{
|
||||||
|
logger: logger,
|
||||||
|
readFile: readFile,
|
||||||
|
abs: abs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *creator) CreateFromYaml(content []byte, file string, env string) (*HelmState, error) {
|
||||||
var state HelmState
|
var state HelmState
|
||||||
|
|
||||||
state.basePath, _ = filepath.Abs(filepath.Dir(file))
|
basePath, err := c.abs(filepath.Dir(file))
|
||||||
|
if err != nil {
|
||||||
|
return nil, &StateLoadError{fmt.Sprintf("failed to read %s", file), err}
|
||||||
|
}
|
||||||
|
state.basePath = basePath
|
||||||
|
|
||||||
if err := yaml.UnmarshalStrict(content, &state); err != nil {
|
if err := yaml.UnmarshalStrict(content, &state); err != nil {
|
||||||
return nil, &StateLoadError{fmt.Sprintf("failed to read %s", file), err}
|
return nil, &StateLoadError{fmt.Sprintf("failed to read %s", file), err}
|
||||||
}
|
}
|
||||||
|
|
@ -51,15 +75,15 @@ func createFromYamlWithFileReader(content []byte, file string, env string, logge
|
||||||
state.DeprecatedReleases = []ReleaseSpec{}
|
state.DeprecatedReleases = []ReleaseSpec{}
|
||||||
}
|
}
|
||||||
|
|
||||||
state.logger = logger
|
state.logger = c.logger
|
||||||
|
|
||||||
e, err := state.loadEnv(env, readFile)
|
e, err := state.loadEnv(env, c.readFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, &StateLoadError{fmt.Sprintf("failed to read %s", file), err}
|
return nil, &StateLoadError{fmt.Sprintf("failed to read %s", file), err}
|
||||||
}
|
}
|
||||||
state.env = *e
|
state.env = *e
|
||||||
|
|
||||||
state.readFile = readFile
|
state.readFile = c.readFile
|
||||||
|
|
||||||
return &state, nil
|
return &state, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package state
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
@ -13,7 +14,7 @@ func TestReadFromYaml(t *testing.T) {
|
||||||
namespace: mynamespace
|
namespace: mynamespace
|
||||||
chart: mychart
|
chart: mychart
|
||||||
`)
|
`)
|
||||||
state, err := CreateFromYaml(yamlContent, yamlFile, DefaultEnv, logger)
|
state, err := createFromYaml(yamlContent, yamlFile, DefaultEnv, logger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unxpected error: %v", err)
|
t.Errorf("unxpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -36,7 +37,7 @@ func TestReadFromYaml_InexistentEnv(t *testing.T) {
|
||||||
namespace: mynamespace
|
namespace: mynamespace
|
||||||
chart: mychart
|
chart: mychart
|
||||||
`)
|
`)
|
||||||
_, err := CreateFromYaml(yamlContent, yamlFile, "production", logger)
|
_, err := createFromYaml(yamlContent, yamlFile, "production", logger)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("expected error")
|
t.Error("expected error")
|
||||||
}
|
}
|
||||||
|
|
@ -97,7 +98,7 @@ bar: {{ readFile "bar.txt" }}
|
||||||
return nil, fmt.Errorf("unexpected filename: %s", filename)
|
return nil, fmt.Errorf("unexpected filename: %s", filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
state, err := createFromYamlWithFileReader(yamlContent, yamlFile, "production", logger, readFile)
|
state, err := NewCreator(logger, readFile, filepath.Abs).CreateFromYaml(yamlContent, yamlFile, "production")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error: %v", err)
|
t.Errorf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -125,7 +126,7 @@ func TestReadFromYaml_StrictUnmarshalling(t *testing.T) {
|
||||||
namespace: mynamespace
|
namespace: mynamespace
|
||||||
releases: mychart
|
releases: mychart
|
||||||
`)
|
`)
|
||||||
_, err := CreateFromYaml(yamlContent, yamlFile, DefaultEnv, logger)
|
_, err := createFromYaml(yamlContent, yamlFile, DefaultEnv, logger)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("expected an error for wrong key 'releases' which is not in struct")
|
t.Error("expected an error for wrong key 'releases' which is not in struct")
|
||||||
}
|
}
|
||||||
|
|
@ -137,7 +138,7 @@ func TestReadFromYaml_DeprecatedReleaseReferences(t *testing.T) {
|
||||||
- name: myrelease
|
- name: myrelease
|
||||||
chart: mychart
|
chart: mychart
|
||||||
`)
|
`)
|
||||||
state, err := CreateFromYaml(yamlContent, yamlFile, DefaultEnv, logger)
|
state, err := createFromYaml(yamlContent, yamlFile, DefaultEnv, logger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unxpected error: %v", err)
|
t.Errorf("unxpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -159,7 +160,7 @@ releases:
|
||||||
- name: myrelease2
|
- name: myrelease2
|
||||||
chart: mychart2
|
chart: mychart2
|
||||||
`)
|
`)
|
||||||
_, err := CreateFromYaml(yamlContent, yamlFile, DefaultEnv, logger)
|
_, err := createFromYaml(yamlContent, yamlFile, DefaultEnv, logger)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("expected error")
|
t.Error("expected error")
|
||||||
}
|
}
|
||||||
|
|
@ -195,7 +196,7 @@ func TestReadFromYaml_FilterReleasesOnLabels(t *testing.T) {
|
||||||
{LabelFilter{positiveLabels: [][]string{[]string{"tier", "frontend"}}, negativeLabels: [][]string{[]string{"foo", "bar"}}},
|
{LabelFilter{positiveLabels: [][]string{[]string{"tier", "frontend"}}, negativeLabels: [][]string{[]string{"foo", "bar"}}},
|
||||||
[]bool{false, true, false}},
|
[]bool{false, true, false}},
|
||||||
}
|
}
|
||||||
state, err := CreateFromYaml(yamlContent, yamlFile, DefaultEnv, logger)
|
state, err := createFromYaml(yamlContent, yamlFile, DefaultEnv, logger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error: %v", err)
|
t.Errorf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -234,7 +235,7 @@ func TestReadFromYaml_FilterNegatives(t *testing.T) {
|
||||||
{LabelFilter{negativeLabels: [][]string{[]string{"stage", "pre"}, []string{"stage", "post"}}},
|
{LabelFilter{negativeLabels: [][]string{[]string{"stage", "pre"}, []string{"stage", "post"}}},
|
||||||
[]bool{false, false, true}},
|
[]bool{false, false, true}},
|
||||||
}
|
}
|
||||||
state, err := CreateFromYaml(yamlContent, yamlFile, DefaultEnv, logger)
|
state, err := createFromYaml(yamlContent, yamlFile, DefaultEnv, logger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error: %v", err)
|
t.Errorf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -742,10 +742,8 @@ func (state *HelmState) FilterReleases(labels []string) error {
|
||||||
filteredReleases = append(filteredReleases, r)
|
filteredReleases = append(filteredReleases, r)
|
||||||
}
|
}
|
||||||
state.Releases = filteredReleases
|
state.Releases = filteredReleases
|
||||||
if len(filteredReleases) == 0 {
|
numFound := len(filteredReleases)
|
||||||
state.logger.Debugf("specified selector did not match any releases in %s\n", state.FilePath)
|
state.logger.Debugf("%d release(s) matching %s found in %s\n", numFound, strings.Join(labels, ","), state.FilePath)
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue