Skip to content

Commit

Permalink
Merge pull request #622 from Praqma/respect_protected
Browse files Browse the repository at this point in the history
fix: the release protection flag should be respected even when destroying
  • Loading branch information
luisdavim authored Aug 26, 2021
2 parents be474d4 + eb797c8 commit 20c724e
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 37 deletions.
76 changes: 39 additions & 37 deletions internal/app/decision_maker.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,12 @@ func (cs *currentState) decide(r *release, n *namespace, p *plan, c *chartInfo)
return
}

if r.isProtected(cs, n) {
p.addDecision("Release [ "+r.Name+" ] in namespace [ "+r.Namespace+" ] is PROTECTED. Operations are not allowed on this release until "+
"protection is removed.", r.Priority, noop)
return
}

if flags.destroy {
if ok := cs.releaseExists(r, ""); ok {
p.addDecision("Release [ "+r.Name+" ] will be DELETED (destroy flag enabled).", r.Priority, delete)
Expand All @@ -104,48 +110,33 @@ func (cs *currentState) decide(r *release, n *namespace, p *plan, c *chartInfo)

if !r.Enabled {
if ok := cs.releaseExists(r, ""); ok {
if r.isProtected(cs, n) {
p.addDecision("Release [ "+r.Name+" ] in namespace [ "+r.Namespace+" ] is PROTECTED. Operations are not allowed on this release until "+
"protection is removed.", r.Priority, noop)
return
}
p.addDecision("Release [ "+r.Name+" ] is desired to be DELETED.", r.Priority, delete)
r.uninstall(p)
return
} else {
p.addDecision("Release [ "+r.Name+" ] disabled", r.Priority, noop)
}
p.addDecision("Release [ "+r.Name+" ] disabled", r.Priority, noop)
return
}

if ok := cs.releaseExists(r, helmStatusDeployed); ok {
if !r.isProtected(cs, n) {
if err := cs.inspectUpgradeScenario(r, p, c); err != nil { // upgrade or move
log.Fatal(err.Error())
}
} else {
p.addDecision("Release [ "+r.Name+" ] in namespace [ "+r.Namespace+" ] is PROTECTED. Operations are not allowed on this release until "+
"you remove its protection.", r.Priority, noop)
switch cs.releaseStatus(r) {
case helmStatusDeployed:
if err := cs.inspectUpgradeScenario(r, p, c); err != nil { // upgrade or move
log.Fatal(err.Error())
}
} else if ok := cs.releaseExists(r, helmStatusUninstalled); ok {
if !r.isProtected(cs, n) {
r.rollback(cs, p) // rollback
} else {
p.addDecision("Release [ "+r.Name+" ] in namespace [ "+r.Namespace+" ] is PROTECTED. Operations are not allowed on this release until "+
"you remove its protection.", r.Priority, noop)
}
} else if ok := cs.releaseExists(r, helmStatusFailed); ok {
if !r.isProtected(cs, n) {
p.addDecision("Release [ "+r.Name+" ] in namespace [ "+r.Namespace+" ] is in FAILED state. Upgrade is scheduled!", r.Priority, change)
r.upgrade(p)
} else {
p.addDecision("Release [ "+r.Name+" ] in namespace [ "+r.Namespace+" ] is PROTECTED. Operations are not allowed on this release until "+
"you remove its protection.", r.Priority, noop)
}
} else if cs.releaseExists(r, helmStatusPendingInstall) || cs.releaseExists(r, helmStatusPendingUpgrade) || cs.releaseExists(r, helmStatusPendingRollback) || cs.releaseExists(r, helmStatusUninstalling) {

case helmStatusUninstalled:
r.rollback(cs, p) // rollback

case helmStatusFailed:
p.addDecision("Release [ "+r.Name+" ] in namespace [ "+r.Namespace+" ] is in FAILED state. Upgrade is scheduled!", r.Priority, change)
r.upgrade(p)
return

case helmStatusPendingInstall, helmStatusPendingUpgrade, helmStatusPendingRollback, helmStatusUninstalling:
log.Fatal("Release [ " + r.Name + " ] in namespace [ " + r.Namespace + " ] is in a pending (install/upgrade/rollback or uninstalling) state. " +
"This means application is being operated on outside of this Helmsman invocation's scope." +
"Exiting, as this may cause issues when continuing...")
} else {
default:
// If there is no release in the cluster with this name and in this namespace, then install it!
if _, ok := cs.releases[r.key()]; !ok {
p.addDecision("Release [ "+r.Name+" ] version [ "+r.Version+" ] will be installed in [ "+r.Namespace+" ] namespace", r.Priority, create)
Expand All @@ -158,19 +149,30 @@ func (cs *currentState) decide(r *release, n *namespace, p *plan, c *chartInfo)
}
}

// releaseStatus returns the status of a release in the Current State.
func (cs *currentState) releaseStatus(r *release) string {
v, ok := cs.releases[r.key()]
if !ok || v.HelmsmanContext != curContext {
return helmStatusMissing
}
return v.Status
}

// releaseExists checks if a Helm release is/was deployed in a k8s cluster.
// It searches the Current State for releases.
// The key format for releases uniqueness is: <release name - release namespace>
// If status is provided as an input [deployed, deleted, failed], then the search will verify the release status matches the search status.
func (cs *currentState) releaseExists(r *release, status string) bool {
v, ok := cs.releases[r.key()]
if !ok || v.HelmsmanContext != curContext {
return false
}
currentState := cs.releaseStatus(r)

if status != "" {
return v.Status == status
return currentState == status
}

if currentState == helmStatusMissing {
return false
}

return true
}

Expand Down
2 changes: 2 additions & 0 deletions internal/app/helm_release.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"sync"
)

// TODO: can we import these from helm?
const (
helmStatusDeployed = "deployed"
helmStatusUninstalled = "uninstalled"
Expand All @@ -17,6 +18,7 @@ const (
helmStatusPendingInstall = "pending-install"
helmStatusPendingRollback = "pending-rollback"
helmStatusUninstalling = "uninstalling"
helmStatusMissing = "missing"
)

// helmRelease represents the current state of a release
Expand Down

0 comments on commit 20c724e

Please sign in to comment.