Skip to content

Commit

Permalink
Add background analysis runs for rollouts
Browse files Browse the repository at this point in the history
  • Loading branch information
dthomson25 committed Oct 10, 2019
1 parent 2114be0 commit cfb56e1
Show file tree
Hide file tree
Showing 8 changed files with 172 additions and 15 deletions.
50 changes: 47 additions & 3 deletions rollout/analysis.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,13 @@ func (c *RolloutController) reconcileAnalysisRuns(rollout *v1alpha1.Rollout, cur
newCurrentAnalysisRuns = append(newCurrentAnalysisRuns, stepAnalysisRun)
}

//TODO(dthomson) implement reconcileBackgroundBasedAnalysisRun
backgroundAnalysisRun, err := c.reconcileBackgroundAnalysisRun(rollout, currentArs, stableRS, newRS)
if err != nil {
return currentArs, err
}
if backgroundAnalysisRun != nil {
newCurrentAnalysisRuns = append(newCurrentAnalysisRuns, backgroundAnalysisRun)
}

err = c.cancelAnalysisRuns(rollout, otherArs)
if err != nil {
Expand All @@ -66,6 +72,44 @@ func (c *RolloutController) reconcileAnalysisRuns(rollout *v1alpha1.Rollout, cur
return newCurrentAnalysisRuns, nil
}

func (c *RolloutController) reconcileBackgroundAnalysisRun(rollout *v1alpha1.Rollout, currentArs []*v1alpha1.AnalysisRun, stableRS, newRS *appsv1.ReplicaSet) (*v1alpha1.AnalysisRun, error) {
currentAr := analysisutil.FilterAnalysisRunsByName(currentArs, rollout.Status.Canary.CurrentBackgroundAnalysisRun)
if rollout.Spec.Strategy.CanaryStrategy.Analysis == nil {
err := c.cancelAnalysisRuns(rollout, []*v1alpha1.AnalysisRun{currentAr})
if err != nil {
return nil, err
}
return nil, err
}
if currentAr == nil {
return c.createBackgroundAnalysisRun(rollout, rollout.Spec.Strategy.CanaryStrategy.Analysis, stableRS, newRS)
}

return currentAr, nil
}

func (c *RolloutController) createBackgroundAnalysisRun(rollout *v1alpha1.Rollout, rolloutAnalysisStep *v1alpha1.RolloutAnalysisStep, stableRS, newRS *appsv1.ReplicaSet) (*v1alpha1.AnalysisRun, error) {
podHash := controller.ComputeHash(&rollout.Spec.Template, rollout.Status.CollisionCount)
// Since the compute hash function is not guaranteed to be stable, we will use the podHash attached the newRS if possible.
if newRS != nil {
if newRsPodHash, ok := newRS.Labels[v1alpha1.DefaultRolloutUniqueLabelKey]; ok {
podHash = newRsPodHash
}
}
analysisRunLabels := analysisutil.BackgroundLabels(podHash)
args := analysisutil.BuildArgumentsForRolloutAnalysisRun(rolloutAnalysisStep, stableRS, newRS)
ar, err := c.getAnalysisRunFromRollout(rollout, rolloutAnalysisStep, args, podHash, analysisRunLabels)
if err != nil {
return nil, err
}
ar, err = c.argoprojclientset.ArgoprojV1alpha1().AnalysisRuns(ar.Namespace).Create(ar)
if err != nil {
return nil, err
}
logutil.WithRollout(rollout).WithField(logutil.AnalysisRunKey, ar.Name).Info("Created background AnalysisRun")
return ar, nil
}

func (c *RolloutController) reconcileStepBasedAnalysisRun(rollout *v1alpha1.Rollout, currentArs []*v1alpha1.AnalysisRun, stableRS, newRS *appsv1.ReplicaSet) (*v1alpha1.AnalysisRun, error) {
step, index := replicasetutil.GetCurrentCanaryStep(rollout)
currentAr := analysisutil.FilterAnalysisRunsByName(currentArs, rollout.Status.Canary.CurrentStepAnalysisRun)
Expand All @@ -91,7 +135,7 @@ func (c *RolloutController) createStepBasedAnalysisRun(rollout *v1alpha1.Rollout
podHash = newRsPodHash
}
}
analysisRunLabels := analysisutil.StepLabels(rollout, index, podHash)
analysisRunLabels := analysisutil.StepLabels(index, podHash)
args := analysisutil.BuildArgumentsForRolloutAnalysisRun(rolloutAnalysisStep, stableRS, newRS)
ar, err := c.getAnalysisRunFromRollout(rollout, rolloutAnalysisStep, args, podHash, analysisRunLabels)
if err != nil {
Expand Down Expand Up @@ -138,7 +182,7 @@ func (c *RolloutController) getAnalysisRunFromRollout(r *v1alpha1.Rollout, rollo

ar := v1alpha1.AnalysisRun{
ObjectMeta: metav1.ObjectMeta{
GenerateName: fmt.Sprintf("%s-%s-%s", r.Name, rolloutAnalysisStep.TemplateName, podHash),
GenerateName: fmt.Sprintf("%s-%s-%s-", r.Name, rolloutAnalysisStep.TemplateName, podHash),
Namespace: r.Namespace,
Labels: labels,
Annotations: map[string]string{
Expand Down
61 changes: 58 additions & 3 deletions rollout/analysis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ func analysisRun(at *v1alpha1.AnalysisTemplate, analysisRunType string, r *v1alp
labels := map[string]string{}
podHash := controller.ComputeHash(&r.Spec.Template, r.Status.CollisionCount)
if analysisRunType == v1alpha1.RolloutTypeStepLabel {
labels = analysisutil.StepLabels(r, *r.Status.CurrentStepIndex, podHash)
labels = analysisutil.StepLabels(*r.Status.CurrentStepIndex, podHash)
} else if analysisRunType == v1alpha1.RolloutTypeBackgroundRunLabel {
labels = analysisutil.BackgroundLabels(podHash)
}
return &v1alpha1.AnalysisRun{
ObjectMeta: metav1.ObjectMeta{
Expand All @@ -50,6 +52,59 @@ func analysisRun(at *v1alpha1.AnalysisTemplate, analysisRunType string, r *v1alp
}
}

func TestCreateBackgroundAnalysisRun(t *testing.T) {
f := newFixture(t)
defer f.Close()

steps := []v1alpha1.CanaryStep{{
SetWeight: int32Ptr(10),
}}
at := analysisTemplate("bar")
r1 := newCanaryRollout("foo", 10, nil, steps, pointer.Int32Ptr(0), intstr.FromInt(0), intstr.FromInt(1))
r2 := bumpVersion(r1)
ar := analysisRun(at, v1alpha1.RolloutTypeBackgroundRunLabel, r2)
r2.Spec.Strategy.CanaryStrategy.Analysis = &v1alpha1.RolloutAnalysisStep{
TemplateName: at.Name,
}

rs1 := newReplicaSetWithStatus(r1, 10, 10)
rs2 := newReplicaSetWithStatus(r2, 0, 0)
f.kubeobjects = append(f.kubeobjects, rs1, rs2)
f.replicaSetLister = append(f.replicaSetLister, rs1, rs2)
rs1PodHash := rs1.Labels[v1alpha1.DefaultRolloutUniqueLabelKey]
rs2PodHash := rs2.Labels[v1alpha1.DefaultRolloutUniqueLabelKey]

r2 = updateCanaryRolloutStatus(r2, rs1PodHash, 10, 0, 10, false)
progressingCondition, _ := newProgressingCondition(conditions.ReplicaSetUpdatedReason, rs2)
conditions.SetRolloutCondition(&r2.Status, progressingCondition)
availableCondition, _ := newAvailableCondition(true)
conditions.SetRolloutCondition(&r2.Status, availableCondition)

f.rolloutLister = append(f.rolloutLister, r2)
f.analysisTemplateLister = append(f.analysisTemplateLister, at)
f.objects = append(f.objects, r2, at)

createdIndex := f.expectCreateAnalysisRunAction(ar)
f.expectUpdateReplicaSetAction(rs2)
index := f.expectPatchRolloutAction(r1)

f.run(getKey(r2, t))
createdAr := f.getCreatedAnalysisRun(createdIndex)
expectedArGeneratedName := fmt.Sprintf("%s-%s-%s-", r2.Name, at.Name, rs2PodHash)
expectedArName := fmt.Sprintf("%s%s", expectedArGeneratedName, MockGeneratedNameSuffix)
assert.Equal(t, expectedArGeneratedName, createdAr.GenerateName)

patch := f.getPatchedRollout(index)
expectedPatch := `{
"status": {
"canary": {
"currentBackgroundAnalysisRun": "%s"
}
}
}`
assert.Equal(t, calculatePatch(r2, fmt.Sprintf(expectedPatch, expectedArName)), patch)
}

func TestCreateAnalysisRunOnAnalysisStep(t *testing.T) {
f := newFixture(t)
defer f.Close()
Expand Down Expand Up @@ -87,8 +142,8 @@ func TestCreateAnalysisRunOnAnalysisStep(t *testing.T) {

f.run(getKey(r2, t))
createdAr := f.getCreatedAnalysisRun(createdIndex)
expectedArGeneratedName := fmt.Sprintf("%s-%s-%s", r2.Name, at.Name, rs2PodHash)
expectedArName := fmt.Sprintf("%s-%s", expectedArGeneratedName, MockGeneratedNameSuffix)
expectedArGeneratedName := fmt.Sprintf("%s-%s-%s-", r2.Name, at.Name, rs2PodHash)
expectedArName := fmt.Sprintf("%s%s", expectedArGeneratedName, MockGeneratedNameSuffix)
assert.Equal(t, expectedArGeneratedName, createdAr.GenerateName)

patch := f.getPatchedRollout(index)
Expand Down
8 changes: 7 additions & 1 deletion rollout/canary.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,13 @@ func (c *RolloutController) syncRolloutStatusCanary(olderRSs []*appsv1.ReplicaSe
newStatus.Canary.CurrentStepAnalysisRun = currStepAr.Name
}

}
currBackgroundAr := analysisutil.GetCurrentBackgroundAnalysisRun(currArs)
if currBackgroundAr != nil {
if currBackgroundAr.Status == nil || !currBackgroundAr.Status.Status.Completed() || analysisutil.IsTerminating(currBackgroundAr) {
newStatus.Canary.CurrentBackgroundAnalysisRun = currBackgroundAr.Name
}

}

if !r.Spec.Paused {
Expand All @@ -292,7 +299,6 @@ func (c *RolloutController) syncRolloutStatusCanary(olderRSs []*appsv1.ReplicaSe
return c.persistRolloutStatus(r, &newStatus, pointer.BoolPtr(false))
}

//TODO(dthomson): Add steps to store CurrentBackgroundAnalysisRun
if completedCurrentCanaryStep(olderRSs, newRS, stableRS, currExp, currStepAr, r) {
*currentStepIndex++
newStatus.CurrentStepIndex = currentStepIndex
Expand Down
2 changes: 1 addition & 1 deletion rollout/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ func (f *fixture) newController(resync resyncFunc) (*RolloutController, informer
converter := runtime.NewTestUnstructuredConverter(equality.Semantic)
objMap, _ := converter.ToUnstructured(createAction.GetObject())
runtime.NewTestUnstructuredConverter(equality.Semantic).FromUnstructured(objMap, ar)
ar.Name = ar.GenerateName + "-" + MockGeneratedNameSuffix
ar.Name = ar.GenerateName + MockGeneratedNameSuffix
return true, ar.DeepCopyObject(), nil
})

Expand Down
10 changes: 9 additions & 1 deletion utils/analysis/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,16 @@ func BuildArgumentsForRolloutAnalysisRun(rolloutAnalysisRun *v1alpha1.RolloutAna
return arguments
}

// BackgroundLabels returns a map[string]string of common labels for the background analysis
func BackgroundLabels(podHash string) map[string]string {
return map[string]string{
v1alpha1.DefaultRolloutUniqueLabelKey: podHash,
v1alpha1.RolloutTypeLabel: v1alpha1.RolloutTypeBackgroundRunLabel,
}
}

// StepLabels returns a map[string]string of common labels for analysisruns created from an analysis step
func StepLabels(r *v1alpha1.Rollout, index int32, podHash string) map[string]string {
func StepLabels(index int32, podHash string) map[string]string {
indexStr := strconv.Itoa(int(index))
return map[string]string{
v1alpha1.DefaultRolloutUniqueLabelKey: podHash,
Expand Down
17 changes: 11 additions & 6 deletions utils/analysis/factory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,23 @@ func TestBuildArgumentsForRolloutAnalysisRun(t *testing.T) {
}

func TestStepLabels(t *testing.T) {
ro := &v1alpha1.Rollout{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
},
}
podHash := "abcd123"
expected := map[string]string{
v1alpha1.DefaultRolloutUniqueLabelKey: podHash,
v1alpha1.RolloutTypeLabel: v1alpha1.RolloutTypeStepLabel,
v1alpha1.RolloutCanaryStepIndexLabel: "1",
}
generated := StepLabels(ro, 1, podHash)
generated := StepLabels(1, podHash)
assert.Equal(t, expected, generated)
}

func TestBackgroundLabels(t *testing.T) {
podHash := "abcd123"
expected := map[string]string{
v1alpha1.DefaultRolloutUniqueLabelKey: podHash,
v1alpha1.RolloutTypeLabel: v1alpha1.RolloutTypeBackgroundRunLabel,
}
generated := BackgroundLabels(podHash)
assert.Equal(t, expected, generated)
}

Expand Down
12 changes: 12 additions & 0 deletions utils/analysis/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,18 @@ func GetCurrentStepAnalysisRun(currentArs []*v1alpha1.AnalysisRun) *v1alpha1.Ana
return nil
}

//GetCurrentBackgroundAnalysisRun filters the currentArs and returns the background based analysis run
func GetCurrentBackgroundAnalysisRun(currentArs []*v1alpha1.AnalysisRun) *v1alpha1.AnalysisRun {
for i := range currentArs {
ar := currentArs[i]
rolloutType, ok := ar.Labels[v1alpha1.RolloutTypeLabel]
if ok && rolloutType == v1alpha1.RolloutTypeBackgroundRunLabel {
return ar
}
}
return nil
}

// FilterCurrentRolloutAnalysisRuns returns analysisRuns that match the analysisRuns listed in the rollout status
func FilterCurrentRolloutAnalysisRuns(analysisRuns []*v1alpha1.AnalysisRun, r *v1alpha1.Rollout) ([]*v1alpha1.AnalysisRun, []*v1alpha1.AnalysisRun) {
return filterAnalysisRuns(analysisRuns, func(ar *v1alpha1.AnalysisRun) bool {
Expand Down
27 changes: 27 additions & 0 deletions utils/analysis/filter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,33 @@ import (
"github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1"
)

func TestGetCurrentBackgroundAnalysisRun(t *testing.T) {
arsWithBackground := []*v1alpha1.AnalysisRun{
{
ObjectMeta: metav1.ObjectMeta{
Name: "bar",
Labels: map[string]string{
v1alpha1.RolloutTypeLabel: v1alpha1.RolloutTypeBackgroundRunLabel,
},
},
},
}
currAr := GetCurrentBackgroundAnalysisRun(arsWithBackground)
assert.Equal(t, arsWithBackground[0], currAr)
arsWithNoBackground := []*v1alpha1.AnalysisRun{
{
ObjectMeta: metav1.ObjectMeta{
Name: "bar",
Labels: map[string]string{
v1alpha1.RolloutTypeLabel: v1alpha1.RolloutTypeStepLabel,
},
},
},
}
currAr = GetCurrentBackgroundAnalysisRun(arsWithNoBackground)
assert.Nil(t, currAr)
}

func TestGetCurrentStepAnalysisRun(t *testing.T) {
arsWithSteps := []*v1alpha1.AnalysisRun{
{
Expand Down

0 comments on commit cfb56e1

Please sign in to comment.