Skip to content

Commit

Permalink
feature: introduce rollback windows
Browse files Browse the repository at this point in the history
fixes: argoproj#574
Signed-off-by: Alex Eftimie <[email protected]>
  • Loading branch information
alexef committed Nov 3, 2022
1 parent 2d6f5a0 commit c7b4625
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 0 deletions.
7 changes: 7 additions & 0 deletions pkg/apis/rollouts/v1alpha1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ type RolloutSpec struct {
// Defaults to 0 (pod will be considered available as soon as it is ready)
// +optional
MinReadySeconds int32 `json:"minReadySeconds,omitempty" protobuf:"varint,4,opt,name=minReadySeconds"`
// The window in which a rollback will be fast tracked (fully promoted)
// +optional
RollbackWindow *RollbackWindowSpec `json:"rollbackWindow,omtempty" protobuf:"bytes,13,opt,name=rollbackWindow"`
// The deployment strategy to use to replace existing pods with new ones.
// +optional
Strategy RolloutStrategy `json:"strategy" protobuf:"bytes,5,opt,name=strategy"`
Expand Down Expand Up @@ -1021,3 +1024,7 @@ type RolloutList struct {

Items []Rollout `json:"items" protobuf:"bytes,2,rep,name=items"`
}

type RollbackWindowSpec struct {
Revisions int32 `json:"revisions,omitempty" protobuf:"varint,1,opt,name=revisions"`
}
31 changes: 31 additions & 0 deletions rollout/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -857,6 +857,31 @@ func (c *rolloutContext) resetRolloutStatus(newStatus *v1alpha1.RolloutStatus) {
newStatus.CurrentStepIndex = replicasetutil.ResetCurrentStepIndex(c.rollout)
}

func (c *rolloutContext) isRollbackWithinWindow() bool {
if c.newRS == nil || c.stableRS == nil {
return false
}
// first check if this is a rollback
if c.newRS.CreationTimestamp.Before(&c.stableRS.CreationTimestamp) {
// then check if we are within window
if c.rollout.Spec.RollbackWindow != nil {
if c.rollout.Spec.RollbackWindow.Revisions > 0 {
var windowSize int32
for _, rs := range c.allRSs {
if rs.CreationTimestamp.Before(&c.stableRS.CreationTimestamp) &&
c.stableRS.CreationTimestamp.Before(&rs.CreationTimestamp) {
windowSize = windowSize + 1
}
}
if windowSize <= c.rollout.Spec.RollbackWindow.Revisions {
return true
}
}
}
}
return false
}

// shouldFullPromote returns a reason string explaining why a rollout should fully promote, marking
// the desired ReplicaSet as stable. Returns empty string if the rollout is in middle of update
func (c *rolloutContext) shouldFullPromote(newStatus v1alpha1.RolloutStatus) string {
Expand All @@ -873,6 +898,9 @@ func (c *rolloutContext) shouldFullPromote(newStatus v1alpha1.RolloutStatus) str
if c.rollout.Status.PromoteFull {
return "Full promotion requested"
}
if c.isRollbackWithinWindow() {
return "Rollback within window"
}
_, currentStepIndex := replicasetutil.GetCurrentCanaryStep(c.rollout)
stepCount := len(c.rollout.Spec.Strategy.Canary.Steps)
completedAllSteps := stepCount == 0 || (currentStepIndex != nil && *currentStepIndex == int32(stepCount))
Expand All @@ -897,6 +925,9 @@ func (c *rolloutContext) shouldFullPromote(newStatus v1alpha1.RolloutStatus) str
if c.rollout.Status.PromoteFull {
return "Full promotion requested"
}
if c.isRollbackWithinWindow() {
return "Rollback within window"
}
if c.pauseContext.IsAborted() {
return ""
}
Expand Down
58 changes: 58 additions & 0 deletions rollout/sync_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -453,3 +453,61 @@ func TestSendStateChangeEvents(t *testing.T) {
assert.Equal(t, test.expectedEventReasons, recorder.Events)
}
}

// TestRollbackWindow verifies the rollback window conditions
func TestRollbackWindow(t *testing.T) {
now := timeutil.MetaNow()
before := metav1.Time{Time: now.Add(-time.Minute)}

replicaSets := []*appsv1.ReplicaSet{
{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
CreationTimestamp: before,
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "foo-1",
CreationTimestamp: now,
},
},
}
// FIXME: parametrize this
ctx := &rolloutContext{
allRSs: replicaSets,
newRS: replicaSets[0],
stableRS: replicaSets[1],
}
ctx.rollout = &v1alpha1.Rollout{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
Namespace: "default",
},
Spec: v1alpha1.RolloutSpec{
RollbackWindow: &v1alpha1.RollbackWindowSpec{
Revisions: 1,
},
},
}
assert.True(t, ctx.isRollbackWithinWindow())

ctx = &rolloutContext{
allRSs: replicaSets,
newRS: replicaSets[1],
stableRS: replicaSets[0],
}
ctx.rollout = &v1alpha1.Rollout{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
Namespace: "default",
},
Spec: v1alpha1.RolloutSpec{
RollbackWindow: &v1alpha1.RollbackWindowSpec{
Revisions: 1,
},
},
}

assert.False(t, ctx.isRollbackWithinWindow())
}

0 comments on commit c7b4625

Please sign in to comment.