diff --git a/e2e/adapter/adapter_with_maestro.go b/e2e/adapter/adapter_with_maestro.go index 7eb8e3f1..3ce4adf4 100644 --- a/e2e/adapter/adapter_with_maestro.go +++ b/e2e/adapter/adapter_with_maestro.go @@ -65,16 +65,17 @@ var _ = ginkgo.Describe("[Suite: adapter][maestro-transport] Adapter Framework - ginkgo.By("Step 2: Verify ManifestWork (resource bundle) was created on Maestro") // Query Maestro API via HTTP client Eventually(func(g Gomega) { - rb, err := h.GetMaestroClient().FindResourceBundleByClusterID(ctx, clusterID) - g.Expect(err).NotTo(HaveOccurred(), "failed to find resource bundle for cluster") - resourceBundle = rb + resourceBundles, err := h.GetMaestroClient().FindResourceBundlesByClusterAndAdapter(ctx, clusterID, adapterName) + g.Expect(err).NotTo(HaveOccurred(), "should be able to query Maestro for resource bundles") + g.Expect(resourceBundles).NotTo(BeEmpty(), "should be able to find resource bundle for cluster") + resourceBundle = &resourceBundles[0] // Verify consumer name - g.Expect(rb.ConsumerName).To(Equal(maestroConsumerName), + g.Expect(resourceBundle.ConsumerName).To(Equal(maestroConsumerName), "resource bundle should target correct consumer") // Verify version - g.Expect(rb.Version).To(Equal(1), + g.Expect(resourceBundle.Version).To(Equal(1), "resource bundle should have version=1") // Verify manifest names @@ -82,17 +83,17 @@ var _ = ginkgo.Describe("[Suite: adapter][maestro-transport] Adapter Framework - fmt.Sprintf("%s-%s-namespace", clusterID, adapterName), fmt.Sprintf("%s-%s-configmap", clusterID, adapterName), } - g.Expect(rb.Manifests).To(HaveLen(2), + g.Expect(resourceBundle.Manifests).To(HaveLen(2), "resource bundle should contain 2 manifests") - manifestNames := make([]string, len(rb.Manifests)) - for i, m := range rb.Manifests { + manifestNames := make([]string, len(resourceBundle.Manifests)) + for i, m := range resourceBundle.Manifests { manifestNames[i] = m.Metadata.Name } g.Expect(manifestNames).To(ConsistOf(expectedManifests), "manifest names should match expected pattern") - ginkgo.GinkgoWriter.Printf("Found resource bundle ID: %s\n", rb.ID) + ginkgo.GinkgoWriter.Printf("Found resource bundle ID: %s\n", resourceBundle.ID) }, h.Cfg.Timeouts.Adapter.Processing, h.Cfg.Polling.Interval).Should(Succeed()) ginkgo.By("Step 3: Verify ManifestWork metadata (labels and annotations)") @@ -343,15 +344,16 @@ var _ = ginkgo.Describe("[Suite: adapter][maestro-transport] Adapter Framework - ginkgo.By("Step 2: Wait for initial ManifestWork creation and capture resource bundle ID") // Query Maestro API to find the resource bundle Eventually(func(g Gomega) { - rb, err := h.GetMaestroClient().FindResourceBundleByClusterID(ctx, clusterID) + rbs, err := h.GetMaestroClient().FindResourceBundlesByClusterAndAdapter(ctx, clusterID, adapterName) g.Expect(err).NotTo(HaveOccurred(), "failed to find resource bundle for cluster") - resourceBundle = rb + g.Expect(rbs).NotTo(BeEmpty(), "should find resource bundle for adapter") + resourceBundle = &rbs[0] // Verify version is 1 (initial creation) - g.Expect(rb.Version).To(Equal(1), + g.Expect(resourceBundle.Version).To(Equal(1), "resource bundle should have version=1 after initial creation") - ginkgo.GinkgoWriter.Printf("Found resource bundle ID: %s with version: %d\n", rb.ID, rb.Version) + ginkgo.GinkgoWriter.Printf("Found resource bundle ID: %s with version: %d\n", resourceBundle.ID, resourceBundle.Version) }, h.Cfg.Timeouts.Adapter.Processing, h.Cfg.Polling.Interval).Should(Succeed()) Expect(resourceBundle).NotTo(BeNil(), "resource bundle should be found") @@ -408,14 +410,15 @@ var _ = ginkgo.Describe("[Suite: adapter][maestro-transport] Adapter Framework - ginkgo.By("Step 5: Verify Maestro resource version does not change on Skip") // Query the resource bundle again to verify version remains unchanged Eventually(func(g Gomega) { - rb, err := h.GetMaestroClient().FindResourceBundleByClusterID(ctx, clusterID) + rbs, err := h.GetMaestroClient().FindResourceBundlesByClusterAndAdapter(ctx, clusterID, adapterName) g.Expect(err).NotTo(HaveOccurred(), "failed to find resource bundle") + g.Expect(rbs).NotTo(BeEmpty(), "should find resource bundle for adapter") // Version should remain at initial version (1) - g.Expect(rb.Version).To(Equal(initialVersion), + g.Expect(rbs[0].Version).To(Equal(initialVersion), "resource bundle version should remain unchanged across Skip operations") - ginkgo.GinkgoWriter.Printf("Verified resource bundle version remains at: %d\n", rb.Version) + ginkgo.GinkgoWriter.Printf("Verified resource bundle version remains at: %d\n", rbs[0].Version) }, h.Cfg.Timeouts.Adapter.Processing, h.Cfg.Polling.Interval).Should(Succeed()) }) }) @@ -424,7 +427,7 @@ var _ = ginkgo.Describe("[Suite: adapter][maestro-transport] Adapter Framework - ) var _ = ginkgo.Describe("[Suite: adapter][maestro-transport][negative] Adapter Framework - Maestro Transport Negative Scenarios", - ginkgo.Label(labels.Tier1), + ginkgo.Label(labels.Tier1, labels.Adapter, labels.Negative), func() { var ( h *helper.Helper @@ -483,14 +486,28 @@ var _ = ginkgo.Describe("[Suite: adapter][maestro-transport][negative] Adapter F ginkgo.GinkgoWriter.Printf("Warning: failed to cleanup cluster %s: %v\n", clusterID, err) } } + if adapterName != "" { if h.Cfg.BrokerType == "googlepubsub" { - ginkgo.By("Clean up Pub/Sub subscription and dlq topic for adapter") + ginkgo.By("Cleanup Pub/Sub subscription and dlq topic for adapter") if err := h.DeletePubSubResourcesForAdapter(ctx, adapterName, baseDeployOpts.ResourceType); err != nil { ginkgo.GinkgoWriter.Printf("Warning: failed to delete Pub/Sub subscription and dlq topic for adapter %s: %v\n", adapterName, err) } } } + + if clusterID != "" && adapterName != "" { + ginkgo.By("Cleanup Resource Bundles by clusterID " + clusterID + " and adapterName " + adapterName) + // Best effort delete outstanding resource bundles created on cluster creation + if rbs, err := h.MaestroClient.FindResourceBundlesByClusterAndAdapter(ctx, clusterID, adapterName); err == nil { + for _, rb := range rbs { + err := h.MaestroClient.DeleteResourceBundle(ctx, rb.ID) + if err != nil { + ginkgo.GinkgoWriter.Printf("Warning: failed to delete resource bundle %s: %v\n", rb.ID, err) + } + } + } + } }) }) @@ -603,19 +620,10 @@ var _ = ginkgo.Describe("[Suite: adapter][maestro-transport][negative] Adapter F ginkgo.By("Verify no ManifestWork was created by the test adapter on Maestro") Eventually(func(g Gomega) { - // Query by cluster ID first to scope to current cluster - rbs, err := h.GetMaestroClient().FindAllResourceBundlesByClusterID(ctx, clusterID) + resourceBundles, err := h.GetMaestroClient().FindResourceBundlesByClusterAndAdapter(ctx, clusterID, adapterName) g.Expect(err).NotTo(HaveOccurred(), "should be able to query Maestro for resource bundles") - // Filter by adapter name using source-id label - var adapterBundles []maestro.ResourceBundle - for _, rb := range rbs { - if rb.Metadata.Labels != nil && rb.Metadata.Labels["maestro.io/source-id"] == adapterName { - adapterBundles = append(adapterBundles, rb) - } - } - - g.Expect(adapterBundles).To(BeEmpty(), + g.Expect(resourceBundles).To(BeEmpty(), "no ManifestWork should be created by adapter %s for cluster %s with unregistered consumer", adapterName, clusterID) ginkgo.GinkgoWriter.Printf("Verified no ManifestWork exists from adapter %s for cluster %s\n", adapterName, clusterID) @@ -624,8 +632,8 @@ var _ = ginkgo.Describe("[Suite: adapter][maestro-transport][negative] Adapter F ginkgo.By("Verify no K8s resources were created by the test adapter") Eventually(func(g Gomega) { // Check specifically for namespace that would have been created by THIS adapter - // Expected namespace name pattern: ${clusterID}-${adapterName}-namespace - expectedNamespace := fmt.Sprintf("%s-%s-namespace", clusterID, adapterName) + // Expected namespace name pattern: ${adapterName}-${clusterID} + expectedNamespace := fmt.Sprintf("%s-%s-namespace", adapterName, clusterID) _, err := h.GetNamespace(ctx, expectedNamespace) // We expect the namespace to NOT exist (should get error) @@ -683,26 +691,17 @@ var _ = ginkgo.Describe("[Suite: adapter][maestro-transport][negative] Adapter F // Verify ManifestWork was created by the test adapter despite wrong discovery config ginkgo.By("Verify ManifestWork was created by the test adapter on Maestro") Eventually(func(g Gomega) { - // Query by cluster ID first to scope to current cluster - rbs, err := h.GetMaestroClient().FindAllResourceBundlesByClusterID(ctx, clusterID) + resourceBundles, err := h.GetMaestroClient().FindResourceBundlesByClusterAndAdapter(ctx, clusterID, adapterName) g.Expect(err).NotTo(HaveOccurred(), "should be able to query Maestro for resource bundles") - // Filter by adapter name using source-id label - var adapterBundles []maestro.ResourceBundle - for _, rb := range rbs { - if rb.Metadata.Labels != nil && rb.Metadata.Labels["maestro.io/source-id"] == adapterName { - adapterBundles = append(adapterBundles, rb) - } - } - - g.Expect(adapterBundles).NotTo(BeEmpty(), "ManifestWork should be created by adapter %s for cluster %s despite wrong discovery", adapterName, clusterID) - ginkgo.GinkgoWriter.Printf("Found resource bundle created by adapter %s for cluster %s: ID=%s\n", adapterName, clusterID, adapterBundles[0].ID) + g.Expect(resourceBundles).NotTo(BeEmpty(), "ManifestWork should be created by adapter %s for cluster %s despite wrong discovery", adapterName, clusterID) + ginkgo.GinkgoWriter.Printf("Found resource bundle created by adapter %s for cluster %s: ID=%s\n", adapterName, clusterID, resourceBundles[0].ID) }, h.Cfg.Timeouts.Adapter.Processing, h.Cfg.Polling.Interval).Should(Succeed()) // Verify K8s resources were created by Maestro agent ginkgo.By("Verify K8s resources were created by Maestro agent") - namespaceName := fmt.Sprintf("%s-%s-namespace", clusterID, adapterName) - configmapName := fmt.Sprintf("%s-%s-configmap", clusterID, adapterName) + namespaceName := fmt.Sprintf("%s-%s-namespace", adapterName, clusterID) + configmapName := fmt.Sprintf("%s-%s-configmap", adapterName, clusterID) Eventually(func(g Gomega) { // Verify namespace exists @@ -871,25 +870,16 @@ var _ = ginkgo.Describe("[Suite: adapter][maestro-transport][negative] Adapter F ginkgo.GinkgoWriter.Printf("Created cluster ID: %s, Name: %s\n", clusterID, cluster.Name) // Construct namespace name AFTER cluster is created - namespaceName := fmt.Sprintf("%s-%s-namespace", clusterID, adapterName) + namespaceName := fmt.Sprintf("%s-%s-namespace", adapterName, clusterID) // Verify ManifestWork was created by the test adapter ginkgo.By("Verify ManifestWork was created by the test adapter on Maestro") Eventually(func(g Gomega) { - // Query by cluster ID first to scope to current cluster - rbs, err := h.GetMaestroClient().FindAllResourceBundlesByClusterID(ctx, clusterID) + resourceBundles, err := h.GetMaestroClient().FindResourceBundlesByClusterAndAdapter(ctx, clusterID, adapterName) g.Expect(err).NotTo(HaveOccurred(), "should be able to query Maestro for resource bundles") - // Filter by adapter name using source-id label - var adapterBundles []maestro.ResourceBundle - for _, rb := range rbs { - if rb.Metadata.Labels != nil && rb.Metadata.Labels["maestro.io/source-id"] == adapterName { - adapterBundles = append(adapterBundles, rb) - } - } - - g.Expect(adapterBundles).NotTo(BeEmpty(), "ManifestWork should be created by adapter %s for cluster %s", adapterName, clusterID) - ginkgo.GinkgoWriter.Printf("Found resource bundle created by adapter %s for cluster %s: ID=%s\n", adapterName, clusterID, adapterBundles[0].ID) + g.Expect(resourceBundles).NotTo(BeEmpty(), "ManifestWork should be created by adapter %s for cluster %s", adapterName, clusterID) + ginkgo.GinkgoWriter.Printf("Found resource bundle created by adapter %s for cluster %s: ID=%s\n", adapterName, clusterID, resourceBundles[0].ID) }, h.Cfg.Timeouts.Adapter.Processing, h.Cfg.Polling.Interval).Should(Succeed()) // Verify K8s resources were created @@ -1039,28 +1029,19 @@ var _ = ginkgo.Describe("[Suite: adapter][maestro-transport][negative] Adapter F ginkgo.GinkgoWriter.Printf("Created cluster ID: %s, Name: %s\n", clusterID, cluster.Name) // Construct namespace name AFTER cluster is created - namespaceName := fmt.Sprintf("%s-%s-namespace", clusterID, adapterName) + namespaceName := fmt.Sprintf("%s-%s-namespace", adapterName, clusterID) ginkgo.By("Verify ManifestWork was applied successfully by the test adapter in Maestro") // Even though post-action failed, the ManifestWork should exist in Maestro Eventually(func(g Gomega) { - // Query by cluster ID first to scope to current cluster - rbs, err := h.GetMaestroClient().FindAllResourceBundlesByClusterID(ctx, clusterID) + resourceBundles, err := h.GetMaestroClient().FindResourceBundlesByClusterAndAdapter(ctx, clusterID, adapterName) g.Expect(err).NotTo(HaveOccurred(), "should be able to query Maestro for resource bundles") - // Filter by adapter name using source-id label - var adapterBundles []maestro.ResourceBundle - for _, rb := range rbs { - if rb.Metadata.Labels != nil && rb.Metadata.Labels["maestro.io/source-id"] == adapterName { - adapterBundles = append(adapterBundles, rb) - } - } - - g.Expect(adapterBundles).NotTo(BeEmpty(), "ManifestWork should exist in Maestro created by adapter %s for cluster %s", adapterName, clusterID) - g.Expect(adapterBundles[0].ID).NotTo(BeEmpty(), "ManifestWork should have an ID") - g.Expect(adapterBundles[0].ConsumerName).NotTo(BeEmpty(), "ManifestWork should have a consumer") + g.Expect(resourceBundles).NotTo(BeEmpty(), "ManifestWork should exist in Maestro created by adapter %s for cluster %s", adapterName, clusterID) + g.Expect(resourceBundles[0].ID).NotTo(BeEmpty(), "ManifestWork should have an ID") + g.Expect(resourceBundles[0].ConsumerName).NotTo(BeEmpty(), "ManifestWork should have a consumer") ginkgo.GinkgoWriter.Printf("ManifestWork verified in Maestro for adapter %s and cluster %s: ID=%s, Consumer=%s\n", - adapterName, clusterID, adapterBundles[0].ID, adapterBundles[0].ConsumerName) + adapterName, clusterID, resourceBundles[0].ID, resourceBundles[0].ConsumerName) }, h.Cfg.Timeouts.Adapter.Processing, h.Cfg.Polling.Interval).Should(Succeed()) // Verify K8s resources were created diff --git a/e2e/cluster/adapter_failure.go b/e2e/cluster/adapter_failure.go index fd0487d2..2137df3c 100644 --- a/e2e/cluster/adapter_failure.go +++ b/e2e/cluster/adapter_failure.go @@ -14,7 +14,7 @@ import ( var _ = ginkgo.Describe("[Suite: cluster][negative] Cluster Can Reflect Adapter Failure in Top-Level Status", ginkgo.Serial, // Serial: deploys temp adapter subscribing to all events, causes cross-talk - ginkgo.Label(labels.Tier1, labels.Negative), + ginkgo.Label(labels.Tier1, labels.Negative, labels.Adapter), func() { var ( h *helper.Helper diff --git a/e2e/cluster/crash_recovery.go b/e2e/cluster/crash_recovery.go index 7165f524..201dc1c1 100644 --- a/e2e/cluster/crash_recovery.go +++ b/e2e/cluster/crash_recovery.go @@ -14,7 +14,7 @@ import ( var _ = ginkgo.Describe("[Suite: cluster][negative] Cluster Can Reach Correct Status After Adapter Crash and Recovery", ginkgo.Serial, // Serial: kills and restarts adapter pod, disrupts concurrent specs - ginkgo.Label(labels.Tier2, labels.Negative), + ginkgo.Label(labels.Tier2, labels.Negative, labels.Adapter), func() { var ( h *helper.Helper diff --git a/e2e/cluster/stuck_deletion.go b/e2e/cluster/stuck_deletion.go index 38aacc31..c0c7186a 100644 --- a/e2e/cluster/stuck_deletion.go +++ b/e2e/cluster/stuck_deletion.go @@ -2,6 +2,7 @@ package cluster import ( "context" + "fmt" "net/http" "os" @@ -15,7 +16,7 @@ import ( var _ = ginkgo.Describe("[Suite: cluster][negative] Stuck Deletion -- Adapter Unable to Finalize Prevents Hard-Delete", ginkgo.Serial, // Serial: deploys stuck adapter that blocks deletion of all clusters - ginkgo.Label(labels.Tier2, labels.Negative), + ginkgo.Label(labels.Tier2, labels.Negative, labels.Adapter), func() { var ( h *helper.Helper @@ -218,8 +219,8 @@ var _ = ginkgo.Describe("[Suite: cluster][negative] Stuck Deletion -- Adapter Un Eventually(h.PollClusterHTTPStatus(ctx, clusterID), h.Cfg.Timeouts.Cluster.Reconciled, h.Cfg.Polling.Interval). Should(Equal(http.StatusNotFound)) - ginkgo.By("Verify downstream K8s namespace is cleaned up") - Eventually(h.PollNamespacesByPrefix(ctx, clusterID), h.Cfg.Timeouts.Adapter.Processing, h.Cfg.Polling.Interval). + ginkgo.By("Verify downstream K8s cl-stuck- namespace is cleaned up") + Eventually(h.PollNamespacesByPrefix(ctx, fmt.Sprintf("%s-%s", adapterName, clusterID)), h.Cfg.Timeouts.Adapter.Processing, h.Cfg.Polling.Interval). Should(BeEmpty()) ginkgo.GinkgoWriter.Printf("Verified: stuck-adapter recovered, cluster hard-deleted\n") diff --git a/pkg/client/maestro/client.go b/pkg/client/maestro/client.go index 548b1d07..f465a08a 100644 --- a/pkg/client/maestro/client.go +++ b/pkg/client/maestro/client.go @@ -8,6 +8,7 @@ import ( "net/http" "net/url" "os" + "strings" "time" "github.com/openshift-hyperfleet/hyperfleet-e2e/pkg/client" @@ -29,6 +30,26 @@ func toJSONBLabelSearch(key, value string) string { return fmt.Sprintf("payload->'metadata'->'labels'@>'{%q:%q}'", key, value) } +// toJSONBMultiLabelSearch combines multiple label key=value pairs into a single Maestro JSONB search query. +// All labels must be present for a match (AND logic). +func toJSONBMultiLabelSearch(labels map[string]string) string { + if len(labels) == 0 { + return "" + } + var buf strings.Builder + buf.WriteString("{") + first := true + for k, v := range labels { + if !first { + buf.WriteString(", ") + } + fmt.Fprintf(&buf, "%q:%q", k, v) + first = false + } + buf.WriteString("}") + return fmt.Sprintf("payload->'metadata'->'labels'@>'%s'", buf.String()) +} + // Client provides methods to interact with the Maestro API type Client struct { baseURL string @@ -143,13 +164,12 @@ func (c *Client) DeleteResourceBundle(ctx context.Context, id string) error { return nil } -// FindResourceBundleByClusterID finds a resource bundle by cluster ID label -// Uses server-side filtering via Maestro's search parameter with JSONB syntax -func (c *Client) FindResourceBundleByClusterID(ctx context.Context, clusterID string) (*ResourceBundle, error) { +// FindResourcesByLabel finds all resource bundles matching a Maestro JSONB label search expression. +func (c *Client) FindResourcesByLabel(ctx context.Context, labelQuery string) ([]ResourceBundle, error) { apiURL := fmt.Sprintf("%s%s?search=%s", c.baseURL, resourceBundlesBasePath, - url.QueryEscape(toJSONBLabelSearch(client.KeyClusterID, clusterID))) + url.QueryEscape(labelQuery)) req, err := http.NewRequestWithContext(ctx, http.MethodGet, apiURL, nil) if err != nil { @@ -173,106 +193,35 @@ func (c *Client) FindResourceBundleByClusterID(ctx context.Context, clusterID st if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { return nil, fmt.Errorf("failed to decode response: %w", err) } - - if len(result.Items) == 0 { - return nil, fmt.Errorf("no resource bundle found for cluster ID: %s", clusterID) - } - - // Verify the result matches our cluster ID (defense in depth) - for i := range result.Items { - if result.Items[i].Metadata.Labels != nil && - result.Items[i].Metadata.Labels[client.KeyClusterID] == clusterID { - return &result.Items[i], nil - } - } - - return nil, fmt.Errorf("no resource bundle found for cluster ID: %s", clusterID) + // Trust the search query worked as expected + return result.Items, nil } -// FindAllResourceBundlesByClusterID finds all resource bundles for a cluster ID -// Returns all matching resource bundles (multiple adapters may create ManifestWorks for the same cluster) -func (c *Client) FindAllResourceBundlesByClusterID(ctx context.Context, clusterID string) ([]ResourceBundle, error) { - apiURL := fmt.Sprintf("%s%s?search=%s", - c.baseURL, - resourceBundlesBasePath, - url.QueryEscape(toJSONBLabelSearch(client.KeyClusterID, clusterID))) - - req, err := http.NewRequestWithContext(ctx, http.MethodGet, apiURL, nil) - if err != nil { - return nil, fmt.Errorf("failed to create request: %w", err) - } - - resp, err := c.httpClient.Do(req) - if err != nil { - return nil, fmt.Errorf("failed to execute request: %w", err) - } - defer func() { - _ = resp.Body.Close() - }() - - if resp.StatusCode != http.StatusOK { - body, _ := io.ReadAll(resp.Body) - return nil, fmt.Errorf("unexpected status code %d: %s", resp.StatusCode, string(body)) - } - - var result ResourceBundleList - if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { - return nil, fmt.Errorf("failed to decode response: %w", err) - } - - // Filter and return all matching resource bundles - var bundles []ResourceBundle - for i := range result.Items { - if result.Items[i].Metadata.Labels != nil && - result.Items[i].Metadata.Labels[client.KeyClusterID] == clusterID { - bundles = append(bundles, result.Items[i]) - } - } - - return bundles, nil +// FindResourceBundlesByRunID finds all resource bundles created by a specific test run +// Uses the e2e.hyperfleet.io/run-id label to filter by test runID +func (c *Client) FindResourceBundlesByRunID(ctx context.Context, runID string) ([]ResourceBundle, error) { + return c.FindResourcesByLabel(ctx, toJSONBLabelSearch("e2e.hyperfleet.io/run-id", runID)) } // FindResourceBundlesByAdapterName finds all resource bundles created by a specific adapter // Uses the maestro.io/source-id label to filter by adapter name func (c *Client) FindResourceBundlesByAdapterName(ctx context.Context, adapterName string) ([]ResourceBundle, error) { - apiURL := fmt.Sprintf("%s%s?search=%s", - c.baseURL, - resourceBundlesBasePath, - url.QueryEscape(toJSONBLabelSearch("maestro.io/source-id", adapterName))) - - req, err := http.NewRequestWithContext(ctx, http.MethodGet, apiURL, nil) - if err != nil { - return nil, fmt.Errorf("failed to create request: %w", err) - } - - resp, err := c.httpClient.Do(req) - if err != nil { - return nil, fmt.Errorf("failed to execute request: %w", err) - } - defer func() { - _ = resp.Body.Close() - }() - - if resp.StatusCode != http.StatusOK { - body, _ := io.ReadAll(resp.Body) - return nil, fmt.Errorf("unexpected status code %d: %s", resp.StatusCode, string(body)) - } - - var result ResourceBundleList - if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { - return nil, fmt.Errorf("failed to decode response: %w", err) - } + return c.FindResourcesByLabel(ctx, toJSONBLabelSearch("maestro.io/source-id", adapterName)) +} - // Filter and return all matching resource bundles - var bundles []ResourceBundle - for i := range result.Items { - if result.Items[i].Metadata.Labels != nil && - result.Items[i].Metadata.Labels["maestro.io/source-id"] == adapterName { - bundles = append(bundles, result.Items[i]) - } - } +// FindResourceBundlesByClusterID finds all resource bundles for a cluster ID +// Uses the cluster ID label to filter by cluster ID +func (c *Client) FindResourceBundlesByClusterID(ctx context.Context, clusterID string) ([]ResourceBundle, error) { + return c.FindResourcesByLabel(ctx, toJSONBLabelSearch(client.KeyClusterID, clusterID)) +} - return bundles, nil +// FindResourceBundlesByClusterAndAdapter finds all resource bundles for a specific cluster and adapter +// Uses both cluster ID and adapter name labels in a single query +func (c *Client) FindResourceBundlesByClusterAndAdapter(ctx context.Context, clusterID, adapterName string) ([]ResourceBundle, error) { + return c.FindResourcesByLabel(ctx, toJSONBMultiLabelSearch(map[string]string{ + client.KeyClusterID: clusterID, + "maestro.io/source-id": adapterName, + })) } // ListConsumers retrieves the list of registered Maestro consumers diff --git a/pkg/helper/cleanup.go b/pkg/helper/cleanup.go index 5afa2c72..1feda666 100644 --- a/pkg/helper/cleanup.go +++ b/pkg/helper/cleanup.go @@ -7,28 +7,21 @@ import ( "time" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/wait" "github.com/openshift-hyperfleet/hyperfleet-e2e/pkg/client/kubernetes" + "github.com/openshift-hyperfleet/hyperfleet-e2e/pkg/client/maestro" "github.com/openshift-hyperfleet/hyperfleet-e2e/pkg/config" "github.com/openshift-hyperfleet/hyperfleet-e2e/pkg/helper/helm" "github.com/openshift-hyperfleet/hyperfleet-e2e/pkg/logger" ) -var AppliedManifestWorksGVR = &schema.GroupVersionResource{ - Group: "work.open-cluster-management.io", - Version: "v1", - Resource: "appliedmanifestworks", -} - type CleanupHelper struct { cfg *config.Config k8sClient *kubernetes.Client - dynamicClient *kubernetes.DynamicClient labelSelectorListOptions metav1.ListOptions adapterDeploymentList *AdapterDeploymentList + maestroClient *maestro.Client } // NewCleanupHelper creates a new CleanupHelper @@ -47,18 +40,18 @@ func NewCleanupHelper() (*CleanupHelper, error) { if adapterDeploymentList == nil { return nil, fmt.Errorf("adapter deployment list must be set for resource cleanup tracking") } + // RUN_ID is set when tests are executed, forms the label: e2e.hyperfleet.io/run-id= // Label applied to adapters and resources created during test suite execution labelSelector := fmt.Sprintf("e2e.hyperfleet.io/run-id=%s", cfg.RunID) - dynamicClient, err := kubernetes.NewDynamicClient() - if err != nil { - return nil, fmt.Errorf("failed to create dynamic client: %w", err) - } labelSelectorListOptions := metav1.ListOptions{ LabelSelector: labelSelector, } - return &CleanupHelper{k8sClient: k8sClient, dynamicClient: dynamicClient, labelSelectorListOptions: labelSelectorListOptions, cfg: cfg, adapterDeploymentList: adapterDeploymentList}, nil + // Create Maestro Client for cleanup workflow + maestroClient := maestro.NewClient("") + + return &CleanupHelper{k8sClient: k8sClient, labelSelectorListOptions: labelSelectorListOptions, cfg: cfg, adapterDeploymentList: adapterDeploymentList, maestroClient: maestroClient}, nil } // CleanupPubSubResources sweeps Pub/Sub topics and subscriptions created by adapters @@ -153,12 +146,22 @@ func (c *CleanupHelper) SweepPubsubTestAdapterResources(ctx context.Context) err func (c *CleanupHelper) SweepLabeledResources(ctx context.Context) error { logger.Info("Starting robust test cleanup with label selector:", "labelSelector", c.labelSelectorListOptions.LabelSelector) - // Phase 1: Remove AppliedManifestWork finalizers to break controller dependencies - logger.Info("Phase 1: Removing finalizers from AppliedManifestWorks") - c.removeAppliedManifestWorkFinalizers(ctx) + // Phase 1: Delete ResourceBundles Created by Run ID + logger.Info("Phase 1: Best effort to delete Resource Bundles created by run ID") + if rbs, err := c.maestroClient.FindResourceBundlesByRunID(ctx, c.cfg.RunID); err == nil { + for _, rb := range rbs { + // Best effort deletion of resource bundles + err := c.maestroClient.DeleteResourceBundle(ctx, rb.ID) + if err != nil { + logger.Error("failed to delete resource bundle", "error", err) + } + } + } else { + logger.Error("failed to get resource bundles by run Id", "error", err) + } // Phase 2: Delete resources (Background propagation - don't wait for cascade) - logger.Info("Phase 2: Deleting resources") + logger.Info("Phase 2: Best effort to delete resources") if err := c.deleteJobs(ctx); err != nil { logger.Error("failed to delete jobs", "error", err) } @@ -168,9 +171,6 @@ func (c *CleanupHelper) SweepLabeledResources(ctx context.Context) error { if err := c.deleteConfigMaps(ctx); err != nil { logger.Error("failed to delete configmaps", "error", err) } - if err := c.deleteAppliedManifestWorksForce(ctx); err != nil { - logger.Error("failed to delete applied manifest works", "error", err) - } if err := c.deleteNamespacesForce(ctx); err != nil { logger.Error("failed to delete namespaces", "error", err) } @@ -198,73 +198,11 @@ func (c *CleanupHelper) SweepLabeledResources(ctx context.Context) error { return nil } -// removeAllFinalizers strips finalizers from AppliedManifestWorks -// These are the resources with custom finalizers that block deletion -func (c *CleanupHelper) removeAppliedManifestWorkFinalizers(ctx context.Context) { - amws, err := c.dynamicClient.Resource(*AppliedManifestWorksGVR).List(ctx, c.labelSelectorListOptions) - if err != nil { - logger.Error("failed to list AppliedManifestWorks for finalizer removal", "error", err) - return - } - for _, amw := range amws.Items { - if len(amw.GetFinalizers()) > 0 { - name := amw.GetName() - logger.Info("Removing finalizers from AppliedManifestWork", "name", name, "finalizers", amw.GetFinalizers()) - - // Patch to remove finalizers - patch := []byte(`{"metadata":{"finalizers":null}}`) - _, err := c.dynamicClient.Resource(*AppliedManifestWorksGVR).Patch( - ctx, - name, - types.MergePatchType, - patch, - metav1.PatchOptions{}, - ) - if err != nil { - logger.Error("failed to remove finalizers from AppliedManifestWork", "name", name, "error", err) - } - } - } -} - -// deleteAppliedManifestWorksForce deletes AMWs without relying on propagation -func (c *CleanupHelper) deleteAppliedManifestWorksForce(ctx context.Context) error { - appliedManifestWorks, err := c.dynamicClient.Resource(*AppliedManifestWorksGVR).List(ctx, c.labelSelectorListOptions) - if err != nil { - return fmt.Errorf("failed to list AppliedManifestWorks: %w", err) - } - - // Use Background propagation - we already removed finalizers - propagationPolicy := metav1.DeletePropagationBackground - zeroInt64 := int64(0) - deleteOptions := metav1.DeleteOptions{ - PropagationPolicy: &propagationPolicy, - GracePeriodSeconds: &zeroInt64, - } - - for _, appliedManifestWork := range appliedManifestWorks.Items { - appliedManifestWorkName := appliedManifestWork.GetName() - logger.Warn("Deleting AppliedManifestWork", "name", appliedManifestWorkName) - if err := c.dynamicClient.Resource(*AppliedManifestWorksGVR).Delete(ctx, appliedManifestWorkName, deleteOptions); err != nil { - logger.Error("failed to delete AppliedManifestWork", "name", appliedManifestWorkName, "error", err) - } - } - return nil -} - // countRemainingResources returns the count of resources still present // If any error occurs, the count that was obtained is returned and an error is returned func (c *CleanupHelper) countRemainingResources(ctx context.Context) (int, error) { count := 0 errorList := []string{} - // Count AppliedManifestWorks - amws, err := c.dynamicClient.Resource(*AppliedManifestWorksGVR).List(ctx, c.labelSelectorListOptions) - if err != nil { - logger.Error("failed to list AppliedManifestWorks", "error", err) - errorList = append(errorList, "AppliedManifestWorks") - } else { - count += len(amws.Items) - } // Count Namespaces namespaces, err := c.k8sClient.CoreV1().Namespaces().List(ctx, c.labelSelectorListOptions) diff --git a/pkg/labels/labels.go b/pkg/labels/labels.go index c2a46d9f..44f77ec4 100644 --- a/pkg/labels/labels.go +++ b/pkg/labels/labels.go @@ -25,6 +25,7 @@ const ( // Functionality labels - Feature category dimension: describes test coverage target const ( Upgrade = "upgrade" // Version compatibility: smooth upgrades + Adapter = "adapter" // Adapter: specific adapter tests that install and uninstall the adapter chart ) // Constraint labels - Execution constraint dimension: determines scheduling strategy diff --git a/testdata/adapter-configs/cl-crash/adapter-task-config.yaml b/testdata/adapter-configs/cl-crash/adapter-task-config.yaml index b65b5923..5c7a0525 100644 --- a/testdata/adapter-configs/cl-crash/adapter-task-config.yaml +++ b/testdata/adapter-configs/cl-crash/adapter-task-config.yaml @@ -55,7 +55,7 @@ resources: apiVersion: v1 kind: Namespace metadata: - name: "{{ .clusterId }}-cl-crash" + name: "{{ .adapter.name }}-{{ .clusterId }}" labels: hyperfleet.io/cluster-id: "{{ .clusterId }}" hyperfleet.io/cluster-name: "{{ .clusterName }}" diff --git a/testdata/adapter-configs/cl-m-bad-api/adapter-task-config.yaml b/testdata/adapter-configs/cl-m-bad-api/adapter-task-config.yaml index d6ebe896..f710028f 100644 --- a/testdata/adapter-configs/cl-m-bad-api/adapter-task-config.yaml +++ b/testdata/adapter-configs/cl-m-bad-api/adapter-task-config.yaml @@ -42,7 +42,7 @@ resources: kind: ManifestWork metadata: # ManifestWork name - must be unique within consumer namespace - name: "{{ .clusterId }}-{{ .adapter.name }}" + name: "{{ .adapter.name }}-{{ .clusterId }}" # Labels for identification, filtering, and management labels: @@ -94,7 +94,7 @@ resources: - apiVersion: v1 kind: Namespace metadata: - name: "{{ .clusterId | lower }}-{{ .adapter.name }}-namespace" + name: "{{ .adapter.name }}-{{ .clusterId }}-namespace" labels: app.kubernetes.io/component: adapter-task-config app.kubernetes.io/instance: "{{ .adapter.name }}" @@ -109,8 +109,8 @@ resources: cluster_id: "{{ .clusterId }}" cluster_name: "{{ .clusterId }}" metadata: - name: "{{ .clusterId | lower }}-{{ .adapter.name }}-configmap" - namespace: "{{ .clusterId | lower }}-{{ .adapter.name }}-namespace" + name: "{{ .adapter.name }}-{{ .clusterId }}-configmap" + namespace: "{{ .adapter.name }}-{{ .clusterId }}-namespace" labels: app.kubernetes.io/component: adapter-task-config app.kubernetes.io/instance: "{{ .adapter.name }}" @@ -141,7 +141,7 @@ resources: - resourceIdentifier: group: "" # Core API group (empty for v1 resources) resource: "namespaces" # Resource type - name: "{{ .clusterId | lower }}-{{ .adapter.name }}-namespace" # Specific resource name + name: "{{ .adapter.name }}-{{ .clusterId }}-namespace" updateStrategy: type: "ServerSideApply" # Use server-side apply for namespaces feedbackRules: @@ -155,8 +155,8 @@ resources: - resourceIdentifier: group: "" # Core API group (empty for v1 resources) resource: "configmaps" # Resource type - name: "{{ .clusterId | lower }}-{{ .adapter.name }}-configmap" # Specific resource name - namespace: "{{ .clusterId | lower }}-{{ .adapter.name }}-namespace" + name: "{{ .adapter.name }}-{{ .clusterId }}-configmap" + namespace: "{{ .adapter.name }}-{{ .clusterId }}-namespace" updateStrategy: type: "ServerSideApply" # Use server-side apply for namespaces serverSideApply: @@ -171,16 +171,16 @@ resources: path: ".metadata.resourceVersion" # Discover the ResourceBundle (ManifestWork) by name from Maestro discovery: - by_name: "{{ .clusterId }}-{{ .adapter.name }}" + by_name: "{{ .adapter.name }}-{{ .clusterId }}" # Discover nested resources deployed by the ManifestWork nested_discoveries: - name: "namespace0" discovery: - by_name: "{{ .clusterId | lower }}-{{ .adapter.name }}-namespace" + by_name: "{{ .adapter.name }}-{{ .clusterId }}-namespace" - name: "configmap0" discovery: - by_name: "{{ .clusterId | lower }}-{{ .adapter.name }}-configmap" + by_name: "{{ .adapter.name }}-{{ .clusterId }}-configmap" post: payloads: diff --git a/testdata/adapter-configs/cl-m-unreg-consumer/adapter-task-config.yaml b/testdata/adapter-configs/cl-m-unreg-consumer/adapter-task-config.yaml index f810b82c..5e7ab5b5 100644 --- a/testdata/adapter-configs/cl-m-unreg-consumer/adapter-task-config.yaml +++ b/testdata/adapter-configs/cl-m-unreg-consumer/adapter-task-config.yaml @@ -66,7 +66,7 @@ resources: kind: ManifestWork metadata: # ManifestWork name - must be unique within consumer namespace - name: "{{ .clusterId }}-{{ .adapter.name }}" + name: "{{ .adapter.name }}-{{ .clusterId }}" # Labels for identification, filtering, and management labels: @@ -118,7 +118,7 @@ resources: - apiVersion: v1 kind: Namespace metadata: - name: "{{ .clusterId | lower }}-{{ .adapter.name }}-namespace" + name: "{{ .adapter.name }}-{{ .clusterId }}-namespace" labels: app.kubernetes.io/component: adapter-task-config app.kubernetes.io/instance: "{{ .adapter.name }}" @@ -133,8 +133,8 @@ resources: cluster_id: "{{ .clusterId }}" cluster_name: "{{ .clusterName }}" metadata: - name: "{{ .clusterId | lower }}-{{ .adapter.name }}-configmap" - namespace: "{{ .clusterId | lower }}-{{ .adapter.name }}-namespace" + name: "{{ .adapter.name }}-{{ .clusterId }}-configmap" + namespace: "{{ .adapter.name }}-{{ .clusterId }}-namespace" labels: app.kubernetes.io/component: adapter-task-config app.kubernetes.io/instance: "{{ .adapter.name }}" @@ -165,7 +165,7 @@ resources: - resourceIdentifier: group: "" # Core API group (empty for v1 resources) resource: "namespaces" # Resource type - name: "{{ .clusterId | lower }}-{{ .adapter.name }}-namespace" # Specific resource name + name: "{{ .adapter.name }}-{{ .clusterId }}-namespace" updateStrategy: type: "ServerSideApply" # Use server-side apply for namespaces feedbackRules: @@ -179,8 +179,8 @@ resources: - resourceIdentifier: group: "" # Core API group (empty for v1 resources) resource: "configmaps" # Resource type - name: "{{ .clusterId | lower }}-{{ .adapter.name }}-configmap" # Specific resource name - namespace: "{{ .clusterId | lower }}-{{ .adapter.name }}-namespace" + name: "{{ .adapter.name }}-{{ .clusterId }}-configmap" + namespace: "{{ .adapter.name }}-{{ .clusterId }}-namespace" updateStrategy: type: "ServerSideApply" # Use server-side apply for namespaces serverSideApply: @@ -195,16 +195,16 @@ resources: path: ".metadata.resourceVersion" # Discover the ResourceBundle (ManifestWork) by name from Maestro discovery: - by_name: "{{ .clusterId }}-{{ .adapter.name }}" + by_name: "{{ .adapter.name }}-{{ .clusterId }}" # Discover nested resources deployed by the ManifestWork nested_discoveries: - name: "namespace0" discovery: - by_name: "{{ .clusterId | lower }}-{{ .adapter.name }}-namespace" + by_name: "{{ .adapter.name }}-{{ .clusterId }}-namespace" - name: "configmap0" discovery: - by_name: "{{ .clusterId | lower }}-{{ .adapter.name }}-configmap" + by_name: "{{ .adapter.name }}-{{ .clusterId }}-configmap" post: payloads: diff --git a/testdata/adapter-configs/cl-m-wrong-ds/adapter-task-config.yaml b/testdata/adapter-configs/cl-m-wrong-ds/adapter-task-config.yaml index b64c44ab..a1e9e979 100644 --- a/testdata/adapter-configs/cl-m-wrong-ds/adapter-task-config.yaml +++ b/testdata/adapter-configs/cl-m-wrong-ds/adapter-task-config.yaml @@ -66,7 +66,7 @@ resources: kind: ManifestWork metadata: # ManifestWork name - must be unique within consumer namespace - name: "{{ .clusterId }}-{{ .adapter.name }}" + name: "{{ .adapter.name }}-{{ .clusterId }}" # Labels for identification, filtering, and management labels: @@ -118,7 +118,7 @@ resources: - apiVersion: v1 kind: Namespace metadata: - name: "{{ .clusterId | lower }}-{{ .adapter.name }}-namespace" + name: "{{ .adapter.name }}-{{ .clusterId }}-namespace" labels: app.kubernetes.io/component: adapter-task-config app.kubernetes.io/instance: "{{ .adapter.name }}" @@ -133,8 +133,8 @@ resources: cluster_id: "{{ .clusterId }}" cluster_name: "{{ .clusterName }}" metadata: - name: "{{ .clusterId | lower }}-{{ .adapter.name }}-configmap" - namespace: "{{ .clusterId | lower }}-{{ .adapter.name }}-namespace" + name: "{{ .adapter.name }}-{{ .clusterId }}-configmap" + namespace: "{{ .adapter.name }}-{{ .clusterId }}-namespace" labels: app.kubernetes.io/component: adapter-task-config app.kubernetes.io/instance: "{{ .adapter.name }}" @@ -165,7 +165,7 @@ resources: - resourceIdentifier: group: "" # Core API group (empty for v1 resources) resource: "namespaces" # Resource type - name: "{{ .clusterId | lower }}-{{ .adapter.name }}-namespace" # Specific resource name + name: "{{ .adapter.name }}-{{ .clusterId }}-namespace" updateStrategy: type: "ServerSideApply" # Use server-side apply for namespaces feedbackRules: @@ -179,8 +179,8 @@ resources: - resourceIdentifier: group: "" # Core API group (empty for v1 resources) resource: "configmaps" # Resource type - name: "{{ .clusterId | lower }}-{{ .adapter.name }}-configmap" # Specific resource name - namespace: "{{ .clusterId | lower }}-{{ .adapter.name }}-namespace" + name: "{{ .adapter.name }}-{{ .clusterId }}-configmap" + namespace: "{{ .adapter.name }}-{{ .clusterId }}-namespace" updateStrategy: type: "ServerSideApply" # Use server-side apply for namespaces serverSideApply: @@ -196,17 +196,17 @@ resources: # Discover the ResourceBundle (ManifestWork) by name from Maestro # NOTE: This discovery name is intentionally WRONG to test main discovery failure discovery: - by_name: "{{ .clusterId }}-{{ .adapter.name }}-wrong" + by_name: "{{ .adapter.name }}-{{ .clusterId }}-wrong" # Discover nested resources deployed by the ManifestWork # These are correct, but won't be reached if main discovery fails nested_discoveries: - name: "namespace0" discovery: - by_name: "{{ .clusterId | lower }}-{{ .adapter.name }}-namespace" + by_name: "{{ .adapter.name }}-{{ .clusterId }}-namespace" - name: "configmap0" discovery: - by_name: "{{ .clusterId | lower }}-{{ .adapter.name }}-configmap" + by_name: "{{ .adapter.name }}-{{ .clusterId }}-configmap" post: payloads: diff --git a/testdata/adapter-configs/cl-m-wrong-nest/adapter-task-config.yaml b/testdata/adapter-configs/cl-m-wrong-nest/adapter-task-config.yaml index 8b63d8c5..45a1b969 100644 --- a/testdata/adapter-configs/cl-m-wrong-nest/adapter-task-config.yaml +++ b/testdata/adapter-configs/cl-m-wrong-nest/adapter-task-config.yaml @@ -66,7 +66,7 @@ resources: kind: ManifestWork metadata: # ManifestWork name - must be unique within consumer namespace - name: "{{ .clusterId }}-{{ .adapter.name }}" + name: "{{ .adapter.name }}-{{ .clusterId }}" # Labels for identification, filtering, and management labels: @@ -118,7 +118,7 @@ resources: - apiVersion: v1 kind: Namespace metadata: - name: "{{ .clusterId | lower }}-{{ .adapter.name }}-namespace" + name: "{{ .adapter.name }}-{{ .clusterId }}-namespace" labels: app.kubernetes.io/component: adapter-task-config app.kubernetes.io/instance: "{{ .adapter.name }}" @@ -133,8 +133,8 @@ resources: cluster_id: "{{ .clusterId }}" cluster_name: "{{ .clusterName }}" metadata: - name: "{{ .clusterId | lower }}-{{ .adapter.name }}-configmap" - namespace: "{{ .clusterId | lower }}-{{ .adapter.name }}-namespace" + name: "{{ .adapter.name }}-{{ .clusterId }}-configmap" + namespace: "{{ .adapter.name }}-{{ .clusterId }}-namespace" labels: app.kubernetes.io/component: adapter-task-config app.kubernetes.io/instance: "{{ .adapter.name }}" @@ -165,7 +165,7 @@ resources: - resourceIdentifier: group: "" # Core API group (empty for v1 resources) resource: "namespaces" # Resource type - name: "{{ .clusterId | lower }}-{{ .adapter.name }}-namespace" # Specific resource name + name: "{{ .adapter.name }}-{{ .clusterId }}-namespace" updateStrategy: type: "ServerSideApply" # Use server-side apply for namespaces feedbackRules: @@ -179,8 +179,8 @@ resources: - resourceIdentifier: group: "" # Core API group (empty for v1 resources) resource: "configmaps" # Resource type - name: "{{ .clusterId | lower }}-{{ .adapter.name }}-configmap" # Specific resource name - namespace: "{{ .clusterId | lower }}-{{ .adapter.name }}-namespace" + name: "{{ .adapter.name }}-{{ .clusterId }}-configmap" + namespace: "{{ .adapter.name }}-{{ .clusterId }}-namespace" updateStrategy: type: "ServerSideApply" # Use server-side apply for namespaces serverSideApply: @@ -195,17 +195,17 @@ resources: path: ".metadata.resourceVersion" # Discover the ResourceBundle (ManifestWork) by name from Maestro discovery: - by_name: "{{ .clusterId }}-{{ .adapter.name }}" + by_name: "{{ .adapter.name }}-{{ .clusterId }}" # Discover nested resources deployed by the ManifestWork # NOTE: These discovery names are intentionally WRONG for testing discovery failure nested_discoveries: - name: "namespace0" discovery: - by_name: "{{ .clusterId | lower }}-{{ .adapter.name }}-namespace-wrong" + by_name: "{{ .adapter.name }}-{{ .clusterId }}-wrong" - name: "configmap0" discovery: - by_name: "{{ .clusterId | lower }}-{{ .adapter.name }}-configmap-wrong" + by_name: "{{ .adapter.name }}-{{ .clusterId }}-wrong" post: payloads: diff --git a/testdata/adapter-configs/cl-param-error/adapter-task-config.yaml b/testdata/adapter-configs/cl-param-error/adapter-task-config.yaml index 68e3fb7d..a4aea837 100644 --- a/testdata/adapter-configs/cl-param-error/adapter-task-config.yaml +++ b/testdata/adapter-configs/cl-param-error/adapter-task-config.yaml @@ -44,7 +44,7 @@ resources: apiVersion: v1 kind: Namespace metadata: - name: "{{ .clusterId }}" + name: "{{ .adapter.name }}-{{ .clusterId }}" labels: hyperfleet.io/cluster-id: "{{ .clusterId }}" e2e.hyperfleet.io/ci: "{{ .ci }}" diff --git a/testdata/adapter-configs/cl-stuck/adapter-task-config.yaml b/testdata/adapter-configs/cl-stuck/adapter-task-config.yaml index 6e0b91d8..3692abb1 100644 --- a/testdata/adapter-configs/cl-stuck/adapter-task-config.yaml +++ b/testdata/adapter-configs/cl-stuck/adapter-task-config.yaml @@ -59,7 +59,7 @@ resources: apiVersion: v1 kind: Namespace metadata: - name: "{{ .clusterId }}-cl-stuck" + name: "{{ .adapter.name }}-{{ .clusterId }}" labels: hyperfleet.io/cluster-id: "{{ .clusterId }}" hyperfleet.io/cluster-name: "{{ .clusterName }}"