parent
c5bc932ba2
commit
cf31d02f25
26
main.go
26
main.go
|
|
@ -326,6 +326,11 @@ func main() {
|
||||||
|
|
||||||
releases, errs := executeDiffCommand(c, st, helm, true, c.Bool("suppress-secrets"))
|
releases, errs := executeDiffCommand(c, st, helm, true, c.Bool("suppress-secrets"))
|
||||||
|
|
||||||
|
releasesToBeDeleted, err := st.DetectReleasesToBeDeleted(helm)
|
||||||
|
if err != nil {
|
||||||
|
errs = append(errs, err)
|
||||||
|
}
|
||||||
|
|
||||||
noError := true
|
noError := true
|
||||||
for _, e := range errs {
|
for _, e := range errs {
|
||||||
switch err := e.(type) {
|
switch err := e.(type) {
|
||||||
|
|
@ -338,15 +343,18 @@ func main() {
|
||||||
|
|
||||||
// sync only when there are changes
|
// sync only when there are changes
|
||||||
if noError {
|
if noError {
|
||||||
if len(releases) == 0 {
|
if len(releases) == 0 && len(releasesToBeDeleted) == 0 {
|
||||||
// TODO better way to get the logger
|
// TODO better way to get the logger
|
||||||
logger := c.App.Metadata["logger"].(*zap.SugaredLogger)
|
logger := c.App.Metadata["logger"].(*zap.SugaredLogger)
|
||||||
logger.Infof("")
|
logger.Infof("")
|
||||||
logger.Infof("No affected releases")
|
logger.Infof("No affected releases")
|
||||||
} else {
|
} else {
|
||||||
names := make([]string, len(releases))
|
names := []string{}
|
||||||
for i, r := range releases {
|
for _, r := range releases {
|
||||||
names[i] = fmt.Sprintf(" %s (%s)", r.Name, r.Chart)
|
names = append(names, fmt.Sprintf(" %s (%s) UPDATED", r.Name, r.Chart))
|
||||||
|
}
|
||||||
|
for _, r := range releasesToBeDeleted {
|
||||||
|
names = append(names, fmt.Sprintf(" %s (%s) DELETED", r.Name, r.Chart))
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := fmt.Sprintf(`Affected releases are:
|
msg := fmt.Sprintf(`Affected releases are:
|
||||||
|
|
@ -358,10 +366,14 @@ Do you really want to apply?
|
||||||
`, strings.Join(names, "\n"))
|
`, strings.Join(names, "\n"))
|
||||||
autoApprove := c.Bool("auto-approve")
|
autoApprove := c.Bool("auto-approve")
|
||||||
if autoApprove || !autoApprove && askForConfirmation(msg) {
|
if autoApprove || !autoApprove && askForConfirmation(msg) {
|
||||||
rs := make([]state.ReleaseSpec, len(releases))
|
rs := []state.ReleaseSpec{}
|
||||||
for i, r := range releases {
|
for _, r := range releases {
|
||||||
rs[i] = *r
|
rs = append(rs, *r)
|
||||||
}
|
}
|
||||||
|
for _, r := range releasesToBeDeleted {
|
||||||
|
rs = append(rs, *r)
|
||||||
|
}
|
||||||
|
|
||||||
st.Releases = rs
|
st.Releases = rs
|
||||||
return executeSyncCommand(c, st, helm)
|
return executeSyncCommand(c, st, helm)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,8 @@ type ReleaseSpec struct {
|
||||||
RecreatePods *bool `yaml:"recreatePods"`
|
RecreatePods *bool `yaml:"recreatePods"`
|
||||||
// Force, when set to true, forces resource update through delete/recreate if needed
|
// Force, when set to true, forces resource update through delete/recreate if needed
|
||||||
Force *bool `yaml:"force"`
|
Force *bool `yaml:"force"`
|
||||||
|
// Installed, when set to true, `delete --purge` the release
|
||||||
|
Installed *bool `yaml:"installed"`
|
||||||
|
|
||||||
// Name is the name of this release
|
// Name is the name of this release
|
||||||
Name string `yaml:"name"`
|
Name string `yaml:"name"`
|
||||||
|
|
@ -161,7 +163,8 @@ type syncPrepareResult struct {
|
||||||
|
|
||||||
// SyncReleases wrapper for executing helm upgrade on the releases
|
// SyncReleases wrapper for executing helm upgrade on the releases
|
||||||
func (state *HelmState) prepareSyncReleases(helm helmexec.Interface, additionalValues []string, concurrency int) ([]syncPrepareResult, []error) {
|
func (state *HelmState) prepareSyncReleases(helm helmexec.Interface, additionalValues []string, concurrency int) ([]syncPrepareResult, []error) {
|
||||||
numReleases := len(state.Releases)
|
releases := state.Releases
|
||||||
|
numReleases := len(releases)
|
||||||
jobs := make(chan *ReleaseSpec, numReleases)
|
jobs := make(chan *ReleaseSpec, numReleases)
|
||||||
results := make(chan syncPrepareResult, numReleases)
|
results := make(chan syncPrepareResult, numReleases)
|
||||||
|
|
||||||
|
|
@ -202,7 +205,7 @@ func (state *HelmState) prepareSyncReleases(helm helmexec.Interface, additionalV
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < numReleases; i++ {
|
for i := 0; i < numReleases; i++ {
|
||||||
jobs <- &state.Releases[i]
|
jobs <- &releases[i]
|
||||||
}
|
}
|
||||||
close(jobs)
|
close(jobs)
|
||||||
|
|
||||||
|
|
@ -222,6 +225,31 @@ func (state *HelmState) prepareSyncReleases(helm helmexec.Interface, additionalV
|
||||||
return res, errs
|
return res, errs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (state *HelmState) DetectReleasesToBeDeleted(helm helmexec.Interface) ([]*ReleaseSpec, error) {
|
||||||
|
detected := []*ReleaseSpec{}
|
||||||
|
for i, _ := range state.Releases {
|
||||||
|
release := state.Releases[i]
|
||||||
|
if release.Installed != nil && !*release.Installed {
|
||||||
|
err := helm.ReleaseStatus(release.Name)
|
||||||
|
if err != nil {
|
||||||
|
switch e := err.(type) {
|
||||||
|
case *exec.ExitError:
|
||||||
|
// Propagate any non-zero exit status from the external command like `helm` that is failed under the hood
|
||||||
|
status := e.Sys().(syscall.WaitStatus)
|
||||||
|
if status.ExitStatus() != 1 {
|
||||||
|
return nil, e
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return nil, e
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
detected = append(detected, &release)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return detected, nil
|
||||||
|
}
|
||||||
|
|
||||||
// SyncReleases wrapper for executing helm upgrade on the releases
|
// SyncReleases wrapper for executing helm upgrade on the releases
|
||||||
func (state *HelmState) SyncReleases(helm helmexec.Interface, additionalValues []string, workerLimit int) []error {
|
func (state *HelmState) SyncReleases(helm helmexec.Interface, additionalValues []string, workerLimit int) []error {
|
||||||
preps, prepErrs := state.prepareSyncReleases(helm, additionalValues, workerLimit)
|
preps, prepErrs := state.prepareSyncReleases(helm, additionalValues, workerLimit)
|
||||||
|
|
@ -233,7 +261,7 @@ func (state *HelmState) SyncReleases(helm helmexec.Interface, additionalValues [
|
||||||
results := make(chan syncResult, len(preps))
|
results := make(chan syncResult, len(preps))
|
||||||
|
|
||||||
if workerLimit < 1 {
|
if workerLimit < 1 {
|
||||||
workerLimit = len(state.Releases)
|
workerLimit = len(preps)
|
||||||
}
|
}
|
||||||
for w := 1; w <= workerLimit; w++ {
|
for w := 1; w <= workerLimit; w++ {
|
||||||
go func() {
|
go func() {
|
||||||
|
|
@ -241,7 +269,15 @@ func (state *HelmState) SyncReleases(helm helmexec.Interface, additionalValues [
|
||||||
release := prep.release
|
release := prep.release
|
||||||
flags := prep.flags
|
flags := prep.flags
|
||||||
chart := normalizeChart(state.basePath, release.Chart)
|
chart := normalizeChart(state.basePath, release.Chart)
|
||||||
if err := helm.SyncRelease(release.Name, chart, flags...); err != nil {
|
if release.Installed != nil && !*release.Installed {
|
||||||
|
if err := helm.ReleaseStatus(release.Name); err == nil {
|
||||||
|
if err := helm.DeleteRelease(release.Name, "--purge"); err != nil {
|
||||||
|
results <- syncResult{errors: []*ReleaseError{&ReleaseError{release, err}}}
|
||||||
|
} else {
|
||||||
|
results <- syncResult{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if err := helm.SyncRelease(release.Name, chart, flags...); err != nil {
|
||||||
results <- syncResult{errors: []*ReleaseError{&ReleaseError{release, err}}}
|
results <- syncResult{errors: []*ReleaseError{&ReleaseError{release, err}}}
|
||||||
} else {
|
} else {
|
||||||
results <- syncResult{}
|
results <- syncResult{}
|
||||||
|
|
@ -466,7 +502,13 @@ type diffPrepareResult struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (state *HelmState) prepareDiffReleases(helm helmexec.Interface, additionalValues []string, concurrency int, detailedExitCode, suppressSecrets bool) ([]diffPrepareResult, []error) {
|
func (state *HelmState) prepareDiffReleases(helm helmexec.Interface, additionalValues []string, concurrency int, detailedExitCode, suppressSecrets bool) ([]diffPrepareResult, []error) {
|
||||||
numReleases := len(state.Releases)
|
releases := []ReleaseSpec{}
|
||||||
|
for _, r := range state.Releases {
|
||||||
|
if r.Installed == nil || *r.Installed {
|
||||||
|
releases = append(releases, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
numReleases := len(releases)
|
||||||
jobs := make(chan *ReleaseSpec, numReleases)
|
jobs := make(chan *ReleaseSpec, numReleases)
|
||||||
results := make(chan diffPrepareResult, numReleases)
|
results := make(chan diffPrepareResult, numReleases)
|
||||||
|
|
||||||
|
|
@ -520,7 +562,7 @@ func (state *HelmState) prepareDiffReleases(helm helmexec.Interface, additionalV
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < numReleases; i++ {
|
for i := 0; i < numReleases; i++ {
|
||||||
jobs <- &state.Releases[i]
|
jobs <- &releases[i]
|
||||||
}
|
}
|
||||||
close(jobs)
|
close(jobs)
|
||||||
|
|
||||||
|
|
@ -554,7 +596,7 @@ func (state *HelmState) DiffReleases(helm helmexec.Interface, additionalValues [
|
||||||
results := make(chan diffResult, len(preps))
|
results := make(chan diffResult, len(preps))
|
||||||
|
|
||||||
if workerLimit < 1 {
|
if workerLimit < 1 {
|
||||||
workerLimit = len(state.Releases)
|
workerLimit = len(preps)
|
||||||
}
|
}
|
||||||
|
|
||||||
for w := 1; w <= workerLimit; w++ {
|
for w := 1; w <= workerLimit; w++ {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue