From fb8a69060d59c227ed3add621e95903baed405ff Mon Sep 17 00:00:00 2001 From: Devtools Date: Mon, 11 Nov 2024 12:10:07 +0100 Subject: [PATCH 01/23] wip add ttr tests --- testsupport/init.go | 4 +-- testsupport/wait/host.go | 57 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 57 insertions(+), 4 deletions(-) diff --git a/testsupport/init.go b/testsupport/init.go index 5baa268bd..165b47752 100644 --- a/testsupport/init.go +++ b/testsupport/init.go @@ -214,8 +214,8 @@ func WaitForDeployments(t *testing.T) wait.Awaitilities { initMemberAwait.WaitForMemberWebhooks(t, webhookImage) // wait for autoscaler buffer apps - initMemberAwait.WaitForAutoscalingBufferApp(t) - initMember2Await.WaitForAutoscalingBufferApp(t) + //initMemberAwait.WaitForAutoscalingBufferApp(t) + //initMember2Await.WaitForAutoscalingBufferApp(t) // check that the tier exists, and all its namespace other cluster-scoped resource revisions // are different from `000000a` which is the value specified in the initial manifest (used for base tier) diff --git a/testsupport/wait/host.go b/testsupport/wait/host.go index d0634e017..38764155d 100644 --- a/testsupport/wait/host.go +++ b/testsupport/wait/host.go @@ -1023,18 +1023,45 @@ func (a *HostAwaitility) WaitForNSTemplateTierAndCheckTemplates(t *testing.T, na if ns.TemplateRef == "" { return nil, fmt.Errorf("missing 'templateRef' in namespace #%d in NSTemplateTier '%s'", i, tier.Name) } - if _, err := a.WaitForTierTemplate(t, ns.TemplateRef); err != nil { + tierTemplateNamespaces, err := a.WaitForTierTemplate(t, ns.TemplateRef) + if err != nil { return nil, err } + // if the tier template supports Tier Template Revisions then let's check those + if tierTemplateNamespaces.Spec.TemplateObjects != nil { + if _, err := a.WaitForTierTemplateRevision(t, tierTemplateNamespaces.GetName()); err != nil { + return nil, err + } + } } if tier.Spec.ClusterResources != nil { if tier.Spec.ClusterResources.TemplateRef == "" { return nil, fmt.Errorf("missing 'templateRef' for the cluster resources in NSTemplateTier '%s'", tier.Name) } - if _, err := a.WaitForTierTemplate(t, tier.Spec.ClusterResources.TemplateRef); err != nil { + tierTemplateClusterResources, err := a.WaitForTierTemplate(t, tier.Spec.ClusterResources.TemplateRef) + if err != nil { + return nil, err + } + // if the tier template supports Tier Template Revisions then let's check those + if tierTemplateClusterResources.Spec.TemplateObjects != nil { + if _, err := a.WaitForTierTemplateRevision(t, tierTemplateClusterResources.GetName()); err != nil { + return nil, err + } + } + } + + for _, r := range tier.Spec.SpaceRoles { + if r.TemplateRef == "" { + return nil, fmt.Errorf("missing 'templateRef' in spaceRole %s in NSTemplateTier '%s'", r.TemplateRef, tier.Name) + } + if _, err := a.WaitForTierTemplate(t, r.TemplateRef); err != nil { + return nil, err + } + if _, err := a.WaitForTierTemplateRevision(t, r.TemplateRef); err != nil { return nil, err } } + return tier, err } @@ -1061,6 +1088,32 @@ func (a *HostAwaitility) WaitForTierTemplate(t *testing.T, name string) (*toolch return tierTemplate, err } +// WaitForTierTemplateRevision waits until a TierTemplateRevision with the given labels to exists +// Returns an error if the resource did not exist (or something wrong happened) +func (a *HostAwaitility) WaitForTierTemplateRevision(t *testing.T, templateRef string) (*toolchainv1alpha1.TierTemplateRevision, error) { // nolint:unparam + ttr := &toolchainv1alpha1.TierTemplateRevision{} + t.Logf("waiting until TierTemplateRevision for templateRef '%s' exists in namespace '%s'...", templateRef, a.Namespace) + err := wait.Poll(a.RetryInterval, a.Timeout, func() (done bool, err error) { + objs := &toolchainv1alpha1.TierTemplateRevisionList{} + if err := a.Client.List(context.TODO(), objs, client.InNamespace(a.Namespace), client.MatchingLabels(map[string]string{ + toolchainv1alpha1.TemplateRefLabelKey: templateRef, + })); err != nil { + if errors.IsNotFound(err) { + return false, nil + } + return false, err + } + require.Len(t, objs.Items, 1) + ttr = &objs.Items[0] + return true, nil + }) + // log message if an error occurred + if err != nil { + t.Logf("failed to find TierTemplateRevision templateRef '%s': %v", templateRef, err) + } + return ttr, err +} + // NSTemplateTierWaitCriterion a struct to compare with an expected NSTemplateTier type NSTemplateTierWaitCriterion struct { Match func(*toolchainv1alpha1.NSTemplateTier) bool From d66af28d02936471357d925544aec086516fe2bd Mon Sep 17 00:00:00 2001 From: Devtools Date: Mon, 11 Nov 2024 20:45:30 +0100 Subject: [PATCH 02/23] test TierTemplate revisions are created when templateObjects are set --- test/e2e/parallel/nstemplatetier_test.go | 41 ++++++++++++++++++++++++ testsupport/tiers/tier_setup.go | 8 ++--- testsupport/wait/host.go | 13 ++++---- 3 files changed, 52 insertions(+), 10 deletions(-) diff --git a/test/e2e/parallel/nstemplatetier_test.go b/test/e2e/parallel/nstemplatetier_test.go index c2a3fc983..0cb04dbf9 100644 --- a/test/e2e/parallel/nstemplatetier_test.go +++ b/test/e2e/parallel/nstemplatetier_test.go @@ -20,6 +20,7 @@ import ( . "github.com/codeready-toolchain/toolchain-e2e/testsupport/space" "github.com/codeready-toolchain/toolchain-e2e/testsupport/tiers" "github.com/codeready-toolchain/toolchain-e2e/testsupport/wait" + apiwait "k8s.io/apimachinery/pkg/util/wait" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -378,6 +379,46 @@ func TestFeatureToggles(t *testing.T) { }) } +func TestTierTemplateRevision(t *testing.T) { + t.Parallel() + + awaitilities := WaitForDeployments(t) + hostAwait := awaitilities.Host() + + baseTier, err := hostAwait.WaitForNSTemplateTier(t, "base1ns") + require.NoError(t, err) + + // create new NSTemplateTiers (derived from `base`) + // for the tiertemplaterevisions to be created the tiertemplates need to have template objects populated + namespaceResourcesWithTemplateObjects := tiers.WithNamespaceResources(t, baseTier, func(template *toolchainv1alpha1.TierTemplate) error { + template.Spec.TemplateObjects = template.Spec.Template.Objects + return nil + }) + clusterResroucesWithTemplateObjects := tiers.WithClusterResources(t, baseTier, func(template *toolchainv1alpha1.TierTemplate) error { + template.Spec.TemplateObjects = template.Spec.Template.Objects + return nil + }) + spaceRolesWithTemplateObjects := tiers.WithSpaceRoles(t, baseTier, func(template *toolchainv1alpha1.TierTemplate) error { + template.Spec.TemplateObjects = template.Spec.Template.Objects + return nil + }) + tiers.CreateCustomNSTemplateTier(t, hostAwait, "ttr", baseTier, namespaceResourcesWithTemplateObjects, clusterResroucesWithTemplateObjects, spaceRolesWithTemplateObjects) + + // verify the counters in the status.history for 'tierUsingTierTemplateRevisions' tier + // and verify that TierTemplateRevision CRs were created, since all the tiertemplates now have templateObjects field populated + verifyStatus(t, hostAwait, "ttr", 1) + // check the expected total number of ttr matches + err = apiwait.Poll(hostAwait.RetryInterval, hostAwait.Timeout, func() (done bool, err error) { + objs := &toolchainv1alpha1.TierTemplateRevisionList{} + if err := hostAwait.Client.List(context.TODO(), objs, client.InNamespace(hostAwait.Namespace)); err != nil { + return false, err + } + require.Len(t, objs.Items, 3) // expect one TTR per each tiertemplate ( clusterresource, namespace and spacerole ) + return true, nil + }) + require.NoError(t, err) +} + func withClusterRoleBindings(t *testing.T, otherTier *toolchainv1alpha1.NSTemplateTier, feature string) tiers.CustomNSTemplateTierModifier { clusterRB := getCRBforFeature(t, feature) // This is the ClusterRoleBinding for the desired feature noiseCRB := getCRBforFeature(t, unknownFeature) // This is a noise CRB for unknown/disabled feature. To be used to check that this CRB is never created. diff --git a/testsupport/tiers/tier_setup.go b/testsupport/tiers/tier_setup.go index e56676104..3e040e643 100644 --- a/testsupport/tiers/tier_setup.go +++ b/testsupport/tiers/tier_setup.go @@ -47,13 +47,13 @@ func WithClusterResources(t *testing.T, otherTier *toolchainv1alpha1.NSTemplateT } } -func WithNamespaceResources(t *testing.T, otherTier *toolchainv1alpha1.NSTemplateTier) CustomNSTemplateTierModifier { +func WithNamespaceResources(t *testing.T, otherTier *toolchainv1alpha1.NSTemplateTier, modifiers ...TierTemplateModifier) CustomNSTemplateTierModifier { return func(hostAwait *HostAwaitility, tier *CustomNSTemplateTier) error { tier.NamespaceResourcesTier = otherTier // configure the "wrapped" NSTemplateTier tier.Spec.Namespaces = make([]toolchainv1alpha1.NSTemplateTierNamespace, len(otherTier.Spec.Namespaces)) for i, def := range otherTier.Spec.Namespaces { - tmplRef, err := duplicateTierTemplate(t, hostAwait, otherTier.Namespace, tier.Name, def.TemplateRef) + tmplRef, err := duplicateTierTemplate(t, hostAwait, otherTier.Namespace, tier.Name, def.TemplateRef, modifiers...) if err != nil { return err } @@ -63,13 +63,13 @@ func WithNamespaceResources(t *testing.T, otherTier *toolchainv1alpha1.NSTemplat } } -func WithSpaceRoles(t *testing.T, otherTier *toolchainv1alpha1.NSTemplateTier) CustomNSTemplateTierModifier { +func WithSpaceRoles(t *testing.T, otherTier *toolchainv1alpha1.NSTemplateTier, modifiers ...TierTemplateModifier) CustomNSTemplateTierModifier { return func(hostAwait *HostAwaitility, tier *CustomNSTemplateTier) error { tier.SpaceRolesTier = otherTier // configure the "wrapped" NSTemplateTier tier.Spec.SpaceRoles = make(map[string]toolchainv1alpha1.NSTemplateTierSpaceRole, len(otherTier.Spec.SpaceRoles)) for name, def := range otherTier.Spec.SpaceRoles { - tmplRef, err := duplicateTierTemplate(t, hostAwait, otherTier.Namespace, tier.Name, def.TemplateRef) + tmplRef, err := duplicateTierTemplate(t, hostAwait, otherTier.Namespace, tier.Name, def.TemplateRef, modifiers...) if err != nil { return err } diff --git a/testsupport/wait/host.go b/testsupport/wait/host.go index 38764155d..32f3d0e56 100644 --- a/testsupport/wait/host.go +++ b/testsupport/wait/host.go @@ -1054,11 +1054,15 @@ func (a *HostAwaitility) WaitForNSTemplateTierAndCheckTemplates(t *testing.T, na if r.TemplateRef == "" { return nil, fmt.Errorf("missing 'templateRef' in spaceRole %s in NSTemplateTier '%s'", r.TemplateRef, tier.Name) } - if _, err := a.WaitForTierTemplate(t, r.TemplateRef); err != nil { + tierTemplateSpaceRoles, err := a.WaitForTierTemplate(t, r.TemplateRef) + if err != nil { return nil, err } - if _, err := a.WaitForTierTemplateRevision(t, r.TemplateRef); err != nil { - return nil, err + // if the tier template supports Tier Template Revisions then let's check those + if tierTemplateSpaceRoles.Spec.TemplateObjects != nil { + if _, err := a.WaitForTierTemplateRevision(t, r.TemplateRef); err != nil { + return nil, err + } } } @@ -1098,9 +1102,6 @@ func (a *HostAwaitility) WaitForTierTemplateRevision(t *testing.T, templateRef s if err := a.Client.List(context.TODO(), objs, client.InNamespace(a.Namespace), client.MatchingLabels(map[string]string{ toolchainv1alpha1.TemplateRefLabelKey: templateRef, })); err != nil { - if errors.IsNotFound(err) { - return false, nil - } return false, err } require.Len(t, objs.Items, 1) From 62a1a8343aec90891bd3382d31743206e9a08972 Mon Sep 17 00:00:00 2001 From: Devtools Date: Mon, 11 Nov 2024 22:09:36 +0100 Subject: [PATCH 03/23] check for owner refernces --- test/e2e/parallel/nstemplatetier_test.go | 17 ++-- testsupport/wait/host.go | 103 +++++++++++++++++++++-- 2 files changed, 101 insertions(+), 19 deletions(-) diff --git a/test/e2e/parallel/nstemplatetier_test.go b/test/e2e/parallel/nstemplatetier_test.go index 0cb04dbf9..581265d03 100644 --- a/test/e2e/parallel/nstemplatetier_test.go +++ b/test/e2e/parallel/nstemplatetier_test.go @@ -390,19 +390,14 @@ func TestTierTemplateRevision(t *testing.T) { // create new NSTemplateTiers (derived from `base`) // for the tiertemplaterevisions to be created the tiertemplates need to have template objects populated - namespaceResourcesWithTemplateObjects := tiers.WithNamespaceResources(t, baseTier, func(template *toolchainv1alpha1.TierTemplate) error { + updateTierTemplateObjects := func(template *toolchainv1alpha1.TierTemplate) error { template.Spec.TemplateObjects = template.Spec.Template.Objects return nil - }) - clusterResroucesWithTemplateObjects := tiers.WithClusterResources(t, baseTier, func(template *toolchainv1alpha1.TierTemplate) error { - template.Spec.TemplateObjects = template.Spec.Template.Objects - return nil - }) - spaceRolesWithTemplateObjects := tiers.WithSpaceRoles(t, baseTier, func(template *toolchainv1alpha1.TierTemplate) error { - template.Spec.TemplateObjects = template.Spec.Template.Objects - return nil - }) - tiers.CreateCustomNSTemplateTier(t, hostAwait, "ttr", baseTier, namespaceResourcesWithTemplateObjects, clusterResroucesWithTemplateObjects, spaceRolesWithTemplateObjects) + } + namespaceResourcesWithTemplateObjects := tiers.WithNamespaceResources(t, baseTier, updateTierTemplateObjects) + clusterResourcesWithTemplateObjects := tiers.WithClusterResources(t, baseTier, updateTierTemplateObjects) + spaceRolesWithTemplateObjects := tiers.WithSpaceRoles(t, baseTier, updateTierTemplateObjects) + tiers.CreateCustomNSTemplateTier(t, hostAwait, "ttr", baseTier, namespaceResourcesWithTemplateObjects, clusterResourcesWithTemplateObjects, spaceRolesWithTemplateObjects) // verify the counters in the status.history for 'tierUsingTierTemplateRevisions' tier // and verify that TierTemplateRevision CRs were created, since all the tiertemplates now have templateObjects field populated diff --git a/testsupport/wait/host.go b/testsupport/wait/host.go index 32f3d0e56..60f0c1c07 100644 --- a/testsupport/wait/host.go +++ b/testsupport/wait/host.go @@ -1029,7 +1029,13 @@ func (a *HostAwaitility) WaitForNSTemplateTierAndCheckTemplates(t *testing.T, na } // if the tier template supports Tier Template Revisions then let's check those if tierTemplateNamespaces.Spec.TemplateObjects != nil { - if _, err := a.WaitForTierTemplateRevision(t, tierTemplateNamespaces.GetName()); err != nil { + if _, err := a.WaitForTierTemplateRevision(t, tierTemplateNamespaces.GetName(), UntilTierTemplateRevisionsHasOwnerReferences([]metav1.OwnerReference{ + { + APIVersion: tierTemplateNamespaces.APIVersion, + Kind: tierTemplateNamespaces.Kind, + Name: tierTemplateNamespaces.Name, + }, + })); err != nil { return nil, err } } @@ -1044,7 +1050,13 @@ func (a *HostAwaitility) WaitForNSTemplateTierAndCheckTemplates(t *testing.T, na } // if the tier template supports Tier Template Revisions then let's check those if tierTemplateClusterResources.Spec.TemplateObjects != nil { - if _, err := a.WaitForTierTemplateRevision(t, tierTemplateClusterResources.GetName()); err != nil { + if _, err := a.WaitForTierTemplateRevision(t, tierTemplateClusterResources.GetName(), UntilTierTemplateRevisionsHasOwnerReferences([]metav1.OwnerReference{ + { + APIVersion: tierTemplateClusterResources.APIVersion, + Kind: tierTemplateClusterResources.Kind, + Name: tierTemplateClusterResources.Name, + }, + })); err != nil { return nil, err } } @@ -1060,7 +1072,13 @@ func (a *HostAwaitility) WaitForNSTemplateTierAndCheckTemplates(t *testing.T, na } // if the tier template supports Tier Template Revisions then let's check those if tierTemplateSpaceRoles.Spec.TemplateObjects != nil { - if _, err := a.WaitForTierTemplateRevision(t, r.TemplateRef); err != nil { + if _, err := a.WaitForTierTemplateRevision(t, r.TemplateRef, UntilTierTemplateRevisionsHasOwnerReferences([]metav1.OwnerReference{ + { + APIVersion: tierTemplateSpaceRoles.APIVersion, + Kind: tierTemplateSpaceRoles.Kind, + Name: tierTemplateSpaceRoles.Name, + }, + })); err != nil { return nil, err } } @@ -1092,29 +1110,98 @@ func (a *HostAwaitility) WaitForTierTemplate(t *testing.T, name string) (*toolch return tierTemplate, err } +// TierTemplateRevisionWaitCriterion a struct to compare with an expected TierTemplateRevision +type TierTemplateRevisionWaitCriterion struct { + Match func(*toolchainv1alpha1.TierTemplateRevision) bool + Diff func(*toolchainv1alpha1.TierTemplateRevision) string +} + +func matchTierTemplateRevisionWaitCriterion(actual *toolchainv1alpha1.TierTemplateRevision, criteria ...TierTemplateRevisionWaitCriterion) bool { + for _, c := range criteria { + // if at least one criteria does not match, keep waiting + if !c.Match(actual) { + return false + } + } + return true +} + +func (a *HostAwaitility) printTierTemplateRevisionWaitCriterionDiffs(t *testing.T, actual *toolchainv1alpha1.TierTemplateRevision, criteria ...TierTemplateRevisionWaitCriterion) { + buf := &strings.Builder{} + if actual == nil { + buf.WriteString("failed to find TierTemplateRevision\n") + } else { + buf.WriteString("failed to find TierTemplateRevision with matching criteria:\n") + buf.WriteString("actual:\n") + y, _ := StringifyObject(actual) + buf.Write(y) + buf.WriteString("\n----\n") + buf.WriteString("diffs:\n") + for _, c := range criteria { + if !c.Match(actual) { + buf.WriteString(c.Diff(actual)) + buf.WriteString("\n") + } + } + } + // include also all TierTemplateRevisions in the host namespace, to help troubleshooting + a.listAndPrint(t, "TierTemplateRevisions", a.Namespace, &toolchainv1alpha1.TierTemplateRevisionList{}) + + t.Log(buf.String()) +} + // WaitForTierTemplateRevision waits until a TierTemplateRevision with the given labels to exists // Returns an error if the resource did not exist (or something wrong happened) -func (a *HostAwaitility) WaitForTierTemplateRevision(t *testing.T, templateRef string) (*toolchainv1alpha1.TierTemplateRevision, error) { // nolint:unparam +func (a *HostAwaitility) WaitForTierTemplateRevision(t *testing.T, templateRef string, criteria ...TierTemplateRevisionWaitCriterion) (*toolchainv1alpha1.TierTemplateRevision, error) { // nolint:unparam ttr := &toolchainv1alpha1.TierTemplateRevision{} t.Logf("waiting until TierTemplateRevision for templateRef '%s' exists in namespace '%s'...", templateRef, a.Namespace) err := wait.Poll(a.RetryInterval, a.Timeout, func() (done bool, err error) { objs := &toolchainv1alpha1.TierTemplateRevisionList{} - if err := a.Client.List(context.TODO(), objs, client.InNamespace(a.Namespace), client.MatchingLabels(map[string]string{ + err = a.Client.List(context.TODO(), objs, client.InNamespace(a.Namespace), client.MatchingLabels(map[string]string{ toolchainv1alpha1.TemplateRefLabelKey: templateRef, - })); err != nil { + })) + // no match found, print the diffs + if err != nil { return false, err } require.Len(t, objs.Items, 1) ttr = &objs.Items[0] - return true, nil + return matchTierTemplateRevisionWaitCriterion(ttr, criteria...), nil }) // log message if an error occurred if err != nil { - t.Logf("failed to find TierTemplateRevision templateRef '%s': %v", templateRef, err) + a.printTierTemplateRevisionWaitCriterionDiffs(t, ttr, criteria...) } return ttr, err } +// UntilTierTemplateRevisionsHasOwnerReferences verify that the TierTemplateRevision has the specified owner references +func UntilTierTemplateRevisionsHasOwnerReferences(references []metav1.OwnerReference) TierTemplateRevisionWaitCriterion { + return TierTemplateRevisionWaitCriterion{ + Match: func(actual *toolchainv1alpha1.TierTemplateRevision) bool { + actualReferences := actual.GetOwnerReferences() + for _, actualRef := range actualReferences { + found := false + for _, expectedRef := range references { + if expectedRef.Name == actualRef.Name && + expectedRef.APIVersion == actualRef.APIVersion && + expectedRef.Kind == actualRef.Kind { + found = true + break + } + } + if !found { + return false + } + } + return len(references) == len(actualReferences) + }, + Diff: func(actual *toolchainv1alpha1.TierTemplateRevision) string { + return fmt.Sprintf("unable to find expected owner references: %v", references) + }, + } +} + // NSTemplateTierWaitCriterion a struct to compare with an expected NSTemplateTier type NSTemplateTierWaitCriterion struct { Match func(*toolchainv1alpha1.NSTemplateTier) bool From 09fe90b0ced60d77d2041c9533e1a96463c3393c Mon Sep 17 00:00:00 2001 From: Devtools Date: Tue, 12 Nov 2024 09:37:02 +0100 Subject: [PATCH 04/23] fix ownership check --- test/e2e/parallel/nstemplatetier_test.go | 1 + testsupport/wait/host.go | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/test/e2e/parallel/nstemplatetier_test.go b/test/e2e/parallel/nstemplatetier_test.go index 581265d03..61eeea220 100644 --- a/test/e2e/parallel/nstemplatetier_test.go +++ b/test/e2e/parallel/nstemplatetier_test.go @@ -5,6 +5,7 @@ import ( "context" "fmt" "html/template" + "os" "testing" "time" diff --git a/testsupport/wait/host.go b/testsupport/wait/host.go index 60f0c1c07..65afdeccc 100644 --- a/testsupport/wait/host.go +++ b/testsupport/wait/host.go @@ -1031,8 +1031,8 @@ func (a *HostAwaitility) WaitForNSTemplateTierAndCheckTemplates(t *testing.T, na if tierTemplateNamespaces.Spec.TemplateObjects != nil { if _, err := a.WaitForTierTemplateRevision(t, tierTemplateNamespaces.GetName(), UntilTierTemplateRevisionsHasOwnerReferences([]metav1.OwnerReference{ { - APIVersion: tierTemplateNamespaces.APIVersion, - Kind: tierTemplateNamespaces.Kind, + APIVersion: "toolchain.dev.openshift.com/v1alpha1", // for some reason, the apiversion and kind are empty on the CR + Kind: "TierTemplate", Name: tierTemplateNamespaces.Name, }, })); err != nil { @@ -1052,8 +1052,8 @@ func (a *HostAwaitility) WaitForNSTemplateTierAndCheckTemplates(t *testing.T, na if tierTemplateClusterResources.Spec.TemplateObjects != nil { if _, err := a.WaitForTierTemplateRevision(t, tierTemplateClusterResources.GetName(), UntilTierTemplateRevisionsHasOwnerReferences([]metav1.OwnerReference{ { - APIVersion: tierTemplateClusterResources.APIVersion, - Kind: tierTemplateClusterResources.Kind, + APIVersion: "toolchain.dev.openshift.com/v1alpha1", // for some reason, the apiversion and kind are empty on the CR + Kind: "TierTemplate", Name: tierTemplateClusterResources.Name, }, })); err != nil { @@ -1074,8 +1074,8 @@ func (a *HostAwaitility) WaitForNSTemplateTierAndCheckTemplates(t *testing.T, na if tierTemplateSpaceRoles.Spec.TemplateObjects != nil { if _, err := a.WaitForTierTemplateRevision(t, r.TemplateRef, UntilTierTemplateRevisionsHasOwnerReferences([]metav1.OwnerReference{ { - APIVersion: tierTemplateSpaceRoles.APIVersion, - Kind: tierTemplateSpaceRoles.Kind, + APIVersion: "toolchain.dev.openshift.com/v1alpha1", // for some reason, the apiversion and kind are empty on the CR + Kind: "TierTemplate", Name: tierTemplateSpaceRoles.Name, }, })); err != nil { From edcf46704bde969e6c0b34730f34a55d16339a95 Mon Sep 17 00:00:00 2001 From: Devtools Date: Tue, 12 Nov 2024 15:30:03 +0100 Subject: [PATCH 05/23] remove unused import --- test/e2e/parallel/nstemplatetier_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/test/e2e/parallel/nstemplatetier_test.go b/test/e2e/parallel/nstemplatetier_test.go index 61eeea220..581265d03 100644 --- a/test/e2e/parallel/nstemplatetier_test.go +++ b/test/e2e/parallel/nstemplatetier_test.go @@ -5,7 +5,6 @@ import ( "context" "fmt" "html/template" - "os" "testing" "time" From e91f57c0387265826d37aee0d1bfc41d81885a9b Mon Sep 17 00:00:00 2001 From: Devtools Date: Mon, 18 Nov 2024 11:53:15 +0100 Subject: [PATCH 06/23] make linter happy --- test/e2e/parallel/nstemplatetier_test.go | 4 ++-- testsupport/wait/host.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/e2e/parallel/nstemplatetier_test.go b/test/e2e/parallel/nstemplatetier_test.go index 581265d03..9addaff6d 100644 --- a/test/e2e/parallel/nstemplatetier_test.go +++ b/test/e2e/parallel/nstemplatetier_test.go @@ -403,9 +403,9 @@ func TestTierTemplateRevision(t *testing.T) { // and verify that TierTemplateRevision CRs were created, since all the tiertemplates now have templateObjects field populated verifyStatus(t, hostAwait, "ttr", 1) // check the expected total number of ttr matches - err = apiwait.Poll(hostAwait.RetryInterval, hostAwait.Timeout, func() (done bool, err error) { + err = apiwait.PollUntilContextTimeout(context.TODO(), hostAwait.RetryInterval, hostAwait.Timeout, true, func(ctx context.Context) (done bool, err error) { objs := &toolchainv1alpha1.TierTemplateRevisionList{} - if err := hostAwait.Client.List(context.TODO(), objs, client.InNamespace(hostAwait.Namespace)); err != nil { + if err := hostAwait.Client.List(ctx, objs, client.InNamespace(hostAwait.Namespace)); err != nil { return false, err } require.Len(t, objs.Items, 3) // expect one TTR per each tiertemplate ( clusterresource, namespace and spacerole ) diff --git a/testsupport/wait/host.go b/testsupport/wait/host.go index 3035b7591..0312bc019 100644 --- a/testsupport/wait/host.go +++ b/testsupport/wait/host.go @@ -1155,9 +1155,9 @@ func (a *HostAwaitility) printTierTemplateRevisionWaitCriterionDiffs(t *testing. func (a *HostAwaitility) WaitForTierTemplateRevision(t *testing.T, templateRef string, criteria ...TierTemplateRevisionWaitCriterion) (*toolchainv1alpha1.TierTemplateRevision, error) { // nolint:unparam ttr := &toolchainv1alpha1.TierTemplateRevision{} t.Logf("waiting until TierTemplateRevision for templateRef '%s' exists in namespace '%s'...", templateRef, a.Namespace) - err := wait.Poll(a.RetryInterval, a.Timeout, func() (done bool, err error) { + err := wait.PollUntilContextTimeout(context.TODO(), a.RetryInterval, a.Timeout, true, func(ctx context.Context) (done bool, err error) { objs := &toolchainv1alpha1.TierTemplateRevisionList{} - err = a.Client.List(context.TODO(), objs, client.InNamespace(a.Namespace), client.MatchingLabels(map[string]string{ + err = a.Client.List(ctx, objs, client.InNamespace(a.Namespace), client.MatchingLabels(map[string]string{ toolchainv1alpha1.TemplateRefLabelKey: templateRef, })) // no match found, print the diffs From 7d3484356019f094380984c9f819bacb5bbf1695 Mon Sep 17 00:00:00 2001 From: Devtools Date: Wed, 20 Nov 2024 01:12:30 +0100 Subject: [PATCH 07/23] add comments, check for ttr content, check revisions --- go.mod | 7 ++- go.sum | 7 ++- test/e2e/parallel/nstemplatetier_test.go | 39 +++++++++++++---- testsupport/tiers/tier_setup.go | 15 +++++++ testsupport/wait/host.go | 54 +++++++++++++++++++----- 5 files changed, 99 insertions(+), 23 deletions(-) diff --git a/go.mod b/go.mod index 7f5d0098b..80fb14b00 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/fatih/color v1.15.0 github.com/ghodss/yaml v1.0.0 github.com/gofrs/uuid v3.3.0+incompatible - github.com/google/go-cmp v0.5.9 + github.com/google/go-cmp v0.6.0 github.com/gorilla/websocket v1.4.2 github.com/gosuri/uiprogress v0.0.1 github.com/gosuri/uitable v0.0.4 @@ -31,7 +31,10 @@ require ( sigs.k8s.io/controller-runtime v0.15.0 ) -require github.com/google/uuid v1.6.0 +require ( + github.com/google/uuid v1.6.0 + golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f +) require ( github.com/BurntSushi/toml v1.2.1 // indirect diff --git a/go.sum b/go.sum index 63f84a1d6..e6a13f39d 100644 --- a/go.sum +++ b/go.sum @@ -301,8 +301,9 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github/v52 v52.0.0 h1:uyGWOY+jMQ8GVGSX8dkSwCzlehU3WfdxQ7GweO/JP7M= github.com/google/go-github/v52 v52.0.0/go.mod h1:WJV6VEEUPuMo5pXqqa2ZCZEdbQqua4zAk2MZTIo+m+4= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= @@ -746,6 +747,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo= +golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1041,7 +1044,7 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= +golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/test/e2e/parallel/nstemplatetier_test.go b/test/e2e/parallel/nstemplatetier_test.go index 9addaff6d..ab90c92e1 100644 --- a/test/e2e/parallel/nstemplatetier_test.go +++ b/test/e2e/parallel/nstemplatetier_test.go @@ -9,6 +9,7 @@ import ( "time" v1 "k8s.io/api/rbac/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "github.com/gofrs/uuid" @@ -382,33 +383,55 @@ func TestFeatureToggles(t *testing.T) { func TestTierTemplateRevision(t *testing.T) { t.Parallel() + // given awaitilities := WaitForDeployments(t) hostAwait := awaitilities.Host() - + // we create new NSTemplateTiers (derived from `base`) baseTier, err := hostAwait.WaitForNSTemplateTier(t, "base1ns") require.NoError(t, err) - - // create new NSTemplateTiers (derived from `base`) // for the tiertemplaterevisions to be created the tiertemplates need to have template objects populated + // we add the RawExtension objects to the TemplateObjects field + ns := unstructured.Unstructured{ + Object: map[string]interface{}{ + "kind": "Namespace", + "metadata": map[string]interface{}{ + "name": "{{.SPACE_NAME}}", + }, + }, + } + rawTemplateObjects := []runtime.RawExtension{{Object: &ns}} updateTierTemplateObjects := func(template *toolchainv1alpha1.TierTemplate) error { - template.Spec.TemplateObjects = template.Spec.Template.Objects + template.Spec.TemplateObjects = rawTemplateObjects return nil } namespaceResourcesWithTemplateObjects := tiers.WithNamespaceResources(t, baseTier, updateTierTemplateObjects) clusterResourcesWithTemplateObjects := tiers.WithClusterResources(t, baseTier, updateTierTemplateObjects) spaceRolesWithTemplateObjects := tiers.WithSpaceRoles(t, baseTier, updateTierTemplateObjects) - tiers.CreateCustomNSTemplateTier(t, hostAwait, "ttr", baseTier, namespaceResourcesWithTemplateObjects, clusterResourcesWithTemplateObjects, spaceRolesWithTemplateObjects) + tiers.CreateCustomNSTemplateTier(t, hostAwait, "ttr", baseTier, namespaceResourcesWithTemplateObjects, clusterResourcesWithTemplateObjects, spaceRolesWithTemplateObjects, tiers.WithParameter("SPACE_NAME", "janedoe")) - // verify the counters in the status.history for 'tierUsingTierTemplateRevisions' tier + // when + // we verify the counters in the status.history for 'tierUsingTierTemplateRevisions' tier // and verify that TierTemplateRevision CRs were created, since all the tiertemplates now have templateObjects field populated - verifyStatus(t, hostAwait, "ttr", 1) + _, err = hostAwait.WaitForNSTemplateTierAndCheckTemplates(t, "ttr", wait.HasStatusTierTemplateRevisions([]string{ + fmt.Sprintf("ttrfrom%s", baseTier.Spec.Namespaces[0].TemplateRef), // check that the revision field is set using the expected tierTemplate refs as keys + fmt.Sprintf("ttrfrom%s", baseTier.Spec.SpaceRoles["admin"].TemplateRef), + fmt.Sprintf("ttrfrom%s", baseTier.Spec.ClusterResources.TemplateRef), + })) + require.NoError(t, err) + + // then // check the expected total number of ttr matches err = apiwait.PollUntilContextTimeout(context.TODO(), hostAwait.RetryInterval, hostAwait.Timeout, true, func(ctx context.Context) (done bool, err error) { objs := &toolchainv1alpha1.TierTemplateRevisionList{} if err := hostAwait.Client.List(ctx, objs, client.InNamespace(hostAwait.Namespace)); err != nil { return false, err } - require.Len(t, objs.Items, 3) // expect one TTR per each tiertemplate ( clusterresource, namespace and spacerole ) + require.Len(t, objs.Items, 3) // expect one TTR per each tiertemplate (clusterresource, namespace and spacerole) + // we check that the TTR content has the parameters replaced with values from the NSTemplateTier + for _, obj := range objs.Items { + assert.Contains(t, string(obj.Spec.TemplateObjects[0].Raw), "janedoe") // the object should have the namespace name replaced + assert.NotContains(t, string(obj.Spec.TemplateObjects[0].Raw), ".SPACE_NAME") // the object should NOT contain the variable anymore + } return true, nil }) require.NoError(t, err) diff --git a/testsupport/tiers/tier_setup.go b/testsupport/tiers/tier_setup.go index 3e040e643..fb7130b1a 100644 --- a/testsupport/tiers/tier_setup.go +++ b/testsupport/tiers/tier_setup.go @@ -81,6 +81,21 @@ func WithSpaceRoles(t *testing.T, otherTier *toolchainv1alpha1.NSTemplateTier, m } } +func WithParameter(name, value string) CustomNSTemplateTierModifier { + return func(hostAwait *HostAwaitility, tier *CustomNSTemplateTier) error { + if tier.Spec.Parameters == nil { + tier.Spec.Parameters = []toolchainv1alpha1.Parameter{} + } + tier.Spec.Parameters = append(tier.Spec.Parameters, + toolchainv1alpha1.Parameter{ + Name: name, + Value: value, + }, + ) + return nil + } +} + // CreateCustomNSTemplateTier creates a custom tier. // If no modifiers provided then the new tier will use copies of the baseTier cluster, namespace and space roles templates // without any modifications. diff --git a/testsupport/wait/host.go b/testsupport/wait/host.go index 0312bc019..75ad1773f 100644 --- a/testsupport/wait/host.go +++ b/testsupport/wait/host.go @@ -25,6 +25,7 @@ import ( "github.com/redhat-cop/operator-utils/pkg/util" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "golang.org/x/exp/maps" corev1 "k8s.io/api/core/v1" v1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/api/errors" @@ -1029,7 +1030,11 @@ func (a *HostAwaitility) WaitForNSTemplateTierAndCheckTemplates(t *testing.T, na } // if the tier template supports Tier Template Revisions then let's check those if tierTemplateNamespaces.Spec.TemplateObjects != nil { - if _, err := a.WaitForTierTemplateRevision(t, tierTemplateNamespaces.GetName(), UntilTierTemplateRevisionsHasOwnerReferences([]metav1.OwnerReference{ + ttrName, found := tier.Status.Revisions[tierTemplateNamespaces.GetName()] + if !found { + return nil, fmt.Errorf("missing revision for TierTemplate %s in NSTemplateTier '%s'", tierTemplateNamespaces.GetName(), tier.Name) + } + if _, err := a.WaitForTierTemplateRevision(t, ttrName, UntilTierTemplateRevisionsHasOwnerReferences([]metav1.OwnerReference{ { APIVersion: "toolchain.dev.openshift.com/v1alpha1", // for some reason, the apiversion and kind are empty on the CR Kind: "TierTemplate", @@ -1050,7 +1055,11 @@ func (a *HostAwaitility) WaitForNSTemplateTierAndCheckTemplates(t *testing.T, na } // if the tier template supports Tier Template Revisions then let's check those if tierTemplateClusterResources.Spec.TemplateObjects != nil { - if _, err := a.WaitForTierTemplateRevision(t, tierTemplateClusterResources.GetName(), UntilTierTemplateRevisionsHasOwnerReferences([]metav1.OwnerReference{ + ttrName, found := tier.Status.Revisions[tierTemplateClusterResources.GetName()] + if !found { + return nil, fmt.Errorf("missing revision for TierTemplate %s in NSTemplateTier '%s'", tierTemplateClusterResources.GetName(), tier.Name) + } + if _, err := a.WaitForTierTemplateRevision(t, ttrName, UntilTierTemplateRevisionsHasOwnerReferences([]metav1.OwnerReference{ { APIVersion: "toolchain.dev.openshift.com/v1alpha1", // for some reason, the apiversion and kind are empty on the CR Kind: "TierTemplate", @@ -1072,7 +1081,11 @@ func (a *HostAwaitility) WaitForNSTemplateTierAndCheckTemplates(t *testing.T, na } // if the tier template supports Tier Template Revisions then let's check those if tierTemplateSpaceRoles.Spec.TemplateObjects != nil { - if _, err := a.WaitForTierTemplateRevision(t, r.TemplateRef, UntilTierTemplateRevisionsHasOwnerReferences([]metav1.OwnerReference{ + ttrName, found := tier.Status.Revisions[tierTemplateSpaceRoles.GetName()] + if !found { + return nil, fmt.Errorf("missing revision for TierTemplate %s in NSTemplateTier '%s'", tierTemplateSpaceRoles.GetName(), tier.Name) + } + if _, err := a.WaitForTierTemplateRevision(t, ttrName, UntilTierTemplateRevisionsHasOwnerReferences([]metav1.OwnerReference{ { APIVersion: "toolchain.dev.openshift.com/v1alpha1", // for some reason, the apiversion and kind are empty on the CR Kind: "TierTemplate", @@ -1152,20 +1165,19 @@ func (a *HostAwaitility) printTierTemplateRevisionWaitCriterionDiffs(t *testing. // WaitForTierTemplateRevision waits until a TierTemplateRevision with the given labels to exists // Returns an error if the resource did not exist (or something wrong happened) -func (a *HostAwaitility) WaitForTierTemplateRevision(t *testing.T, templateRef string, criteria ...TierTemplateRevisionWaitCriterion) (*toolchainv1alpha1.TierTemplateRevision, error) { // nolint:unparam +func (a *HostAwaitility) WaitForTierTemplateRevision(t *testing.T, ttrName string, criteria ...TierTemplateRevisionWaitCriterion) (*toolchainv1alpha1.TierTemplateRevision, error) { // nolint:unparam ttr := &toolchainv1alpha1.TierTemplateRevision{} - t.Logf("waiting until TierTemplateRevision for templateRef '%s' exists in namespace '%s'...", templateRef, a.Namespace) + t.Logf("waiting until TierTemplateRevision with name '%s' exists in namespace '%s'...", ttrName, a.Namespace) err := wait.PollUntilContextTimeout(context.TODO(), a.RetryInterval, a.Timeout, true, func(ctx context.Context) (done bool, err error) { - objs := &toolchainv1alpha1.TierTemplateRevisionList{} - err = a.Client.List(ctx, objs, client.InNamespace(a.Namespace), client.MatchingLabels(map[string]string{ - toolchainv1alpha1.TemplateRefLabelKey: templateRef, - })) + ttr := &toolchainv1alpha1.TierTemplateRevision{} + err = a.Client.Get(ctx, types.NamespacedName{ + Namespace: a.Namespace, + Name: ttrName, + }, ttr) // no match found, print the diffs if err != nil { return false, err } - require.Len(t, objs.Items, 1) - ttr = &objs.Items[0] return matchTierTemplateRevisionWaitCriterion(ttr, criteria...), nil }) // log message if an error occurred @@ -1272,6 +1284,26 @@ func UntilNSTemplateTierStatusUpdates(expected int) NSTemplateTierWaitCriterion } } +// HasStatusTierTemplateRevisions verifies revisions for the given TierTemplates are set in the `NSTemplateTier.Status.Revisions` +func HasStatusTierTemplateRevisions(revisions []string) NSTemplateTierWaitCriterion { + return NSTemplateTierWaitCriterion{ + Match: func(actual *toolchainv1alpha1.NSTemplateTier) bool { + if len(actual.Status.Revisions) != len(revisions) { + return false + } + for _, tierTemplateRef := range revisions { + if _, found := actual.Status.Revisions[tierTemplateRef]; !found { + return false + } + } + return true + }, + Diff: func(actual *toolchainv1alpha1.NSTemplateTier) string { + return fmt.Sprintf("expected status.revision %v. Actual: %v", revisions, maps.Keys(actual.Status.Revisions)) + }, + } +} + // HasNoTemplateRefWithSuffix checks that ALL namespaces' `TemplateRef` doesn't have the suffix func HasNoTemplateRefWithSuffix(suffix string) NSTemplateTierSpecMatcher { return NSTemplateTierSpecMatcher{ From b826d560f9199652cc94e627201ee0de380427bc Mon Sep 17 00:00:00 2001 From: Devtools Date: Wed, 20 Nov 2024 07:54:33 +0100 Subject: [PATCH 08/23] fix compilation --- testsupport/wait/host.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/testsupport/wait/host.go b/testsupport/wait/host.go index 75ad1773f..a2ed5b0eb 100644 --- a/testsupport/wait/host.go +++ b/testsupport/wait/host.go @@ -25,7 +25,6 @@ import ( "github.com/redhat-cop/operator-utils/pkg/util" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "golang.org/x/exp/maps" corev1 "k8s.io/api/core/v1" v1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/api/errors" @@ -1299,7 +1298,7 @@ func HasStatusTierTemplateRevisions(revisions []string) NSTemplateTierWaitCriter return true }, Diff: func(actual *toolchainv1alpha1.NSTemplateTier) string { - return fmt.Sprintf("expected status.revision %v. Actual: %v", revisions, maps.Keys(actual.Status.Revisions)) + return fmt.Sprintf("expected revision keys %v not found in: %v", revisions, actual.Status.Revisions) }, } } From 9cb5461bfe8b5124bc538959dda9c296aa669d8f Mon Sep 17 00:00:00 2001 From: Devtools Date: Wed, 20 Nov 2024 14:59:44 +0100 Subject: [PATCH 09/23] remove owner ref check --- test/e2e/parallel/nstemplatetier_test.go | 4 +- testsupport/wait/host.go | 51 ++---------------------- 2 files changed, 5 insertions(+), 50 deletions(-) diff --git a/test/e2e/parallel/nstemplatetier_test.go b/test/e2e/parallel/nstemplatetier_test.go index ab90c92e1..43cc5ae49 100644 --- a/test/e2e/parallel/nstemplatetier_test.go +++ b/test/e2e/parallel/nstemplatetier_test.go @@ -413,8 +413,8 @@ func TestTierTemplateRevision(t *testing.T) { // we verify the counters in the status.history for 'tierUsingTierTemplateRevisions' tier // and verify that TierTemplateRevision CRs were created, since all the tiertemplates now have templateObjects field populated _, err = hostAwait.WaitForNSTemplateTierAndCheckTemplates(t, "ttr", wait.HasStatusTierTemplateRevisions([]string{ - fmt.Sprintf("ttrfrom%s", baseTier.Spec.Namespaces[0].TemplateRef), // check that the revision field is set using the expected tierTemplate refs as keys - fmt.Sprintf("ttrfrom%s", baseTier.Spec.SpaceRoles["admin"].TemplateRef), + fmt.Sprintf("ttrfrom%s", baseTier.Spec.Namespaces[0].TemplateRef), // check that the revision field is set using the expected tierTemplate refs as keys + fmt.Sprintf("ttrfrom%s", baseTier.Spec.SpaceRoles["admin"].TemplateRef), // we can safely use the template refs from base tier since the custom tier was created from base one. fmt.Sprintf("ttrfrom%s", baseTier.Spec.ClusterResources.TemplateRef), })) require.NoError(t, err) diff --git a/testsupport/wait/host.go b/testsupport/wait/host.go index a2ed5b0eb..39011be48 100644 --- a/testsupport/wait/host.go +++ b/testsupport/wait/host.go @@ -1033,13 +1033,7 @@ func (a *HostAwaitility) WaitForNSTemplateTierAndCheckTemplates(t *testing.T, na if !found { return nil, fmt.Errorf("missing revision for TierTemplate %s in NSTemplateTier '%s'", tierTemplateNamespaces.GetName(), tier.Name) } - if _, err := a.WaitForTierTemplateRevision(t, ttrName, UntilTierTemplateRevisionsHasOwnerReferences([]metav1.OwnerReference{ - { - APIVersion: "toolchain.dev.openshift.com/v1alpha1", // for some reason, the apiversion and kind are empty on the CR - Kind: "TierTemplate", - Name: tierTemplateNamespaces.Name, - }, - })); err != nil { + if _, err := a.WaitForTierTemplateRevision(t, ttrName); err != nil { return nil, err } } @@ -1058,13 +1052,7 @@ func (a *HostAwaitility) WaitForNSTemplateTierAndCheckTemplates(t *testing.T, na if !found { return nil, fmt.Errorf("missing revision for TierTemplate %s in NSTemplateTier '%s'", tierTemplateClusterResources.GetName(), tier.Name) } - if _, err := a.WaitForTierTemplateRevision(t, ttrName, UntilTierTemplateRevisionsHasOwnerReferences([]metav1.OwnerReference{ - { - APIVersion: "toolchain.dev.openshift.com/v1alpha1", // for some reason, the apiversion and kind are empty on the CR - Kind: "TierTemplate", - Name: tierTemplateClusterResources.Name, - }, - })); err != nil { + if _, err := a.WaitForTierTemplateRevision(t, ttrName); err != nil { return nil, err } } @@ -1084,13 +1072,7 @@ func (a *HostAwaitility) WaitForNSTemplateTierAndCheckTemplates(t *testing.T, na if !found { return nil, fmt.Errorf("missing revision for TierTemplate %s in NSTemplateTier '%s'", tierTemplateSpaceRoles.GetName(), tier.Name) } - if _, err := a.WaitForTierTemplateRevision(t, ttrName, UntilTierTemplateRevisionsHasOwnerReferences([]metav1.OwnerReference{ - { - APIVersion: "toolchain.dev.openshift.com/v1alpha1", // for some reason, the apiversion and kind are empty on the CR - Kind: "TierTemplate", - Name: tierTemplateSpaceRoles.Name, - }, - })); err != nil { + if _, err := a.WaitForTierTemplateRevision(t, ttrName); err != nil { return nil, err } } @@ -1186,33 +1168,6 @@ func (a *HostAwaitility) WaitForTierTemplateRevision(t *testing.T, ttrName strin return ttr, err } -// UntilTierTemplateRevisionsHasOwnerReferences verify that the TierTemplateRevision has the specified owner references -func UntilTierTemplateRevisionsHasOwnerReferences(references []metav1.OwnerReference) TierTemplateRevisionWaitCriterion { - return TierTemplateRevisionWaitCriterion{ - Match: func(actual *toolchainv1alpha1.TierTemplateRevision) bool { - actualReferences := actual.GetOwnerReferences() - for _, actualRef := range actualReferences { - found := false - for _, expectedRef := range references { - if expectedRef.Name == actualRef.Name && - expectedRef.APIVersion == actualRef.APIVersion && - expectedRef.Kind == actualRef.Kind { - found = true - break - } - } - if !found { - return false - } - } - return len(references) == len(actualReferences) - }, - Diff: func(actual *toolchainv1alpha1.TierTemplateRevision) string { - return fmt.Sprintf("unable to find expected owner references: %v", references) - }, - } -} - // NSTemplateTierWaitCriterion a struct to compare with an expected NSTemplateTier type NSTemplateTierWaitCriterion struct { Match func(*toolchainv1alpha1.NSTemplateTier) bool From b50289cc84feabff2dedcc0f2c3311e0bb6c45c4 Mon Sep 17 00:00:00 2001 From: Devtools Date: Wed, 20 Nov 2024 15:25:57 +0100 Subject: [PATCH 10/23] avoid initializing twice --- testsupport/wait/host.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsupport/wait/host.go b/testsupport/wait/host.go index 39011be48..3d3e6938f 100644 --- a/testsupport/wait/host.go +++ b/testsupport/wait/host.go @@ -1150,7 +1150,7 @@ func (a *HostAwaitility) WaitForTierTemplateRevision(t *testing.T, ttrName strin ttr := &toolchainv1alpha1.TierTemplateRevision{} t.Logf("waiting until TierTemplateRevision with name '%s' exists in namespace '%s'...", ttrName, a.Namespace) err := wait.PollUntilContextTimeout(context.TODO(), a.RetryInterval, a.Timeout, true, func(ctx context.Context) (done bool, err error) { - ttr := &toolchainv1alpha1.TierTemplateRevision{} + ttr = &toolchainv1alpha1.TierTemplateRevision{} err = a.Client.Get(ctx, types.NamespacedName{ Namespace: a.Namespace, Name: ttrName, From bdba66330ae205ad2550900ff13500dff2721fa0 Mon Sep 17 00:00:00 2001 From: Devtools Date: Wed, 20 Nov 2024 15:28:34 +0100 Subject: [PATCH 11/23] remove second declaration --- testsupport/wait/host.go | 1 - 1 file changed, 1 deletion(-) diff --git a/testsupport/wait/host.go b/testsupport/wait/host.go index 3d3e6938f..c67b971bf 100644 --- a/testsupport/wait/host.go +++ b/testsupport/wait/host.go @@ -1150,7 +1150,6 @@ func (a *HostAwaitility) WaitForTierTemplateRevision(t *testing.T, ttrName strin ttr := &toolchainv1alpha1.TierTemplateRevision{} t.Logf("waiting until TierTemplateRevision with name '%s' exists in namespace '%s'...", ttrName, a.Namespace) err := wait.PollUntilContextTimeout(context.TODO(), a.RetryInterval, a.Timeout, true, func(ctx context.Context) (done bool, err error) { - ttr = &toolchainv1alpha1.TierTemplateRevision{} err = a.Client.Get(ctx, types.NamespacedName{ Namespace: a.Namespace, Name: ttrName, From b4f334d436a331faee0215c83a643c0a2affec2e Mon Sep 17 00:00:00 2001 From: Devtools Date: Thu, 21 Nov 2024 19:47:20 +0100 Subject: [PATCH 12/23] add ttr cleanup logic --- testsupport/cleanup/clean.go | 43 +++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/testsupport/cleanup/clean.go b/testsupport/cleanup/clean.go index 967f1df09..18e8d2a7e 100644 --- a/testsupport/cleanup/clean.go +++ b/testsupport/cleanup/clean.go @@ -106,6 +106,7 @@ func (c *cleanTask) cleanObject() { objToClean, ok := c.objToClean.DeepCopyObject().(client.Object) require.True(c.t, ok) userSignup, isUserSignup := c.objToClean.(*toolchainv1alpha1.UserSignup) + nsTemplateTier, isNsTemplateTier := c.objToClean.(*toolchainv1alpha1.NSTemplateTier) kind := objToClean.GetObjectKind().GroupVersionKind().Kind if kind == "" { kind = reflect.TypeOf(c.objToClean).Elem().Name() @@ -126,10 +127,13 @@ func (c *cleanTask) cleanObject() { } } } + // if the object was NSTemplateTier, then let's check that the TierTemplateRevisions were deleted as well + _, err := c.verifyTierTemplateRevisionsDeleted(isNsTemplateTier, nsTemplateTier, true) + require.NoError(c.t, err) // wait until deletion is done c.t.Logf("waiting until %s: %s is completely deleted", kind, objToClean.GetName()) - err := wait.PollUntilContextTimeout(context.TODO(), defaultRetryInterval, defaultTimeout, true, func(ctx context.Context) (done bool, err error) { + err = wait.PollUntilContextTimeout(context.TODO(), defaultRetryInterval, defaultTimeout, true, func(ctx context.Context) (done bool, err error) { if err := c.client.Get(context.TODO(), test.NamespacedName(objToClean.GetNamespace(), objToClean.GetName()), objToClean); err != nil { if errors.IsNotFound(err) { // if the object was UserSignup, then let's check that the MUR is deleted as well @@ -140,6 +144,10 @@ func (c *cleanTask) cleanObject() { if spaceDeleted, err := c.verifySpaceDeleted(isUserSignup, userSignup, false); !spaceDeleted || err != nil { return false, err } + // if the object was NSTemplateTier, then let's check that the TTRs were deleted as well + if ttrsDeleted, err := c.verifyTierTemplateRevisionsDeleted(isNsTemplateTier, nsTemplateTier, false); !ttrsDeleted || err != nil { + return false, err + } return true, nil } c.t.Logf("problem with getting the related %s '%s': %s", kind, objToClean.GetName(), err) @@ -240,3 +248,36 @@ func (c *cleanTask) verifySpaceDeleted(isUserSignup bool, userSignup *toolchainv } return true, nil } + +func (c *cleanTask) verifyTierTemplateRevisionsDeleted(isNsTemplateTier bool, nsTemplateTier *toolchainv1alpha1.NSTemplateTier, delete bool) (bool, error) { + if !isNsTemplateTier { + return true, nil + } + ttrs := &toolchainv1alpha1.TierTemplateRevisionList{} + if err := c.client.List(context.TODO(), ttrs, + client.InNamespace(nsTemplateTier.GetNamespace()), + client.MatchingLabels{toolchainv1alpha1.TierLabelKey: nsTemplateTier.GetName()}); err != nil { + c.t.Logf("problem with getting the ttrs for tier %s: %s", nsTemplateTier, err) + return false, err + } + if len(ttrs.Items) == 0 { + c.t.Logf("the NSTemplateTier %s doesn't have TTRs", nsTemplateTier.GetName()) + return true, nil + } + if delete { + for _, ttr := range ttrs.Items { + c.t.Logf("deleting also the related TTR %s", ttr.GetName()) + if err := c.client.Delete(context.TODO(), &ttr, propagationPolicyOpts); err != nil { + if errors.IsNotFound(err) { + continue + } + c.t.Logf("problem with deleting the related TTR %s: %s", ttr.GetName(), err) + return false, err + } + } + } else if len(ttrs.Items) > 0 { + // ttrs are still there + return false, nil + } + return true, nil +} From dc38c1750b10031218b1526981ff8ca78d305458 Mon Sep 17 00:00:00 2001 From: Devtools Date: Thu, 21 Nov 2024 19:52:10 +0100 Subject: [PATCH 13/23] fix linter --- testsupport/cleanup/clean.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/testsupport/cleanup/clean.go b/testsupport/cleanup/clean.go index 18e8d2a7e..ea680a824 100644 --- a/testsupport/cleanup/clean.go +++ b/testsupport/cleanup/clean.go @@ -257,7 +257,7 @@ func (c *cleanTask) verifyTierTemplateRevisionsDeleted(isNsTemplateTier bool, ns if err := c.client.List(context.TODO(), ttrs, client.InNamespace(nsTemplateTier.GetNamespace()), client.MatchingLabels{toolchainv1alpha1.TierLabelKey: nsTemplateTier.GetName()}); err != nil { - c.t.Logf("problem with getting the ttrs for tier %s: %s", nsTemplateTier, err) + c.t.Logf("problem with getting the ttrs for tier %s: %s", nsTemplateTier.GetName(), err) return false, err } if len(ttrs.Items) == 0 { @@ -265,7 +265,8 @@ func (c *cleanTask) verifyTierTemplateRevisionsDeleted(isNsTemplateTier bool, ns return true, nil } if delete { - for _, ttr := range ttrs.Items { + for i := range ttrs.Items { + ttr := ttrs.Items[i] c.t.Logf("deleting also the related TTR %s", ttr.GetName()) if err := c.client.Delete(context.TODO(), &ttr, propagationPolicyOpts); err != nil { if errors.IsNotFound(err) { From a61de181a27f224ebf0f379435d44fc3bd226e0c Mon Sep 17 00:00:00 2001 From: Devtools Date: Tue, 26 Nov 2024 10:56:02 +0100 Subject: [PATCH 14/23] relax number of ttr check --- test/e2e/parallel/nstemplatetier_test.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/e2e/parallel/nstemplatetier_test.go b/test/e2e/parallel/nstemplatetier_test.go index 43cc5ae49..ac16cecc2 100644 --- a/test/e2e/parallel/nstemplatetier_test.go +++ b/test/e2e/parallel/nstemplatetier_test.go @@ -426,7 +426,11 @@ func TestTierTemplateRevision(t *testing.T) { if err := hostAwait.Client.List(ctx, objs, client.InNamespace(hostAwait.Namespace)); err != nil { return false, err } - require.Len(t, objs.Items, 3) // expect one TTR per each tiertemplate (clusterresource, namespace and spacerole) + // we IDEALLY expect one TTR per each tiertemplate to be created (clusterresource, namespace and spacerole), thus a total of 3 TTRs ideally. + // But since the creation of a TTR could be very quick and could trigger another reconcile of the NSTemplateTier before the status is actually updated with the reference, + // this might generate some copies of the TTRs. This is not a problem in production since the cleanup mechanism of TTRs will remove the extra ones but could cause some flakiness with the test, + // thus we assert the number of TTRs doesn't exceed the double of the expected number. + assert.LessOrEqual(t, objs.Items, 6) // we check that the TTR content has the parameters replaced with values from the NSTemplateTier for _, obj := range objs.Items { assert.Contains(t, string(obj.Spec.TemplateObjects[0].Raw), "janedoe") // the object should have the namespace name replaced From 7665e00fce9b6bd0d3467be2a811ac73dffa044a Mon Sep 17 00:00:00 2001 From: Devtools Date: Tue, 26 Nov 2024 13:43:08 +0100 Subject: [PATCH 15/23] fix test --- test/e2e/parallel/nstemplatetier_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/parallel/nstemplatetier_test.go b/test/e2e/parallel/nstemplatetier_test.go index ac16cecc2..22a57e25c 100644 --- a/test/e2e/parallel/nstemplatetier_test.go +++ b/test/e2e/parallel/nstemplatetier_test.go @@ -430,7 +430,7 @@ func TestTierTemplateRevision(t *testing.T) { // But since the creation of a TTR could be very quick and could trigger another reconcile of the NSTemplateTier before the status is actually updated with the reference, // this might generate some copies of the TTRs. This is not a problem in production since the cleanup mechanism of TTRs will remove the extra ones but could cause some flakiness with the test, // thus we assert the number of TTRs doesn't exceed the double of the expected number. - assert.LessOrEqual(t, objs.Items, 6) + assert.LessOrEqual(t, len(objs.Items), 6) // we check that the TTR content has the parameters replaced with values from the NSTemplateTier for _, obj := range objs.Items { assert.Contains(t, string(obj.Spec.TemplateObjects[0].Raw), "janedoe") // the object should have the namespace name replaced From 02797f9bd98aef1219fe87e6ada870ec87a537fd Mon Sep 17 00:00:00 2001 From: Devtools Date: Thu, 28 Nov 2024 16:08:37 +0100 Subject: [PATCH 16/23] handle parameters in TierTemplateRevision --- go.mod | 18 +++++------ go.sum | 23 +++++++------ test/e2e/parallel/nstemplatetier_test.go | 41 +++++++++++++++++------- 3 files changed, 52 insertions(+), 30 deletions(-) diff --git a/go.mod b/go.mod index 80fb14b00..149ea7b02 100644 --- a/go.mod +++ b/go.mod @@ -31,10 +31,7 @@ require ( sigs.k8s.io/controller-runtime v0.15.0 ) -require ( - github.com/google/uuid v1.6.0 - golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f -) +require github.com/google/uuid v1.6.0 require ( github.com/BurntSushi/toml v1.2.1 // indirect @@ -104,13 +101,14 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/xlab/treeprint v1.1.0 // indirect go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect - golang.org/x/crypto v0.21.0 // indirect - golang.org/x/net v0.23.0 // indirect + golang.org/x/crypto v0.29.0 // indirect + golang.org/x/net v0.31.0 // indirect golang.org/x/oauth2 v0.7.0 // indirect - golang.org/x/sys v0.18.0 // indirect - golang.org/x/term v0.18.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/sys v0.27.0 // indirect + golang.org/x/term v0.26.0 // indirect + golang.org/x/text v0.20.0 // indirect golang.org/x/time v0.3.0 // indirect + golang.org/x/tools v0.27.0 // indirect gomodules.xyz/jsonpatch/v2 v2.3.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.33.0 // indirect @@ -132,3 +130,5 @@ require ( ) go 1.20 + +replace github.com/codeready-toolchain/api => github.com/mfrancisc/api v0.0.0-20241128133539-a24a5d454de5 diff --git a/go.sum b/go.sum index e6a13f39d..7479abdc8 100644 --- a/go.sum +++ b/go.sum @@ -119,8 +119,6 @@ github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:z github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= -github.com/codeready-toolchain/api v0.0.0-20241114213029-44333bf24bcf h1:tOHKd4PT6gnV8lLh3kmqqK9YONvL6oFKHpi0kGzfsvw= -github.com/codeready-toolchain/api v0.0.0-20241114213029-44333bf24bcf/go.mod h1:DUq1ffy9Mbersdgji48i/cm9Y+6NMwAdAQJNlfOrPRo= github.com/codeready-toolchain/toolchain-common v0.0.0-20241114215157-a6a85252b2f5 h1:vW0C32c6sI9ZUGcUw3e9ftE9hqJ/bMo+TtRHp84Hung= github.com/codeready-toolchain/toolchain-common v0.0.0-20241114215157-a6a85252b2f5/go.mod h1:wx/d4HVbDPOadwpbxn28ZGClC5OmzelIK8p4wupDJVI= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= @@ -482,6 +480,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5 github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/mfrancisc/api v0.0.0-20241128133539-a24a5d454de5 h1:Qg1+lu+mgzyvvLAqBGCRTOljEbNy9jtLggnyWCMxx00= +github.com/mfrancisc/api v0.0.0-20241128133539-a24a5d454de5/go.mod h1:DUq1ffy9Mbersdgji48i/cm9Y+6NMwAdAQJNlfOrPRo= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/migueleliasweb/go-github-mock v0.0.18 h1:0lWt9MYmZQGnQE2rFtjlft/YtD6hzxuN6JJRFpujzEI= github.com/migueleliasweb/go-github-mock v0.0.18/go.mod h1:CcgXcbMoRnf3rRVHqGssuBquZDIcaplxL2W6G+xs7kM= @@ -735,8 +735,9 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= +golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -747,8 +748,6 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo= -golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -833,8 +832,8 @@ golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= +golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -946,8 +945,9 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -958,8 +958,9 @@ golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= +golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -973,8 +974,9 @@ golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1045,6 +1047,7 @@ golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o= +golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/test/e2e/parallel/nstemplatetier_test.go b/test/e2e/parallel/nstemplatetier_test.go index 22a57e25c..0a1e29b57 100644 --- a/test/e2e/parallel/nstemplatetier_test.go +++ b/test/e2e/parallel/nstemplatetier_test.go @@ -391,15 +391,30 @@ func TestTierTemplateRevision(t *testing.T) { require.NoError(t, err) // for the tiertemplaterevisions to be created the tiertemplates need to have template objects populated // we add the RawExtension objects to the TemplateObjects field - ns := unstructured.Unstructured{ - Object: map[string]interface{}{ - "kind": "Namespace", - "metadata": map[string]interface{}{ - "name": "{{.SPACE_NAME}}", + crq := unstructured.Unstructured{Object: map[string]interface{}{ + "kind": "ClusterResourceQuota", + "metadata": map[string]interface{}{ + "name": "for-{{.SPACE_NAME}}-deployments", + }, + "spec": map[string]interface{}{ + "quota": map[string]interface{}{ + "hard": map[string]string{ + "count/deploymentconfigs.apps": "{{.DEPLOYMENT_QUOTA}}", + "count/deployments.apps": "{{.DEPLOYMENT_QUOTA}}", + "count/pods": "600", + }, + }, + "selector": map[string]interface{}{ + "annotations": map[string]string{}, + "labels": map[string]interface{}{ + "matchLabels": map[string]string{ + "toolchain.dev.openshift.com/space": "'{{.SPACE_NAME}}'", + }, + }, }, }, - } - rawTemplateObjects := []runtime.RawExtension{{Object: &ns}} + }} + rawTemplateObjects := []runtime.RawExtension{{Object: &crq}} updateTierTemplateObjects := func(template *toolchainv1alpha1.TierTemplate) error { template.Spec.TemplateObjects = rawTemplateObjects return nil @@ -407,12 +422,12 @@ func TestTierTemplateRevision(t *testing.T) { namespaceResourcesWithTemplateObjects := tiers.WithNamespaceResources(t, baseTier, updateTierTemplateObjects) clusterResourcesWithTemplateObjects := tiers.WithClusterResources(t, baseTier, updateTierTemplateObjects) spaceRolesWithTemplateObjects := tiers.WithSpaceRoles(t, baseTier, updateTierTemplateObjects) - tiers.CreateCustomNSTemplateTier(t, hostAwait, "ttr", baseTier, namespaceResourcesWithTemplateObjects, clusterResourcesWithTemplateObjects, spaceRolesWithTemplateObjects, tiers.WithParameter("SPACE_NAME", "janedoe")) + tiers.CreateCustomNSTemplateTier(t, hostAwait, "ttr", baseTier, namespaceResourcesWithTemplateObjects, clusterResourcesWithTemplateObjects, spaceRolesWithTemplateObjects, tiers.WithParameter("DEPLOYMENT_QUOTA", "60")) // when // we verify the counters in the status.history for 'tierUsingTierTemplateRevisions' tier // and verify that TierTemplateRevision CRs were created, since all the tiertemplates now have templateObjects field populated - _, err = hostAwait.WaitForNSTemplateTierAndCheckTemplates(t, "ttr", wait.HasStatusTierTemplateRevisions([]string{ + customTier, err := hostAwait.WaitForNSTemplateTierAndCheckTemplates(t, "ttr", wait.HasStatusTierTemplateRevisions([]string{ fmt.Sprintf("ttrfrom%s", baseTier.Spec.Namespaces[0].TemplateRef), // check that the revision field is set using the expected tierTemplate refs as keys fmt.Sprintf("ttrfrom%s", baseTier.Spec.SpaceRoles["admin"].TemplateRef), // we can safely use the template refs from base tier since the custom tier was created from base one. fmt.Sprintf("ttrfrom%s", baseTier.Spec.ClusterResources.TemplateRef), @@ -433,8 +448,12 @@ func TestTierTemplateRevision(t *testing.T) { assert.LessOrEqual(t, len(objs.Items), 6) // we check that the TTR content has the parameters replaced with values from the NSTemplateTier for _, obj := range objs.Items { - assert.Contains(t, string(obj.Spec.TemplateObjects[0].Raw), "janedoe") // the object should have the namespace name replaced - assert.NotContains(t, string(obj.Spec.TemplateObjects[0].Raw), ".SPACE_NAME") // the object should NOT contain the variable anymore + // the object should have all the variables still there since this one will be replaced when provisioning the Space + assert.Contains(t, string(obj.Spec.TemplateObjects[0].Raw), ".SPACE_NAME") + assert.Contains(t, string(obj.Spec.TemplateObjects[0].Raw), ".DEPLOYMENT_QUOTA") + // the parameter is copied from the NSTemplateTier + assert.Equal(t, obj.Spec.Parameters[0].Name, customTier.Spec.Parameters[0].Name) + assert.Equal(t, obj.Spec.Parameters[0].Value, customTier.Spec.Parameters[0].Value) } return true, nil }) From 62ee614eb678d6965b0635bdefb49692a47e477c Mon Sep 17 00:00:00 2001 From: Devtools Date: Sat, 30 Nov 2024 16:48:06 +0100 Subject: [PATCH 17/23] fix test --- test/e2e/parallel/nstemplatetier_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/e2e/parallel/nstemplatetier_test.go b/test/e2e/parallel/nstemplatetier_test.go index 0a1e29b57..1ae806cff 100644 --- a/test/e2e/parallel/nstemplatetier_test.go +++ b/test/e2e/parallel/nstemplatetier_test.go @@ -408,7 +408,7 @@ func TestTierTemplateRevision(t *testing.T) { "annotations": map[string]string{}, "labels": map[string]interface{}{ "matchLabels": map[string]string{ - "toolchain.dev.openshift.com/space": "'{{.SPACE_NAME}}'", + "toolchain.dev.openshift.com/space": "{{.SPACE_NAME}}", }, }, }, @@ -452,6 +452,8 @@ func TestTierTemplateRevision(t *testing.T) { assert.Contains(t, string(obj.Spec.TemplateObjects[0].Raw), ".SPACE_NAME") assert.Contains(t, string(obj.Spec.TemplateObjects[0].Raw), ".DEPLOYMENT_QUOTA") // the parameter is copied from the NSTemplateTier + assert.NotNil(t, obj.Spec.Parameters) + assert.NotNil(t, customTier.Spec.Parameters) assert.Equal(t, obj.Spec.Parameters[0].Name, customTier.Spec.Parameters[0].Name) assert.Equal(t, obj.Spec.Parameters[0].Value, customTier.Spec.Parameters[0].Value) } From aec5c1d9aeece9e1843247d5a47e12835587f007 Mon Sep 17 00:00:00 2001 From: Devtools Date: Mon, 2 Dec 2024 11:09:26 +0100 Subject: [PATCH 18/23] update api --- go.mod | 4 +--- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 149ea7b02..2714f98c1 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,7 @@ module github.com/codeready-toolchain/toolchain-e2e require ( - github.com/codeready-toolchain/api v0.0.0-20241114213029-44333bf24bcf + github.com/codeready-toolchain/api v0.0.0-20241202100321-545317813297 github.com/codeready-toolchain/toolchain-common v0.0.0-20241114215157-a6a85252b2f5 github.com/davecgh/go-spew v1.1.1 github.com/fatih/color v1.15.0 @@ -130,5 +130,3 @@ require ( ) go 1.20 - -replace github.com/codeready-toolchain/api => github.com/mfrancisc/api v0.0.0-20241128133539-a24a5d454de5 diff --git a/go.sum b/go.sum index 7479abdc8..23ccb03d0 100644 --- a/go.sum +++ b/go.sum @@ -119,6 +119,8 @@ github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:z github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= +github.com/codeready-toolchain/api v0.0.0-20241202100321-545317813297 h1:YsZesoSkP4sxGL7d1DtPHbqLGUe2A9srXVyW2IERKrw= +github.com/codeready-toolchain/api v0.0.0-20241202100321-545317813297/go.mod h1:DUq1ffy9Mbersdgji48i/cm9Y+6NMwAdAQJNlfOrPRo= github.com/codeready-toolchain/toolchain-common v0.0.0-20241114215157-a6a85252b2f5 h1:vW0C32c6sI9ZUGcUw3e9ftE9hqJ/bMo+TtRHp84Hung= github.com/codeready-toolchain/toolchain-common v0.0.0-20241114215157-a6a85252b2f5/go.mod h1:wx/d4HVbDPOadwpbxn28ZGClC5OmzelIK8p4wupDJVI= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= @@ -480,8 +482,6 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5 github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/mfrancisc/api v0.0.0-20241128133539-a24a5d454de5 h1:Qg1+lu+mgzyvvLAqBGCRTOljEbNy9jtLggnyWCMxx00= -github.com/mfrancisc/api v0.0.0-20241128133539-a24a5d454de5/go.mod h1:DUq1ffy9Mbersdgji48i/cm9Y+6NMwAdAQJNlfOrPRo= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/migueleliasweb/go-github-mock v0.0.18 h1:0lWt9MYmZQGnQE2rFtjlft/YtD6hzxuN6JJRFpujzEI= github.com/migueleliasweb/go-github-mock v0.0.18/go.mod h1:CcgXcbMoRnf3rRVHqGssuBquZDIcaplxL2W6G+xs7kM= From f818ea94cc6055e1bd73543a0edfa2e6263e8469 Mon Sep 17 00:00:00 2001 From: Devtools Date: Thu, 5 Dec 2024 14:04:31 +0100 Subject: [PATCH 19/23] add comment about param assertion --- test/e2e/parallel/nstemplatetier_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/e2e/parallel/nstemplatetier_test.go b/test/e2e/parallel/nstemplatetier_test.go index 6e1e4fb7d..8e32ad456 100644 --- a/test/e2e/parallel/nstemplatetier_test.go +++ b/test/e2e/parallel/nstemplatetier_test.go @@ -455,6 +455,8 @@ func TestTierTemplateRevision(t *testing.T) { // the parameter is copied from the NSTemplateTier assert.NotNil(t, obj.Spec.Parameters) assert.NotNil(t, customTier.Spec.Parameters) + // we only expect the static parameter DEPLOYMENT_QUOTA to be copied from the tier to the TTR. + // the SPACE_NAME is not a parameter, but a dynamic variable which will be evaluated when provisioning a namespace for the user. assert.Equal(t, obj.Spec.Parameters[0].Name, customTier.Spec.Parameters[0].Name) assert.Equal(t, obj.Spec.Parameters[0].Value, customTier.Spec.Parameters[0].Value) } From b24e0c0095095fc3359d74b5f34865a80c7bff42 Mon Sep 17 00:00:00 2001 From: Devtools Date: Wed, 8 Jan 2025 19:13:57 +0100 Subject: [PATCH 20/23] address PR comments --- test/e2e/parallel/nstemplatetier_test.go | 18 +++++---- testsupport/cleanup/clean.go | 20 +++------- testsupport/wait/host.go | 48 +++++++++++------------- 3 files changed, 36 insertions(+), 50 deletions(-) diff --git a/test/e2e/parallel/nstemplatetier_test.go b/test/e2e/parallel/nstemplatetier_test.go index 0a3437736..b77dd28d4 100644 --- a/test/e2e/parallel/nstemplatetier_test.go +++ b/test/e2e/parallel/nstemplatetier_test.go @@ -424,11 +424,14 @@ func TestTierTemplateRevision(t *testing.T) { template.Spec.TemplateObjects = rawTemplateObjects return nil } - namespaceResourcesWithTemplateObjects := tiers.WithNamespaceResources(t, baseTier, updateTierTemplateObjects) - clusterResourcesWithTemplateObjects := tiers.WithClusterResources(t, baseTier, updateTierTemplateObjects) - spaceRolesWithTemplateObjects := tiers.WithSpaceRoles(t, baseTier, updateTierTemplateObjects) - tiers.CreateCustomNSTemplateTier(t, hostAwait, "ttr", baseTier, namespaceResourcesWithTemplateObjects, clusterResourcesWithTemplateObjects, spaceRolesWithTemplateObjects, tiers.WithParameter("DEPLOYMENT_QUOTA", "60")) - + // for simplicity, we add the CRQ to all types of templates (both cluster scope and namespace scoped), + // even if the CRQ is cluster scoped. + // WARNING: thus THIS NSTemplateTier should NOT be sued to provision a user!!! + tiers.CreateCustomNSTemplateTier(t, hostAwait, "ttr", baseTier, + tiers.WithNamespaceResources(t, baseTier, updateTierTemplateObjects), + tiers.WithClusterResources(t, baseTier, updateTierTemplateObjects), + tiers.WithSpaceRoles(t, baseTier, updateTierTemplateObjects), + tiers.WithParameter("DEPLOYMENT_QUOTA", "60")) // when // we verify the counters in the status.history for 'tierUsingTierTemplateRevisions' tier // and verify that TierTemplateRevision CRs were created, since all the tiertemplates now have templateObjects field populated @@ -450,7 +453,7 @@ func TestTierTemplateRevision(t *testing.T) { // But since the creation of a TTR could be very quick and could trigger another reconcile of the NSTemplateTier before the status is actually updated with the reference, // this might generate some copies of the TTRs. This is not a problem in production since the cleanup mechanism of TTRs will remove the extra ones but could cause some flakiness with the test, // thus we assert the number of TTRs doesn't exceed the double of the expected number. - assert.LessOrEqual(t, len(objs.Items), 6) + assert.LessOrEqual(t, len(objs.Items), len(tiers.GetTemplateRefs(t, hostAwait, "ttr").Flatten())*2) // we check that the TTR content has the parameters replaced with values from the NSTemplateTier for _, obj := range objs.Items { // the object should have all the variables still there since this one will be replaced when provisioning the Space @@ -461,8 +464,7 @@ func TestTierTemplateRevision(t *testing.T) { assert.NotNil(t, customTier.Spec.Parameters) // we only expect the static parameter DEPLOYMENT_QUOTA to be copied from the tier to the TTR. // the SPACE_NAME is not a parameter, but a dynamic variable which will be evaluated when provisioning a namespace for the user. - assert.Equal(t, obj.Spec.Parameters[0].Name, customTier.Spec.Parameters[0].Name) - assert.Equal(t, obj.Spec.Parameters[0].Value, customTier.Spec.Parameters[0].Value) + assert.Equal(t, obj.Spec.Parameters, customTier.Spec.Parameters) } return true, nil }) diff --git a/testsupport/cleanup/clean.go b/testsupport/cleanup/clean.go index ea680a824..ec754ca28 100644 --- a/testsupport/cleanup/clean.go +++ b/testsupport/cleanup/clean.go @@ -265,20 +265,10 @@ func (c *cleanTask) verifyTierTemplateRevisionsDeleted(isNsTemplateTier bool, ns return true, nil } if delete { - for i := range ttrs.Items { - ttr := ttrs.Items[i] - c.t.Logf("deleting also the related TTR %s", ttr.GetName()) - if err := c.client.Delete(context.TODO(), &ttr, propagationPolicyOpts); err != nil { - if errors.IsNotFound(err) { - continue - } - c.t.Logf("problem with deleting the related TTR %s: %s", ttr.GetName(), err) - return false, err - } - } - } else if len(ttrs.Items) > 0 { - // ttrs are still there - return false, nil + return false, c.client.DeleteAllOf(context.TODO(), &toolchainv1alpha1.TierTemplateRevision{}, + client.InNamespace(nsTemplateTier.GetNamespace()), + client.MatchingLabels{toolchainv1alpha1.TierLabelKey: nsTemplateTier.GetName()}) } - return true, nil + // ttrs are still there + return false, nil } diff --git a/testsupport/wait/host.go b/testsupport/wait/host.go index fd6f34704..739da469d 100644 --- a/testsupport/wait/host.go +++ b/testsupport/wait/host.go @@ -923,15 +923,8 @@ func (a *HostAwaitility) WaitForNSTemplateTierAndCheckTemplates(t *testing.T, na if err != nil { return nil, err } - // if the tier template supports Tier Template Revisions then let's check those - if tierTemplateNamespaces.Spec.TemplateObjects != nil { - ttrName, found := tier.Status.Revisions[tierTemplateNamespaces.GetName()] - if !found { - return nil, fmt.Errorf("missing revision for TierTemplate %s in NSTemplateTier '%s'", tierTemplateNamespaces.GetName(), tier.Name) - } - if _, err := a.WaitForTierTemplateRevision(t, ttrName); err != nil { - return nil, err - } + if err := a.checkTTR(t, tier, tierTemplateNamespaces); err != nil { + return nil, err } } if tier.Spec.ClusterResources != nil { @@ -942,15 +935,8 @@ func (a *HostAwaitility) WaitForNSTemplateTierAndCheckTemplates(t *testing.T, na if err != nil { return nil, err } - // if the tier template supports Tier Template Revisions then let's check those - if tierTemplateClusterResources.Spec.TemplateObjects != nil { - ttrName, found := tier.Status.Revisions[tierTemplateClusterResources.GetName()] - if !found { - return nil, fmt.Errorf("missing revision for TierTemplate %s in NSTemplateTier '%s'", tierTemplateClusterResources.GetName(), tier.Name) - } - if _, err := a.WaitForTierTemplateRevision(t, ttrName); err != nil { - return nil, err - } + if err := a.checkTTR(t, tier, tierTemplateClusterResources); err != nil { + return nil, err } } @@ -962,21 +948,29 @@ func (a *HostAwaitility) WaitForNSTemplateTierAndCheckTemplates(t *testing.T, na if err != nil { return nil, err } - // if the tier template supports Tier Template Revisions then let's check those - if tierTemplateSpaceRoles.Spec.TemplateObjects != nil { - ttrName, found := tier.Status.Revisions[tierTemplateSpaceRoles.GetName()] - if !found { - return nil, fmt.Errorf("missing revision for TierTemplate %s in NSTemplateTier '%s'", tierTemplateSpaceRoles.GetName(), tier.Name) - } - if _, err := a.WaitForTierTemplateRevision(t, ttrName); err != nil { - return nil, err - } + if err := a.checkTTR(t, tier, tierTemplateSpaceRoles); err != nil { + return nil, err } } return tier, err } +func (a *HostAwaitility) checkTTR(t *testing.T, tier *toolchainv1alpha1.NSTemplateTier, tierTemplate *toolchainv1alpha1.TierTemplate) error { + // if the tier template supports Tier Template Revisions then let's check those + if tierTemplate.Spec.TemplateObjects != nil { + // TODO improve this since now it requires that WaitForNSTemplateTierAndCheckTemplates should be called with HasStatusTierTemplateRevisions, + ttrName, found := tier.Status.Revisions[tierTemplate.GetName()] + if !found { + return fmt.Errorf("missing revision for TierTemplate %s in NSTemplateTier '%s'", tierTemplate.GetName(), tier.Name) + } + if _, err := For(t, a.Awaitility, &toolchainv1alpha1.TierTemplateRevision{}).WithNameThat(ttrName); err != nil { + return err + } + } + return nil +} + // WaitForTierTemplate waits until a TierTemplate with the given name exists // Returns an error if the resource did not exist (or something wrong happened) func (a *HostAwaitility) WaitForTierTemplate(t *testing.T, name string) (*toolchainv1alpha1.TierTemplate, error) { // nolint:unparam From be087d9756c517310888c8dd900d43d8c281a79c Mon Sep 17 00:00:00 2001 From: Devtools Date: Wed, 8 Jan 2025 19:19:44 +0100 Subject: [PATCH 21/23] fix check --- test/e2e/parallel/nstemplatetier_test.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/test/e2e/parallel/nstemplatetier_test.go b/test/e2e/parallel/nstemplatetier_test.go index b77dd28d4..ce8c0b28f 100644 --- a/test/e2e/parallel/nstemplatetier_test.go +++ b/test/e2e/parallel/nstemplatetier_test.go @@ -435,11 +435,8 @@ func TestTierTemplateRevision(t *testing.T) { // when // we verify the counters in the status.history for 'tierUsingTierTemplateRevisions' tier // and verify that TierTemplateRevision CRs were created, since all the tiertemplates now have templateObjects field populated - customTier, err := hostAwait.WaitForNSTemplateTierAndCheckTemplates(t, "ttr", wait.HasStatusTierTemplateRevisions([]string{ - fmt.Sprintf("ttrfrom%s", baseTier.Spec.Namespaces[0].TemplateRef), // check that the revision field is set using the expected tierTemplate refs as keys - fmt.Sprintf("ttrfrom%s", baseTier.Spec.SpaceRoles["admin"].TemplateRef), // we can safely use the template refs from base tier since the custom tier was created from base one. - fmt.Sprintf("ttrfrom%s", baseTier.Spec.ClusterResources.TemplateRef), - })) + customTier, err := hostAwait.WaitForNSTemplateTierAndCheckTemplates(t, "ttr", + wait.HasStatusTierTemplateRevisions(tiers.GetTemplateRefs(t, hostAwait, "ttr").Flatten())) require.NoError(t, err) // then From 38bb9d68f8668be940e67c74f407382d84a025c5 Mon Sep 17 00:00:00 2001 From: Devtools Date: Wed, 8 Jan 2025 19:21:14 +0100 Subject: [PATCH 22/23] fix assert check --- test/e2e/parallel/nstemplatetier_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/parallel/nstemplatetier_test.go b/test/e2e/parallel/nstemplatetier_test.go index ce8c0b28f..c96fe846a 100644 --- a/test/e2e/parallel/nstemplatetier_test.go +++ b/test/e2e/parallel/nstemplatetier_test.go @@ -461,7 +461,7 @@ func TestTierTemplateRevision(t *testing.T) { assert.NotNil(t, customTier.Spec.Parameters) // we only expect the static parameter DEPLOYMENT_QUOTA to be copied from the tier to the TTR. // the SPACE_NAME is not a parameter, but a dynamic variable which will be evaluated when provisioning a namespace for the user. - assert.Equal(t, obj.Spec.Parameters, customTier.Spec.Parameters) + assert.ElementsMatch(t, customTier.Spec.Parameters, obj.Spec.Parameters) } return true, nil }) From 68362969d9f9a9eccf202e7b4f39750dccac6d1d Mon Sep 17 00:00:00 2001 From: Devtools Date: Wed, 8 Jan 2025 20:44:21 +0100 Subject: [PATCH 23/23] cleanup unused functions --- testsupport/wait/host.go | 63 ---------------------------------------- 1 file changed, 63 deletions(-) diff --git a/testsupport/wait/host.go b/testsupport/wait/host.go index 739da469d..64e605de8 100644 --- a/testsupport/wait/host.go +++ b/testsupport/wait/host.go @@ -994,69 +994,6 @@ func (a *HostAwaitility) WaitForTierTemplate(t *testing.T, name string) (*toolch return tierTemplate, err } -// TierTemplateRevisionWaitCriterion a struct to compare with an expected TierTemplateRevision -type TierTemplateRevisionWaitCriterion struct { - Match func(*toolchainv1alpha1.TierTemplateRevision) bool - Diff func(*toolchainv1alpha1.TierTemplateRevision) string -} - -func matchTierTemplateRevisionWaitCriterion(actual *toolchainv1alpha1.TierTemplateRevision, criteria ...TierTemplateRevisionWaitCriterion) bool { - for _, c := range criteria { - // if at least one criteria does not match, keep waiting - if !c.Match(actual) { - return false - } - } - return true -} - -func (a *HostAwaitility) printTierTemplateRevisionWaitCriterionDiffs(t *testing.T, actual *toolchainv1alpha1.TierTemplateRevision, criteria ...TierTemplateRevisionWaitCriterion) { - buf := &strings.Builder{} - if actual == nil { - buf.WriteString("failed to find TierTemplateRevision\n") - } else { - buf.WriteString("failed to find TierTemplateRevision with matching criteria:\n") - buf.WriteString("actual:\n") - y, _ := StringifyObject(actual) - buf.Write(y) - buf.WriteString("\n----\n") - buf.WriteString("diffs:\n") - for _, c := range criteria { - if !c.Match(actual) { - buf.WriteString(c.Diff(actual)) - buf.WriteString("\n") - } - } - } - // include also all TierTemplateRevisions in the host namespace, to help troubleshooting - a.listAndPrint(t, "TierTemplateRevisions", a.Namespace, &toolchainv1alpha1.TierTemplateRevisionList{}) - - t.Log(buf.String()) -} - -// WaitForTierTemplateRevision waits until a TierTemplateRevision with the given labels to exists -// Returns an error if the resource did not exist (or something wrong happened) -func (a *HostAwaitility) WaitForTierTemplateRevision(t *testing.T, ttrName string, criteria ...TierTemplateRevisionWaitCriterion) (*toolchainv1alpha1.TierTemplateRevision, error) { // nolint:unparam - ttr := &toolchainv1alpha1.TierTemplateRevision{} - t.Logf("waiting until TierTemplateRevision with name '%s' exists in namespace '%s'...", ttrName, a.Namespace) - err := wait.PollUntilContextTimeout(context.TODO(), a.RetryInterval, a.Timeout, true, func(ctx context.Context) (done bool, err error) { - err = a.Client.Get(ctx, types.NamespacedName{ - Namespace: a.Namespace, - Name: ttrName, - }, ttr) - // no match found, print the diffs - if err != nil { - return false, err - } - return matchTierTemplateRevisionWaitCriterion(ttr, criteria...), nil - }) - // log message if an error occurred - if err != nil { - a.printTierTemplateRevisionWaitCriterionDiffs(t, ttr, criteria...) - } - return ttr, err -} - // NSTemplateTierWaitCriterion a struct to compare with an expected NSTemplateTier type NSTemplateTierWaitCriterion struct { Match func(*toolchainv1alpha1.NSTemplateTier) bool