parent
8acbbc596d
commit
0186254e79
8
main.go
8
main.go
|
|
@ -329,6 +329,10 @@ func main() {
|
|||
Value: 0,
|
||||
Usage: "output NUM lines of context around changes",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "detailed-exitcode",
|
||||
Usage: "return a non-zero exit code 2 instead of 0 when there were changes detected AND the changes are synced successfully",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "args",
|
||||
Value: "",
|
||||
|
|
@ -625,11 +629,11 @@ func action(do func(*app.App, configImpl) error) func(*cli.Context) error {
|
|||
|
||||
a := app.New(conf)
|
||||
|
||||
a.ErrorHandler = func(err error) error {
|
||||
if err := do(a, conf); err != nil {
|
||||
return toCliError(implCtx, err)
|
||||
}
|
||||
|
||||
return do(a, conf)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import (
|
|||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"text/tabwriter"
|
||||
|
||||
|
|
@ -40,8 +41,6 @@ type App struct {
|
|||
|
||||
FileOrDir string
|
||||
|
||||
ErrorHandler func(error) error
|
||||
|
||||
readFile func(string) ([]byte, error)
|
||||
fileExists func(string) (bool, error)
|
||||
glob func(string) ([]string, error)
|
||||
|
|
@ -144,9 +143,31 @@ func (a *App) Sync(c SyncConfigProvider) error {
|
|||
}
|
||||
|
||||
func (a *App) Apply(c ApplyConfigProvider) error {
|
||||
return a.ForEachState(func(run *Run) (bool, []error) {
|
||||
return a.apply(run, c)
|
||||
var any bool
|
||||
|
||||
mut := &sync.Mutex{}
|
||||
|
||||
err := a.ForEachState(func(run *Run) (bool, []error) {
|
||||
matched, updated, errs := a.apply(run, c)
|
||||
|
||||
mut.Lock()
|
||||
any = any || updated
|
||||
mut.Unlock()
|
||||
|
||||
return matched, errs
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.DetailedExitcode() && any {
|
||||
code := 2
|
||||
|
||||
return &Error{msg: "", Errors: nil, code: &code}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *App) Status(c StatusesConfigProvider) error {
|
||||
|
|
@ -410,10 +431,6 @@ func (a *App) ForEachStateFiltered(do func(*Run) []error) error {
|
|||
return do(run)
|
||||
})
|
||||
|
||||
if err != nil && a.ErrorHandler != nil {
|
||||
return a.ErrorHandler(err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -424,10 +441,6 @@ func (a *App) ForEachState(do func(*Run) (bool, []error)) error {
|
|||
return do(run)
|
||||
})
|
||||
|
||||
if err != nil && a.ErrorHandler != nil {
|
||||
return a.ErrorHandler(err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -661,7 +674,7 @@ func (a *App) findDesiredStateFiles(specifiedPath string) ([]string, error) {
|
|||
return files, nil
|
||||
}
|
||||
|
||||
func (a *App) apply(r *Run, c ApplyConfigProvider) (bool, []error) {
|
||||
func (a *App) apply(r *Run, c ApplyConfigProvider) (bool, bool, []error) {
|
||||
st := r.state
|
||||
helm := r.helm
|
||||
ctx := r.ctx
|
||||
|
|
@ -670,10 +683,10 @@ func (a *App) apply(r *Run, c ApplyConfigProvider) (bool, []error) {
|
|||
|
||||
toApply, err := st.GetSelectedReleasesWithOverrides()
|
||||
if err != nil {
|
||||
return false, []error{err}
|
||||
return false, false, []error{err}
|
||||
}
|
||||
if len(toApply) == 0 {
|
||||
return false, nil
|
||||
return false, false, nil
|
||||
}
|
||||
|
||||
// Do build deps and prepare only on selected releases so that we won't waste time
|
||||
|
|
@ -682,14 +695,14 @@ func (a *App) apply(r *Run, c ApplyConfigProvider) (bool, []error) {
|
|||
|
||||
if !c.SkipDeps() {
|
||||
if errs := ctx.SyncReposOnce(st, helm); errs != nil && len(errs) > 0 {
|
||||
return false, errs
|
||||
return false, false, errs
|
||||
}
|
||||
if errs := st.BuildDeps(helm); errs != nil && len(errs) > 0 {
|
||||
return false, errs
|
||||
return false, false, errs
|
||||
}
|
||||
}
|
||||
if errs := st.PrepareReleases(helm, "apply"); errs != nil && len(errs) > 0 {
|
||||
return false, errs
|
||||
return false, false, errs
|
||||
}
|
||||
|
||||
// helm must be 2.11+ and helm-diff should be provided `--detailed-exitcode` in order for `helmfile apply` to work properly
|
||||
|
|
@ -730,7 +743,7 @@ func (a *App) apply(r *Run, c ApplyConfigProvider) (bool, []error) {
|
|||
}
|
||||
|
||||
if len(fatalErrs) > 0 {
|
||||
return false, fatalErrs
|
||||
return false, false, fatalErrs
|
||||
}
|
||||
|
||||
releasesToBeDeleted := map[string]state.ReleaseSpec{}
|
||||
|
|
@ -755,7 +768,7 @@ func (a *App) apply(r *Run, c ApplyConfigProvider) (bool, []error) {
|
|||
logger := c.Logger()
|
||||
logger.Infof("")
|
||||
logger.Infof("No affected releases")
|
||||
return true, nil
|
||||
return true, false, nil
|
||||
}
|
||||
|
||||
names := []string{}
|
||||
|
|
@ -838,7 +851,7 @@ Do you really want to apply?
|
|||
}
|
||||
|
||||
affectedReleases.DisplayAffectedReleases(c.Logger())
|
||||
return true, syncErrs
|
||||
return true, true, syncErrs
|
||||
}
|
||||
|
||||
func (a *App) delete(r *Run, purge bool, c DestroyConfigProvider) (bool, []error) {
|
||||
|
|
@ -1133,6 +1146,8 @@ type Error struct {
|
|||
msg string
|
||||
|
||||
Errors []error
|
||||
|
||||
code *int
|
||||
}
|
||||
|
||||
func (e *Error) Error() string {
|
||||
|
|
@ -1165,6 +1180,10 @@ func (e *Error) Error() string {
|
|||
}
|
||||
|
||||
func (e *Error) Code() int {
|
||||
if e.code != nil {
|
||||
return *e.code
|
||||
}
|
||||
|
||||
allDiff := false
|
||||
anyNonZero := false
|
||||
for _, err := range e.Errors {
|
||||
|
|
@ -1195,7 +1214,7 @@ func (e *Error) Code() int {
|
|||
}
|
||||
|
||||
func appError(msg string, err error) error {
|
||||
return &Error{msg, []error{err}}
|
||||
return &Error{msg: msg, Errors: []error{err}}
|
||||
}
|
||||
|
||||
func (c context) clean(errs []error) error {
|
||||
|
|
|
|||
|
|
@ -1890,17 +1890,18 @@ func (c configImpl) Concurrency() int {
|
|||
}
|
||||
|
||||
type applyConfig struct {
|
||||
args string
|
||||
values []string
|
||||
set []string
|
||||
skipDeps bool
|
||||
suppressSecrets bool
|
||||
suppressDiff bool
|
||||
noColor bool
|
||||
context int
|
||||
concurrency int
|
||||
interactive bool
|
||||
logger *zap.SugaredLogger
|
||||
args string
|
||||
values []string
|
||||
set []string
|
||||
skipDeps bool
|
||||
suppressSecrets bool
|
||||
suppressDiff bool
|
||||
noColor bool
|
||||
context int
|
||||
concurrency int
|
||||
detailedExitcode bool
|
||||
interactive bool
|
||||
logger *zap.SugaredLogger
|
||||
}
|
||||
|
||||
func (a applyConfig) Args() string {
|
||||
|
|
@ -1939,6 +1940,10 @@ func (a applyConfig) Concurrency() int {
|
|||
return a.concurrency
|
||||
}
|
||||
|
||||
func (a applyConfig) DetailedExitcode() bool {
|
||||
return a.detailedExitcode
|
||||
}
|
||||
|
||||
func (a applyConfig) Interactive() bool {
|
||||
return a.interactive
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@ type ApplyConfigProvider interface {
|
|||
SuppressSecrets() bool
|
||||
SuppressDiff() bool
|
||||
|
||||
DetailedExitcode() bool
|
||||
|
||||
NoColor() bool
|
||||
Context() int
|
||||
|
||||
|
|
|
|||
|
|
@ -77,6 +77,9 @@ ${helmfile} -f ${dir}/happypath.yaml template
|
|||
code=$?
|
||||
[ ${code} -eq 0 ] || fail "unexpected exit code returned by helmfile template: ${code}"
|
||||
|
||||
info "Applying ${dir}/happypath.yaml"
|
||||
bash -c "${helmfile} -f ${dir}/happypath.yaml apply --detailed-exitcode; code="'$?'"; echo Code: "'$code'"; [ "'${code}'" -eq 2 ]" || fail "unexpected exit code returned by helmfile apply"
|
||||
|
||||
info "Syncing ${dir}/happypath.yaml"
|
||||
${helmfile} -f ${dir}/happypath.yaml sync
|
||||
wait_deploy_ready httpbin-httpbin
|
||||
|
|
@ -84,9 +87,9 @@ retry 5 "curl --fail $(minikube service --url --namespace=${test_ns} httpbin-htt
|
|||
[ ${retry_result} -eq 0 ] || fail "httpbin failed to return 200 OK"
|
||||
|
||||
info "Applying ${dir}/happypath.yaml"
|
||||
${helmfile} -f ${dir}/happypath.yaml apply
|
||||
${helmfile} -f ${dir}/happypath.yaml apply --detailed-exitcode
|
||||
code=$?
|
||||
[ ${code} -eq 0 ] || fail "unexpected exit code returned by helmfile apply: ${code}"
|
||||
[ ${code} -eq 0 ] || fail "unexpected exit code returned by helmfile apply: want 0, got ${code}"
|
||||
|
||||
info "Locking dependencies"
|
||||
${helmfile} -f ${dir}/happypath.yaml deps
|
||||
|
|
|
|||
Loading…
Reference in New Issue