Repository: openshift-kni/numaresources-operator
Pull request #1234: CNF-15623:must-gather: add support for hypershift
Author: login: Tal-or
Labels: name: approved
description: Indicates a PR has been approved by an approver from all required OWNERS files.
name: lgtm
description: Indicates that a PR is ready to be merged.
Created: 2025-03-18T10:47:29Z | Merged: 2025-03-20T15:39:08Z

To support running  MG on hosted clusters, we should check whether we're
running on standard OpenShift or HyperShift
and collect the relevant data accordingly.

Signed-off-by: Talor Itzhak <titzhak@redhat.com>


Diff:
diff --git a/Dockerfile.must-gather b/Dockerfile.must-gather
index 3ab3365b61..29f74d9a31 100644
--- a/Dockerfile.must-gather
+++ b/Dockerfile.must-gather
@@ -2,4 +2,4 @@ FROM quay.io/openshift/origin-cli:4.19
 
 COPY must-gather/collection-scripts/* /usr/bin/
 
-ENTRYPOINT /usr/bin/gather
+ENTRYPOINT ["/usr/bin/gather"]
diff --git a/must-gather/collection-scripts/gather b/must-gather/collection-scripts/gather
index b9c195b8f5..d45e4fdbca 100755
--- a/must-gather/collection-scripts/gather
+++ b/must-gather/collection-scripts/gather
@@ -1,16 +1,32 @@
 #!/bin/bash
 
+
+function is_hypershift() {
+  control_plane_topology=$(/usr/bin/oc get infrastructure cluster -o jsonpath='{.status.controlPlaneTopology}')
+  if [[ "${control_plane_topology}" == "External" ]]; then
+    return 0
+  fi
+  return 1
+}
+
 # generate /must-gather/version file
 . version
-echo "performance-addon-operator/must-gather" > /must-gather/version
+echo "numaresources-operator/must-gather" > /must-gather/version
 version >> /must-gather/version
 
 # machine/node resources
-resources+=(nodes machineconfigs machineconfigpools featuregates kubeletconfigs)
+resources+=(nodes featuregates)
+
+if is_hypershift; then
+  # collect kubeletconfig configmap
+  /usr/bin/oc adm inspect --dest-dir must-gather --namespace openshift-config-managed configmaps
+else
+  resources+=(machineconfigs machineconfigpools kubeletconfigs)
+fi
 
 # run the collection of resources using must-gather
-for resource in ${resources[@]}; do
-  /usr/bin/oc adm inspect --dest-dir must-gather --all-namespaces ${resource}
+for resource in "${resources[@]}"; do
+  /usr/bin/oc adm inspect --dest-dir must-gather --all-namespaces "${resource}"
 done
 
 # Collect NRO details
diff --git a/must-gather/collection-scripts/gather_nro b/must-gather/collection-scripts/gather_nro
index 67c8b28c98..9cc9c14b5b 100755
--- a/must-gather/collection-scripts/gather_nro
+++ b/must-gather/collection-scripts/gather_nro
@@ -4,9 +4,9 @@
 . namespace
 NRO_NAMESPACE=$(nro_namespace)
 
-if [ -z "$NRO_NAMESPACE" ]
+if [ -z "${NRO_NAMESPACE}" ]
 then
-    echo "NUMAresources Operator namespace not detected. Skipping NRO data gathering"
+    echo "NUMAResources Operator namespace not detected. Skipping NRO data gathering"
 else
     # get crds
     for crd_name in numaresourcesschedulers.nodetopology.openshift.io numaresourcesoperators.nodetopology.openshift.io noderesourcetopologies.topology.node.k8s.io
@@ -18,5 +18,5 @@ else
         oc adm inspect --dest-dir must-gather ${crd_name}
     done
 
-    oc adm inspect --dest-dir must-gather ns/${NRO_NAMESPACE}
+    oc adm inspect --dest-dir must-gather ns/"${NRO_NAMESPACE}"
 fi
diff --git a/must-gather/collection-scripts/namespace b/must-gather/collection-scripts/namespace
index 06fda3c367..78c93c6ad7 100644
--- a/must-gather/collection-scripts/namespace
+++ b/must-gather/collection-scripts/namespace
@@ -10,5 +10,5 @@ function nro_namespace() {
   # namespace suggested by the documentation. This is a fancier way to check for its existence
   [ -z "${ns}" ] && ns=$(oc get ns openshift-numaresources -o=jsonpath='{.metadata.name}{"\n"}' 2> /dev/null )
 
-  echo ${ns}
+  echo "${ns}"
 }
diff --git a/must-gather/collection-scripts/version b/must-gather/collection-scripts/version
index d2654b66b4..9592541624 100644
--- a/must-gather/collection-scripts/version
+++ b/must-gather/collection-scripts/version
@@ -13,5 +13,5 @@ function version() {
   # if version still not found, use Unknown
   [ -z "${version}" ] && version="Unknown"
 
-  echo ${version}
+  echo "${version}"
 }
diff --git a/test/e2e/must-gather/README.md b/test/e2e/must-gather/README.md
index 1f645d5db7..7d12561075 100644
--- a/test/e2e/must-gather/README.md
+++ b/test/e2e/must-gather/README.md
@@ -11,3 +11,14 @@
 - `E2E_NROP_MUSTGATHER_IMAGE` (accepts string, e.g. `quay.io/openshift-kni/numaresources-must-gather`) overrides
    the hardcoded must-gather image to use.
 - `E2E_NROP_MUSTGATHER_TAG` (accepts string, e.g. `4.18-snapshot`) overrides the hardcoded must-gather tag to use.
+
+#### Running tests on HyperShift
+
+To be able to run the must-gather suite on HyperShift platform, the following environment variables are required:
+
+- `CLUSTER_NAME` hosted-cluster name, run `oc get np <node-pool-name> -n clusters -o jsonpath='{.spec.clusterName}'` on the MNG cluster to get the name.
+- `KUBECONFIG` should hold the path of the hosted cluster's kubeconfig file.
+- `HYPERSHIFT_MANAGEMENT_CLUSTER_KUBECONFIG` should hold the path of the management/hub cluster's kubeconfig file.
+
+
+
diff --git a/test/e2e/must-gather/must_gather_suite_test.go b/test/e2e/must-gather/must_gather_suite_test.go
index 506bd4ffd5..98b9ba8e9d 100644
--- a/test/e2e/must-gather/must_gather_suite_test.go
+++ b/test/e2e/must-gather/must_gather_suite_test.go
@@ -23,8 +23,6 @@ import (
 	"testing"
 	"time"
 
-	"github.com/k8stopologyawareschedwg/deployer/pkg/deployer/platform"
-
 	nropv1 "github.com/openshift-kni/numaresources-operator/api/v1"
 	e2eclient "github.com/openshift-kni/numaresources-operator/test/internal/clients"
 	"github.com/openshift-kni/numaresources-operator/test/internal/configuration"
@@ -61,10 +59,6 @@ func TestMustGather(t *testing.T) {
 }
 
 var _ = ginkgo.BeforeSuite(func() {
-	if configuration.Plat != platform.OpenShift {
-		ginkgo.Skip(fmt.Sprintf("running on %q platform but must-gather is only supported on %q platform", configuration.Plat, platform.OpenShift))
-	}
-
 	mustGatherImage = getStringValueFromEnv(envVarMustGatherImage, defaultMustGatherImage)
 	mustGatherTag = getStringValueFromEnv(envVarMustGatherTag, defaultMustGatherTag)
 	ginkgo.By(fmt.Sprintf("Using must-gather image %q tag %q", mustGatherImage, mustGatherTag))
diff --git a/test/e2e/must-gather/must_gather_test.go b/test/e2e/must-gather/must_gather_test.go
index ec451cfdf1..bc3018a32b 100644
--- a/test/e2e/must-gather/must_gather_test.go
+++ b/test/e2e/must-gather/must_gather_test.go
@@ -23,19 +23,23 @@ import (
 	"os"
 	"os/exec"
 	"path/filepath"
+	"regexp"
 	"time"
 
 	. "github.com/onsi/ginkgo/v2"
 	. "github.com/onsi/gomega"
 
 	corev1 "k8s.io/api/core/v1"
-	"k8s.io/klog"
+	"k8s.io/klog/v2"
 	"sigs.k8s.io/yaml"
 
+	"github.com/k8stopologyawareschedwg/deployer/pkg/deployer/platform"
 	nropv1 "github.com/openshift-kni/numaresources-operator/api/v1"
 	nodegroupv1 "github.com/openshift-kni/numaresources-operator/api/v1/helper/nodegroup"
+	"github.com/openshift-kni/numaresources-operator/internal/hypershift/consts"
 	"github.com/openshift-kni/numaresources-operator/internal/wait"
 	e2eclient "github.com/openshift-kni/numaresources-operator/test/internal/clients"
+	"github.com/openshift-kni/numaresources-operator/test/internal/configuration"
 	"github.com/openshift-kni/numaresources-operator/test/internal/objects"
 
 	mcov1 "github.com/openshift/machine-config-operator/pkg/apis/machineconfiguration.openshift.io/v1"
@@ -114,15 +118,31 @@ var _ = Describe("[must-gather] NRO data collected", func() {
 				nropInstanceFileName := fmt.Sprintf("%s.yaml", filepath.Join("cluster-scoped-resources/nodetopology.openshift.io/numaresourcesoperators", objects.NROObjectKey().Name))
 				nroschedInstanceFileName := fmt.Sprintf("%s.yaml", filepath.Join("cluster-scoped-resources/nodetopology.openshift.io/numaresourcesschedulers", nroSchedObj.Name))
 
-				collectedMCPs, err := getMachineConfigPools(filepath.Join(mgContentFolder, "cluster-scoped-resources/machineconfiguration.openshift.io/machineconfigpools"))
-				Expect(err).ToNot(HaveOccurred())
-
 				nro := &nropv1.NUMAResourcesOperator{}
-				Expect(e2eclient.Client.Get(context.TODO(), objects.NROObjectKey(), nro)).To(Succeed())
-				ngMCPs, err := nodegroupv1.FindMachineConfigPools(&collectedMCPs, nro.Spec.NodeGroups)
-				Expect(err).ToNot(HaveOccurred())
-
-				nglabels := collectMachineConfigPoolsNodeSelector(ngMCPs)
+				ok, err := getResourceOfType(filepath.Join(mgContentFolder, "cluster-scoped-resources/nodetopology.openshift.io/numaresourcesoperators"), objects.NROObjectKey().Name, nro)
+				Expect(ok).To(BeTrue(), "numaresourcesoperators resources named %s was not found", objects.NROObjectKey().Name)
+				Expect(err).NotTo(HaveOccurred())
+
+				var nglabels []map[string]string
+				if configuration.Plat == platform.OpenShift {
+					collectedMCPs, err := getMachineConfigPools(filepath.Join(mgContentFolder, "cluster-scoped-resources/machineconfiguration.openshift.io/machineconfigpools"))
+					Expect(err).ToNot(HaveOccurred())
+					ngMCPs, err := nodegroupv1.FindMachineConfigPools(&collectedMCPs, nro.Spec.NodeGroups)
+					Expect(err).ToNot(HaveOccurred())
+					nglabels = collectMachineConfigPoolsNodeSelector(ngMCPs)
+				}
+				if configuration.Plat == platform.HyperShift {
+					for _, ng := range nro.Spec.NodeGroups {
+						nglabels = append(nglabels, map[string]string{
+							consts.NodePoolNameLabel: *ng.PoolName,
+						})
+					}
+					By("Check that the ConfigMaps have been collected")
+					configMapsFolder := filepath.Join(mgContentFolder, "namespaces/openshift-config-managed/core/configmaps")
+					re := regexp.MustCompile(`^kubeletconfig-.*\.yaml`)
+					found := checkfileExistByRegex(configMapsFolder, re)
+					Expect(found).To(BeTrue(), "couldn't find a file starts with \"kubeletconfig-\" prefix in directory %q", configMapsFolder)
+				}
 				workerNodesNames, err := getWorkerNodesNames(filepath.Join(mgContentFolder, "cluster-scoped-resources/core/nodes"), nglabels)
 				Expect(err).ToNot(HaveOccurred())
 
@@ -184,6 +204,22 @@ func checkfilesExist(listOfFiles []string, path string) error {
 	return nil
 }
 
+func checkfileExistByRegex(dirPath string, regexp *regexp.Regexp) bool {
+	GinkgoHelper()
+	dirEntry, err := os.ReadDir(dirPath)
+	Expect(err).ToNot(HaveOccurred())
+
+	for _, entry := range dirEntry {
+		if entry.IsDir() {
+			continue
+		}
+		if regexp.MatchString(entry.Name()) {
+			return true
+		}
+	}
+	return false
+}
+
 // Look for node yaml manifest in `folder` and return
 // all the names of all the nodes with
 // any set of labels
@@ -248,6 +284,28 @@ func getMachineConfigPools(folder string) (mcov1.MachineConfigPoolList, error) {
 	return retval, nil
 }
 
+func getResourceOfType(folder, resourceName string, resource any) (bool, error) {
+	items, err := os.ReadDir(folder)
+	if err != nil {
+		return false, err
+	}
+	for _, item := range items {
+		if item.IsDir() {
+			continue
+		}
+		if item.Name() != fmt.Sprintf("%s.yaml", resourceName) {
+			continue
+		}
+
+		data, err := os.ReadFile(filepath.Join(folder, item.Name()))
+		if err != nil {
+			return false, err
+		}
+		return true, yaml.Unmarshal(data, resource)
+	}
+	return false, nil
+}
+
 // return true if b keys and values respectively are part of a, otherwise false
 func isMapSubsetOf(a map[string]string, b map[string]string) bool {
 	if len(a) < len(b) || len(a) == 0 {


Reviews:
user: login: ffromani
body: provisional LGTM, some questions inside
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-19T14:22:26Z
user: login: Tal-or
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-19T14:24:57Z
user: login: ffromani
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-19T14:34:15Z
user: login: shajmakh
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-19T14:54:24Z
user: login: Tal-or
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-19T14:58:31Z
user: login: Tal-or
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-19T14:58:54Z
user: login: shajmakh
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-19T15:31:21Z
user: login: Tal-or
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-19T15:36:19Z
user: login: ffromani
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-20T09:54:33Z
user: login: Tal-or
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-20T10:51:21Z
user: login: ffromani
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-20T11:21:22Z
user: login: ffromani
body: /approve
/lgtm
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-20T13:20:27Z

Review comments:
diff_hunk: @@ -1,12 +1,27 @@
 #!/bin/bash
 
+
+function is_hypershift() {
+  control_plane_topology=$(/usr/bin/oc get infrastructure cluster -ojson | jq .status.controlPlaneTopology)
path: must-gather/collection-scripts/gather
user: login: ffromani
body: we can also use kubectl advanced formatting and very likely get rid of the `jq` part, but AFAIR `jq` is already installed, so good enough for now
created_at: 2025-03-19T14:20:04Z
author_association: MEMBER
diff_hunk: @@ -1,12 +1,27 @@
 #!/bin/bash
 
+
+function is_hypershift() {
+  control_plane_topology=$(/usr/bin/oc get infrastructure cluster -ojson | jq .status.controlPlaneTopology)
+  if [[ "${control_plane_topology}" == "External" ]]; then
+    return 0
+  fi
+  return 1
+}
+
 # generate /must-gather/version file
 . version
 echo "numaresources-operator/must-gather" > /must-gather/version
 version >> /must-gather/version
 
 # machine/node resources
-resources+=(nodes machineconfigs machineconfigpools featuregates kubeletconfigs)
+resources+=(nodes featuregates)
+
+if is_hypershift; then
+  resources+=(configmaps)
path: must-gather/collection-scripts/gather
user: login: ffromani
body: all of them?
created_at: 2025-03-19T14:20:20Z
author_association: MEMBER
diff_hunk: @@ -2,4 +2,4 @@ FROM quay.io/openshift/origin-cli:4.19
 
 COPY must-gather/collection-scripts/* /usr/bin/
 
-ENTRYPOINT /usr/bin/gather
+ENTRYPOINT ["/usr/bin/gather"]
path: Dockerfile.must-gather
user: login: ffromani
body: this is fine, but doesn't clarify why the exec form is better (I'm fine with both TBH)
created_at: 2025-03-19T14:22:15Z
author_association: MEMBER
diff_hunk: @@ -2,4 +2,4 @@ FROM quay.io/openshift/origin-cli:4.19
 
 COPY must-gather/collection-scripts/* /usr/bin/
 
-ENTRYPOINT /usr/bin/gather
+ENTRYPOINT ["/usr/bin/gather"]
path: Dockerfile.must-gather
user: login: Tal-or
body: I added a link to the official docs that explains why
created_at: 2025-03-19T14:24:57Z
author_association: COLLABORATOR
diff_hunk: @@ -1,12 +1,27 @@
 #!/bin/bash
 
+
+function is_hypershift() {
+  control_plane_topology=$(/usr/bin/oc get infrastructure cluster -ojson | jq .status.controlPlaneTopology)
+  if [[ "${control_plane_topology}" == "External" ]]; then
+    return 0
+  fi
+  return 1
+}
+
 # generate /must-gather/version file
 . version
 echo "numaresources-operator/must-gather" > /must-gather/version
 version >> /must-gather/version
 
 # machine/node resources
-resources+=(nodes machineconfigs machineconfigpools featuregates kubeletconfigs)
+resources+=(nodes featuregates)
+
+if is_hypershift; then
+  resources+=(configmaps)
path: must-gather/collection-scripts/gather
user: login: ffromani
body: I mean, on which namespace?
created_at: 2025-03-19T14:34:15Z
author_association: MEMBER
diff_hunk: @@ -1,12 +1,27 @@
 #!/bin/bash
 
+
+function is_hypershift() {
+  control_plane_topology=$(/usr/bin/oc get infrastructure cluster -ojson | jq .status.controlPlaneTopology)
+  if [[ "${control_plane_topology}" == "External" ]]; then
+    return 0
+  fi
+  return 1
+}
+
 # generate /must-gather/version file
 . version
 echo "numaresources-operator/must-gather" > /must-gather/version
 version >> /must-gather/version
 
 # machine/node resources
-resources+=(nodes machineconfigs machineconfigpools featuregates kubeletconfigs)
+resources+=(nodes featuregates)
+
+if is_hypershift; then
+  resources+=(configmaps)
path: must-gather/collection-scripts/gather
user: login: shajmakh
body: the tool will collect them on all namespaces later:
https://github.com/openshift-kni/numaresources-operator/pull/1234/commits/b9a6d27805ec54527ad5148e0318043b2163f77e#diff-e5c2a69519b4a8fddd46d182316399558c9fd41434650a1196c7a9beaa14ada0R28
but I think NRO CMs are enough. Also CMs are useful to be gathered on openshift too.
created_at: 2025-03-19T14:48:29Z
author_association: MEMBER
diff_hunk: @@ -1,12 +1,27 @@
 #!/bin/bash
 
+
+function is_hypershift() {
+  control_plane_topology=$(/usr/bin/oc get infrastructure cluster -ojson | jq .status.controlPlaneTopology)
+  if [[ "${control_plane_topology}" == "External" ]]; then
+    return 0
+  fi
+  return 1
+}
+
 # generate /must-gather/version file
 . version
 echo "numaresources-operator/must-gather" > /must-gather/version
 version >> /must-gather/version
 
 # machine/node resources
-resources+=(nodes machineconfigs machineconfigpools featuregates kubeletconfigs)
+resources+=(nodes featuregates)
+
+if is_hypershift; then
+  resources+=(configmaps)
path: must-gather/collection-scripts/gather
user: login: Tal-or
body: fixed that. configmap will be collected only from `openshift-config-managed` namespace which suppose to contain the kubeletconfig configmap
created_at: 2025-03-19T14:58:31Z
author_association: COLLABORATOR
diff_hunk: @@ -1,12 +1,27 @@
 #!/bin/bash
 
+
+function is_hypershift() {
+  control_plane_topology=$(/usr/bin/oc get infrastructure cluster -ojson | jq .status.controlPlaneTopology)
path: must-gather/collection-scripts/gather
user: login: Tal-or
body: should be better now
created_at: 2025-03-19T14:58:54Z
author_association: COLLABORATOR
diff_hunk: @@ -1,12 +1,27 @@
 #!/bin/bash
 
+
+function is_hypershift() {
+  control_plane_topology=$(/usr/bin/oc get infrastructure cluster -ojson | jq .status.controlPlaneTopology)
+  if [[ "${control_plane_topology}" == "External" ]]; then
+    return 0
+  fi
+  return 1
+}
+
 # generate /must-gather/version file
 . version
 echo "numaresources-operator/must-gather" > /must-gather/version
 version >> /must-gather/version
 
 # machine/node resources
-resources+=(nodes machineconfigs machineconfigpools featuregates kubeletconfigs)
+resources+=(nodes featuregates)
+
+if is_hypershift; then
+  resources+=(configmaps)
path: must-gather/collection-scripts/gather
user: login: shajmakh
body: Thanks,  and is the CMs of the NRO namespace on openshift collected somewhere else? 
```
oc get cm -n numaresources 
NAME                           DATA   AGE
kube-root-ca.crt               1      23d
**numaresourcesoperator-worker**   1      22d
openshift-service-ca.crt       1      23d
**topo-aware-scheduler-config**    1      22d
```
I don't have a HCP handy but in which NS would the scheduler CM be stored? are we collecting that? 

created_at: 2025-03-19T15:31:21Z
author_association: MEMBER
diff_hunk: @@ -1,12 +1,27 @@
 #!/bin/bash
 
+
+function is_hypershift() {
+  control_plane_topology=$(/usr/bin/oc get infrastructure cluster -ojson | jq .status.controlPlaneTopology)
+  if [[ "${control_plane_topology}" == "External" ]]; then
+    return 0
+  fi
+  return 1
+}
+
 # generate /must-gather/version file
 . version
 echo "numaresources-operator/must-gather" > /must-gather/version
 version >> /must-gather/version
 
 # machine/node resources
-resources+=(nodes machineconfigs machineconfigpools featuregates kubeletconfigs)
+resources+=(nodes featuregates)
+
+if is_hypershift; then
+  resources+=(configmaps)
path: must-gather/collection-scripts/gather
user: login: Tal-or
body: yes. should be here: https://github.com/Tal-or/numaresources-operator/blob/support_mg_hcp/must-gather/collection-scripts/gather_nro#L21
created_at: 2025-03-19T15:36:19Z
author_association: COLLABORATOR
diff_hunk: @@ -2,4 +2,4 @@ FROM quay.io/openshift/origin-cli:4.19
 
 COPY must-gather/collection-scripts/* /usr/bin/
 
-ENTRYPOINT /usr/bin/gather
+ENTRYPOINT ["/usr/bin/gather"]
path: Dockerfile.must-gather
user: login: ffromani
body: Yes, I saw it, thanks. Could you please make it explicit which of the reasons apply to us?
1. just use the preferred form because both are valid for our use case (a bit light, but OK)
2. prevent the shell process to be run
3. avoid any possible issue with signal delivery
4. streamline `ENTRYPOINT` and `CMD` interaction and avoid future bugs

all the above?
something else?
created_at: 2025-03-20T09:54:33Z
author_association: MEMBER
diff_hunk: @@ -2,4 +2,4 @@ FROM quay.io/openshift/origin-cli:4.19
 
 COPY must-gather/collection-scripts/* /usr/bin/
 
-ENTRYPOINT /usr/bin/gather
+ENTRYPOINT ["/usr/bin/gather"]
path: Dockerfile.must-gather
user: login: Tal-or
body: `1` the default approach is that we should always follow best-practice unless we have a well defined reason why not to.

Please correct me if i'm wrong here
created_at: 2025-03-20T10:51:21Z
author_association: COLLABORATOR
diff_hunk: @@ -2,4 +2,4 @@ FROM quay.io/openshift/origin-cli:4.19
 
 COPY must-gather/collection-scripts/* /usr/bin/
 
-ENTRYPOINT /usr/bin/gather
+ENTRYPOINT ["/usr/bin/gather"]
path: Dockerfile.must-gather
user: login: ffromani
body: ok, that's good enough
created_at: 2025-03-20T11:21:22Z
author_association: MEMBER

PR comments:
user: login: Tal-or
created_at: 2025-03-18T10:47:52Z
body: /hold 
e2e tests are missing
author_association: COLLABORATOR
user: login: openshift-ci-robot
created_at: 2025-03-18T10:48:38Z
body: @Tal-or: This pull request references CNF-15623 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.19.0" version, but no target version was set.

<details>

In response to [this](https://github.com/openshift-kni/numaresources-operator/pull/1234):

>To support running  MG on hosted clusters, we should check whether we're
>running on standard OpenShift or HyperShift
>and collect the relevant data accordingly.
>
>Signed-off-by: Talor Itzhak <titzhak@redhat.com>


Instructions for interacting with me using PR comments are available [here](https://prow.ci.openshift.org/command-help?repo=openshift-kni%2Fnumaresources-operator).  If you have questions or suggestions related to my behavior, please file an issue against the [openshift-eng/jira-lifecycle-plugin](https://github.com/openshift-eng/jira-lifecycle-plugin/issues/new) repository.
</details>
author_association: NONE
user: login: Tal-or
created_at: 2025-03-19T14:08:22Z
body: /hold cancel

PR is reviewable
author_association: COLLABORATOR
user: login: Tal-or
created_at: 2025-03-19T14:11:46Z
body: /cc @ffromani @shajmakh 
author_association: COLLABORATOR
user: login: Tal-or
created_at: 2025-03-20T10:53:37Z
body: /hold

I would like to add some additional tests
author_association: COLLABORATOR
user: login: Tal-or
created_at: 2025-03-20T12:56:49Z
body: /hold cancel

The tests are more robust now. 
author_association: COLLABORATOR
user: login: openshift-ci[bot]
created_at: 2025-03-20T13:20:34Z
body: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/openshift-kni/numaresources-operator/pull/1234#pullrequestreview-2702708428" title="LGTM">ffromani</a>*, *<a href="https://github.com/openshift-kni/numaresources-operator/pull/1234#" title="Author self-approved">Tal-or</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=openshift-kni%2Fnumaresources-operator).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/openshift-kni/numaresources-operator/blob/main/OWNERS)~~ [Tal-or,ffromani]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
author_association: CONTRIBUTOR