Repository: VictoriaMetrics/operator

Issue:
Add cluster env check in e2e test
# Problem
Now when I run `make e2e-test`, the test process just operate the clsuter which my local `kubectl` points to.

Unfortunately my local `kubectl` points to my product k8s cluster. It's very dangerous becuase it make chanages to the product cluster accidentally.

# Solution
As the [contributing guide](https://github.com/VictoriaMetrics/operator/blob/master/CONTRIBUTING.md#publish-changes) mentioned, the changes should be applied to the minikube cluster. **So we should check the cluster which the changes will be applied to.** If the cluster is not the minukube cluster, we should terminate the e2e test process and print a notice.

Discussion:
@xiaozongyang: cc @f41gh7 @Haleygo @AndrewChubatiuk @xiaozongyang: There are two possible ways to do this check:
1. get clsuter name with the command `kubectx -c` , and check the cluster name is `minikube` or not in makefile or bash script. Maybe we can just run `kubectx minikube` to switch to the minukube clsuter before run [`test-e2e`](https://github.com/VictoriaMetrics/operator/blob/master/Makefile#L134)
2. check apiserver address in [e2e_test.go](https://github.com/VictoriaMetrics/operator/blob/master/test/e2e/e2e_test.go), if the ip of apiserver is local ip address or not@f41gh7: I like second approach with local IP address check. 

Locally, I usually test operator with a `kind` and multiple clusters. It will be hard to use hard-coded cluster name with it. 

Solution patch:
diff --git a/.github/workflows/operatorhub.yaml b/.github/workflows/operatorhub.yaml
index c881c83b..ec00ee00 100644
--- a/.github/workflows/operatorhub.yaml
+++ b/.github/workflows/operatorhub.yaml
@@ -1,13 +1,6 @@
 name: Publish OperatorHub release
 
 on:
-  workflow_dispatch:
-    ref: master
-    branches:
-      - master
-    permissions:
-      teams:
-        - development
   workflow_run:
     workflows:
       - Release
@@ -52,7 +45,6 @@ jobs:
           workdir: __k8s-operatorhub-repo
       
       - uses: dawidd6/action-download-artifact@v6
-        if: ${{ github.event_name == 'workflow_run' }}
         with:
           name: olm
           workflow: main.yaml
@@ -63,26 +55,33 @@ jobs:
       - name: Add operatorhub bundle
         id: update
         run: |
-          mkdir -p __k8s-operatorhub-repo/catalogs
+          if [ ! -d bundle ]; then
+            echo "No bundle directory found"
+            exit 1;
+          fi
           OPERATOR_DIR=__k8s-operatorhub-repo/operators/victoriametrics-operator
+          CATALOGS_DIR=__k8s-operatorhub-repo/catalogs
+
+          mkdir -p ${CATALOGS_DIR}
           mkdir -p ${OPERATOR_DIR}
-          export PREV_VERSION=$(find ${OPERATOR_DIR}/* ! -path "*/catalog-templates" -maxdepth 0 -type d -exec basename {} \; | sort -V -r | head -2 | tail -1)
-          export LATEST_VERSION=$(find ${OPERATOR_DIR}/* ! -path "*/catalog-templates" -maxdepth 0 -type d -exec basename {} \; | sort -V -r | head -1)
-          if [ -d bundle ]; then
-            export VERSION=$(ls bundle | head -1)
-            export MANIFEST_PATH=bundle/${VERSION}/manifests/victoriametrics-operator.clusterserviceversion.yaml
-            yq -i '.spec.replaces = "victoriametrics-operator.v" + strenv(LATEST_VERSION)' $MANIFEST_PATH
-            mv bundle/* ${OPERATOR_DIR}/
-            if [ -f ${OPERATOR_DIR}/Makefile ]; then
-              yq -i '.fbc.enabled = true' ${OPERATOR_DIR}/ci.yaml
-            else
-              yq -i '.updateGraph = "replaces-mode"' ${OPERATOR_DIR}/ci.yaml
-            fi
-          elif [ -f ${OPERATOR_DIR}/Makefile ]; then
+
+          export OLD_VERSION=$(find ${OPERATOR_DIR}/* ! -path "*/catalog-templates" -maxdepth 0 -type d -exec basename {} \; | sort -V -r | head -1)
+          export OLD_ENTRY="victoriametrics-operator.v${OLD_VERSION}"
+
+          export NEW_VERSION=$(ls bundle | head -1)
+          export NEW_ENTRY="victoriametrics-operator.v${NEW_VERSION}"
+
+          export MANIFEST_PATH=bundle/${NEW_VERSION}/manifests/victoriametrics-operator.clusterserviceversion.yaml
+          export BUNDLE_IMAGE="quay.io/community-operator-pipeline-prod/victoriametrics-operator:${NEW_VERSION}"
+
+          if [ ! -z $OLD_VERSION ]; then
+            yq -i '.spec.replaces = "victoriametrics-operator.v" + strenv(OLD_VERSION)' $MANIFEST_PATH
+          fi
+
+          mv bundle/* ${OPERATOR_DIR}/
+          if [ -f ${OPERATOR_DIR}/Makefile ]; then
+            yq -i 'del(.updateGraph)' ${OPERATOR_DIR}/ci.yaml
             cd ${OPERATOR_DIR}
-            export NEW_ENTRY="victoriametrics-operator.v${LATEST_VERSION}"
-            export OLD_ENTRY="victoriametrics-operator.v${PREV_VERSION}"
-            export BUNDLE_IMAGE="quay.io/community-operator-pipeline-prod/victoriametrics-operator:${LATEST_VERSION}"
             find catalog-templates \
               -path "*.yaml" \
               -exec yq -i -I2 '.entries |= .[] |= select(. | has("entries")).entries += [{"name": strenv(NEW_ENTRY), "replaces": strenv(OLD_ENTRY)}]' {} \;
@@ -90,9 +89,10 @@ jobs:
               -path "*.yaml" \
               -exec yq -i -I2 '.entries |= . += [{"image": strenv(BUNDLE_IMAGE), "schema": "olm.bundle"}]' {} \;
             make catalogs
-            export VERSION=${LATEST_VERSION}
+          else
+            yq -i 'del(.fbc)' ${OPERATOR_DIR}/ci.yaml
           fi
-          echo "VERSION=$VERSION" >> $GITHUB_OUTPUT
+          echo "VERSION=$NEW_VERSION" >> $GITHUB_OUTPUT
 
       - name: Create Pull Request
         if: ${{ steps.update.outputs.VERSION != '' }}
diff --git a/config/manifests/ci.yaml b/config/manifests/ci.yaml
index 17874d81..d6cfce40 100644
--- a/config/manifests/ci.yaml
+++ b/config/manifests/ci.yaml
@@ -6,3 +6,28 @@ reviewers:
 - AndrewChubatiuk
 - Haleygo
 - victoriametrics-bot
+updateGraph: replaces-mode
+fbc:
+  enabled: true
+  catalog_mapping:
+  - template_name: v4.12.yaml
+    catalog_names: ["v4.12"]
+    type: olm.template.basic
+  - template_name: v4.13.yaml
+    catalog_names: ["v4.13"]
+    type: olm.template.basic
+  - template_name: v4.14.yaml
+    catalog_names: ["v4.14"]
+    type: olm.template.basic
+  - template_name: v4.15.yaml
+    catalog_names: ["v4.15"]
+    type: olm.template.basic
+  - template_name: v4.16.yaml
+    catalog_names: ["v4.16"]
+    type: olm.template.basic
+  - template_name: v4.17.yaml
+    catalog_names: ["v4.17"]
+    type: olm.template.basic
+  - template_name: v4.18.yaml
+    catalog_names: ["v4.18"]
+    type: olm.template.basic
diff --git a/docs/resources/vmauth.md b/docs/resources/vmauth.md
index 1147c5c1..ec0016fc 100644
--- a/docs/resources/vmauth.md
+++ b/docs/resources/vmauth.md
@@ -119,7 +119,7 @@ kind: VMAuth
 metadata:
   name: vmauth-example
 spec:
-    replicas: 3
+    replicaCount: 3
     # ...
 ```
 
diff --git a/docs/resources/vmpodscrape.md b/docs/resources/vmpodscrape.md
index 3c886273..73a96117 100644
--- a/docs/resources/vmpodscrape.md
+++ b/docs/resources/vmpodscrape.md
@@ -26,10 +26,11 @@ The `VMPodScrape` object discovers pods and generates the relevant scraping conf
 The `PodMetricsEndpoints` section of the `VMPodScrapeSpec` is used to configure which ports of a pod are going to be
 scraped for metrics and with which parameters.
 
-Both `VMPodScrapes` and discovered targets may belong to any namespace. It is important for cross-namespace monitoring
-use cases, e.g. for meta-monitoring. Using the `namespaceSelector` of the `VMPodScrapeSpec` one can restrict the
-namespaces from which `Pods` are discovered from. To discover targets in all namespaces the `namespaceSelector` has to
-be empty:
+Both `VMPodScrape` and discovered targets may belong to any namespace. It is important for cross-namespace monitoring
+use cases, e.g. for meta-monitoring. Using the `podScrapeNamespaceSelector` of the `VMAgentSpec`
+one can restrict the namespaces from which `VMPodScrape`s are selected from by the respective [VMAgent](https://docs.victoriametrics.com/operator/resources/vmagent) server.
+Using the `namespaceSelector` of the `VMPodScrapeSpec` one can restrict the namespaces from which `Pods` are discovered from.
+To discover targets in all namespaces the `namespaceSelector` has to have value `any: true` specified:
 
 ```yaml
 apiVersion: operator.victoriametrics.com/v1beta1
@@ -70,5 +71,5 @@ spec:
       scheme: http
   selector:
     matchLabels:
-     owner: dev
+      owner: dev
 ```
diff --git a/docs/resources/vmservicescrape.md b/docs/resources/vmservicescrape.md
index 01aa7eca..59125808 100644
--- a/docs/resources/vmservicescrape.md
+++ b/docs/resources/vmservicescrape.md
@@ -19,7 +19,7 @@ need to reconfigure.
 [kubernetes service discovery](https://docs.victoriametrics.com/sd_configs#kubernetes_sd_configs) targets by corresponding `Service`.
 It has various options for scraping configuration of target (with basic auth,tls access, by specific port name etc.).
 
-Monitoring configuration based on  `discoveryRole` setting. By default, `endpoints` is used to get objects from kubernetes api.
+Monitoring configuration is based on `discoveryRole` setting. By default, `endpoints` is used to get objects from kubernetes api.
 It's also possible to use `discoveryRole: service` or `discoveryRole: endpointslices`.
 
 `Endpoints` objects are essentially lists of IP addresses.
@@ -38,10 +38,10 @@ Therefore, when specifying an endpoint in the `endpoints` section, they are stri
 **Note:** `endpoints` (lowercase) is the field in the `VMServiceScrape` CRD, while `Endpoints` (capitalized) is the Kubernetes object kind.
 
 Both `VMServiceScrape` and discovered targets may belong to any namespace. It is important for cross-namespace monitoring
-use cases, e.g. for meta-monitoring. Using the `serviceScrapeSelector` of the `VMAgentSpec`
+use cases, e.g. for meta-monitoring. Using the `serviceScrapeNamespaceSelector` of the `VMAgentSpec`
 one can restrict the namespaces from which `VMServiceScrape`s are selected from by the respective [VMAgent](https://docs.victoriametrics.com/operator/resources/vmagent) server.
-Using the `namespaceSelector` of the `VMServiceScrape` one can restrict the namespaces from which `Endpoints` can be
-discovered from. To discover targets in all namespaces the `namespaceSelector` has to be empty:
+Using the `namespaceSelector` of the `VMServiceScrapeSpec` one can restrict the namespaces from which `Endpoints` are discovered from.
+To discover targets in all namespaces the `namespaceSelector` has to have value `any: true` specified:
 
 ```yaml
 apiVersion: operator.victoriametrics.com/v1beta1
@@ -49,8 +49,8 @@ kind: VMServiceScrape
 metadata:
   name: example-service-scrape
 spec:
-  namespaceSelector: {}
-  # ...
+  namespaceSelector:
+    any: true
 ```
 
 More information about selectors you can find in [this doc](https://docs.victoriametrics.com/operator/resources/vmagent#scraping).
@@ -75,13 +75,13 @@ More details about migration from prometheus-operator you can read in [this doc]
 apiVersion: operator.victoriametrics.com/v1beta1
 kind: VMServiceScrape
 metadata:
-  name: example-app
+  name: example-service-scrape
   labels:
     team: frontend
 spec:
+  endpoints:
+    - port: web
   selector:
     matchLabels:
       app: example-app
-  endpoints:
-  - port: web
 ```
diff --git a/docs/setup.md b/docs/setup.md
index a213cc20..5106151b 100644
--- a/docs/setup.md
+++ b/docs/setup.md
@@ -39,7 +39,7 @@ export VM_VERSION=`basename $(curl -fs -o/dev/null -w %{redirect_url} https://gi
 wget -O install.yaml https://github.com/VictoriaMetrics/operator/releases/download/$VM_VERSION/install-with-webhook.yaml
 
 # Or download manifest without webhook
-wget -O install.yaml https://github.com/VictoriaMetrics/operator/releases/download/$VM_VERSION/install-without-webhook.yaml
+wget -O install.yaml https://github.com/VictoriaMetrics/operator/releases/download/$VM_VERSION/install-no-webhook.yaml
 ```
 
 Operator use `vm` namespace, but you can install it to specific namespace with command:



Test patch:
diff --git a/test/e2e/suite/suite.go b/test/e2e/suite/suite.go
index 2eda8f6c..4d2e0c07 100644
--- a/test/e2e/suite/suite.go
+++ b/test/e2e/suite/suite.go
@@ -2,8 +2,11 @@ package suite
 
 import (
 	"context"
+	"fmt"
+	"net"
 	"os"
 	"path/filepath"
+	"strings"
 
 	vmv1beta1 "github.com/VictoriaMetrics/operator/api/operator/v1beta1"
 	"github.com/VictoriaMetrics/operator/internal/controller/operator/factory/build"
@@ -45,7 +48,9 @@ func GetClient() client.Client {
 		ErrorIfCRDPathMissing:    false,
 	}
 	cfg, err := testEnv.Start()
+
 	Expect(err).NotTo(HaveOccurred())
+	Expect(isLocalHost(cfg.Host)).To(BeTrue())
 
 	K8sClient, err := client.New(cfg, client.Options{Scheme: scheme.Scheme})
 	Expect(err).ToNot(HaveOccurred())
@@ -149,3 +154,61 @@ func ShutdownOperatorProcess() {
 	cancelManager()
 	Eventually(stopped, 60, 2).Should(BeClosed())
 }
+
+func isLocalHost(host string) bool {
+	ips, err := getLocalIPs()
+	if err != nil {
+		return false
+	}
+
+	for _, ip := range ips {
+		if strings.Contains(host, ip) {
+			return true
+		}
+	}
+	return false
+}
+
+// GetLocalIPs returns a list of local IP addresses
+func getLocalIPs() ([]string, error) {
+	var ips []string
+
+	// Add loopback IPs
+	loopbackIPs := []string{"127.0.0.1", "::1"}
+	ips = append(ips, loopbackIPs...)
+
+	// Get all network interfaces
+	interfaces, err := net.Interfaces()
+	if err != nil {
+		return nil, fmt.Errorf("failed to get network interfaces: %w", err)
+	}
+
+	for _, iface := range interfaces {
+		// Skip loopback, down, or interfaces without addresses
+		if iface.Flags&net.FlagLoopback != 0 || iface.Flags&net.FlagUp == 0 {
+			continue
+		}
+
+		addrs, err := iface.Addrs()
+		if err != nil {
+			continue
+		}
+
+		for _, addr := range addrs {
+			// Check if the address is IP
+			switch v := addr.(type) {
+			case *net.IPNet:
+				// Skip loopback and link-local addresses
+				if v.IP.IsLoopback() || v.IP.IsLinkLocalUnicast() || v.IP.IsLinkLocalMulticast() {
+					continue
+				}
+				// Only include IPv4 addresses
+				if v.IP.To4() != nil {
+					ips = append(ips, v.IP.String())
+				}
+			}
+		}
+	}
+
+	return ips, nil
+}