Repository: kubean-io/kubean (go)

Issue:
software bug: when install kubean operator and cluster related resource not in the same namespace, the job can not setup the pod
1. install kubean on namsspace kubean-test
2. apply resource(hostconf, cluster, vars, ClusterOperation） to namespace kubean-system
3. the job is created, but job not create a pod to do the job
![企业微信截图_f8a32238-d9fc-4428-b045-09936ca081b8](https://user-images.githubusercontent.com/99961476/213387105-7c0f28f0-4817-4915-a7f3-82612da3fccd.png)
4. reinstall kubean on kubean-system
5. reapply the cluster related resource to ns kubean-system
6. the job successfully create a related pod

**Job info**
`
kubectl get job kubean-cluster1-enable-10-51-999-job -n kubean-system -o yaml
apiVersion: batch/v1
kind: Job
metadata:
  annotations:
    batch.kubernetes.io/job-tracking: ""
  creationTimestamp: "2023-01-19T07:38:14Z"
  generation: 1
  labels:
    controller-uid: e04a90b8-5800-436b-b5ef-8453a35767ea
    job-name: kubean-cluster1-enable-10-51-999-job
  name: kubean-cluster1-enable-10-51-999-job
  namespace: kubean-system
  ownerReferences:
  - apiVersion: kubean.io/v1alpha1
    blockOwnerDeletion: true
    controller: true
    kind: ClusterOperation
    name: cluster1-enable-10-51-999
    uid: 7666b020-603c-4f2d-bc41-321497dc7da9
  resourceVersion: "30950"
  uid: e04a90b8-5800-436b-b5ef-8453a35767ea
spec:
  backoffLimit: 0
  completionMode: NonIndexed
  completions: 1
  parallelism: 1
  selector:
    matchLabels:
      controller-uid: e04a90b8-5800-436b-b5ef-8453a35767ea
  suspend: false
  template:
    metadata:
      creationTimestamp: null
      labels:
        controller-uid: e04a90b8-5800-436b-b5ef-8453a35767ea
        job-name: kubean-cluster1-enable-10-51-999-job
    spec:
      containers:
      - command:
        - /bin/entrypoint.sh
        env:
        - name: CLUSTER_NAME
          value: cluster1
        image: m.daocloud.io/ghcr.io/kubean-io/spray-job:v0.4.2-rc8
        imagePullPolicy: IfNotPresent
        name: kubespray
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /bin/entrypoint.sh
          name: entrypoint
          readOnly: true
          subPath: entrypoint.sh
        - mountPath: /conf/hosts.yml
          name: hosts-conf
          subPath: hosts.yml
        - mountPath: /conf/group_vars.yml
          name: vars-conf
          subPath: group_vars.yml
      dnsPolicy: ClusterFirst
      restartPolicy: Never
      schedulerName: default-scheduler
      securityContext: {}
      serviceAccount: kubean
      serviceAccountName: kubean
      terminationGracePeriodSeconds: 30
      volumes:
      - configMap:
          defaultMode: 448
          name: cluster1-enable-10-51-999-entrypoint
        name: entrypoint
      - configMap:
          defaultMode: 420
          name: cluster1-hosts-conf-1674113894686
        name: hosts-conf
      - configMap:
          defaultMode: 420
          name: cluster1-vars-conf-1674113894709
        name: vars-conf
status:
  ready: 0
  startTime: "2023-01-19T07:38:14Z"
  uncountedTerminatedPods: {}
`

Pull request:
Fix job creating failure across different namespace
Signed-off-by: tu1h <lihai.tu@daocloud.io>

<!--  

Thanks for sending a pull request!  Here are some tips for you:

* make sure your commit is signed off

-->

**What type of PR is this?**
<!-- 
Uncomment only one ` /kind <>` line, hit enter to put that in a new line, and remove leading whitespaces from that line:

/kind api-change
/kind bug
/kind cleanup
/kind design
/kind documentation
/kind failing-test
/kind feature
/kind flake
-->
/kind bug

**What this PR does / why we need it**:
  Support for kubean and the resources it reference are not in the same namespace

**Which issue(s) this PR fixes**:
<!--
*Automatically closes linked issue when PR is merged.
Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`.
_If PR is about `failing-tests or flakes`, please post the related issues/tests in a comment and do not use `Fixes`_*
-->
Fixes #481 

**Special notes for your reviewer**:



Patch:
diff --git a/pkg/controllers/clusterops/controller.go b/pkg/controllers/clusterops/controller.go
index 06e6f19f5..dda48c280 100644
--- a/pkg/controllers/clusterops/controller.go
+++ b/pkg/controllers/clusterops/controller.go
@@ -10,6 +10,7 @@ import (
 	"time"
 	"unicode"
 
+	"github.com/kubean-io/kubean/pkg/util"
 	"github.com/kubean-io/kubean/pkg/util/entrypoint"
 
 	batchv1 "k8s.io/api/batch/v1"
@@ -351,7 +352,7 @@ func (c *Controller) NewKubesprayJob(clusterOps *clusteroperationv1alpha1.Cluste
 	DefaultMode := int32(0o700)
 	PrivatekeyMode := int32(0o400)
 	jobName := c.GenerateJobName(clusterOps)
-	namespace := clusterOps.Spec.HostsConfRef.NameSpace
+	namespace := util.GetCurrentNSOrDefault()
 	job := &batchv1.Job{
 		TypeMeta: metav1.TypeMeta{
 			APIVersion: "batch/v1",
@@ -548,7 +549,7 @@ func (c *Controller) CreateEntryPointShellConfigMap(clusterOps *clusteroperation
 		},
 		ObjectMeta: metav1.ObjectMeta{
 			Name:      fmt.Sprintf("%s-entrypoint", clusterOps.Name),
-			Namespace: clusterOps.Spec.HostsConfRef.NameSpace,
+			Namespace: util.GetCurrentNSOrDefault(),
 		},
 		Data: map[string]string{"entrypoint.sh": strings.TrimSpace(configMapData)}, // |2+
 	}
@@ -570,11 +571,15 @@ func (c *Controller) SetOwnerReferences(objectMetaData *metav1.ObjectMeta, clust
 	objectMetaData.OwnerReferences = []metav1.OwnerReference{*metav1.NewControllerRef(clusterOps, clusteroperationv1alpha1.SchemeGroupVersion.WithKind("ClusterOperation"))}
 }
 
-func (c *Controller) CopyConfigMap(clusterOps *clusteroperationv1alpha1.ClusterOperation, oldConfigMapRef *apis.ConfigMapRef, newName string) (*corev1.ConfigMap, error) {
+func (c *Controller) CopyConfigMap(clusterOps *clusteroperationv1alpha1.ClusterOperation, oldConfigMapRef *apis.ConfigMapRef, newName, newNamespace string) (*corev1.ConfigMap, error) {
 	oldConfigMap, err := c.ClientSet.CoreV1().ConfigMaps(oldConfigMapRef.NameSpace).Get(context.Background(), oldConfigMapRef.Name, metav1.GetOptions{})
 	if err != nil {
 		return nil, err
 	}
+	namespace := oldConfigMapRef.NameSpace
+	if newNamespace != "" {
+		namespace = newNamespace
+	}
 	newConfigMap := &corev1.ConfigMap{
 		TypeMeta: metav1.TypeMeta{
 			Kind:       "ConfigMap",
@@ -582,7 +587,7 @@ func (c *Controller) CopyConfigMap(clusterOps *clusteroperationv1alpha1.ClusterO
 		},
 		ObjectMeta: metav1.ObjectMeta{
 			Name:      newName,
-			Namespace: oldConfigMapRef.NameSpace,
+			Namespace: namespace,
 		},
 		Data: oldConfigMap.Data,
 	}
@@ -594,11 +599,15 @@ func (c *Controller) CopyConfigMap(clusterOps *clusteroperationv1alpha1.ClusterO
 	return newConfigMap, nil
 }
 
-func (c *Controller) CopySecret(clusterOps *clusteroperationv1alpha1.ClusterOperation, oldSecretRef *apis.SecretRef, newName string) (*corev1.Secret, error) {
+func (c *Controller) CopySecret(clusterOps *clusteroperationv1alpha1.ClusterOperation, oldSecretRef *apis.SecretRef, newName, newNamespace string) (*corev1.Secret, error) {
 	oldSecret, err := c.ClientSet.CoreV1().Secrets(oldSecretRef.NameSpace).Get(context.Background(), oldSecretRef.Name, metav1.GetOptions{})
 	if err != nil {
 		return nil, err
 	}
+	namespace := oldSecretRef.NameSpace
+	if newNamespace != "" {
+		namespace = newNamespace
+	}
 	newSecret := &corev1.Secret{
 		TypeMeta: metav1.TypeMeta{
 			Kind:       "Secret",
@@ -606,7 +615,7 @@ func (c *Controller) CopySecret(clusterOps *clusteroperationv1alpha1.ClusterOper
 		},
 		ObjectMeta: metav1.ObjectMeta{
 			Name:      newName,
-			Namespace: oldSecretRef.NameSpace,
+			Namespace: namespace,
 		},
 		Data: oldSecret.Data,
 	}
@@ -630,8 +639,9 @@ func (c *Controller) BackUpDataRef(clusterOps *clusteroperationv1alpha1.ClusterO
 	} else {
 		clusterOps.Labels[constants.KubeanClusterLabelKey] = cluster.Name
 	}
+	currentNS := util.GetCurrentNSOrDefault()
 	if clusterOps.Spec.HostsConfRef.IsEmpty() {
-		newConfigMap, err := c.CopyConfigMap(clusterOps, cluster.Spec.HostsConfRef, cluster.Spec.HostsConfRef.Name+timestamp)
+		newConfigMap, err := c.CopyConfigMap(clusterOps, cluster.Spec.HostsConfRef, cluster.Spec.HostsConfRef.Name+timestamp, currentNS)
 		if err != nil {
 			return false, err
 		}
@@ -645,7 +655,7 @@ func (c *Controller) BackUpDataRef(clusterOps *clusteroperationv1alpha1.ClusterO
 		return true, nil
 	}
 	if clusterOps.Spec.VarsConfRef.IsEmpty() {
-		newConfigMap, err := c.CopyConfigMap(clusterOps, cluster.Spec.VarsConfRef, cluster.Spec.VarsConfRef.Name+timestamp)
+		newConfigMap, err := c.CopyConfigMap(clusterOps, cluster.Spec.VarsConfRef, cluster.Spec.VarsConfRef.Name+timestamp, currentNS)
 		if err != nil {
 			return false, err
 		}
@@ -660,7 +670,7 @@ func (c *Controller) BackUpDataRef(clusterOps *clusteroperationv1alpha1.ClusterO
 	}
 	if clusterOps.Spec.SSHAuthRef.IsEmpty() && !cluster.Spec.SSHAuthRef.IsEmpty() {
 		// clusterOps backups ssh data when cluster has ssh data.
-		newSecret, err := c.CopySecret(clusterOps, cluster.Spec.SSHAuthRef, cluster.Spec.SSHAuthRef.Name+timestamp)
+		newSecret, err := c.CopySecret(clusterOps, cluster.Spec.SSHAuthRef, cluster.Spec.SSHAuthRef.Name+timestamp, currentNS)
 		if err != nil {
 			return false, err
 		}


Test patch:
diff --git a/pkg/controllers/clusterops/controller_test.go b/pkg/controllers/clusterops/controller_test.go
index 3f3b9f732..c82cffd80 100644
--- a/pkg/controllers/clusterops/controller_test.go
+++ b/pkg/controllers/clusterops/controller_test.go
@@ -4,6 +4,7 @@ import (
 	"context"
 	"encoding/base64"
 	"fmt"
+	"os"
 	"strings"
 	"testing"
 	"time"
@@ -408,6 +409,7 @@ func TestController_SetOwnerReferences(t *testing.T) {
 }
 
 func TestNewKubesprayJob(t *testing.T) {
+	os.Setenv("POD_NAMESPACE", "mynamespace")
 	controller := Controller{
 		Client:                newFakeClient(),
 		ClientSet:             clientsetfake.NewSimpleClientset(),
@@ -1282,7 +1284,7 @@ func Test_CopyConfigMap(t *testing.T) {
 						Labels: map[string]string{constants.KubeanClusterLabelKey: "kubeanCluster-123"},
 					},
 				}
-				_, err := controller.CopyConfigMap(clusterOps, &apis.ConfigMapRef{}, "")
+				_, err := controller.CopyConfigMap(clusterOps, &apis.ConfigMapRef{}, "", "")
 				return err != nil && apierrors.IsNotFound(err)
 			},
 			want: true,
@@ -1311,7 +1313,7 @@ func Test_CopyConfigMap(t *testing.T) {
 					},
 				}
 				controller.ClientSet.CoreV1().ConfigMaps("kubean-system").Create(context.Background(), configMap, metav1.CreateOptions{})
-				result, _ := controller.CopyConfigMap(clusterOps, &apis.ConfigMapRef{NameSpace: "kubean-system", Name: "a-configmap"}, "b-configmap")
+				result, _ := controller.CopyConfigMap(clusterOps, &apis.ConfigMapRef{NameSpace: "kubean-system", Name: "a-configmap"}, "b-configmap", "")
 				return result.Name == "b-configmap"
 			},
 			want: true,
@@ -1351,7 +1353,7 @@ func Test_CopySecret(t *testing.T) {
 						Labels: map[string]string{constants.KubeanClusterLabelKey: "kubeanCluster-123"},
 					},
 				}
-				_, err := controller.CopySecret(clusterOps, &apis.SecretRef{}, "")
+				_, err := controller.CopySecret(clusterOps, &apis.SecretRef{}, "", "")
 				return err != nil && apierrors.IsNotFound(err)
 			},
 			want: true,
@@ -1380,7 +1382,7 @@ func Test_CopySecret(t *testing.T) {
 					},
 				}
 				controller.ClientSet.CoreV1().Secrets("kubean-system").Create(context.Background(), secret, metav1.CreateOptions{})
-				result, _ := controller.CopySecret(clusterOps, &apis.SecretRef{NameSpace: "kubean-system", Name: "a-secret"}, "b-secret")
+				result, _ := controller.CopySecret(clusterOps, &apis.SecretRef{NameSpace: "kubean-system", Name: "a-secret"}, "b-secret", "")
 				return result.Name == "b-secret"
 			},
 			want: true,