Ordered helmfile(s) from a directory (#160)
Resolves #151 #137 Notes: - You can have either helmfile.d or helmfile.yaml/charts.yaml, not both
This commit is contained in:
parent
df264e2736
commit
2fba241122
262
main.go
262
main.go
|
|
@ -12,11 +12,14 @@ import (
|
|||
"github.com/roboll/helmfile/helmexec"
|
||||
"github.com/roboll/helmfile/state"
|
||||
"github.com/urfave/cli"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultHelmfile = "helmfile.yaml"
|
||||
DeprecatedHelmfile = "charts.yaml"
|
||||
DefaultHelmfile = "helmfile.yaml"
|
||||
DeprecatedHelmfile = "charts.yaml"
|
||||
DefaultHelmfileDirectory = "helmfile.d"
|
||||
)
|
||||
|
||||
var Version string
|
||||
|
|
@ -66,18 +69,14 @@ func main() {
|
|||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
state, helm, err := before(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return eachDesiredStateDo(c, func(state *state.HelmState, helm helmexec.Interface) []error {
|
||||
args := c.String("args")
|
||||
if len(args) > 0 {
|
||||
helm.SetExtraArgs(strings.Split(args, " ")...)
|
||||
}
|
||||
|
||||
args := c.String("args")
|
||||
if len(args) > 0 {
|
||||
helm.SetExtraArgs(strings.Split(args, " ")...)
|
||||
}
|
||||
|
||||
errs := state.SyncRepos(helm)
|
||||
return clean(state, errs)
|
||||
return state.SyncRepos(helm)
|
||||
})
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -100,21 +99,17 @@ func main() {
|
|||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
state, helm, err := before(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return eachDesiredStateDo(c, func(state *state.HelmState, helm helmexec.Interface) []error {
|
||||
args := c.String("args")
|
||||
if len(args) > 0 {
|
||||
helm.SetExtraArgs(strings.Split(args, " ")...)
|
||||
}
|
||||
|
||||
args := c.String("args")
|
||||
if len(args) > 0 {
|
||||
helm.SetExtraArgs(strings.Split(args, " ")...)
|
||||
}
|
||||
values := c.StringSlice("values")
|
||||
workers := c.Int("concurrency")
|
||||
|
||||
values := c.StringSlice("values")
|
||||
workers := c.Int("concurrency")
|
||||
|
||||
errs := state.SyncReleases(helm, values, workers)
|
||||
return clean(state, errs)
|
||||
return state.SyncReleases(helm, values, workers)
|
||||
})
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -141,30 +136,23 @@ func main() {
|
|||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
state, helm, err := before(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
args := c.String("args")
|
||||
if len(args) > 0 {
|
||||
helm.SetExtraArgs(strings.Split(args, " ")...)
|
||||
}
|
||||
|
||||
if c.Bool("sync-repos") {
|
||||
if errs := state.SyncRepos(helm); errs != nil && len(errs) > 0 {
|
||||
for _, err := range errs {
|
||||
fmt.Printf("err: %s\n", err.Error())
|
||||
}
|
||||
os.Exit(1)
|
||||
return eachDesiredStateDo(c, func(state *state.HelmState, helm helmexec.Interface) []error {
|
||||
args := c.String("args")
|
||||
if len(args) > 0 {
|
||||
helm.SetExtraArgs(strings.Split(args, " ")...)
|
||||
}
|
||||
}
|
||||
|
||||
values := c.StringSlice("values")
|
||||
workers := c.Int("concurrency")
|
||||
if c.Bool("sync-repos") {
|
||||
if errs := state.SyncRepos(helm); errs != nil && len(errs) > 0 {
|
||||
return errs
|
||||
}
|
||||
}
|
||||
|
||||
errs := state.DiffReleases(helm, values, workers)
|
||||
return clean(state, errs)
|
||||
values := c.StringSlice("values")
|
||||
workers := c.Int("concurrency")
|
||||
|
||||
return state.DiffReleases(helm, values, workers)
|
||||
})
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -187,35 +175,25 @@ func main() {
|
|||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
state, helm, err := before(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if errs := state.SyncRepos(helm); errs != nil && len(errs) > 0 {
|
||||
for _, err := range errs {
|
||||
fmt.Printf("err: %s\n", err.Error())
|
||||
return eachDesiredStateDo(c, func(state *state.HelmState, helm helmexec.Interface) []error {
|
||||
if errs := state.SyncRepos(helm); errs != nil && len(errs) > 0 {
|
||||
return errs
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if errs := state.UpdateDeps(helm); errs != nil && len(errs) > 0 {
|
||||
for _, err := range errs {
|
||||
fmt.Printf("err: %s\n", err.Error())
|
||||
if errs := state.UpdateDeps(helm); errs != nil && len(errs) > 0 {
|
||||
return errs
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
args := c.String("args")
|
||||
if len(args) > 0 {
|
||||
helm.SetExtraArgs(strings.Split(args, " ")...)
|
||||
}
|
||||
args := c.String("args")
|
||||
if len(args) > 0 {
|
||||
helm.SetExtraArgs(strings.Split(args, " ")...)
|
||||
}
|
||||
|
||||
values := c.StringSlice("values")
|
||||
workers := c.Int("concurrency")
|
||||
values := c.StringSlice("values")
|
||||
workers := c.Int("concurrency")
|
||||
|
||||
errs := state.SyncReleases(helm, values, workers)
|
||||
return clean(state, errs)
|
||||
return state.SyncReleases(helm, values, workers)
|
||||
})
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -234,20 +212,16 @@ func main() {
|
|||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
state, helm, err := before(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return eachDesiredStateDo(c, func(state *state.HelmState, helm helmexec.Interface) []error {
|
||||
workers := c.Int("concurrency")
|
||||
|
||||
workers := c.Int("concurrency")
|
||||
args := c.String("args")
|
||||
if len(args) > 0 {
|
||||
helm.SetExtraArgs(strings.Split(args, " ")...)
|
||||
}
|
||||
|
||||
args := c.String("args")
|
||||
if len(args) > 0 {
|
||||
helm.SetExtraArgs(strings.Split(args, " ")...)
|
||||
}
|
||||
|
||||
errs := state.ReleaseStatuses(helm, workers)
|
||||
return clean(state, errs)
|
||||
return state.ReleaseStatuses(helm, workers)
|
||||
})
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -260,15 +234,11 @@ func main() {
|
|||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
state, helm, err := before(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return eachDesiredStateDo(c, func(state *state.HelmState, helm helmexec.Interface) []error {
|
||||
purge := c.Bool("purge")
|
||||
|
||||
purge := c.Bool("purge")
|
||||
|
||||
errs := state.DeleteReleases(helm, purge)
|
||||
return clean(state, errs)
|
||||
return state.DeleteReleases(helm, purge)
|
||||
})
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -291,21 +261,17 @@ func main() {
|
|||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
state, helm, err := before(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return eachDesiredStateDo(c, func(state *state.HelmState, helm helmexec.Interface) []error {
|
||||
cleanup := c.Bool("cleanup")
|
||||
timeout := c.Int("timeout")
|
||||
|
||||
cleanup := c.Bool("cleanup")
|
||||
timeout := c.Int("timeout")
|
||||
args := c.String("args")
|
||||
if len(args) > 0 {
|
||||
helm.SetExtraArgs(strings.Split(args, " ")...)
|
||||
}
|
||||
|
||||
args := c.String("args")
|
||||
if len(args) > 0 {
|
||||
helm.SetExtraArgs(strings.Split(args, " ")...)
|
||||
}
|
||||
|
||||
errs := state.TestReleases(helm, cleanup, timeout)
|
||||
return clean(state, errs)
|
||||
return state.TestReleases(helm, cleanup, timeout)
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -317,8 +283,83 @@ func main() {
|
|||
}
|
||||
}
|
||||
|
||||
func before(c *cli.Context) (*state.HelmState, helmexec.Interface, error) {
|
||||
file := c.GlobalString("file")
|
||||
func eachDesiredStateDo(c *cli.Context, converge func(*state.HelmState, helmexec.Interface) []error) error {
|
||||
fileOrDirPath := c.GlobalString("file")
|
||||
desiredStateFiles, err := findDesiredStateFiles(fileOrDirPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, f := range desiredStateFiles {
|
||||
state, helm, err := loadDesiredStateFromFile(c, f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
errs := converge(state, helm)
|
||||
if err := clean(state, errs); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func findDesiredStateFiles(specifiedPath string) ([]string, error) {
|
||||
var helmfileDir string
|
||||
if specifiedPath != "" {
|
||||
if fileExistsAt(specifiedPath) {
|
||||
return []string{specifiedPath}, nil
|
||||
} else if directoryExistsAt(specifiedPath) {
|
||||
helmfileDir = specifiedPath
|
||||
} else {
|
||||
return []string{}, fmt.Errorf("specified state file %s is not found", specifiedPath)
|
||||
}
|
||||
} else {
|
||||
var defaultFile string
|
||||
if fileExistsAt(DefaultHelmfile) {
|
||||
defaultFile = DefaultHelmfile
|
||||
} else if fileExistsAt(DeprecatedHelmfile) {
|
||||
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",
|
||||
DeprecatedHelmfile,
|
||||
DeprecatedHelmfile,
|
||||
DefaultHelmfile,
|
||||
)
|
||||
defaultFile = DeprecatedHelmfile
|
||||
}
|
||||
|
||||
if directoryExistsAt(DefaultHelmfileDirectory) {
|
||||
if defaultFile != "" {
|
||||
return []string{}, fmt.Errorf("configuration conlict error: you can have either %s or %s, but not both", defaultFile, DefaultHelmfileDirectory)
|
||||
}
|
||||
|
||||
helmfileDir = DefaultHelmfileDirectory
|
||||
} else if defaultFile != "" {
|
||||
return []string{defaultFile}, nil
|
||||
} else {
|
||||
return []string{}, fmt.Errorf("no state file found. It must be named %s/*.yaml, %s, or %s, or otherwise specified with the --file flag", DefaultHelmfileDirectory, DefaultHelmfile, DeprecatedHelmfile)
|
||||
}
|
||||
}
|
||||
|
||||
files, err := filepath.Glob(filepath.Join(helmfileDir, "*.yaml"))
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
sort.Slice(files, func(i, j int) bool {
|
||||
return files[i] < files[j]
|
||||
})
|
||||
return files, nil
|
||||
}
|
||||
|
||||
func fileExistsAt(path string) bool {
|
||||
fileInfo, err := os.Stat(path)
|
||||
return err == nil && fileInfo.Mode().IsRegular()
|
||||
}
|
||||
|
||||
func directoryExistsAt(path string) bool {
|
||||
fileInfo, err := os.Stat(path)
|
||||
return err == nil && fileInfo.Mode().IsDir()
|
||||
}
|
||||
|
||||
func loadDesiredStateFromFile(c *cli.Context, file string) (*state.HelmState, helmexec.Interface, error) {
|
||||
quiet := c.GlobalBool("quiet")
|
||||
kubeContext := c.GlobalString("kube-context")
|
||||
namespace := c.GlobalString("namespace")
|
||||
|
|
@ -326,16 +367,7 @@ func before(c *cli.Context) (*state.HelmState, helmexec.Interface, error) {
|
|||
|
||||
st, err := state.ReadFromFile(file)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), fmt.Sprintf("open %s:", DefaultHelmfile)) {
|
||||
var fallbackErr error
|
||||
st, fallbackErr = state.ReadFromFile(DeprecatedHelmfile)
|
||||
if fallbackErr != nil {
|
||||
return nil, nil, fmt.Errorf("failed to read %s and %s: %v", file, DeprecatedHelmfile, err)
|
||||
}
|
||||
log.Printf("warn: charts.yaml is loaded: charts.yaml is deprecated in favor of helmfile.yaml. See https://github.com/roboll/helmfile/issues/25 for more information")
|
||||
} else {
|
||||
return nil, nil, fmt.Errorf("failed to read %s: %v", file, err)
|
||||
}
|
||||
return nil, nil, fmt.Errorf("failed to read %s: %v", file, err)
|
||||
}
|
||||
|
||||
if st.Context != "" {
|
||||
|
|
|
|||
Loading…
Reference in New Issue