Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
445 changes: 171 additions & 274 deletions controllers/nstemplateset/cluster_resources.go

Large diffs are not rendered by default.

1,156 changes: 326 additions & 830 deletions controllers/nstemplateset/cluster_resources_test.go

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions controllers/nstemplateset/features.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,9 @@ func shouldCreate(toCreate runtimeclient.Object, nsTmplSet *toolchainv1alpha1.NS
}
return slices.Contains(utils.SplitCommaSeparatedList(winners), feature)
}

// featuresChanged returns true if the features on the NSTemplateSet changed since the last time it was applied.
func featuresChanged(nsTmplSet *toolchainv1alpha1.NSTemplateSet) bool {
changed, _ := featureAnnotationNeedsUpdate(nsTmplSet)
return changed
}
59 changes: 59 additions & 0 deletions controllers/nstemplateset/features_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,65 @@ func TestShouldCreate(t *testing.T) {
}
}

func TestFeaturesChanged(t *testing.T) {
for _, test := range []struct {
name string
annoFeatures string
statusFeatures []string
changed bool
}{
{
name: "should report no change when no features in either annos or status",
changed: false,
},
{
name: "should report change when no features in status",
annoFeatures: "feature",
changed: true,
},
{
name: "should report change when no features in anno",
statusFeatures: []string{"feature"},
changed: true,
},
{
name: "should report no change when features equal",
statusFeatures: []string{"feature1", "feature2"},
annoFeatures: "feature1,feature2",
changed: false,
},
{
name: "should report change when features differ in number",
statusFeatures: []string{"feature1", "feature2"},
annoFeatures: "feature1",
changed: true,
},
{
name: "should report change when features differ",
statusFeatures: []string{"feature1", "feature2"},
annoFeatures: "feature1,feature3",
changed: true,
},
{
name: "should detect duplicates",
statusFeatures: []string{"feature1", "feature2", "feature1"},
annoFeatures: "feature2,feature1",
changed: false,
},
} {
t.Run(test.name, func(t *testing.T) {
// given
nsts := newNSTmplSet("default", "ns", "base", withNSTemplateSetFeatureAnnotation(test.annoFeatures), withStatusFeatureToggles(test.statusFeatures))

// when
changed := featuresChanged(nsts)

// then
assert.Equal(t, test.changed, changed)
})
}
}

func p(s string) *string {
return &s
}
Expand Down
15 changes: 7 additions & 8 deletions controllers/nstemplateset/nstemplateset_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,12 +133,12 @@ func (r *Reconciler) Reconcile(ctx context.Context, request ctrl.Request) (ctrl.
// we proceed with the cluster-scoped resources template, then all namespaces and finally space roles
// as we want to be sure that cluster-scoped resources such as quotas are set
// even before the namespaces exist
if createdOrUpdated, err := r.clusterResources.ensure(ctx, nsTmplSet); err != nil {
// NOTE: the cluster resources are applied ALL AT ONCE, unlike the namespaces.
// This is a work-in-progress change to unify how we apply cluster resources and namespaces.
// In the end, everything will be applied in one go.
if err := r.clusterResources.ensure(ctx, nsTmplSet); err != nil {
logger.Error(err, "failed to either provision or update cluster resources")
return reconcile.Result{}, err
} else if createdOrUpdated {
// we need to requeue to make sure we apply all cluster resources before continuing further
return reconcile.Result{Requeue: true}, nil // wait for cluster resources to be created
}
if err := r.status.updateStatusClusterResourcesRevisions(ctx, nsTmplSet); err != nil {
return reconcile.Result{}, err
Expand Down Expand Up @@ -217,10 +217,9 @@ func (r *Reconciler) deleteNSTemplateSet(ctx context.Context, nsTmplSet *toolcha
}

// if no namespace was to be deleted, then we can proceed with the cluster resources associated with the user
deletedAny, err := r.clusterResources.delete(ctx, nsTmplSet)
if err != nil || deletedAny {
// we need to check if there are some more cluster resources left
return reconcile.Result{Requeue: true}, err
err = r.clusterResources.delete(ctx, nsTmplSet)
if err != nil {
return reconcile.Result{}, err
}

// if nothing was to be deleted, then we can remove the finalizer and we're done
Expand Down
Loading
Loading