From 9b1baeb1d79ce70758b07efd82d9bedc2be9c46b Mon Sep 17 00:00:00 2001 From: cleverhu Date: Sun, 11 Sep 2022 13:56:23 +0800 Subject: [PATCH] fix namespace already exist Signed-off-by: cleverhu --- pkg/karmadactl/cmdinit/karmada/deploy.go | 37 +++++++----- .../cmdinit/karmada/webhook_configuration.go | 17 +++++- pkg/karmadactl/cmdinit/kubernetes/deploy.go | 9 +-- .../cmdinit/kubernetes/namespace.go | 38 ------------- pkg/karmadactl/util/idempotency.go | 56 +++++++++++++++++++ 5 files changed, 99 insertions(+), 58 deletions(-) delete mode 100644 pkg/karmadactl/cmdinit/kubernetes/namespace.go diff --git a/pkg/karmadactl/cmdinit/karmada/deploy.go b/pkg/karmadactl/cmdinit/karmada/deploy.go index 254ba9a39..1df24dccd 100644 --- a/pkg/karmadactl/cmdinit/karmada/deploy.go +++ b/pkg/karmadactl/cmdinit/karmada/deploy.go @@ -14,6 +14,7 @@ import ( corev1 "k8s.io/api/core/v1" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/kubernetes" @@ -22,10 +23,12 @@ import ( apiregistrationv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1" "sigs.k8s.io/yaml" + clusterv1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1" bootstrapagent "github.com/karmada-io/karmada/pkg/karmadactl/cmdinit/bootstraptoken/agent" "github.com/karmada-io/karmada/pkg/karmadactl/cmdinit/bootstraptoken/clusterinfo" "github.com/karmada-io/karmada/pkg/karmadactl/cmdinit/options" "github.com/karmada-io/karmada/pkg/karmadactl/cmdinit/utils" + "github.com/karmada-io/karmada/pkg/karmadactl/util" "github.com/karmada-io/karmada/pkg/karmadactl/util/apiclient" tokenutil "github.com/karmada-io/karmada/pkg/karmadactl/util/bootstraptoken" ) @@ -33,6 +36,8 @@ import ( const ( clusterProxyAdminRole = "cluster-proxy-admin" clusterProxyAdminUser = "system:admin" + + aggregatedApiserverServiceName = "karmada-aggregated-apiserver" ) // InitKarmadaResources Initialize karmada resource @@ -48,11 +53,7 @@ func InitKarmadaResources(dir, caBase64, systemNamespace string) error { } // create namespace - if _, err := clientSet.CoreV1().Namespaces().Create(context.TODO(), &corev1.Namespace{ - ObjectMeta: metav1.ObjectMeta{ - Name: systemNamespace, - }, - }, metav1.CreateOptions{}); err != nil { + if err := util.CreateOrUpdateNamespace(clientSet, util.NewNamespace(systemNamespace)); err != nil { klog.Exitln(err) } @@ -91,8 +92,8 @@ func InitKarmadaResources(dir, caBase64, systemNamespace string) error { if err = createMutatingWebhookConfiguration(clientSet, mutatingConfig(caBase64, systemNamespace)); err != nil { klog.Exitln(err) } - klog.Info("Create ValidatingWebhookConfiguration validating-config.") + klog.Info("Create ValidatingWebhookConfiguration validating-config.") if err = createValidatingWebhookConfiguration(clientSet, validatingConfig(caBase64, systemNamespace)); err != nil { klog.Exitln(err) } @@ -208,10 +209,17 @@ func createCRDs(crdClient *clientset.Clientset, filename string) error { return err } + klog.Infof("Attempting to create CRD") crd := crdClient.ApiextensionsV1().CustomResourceDefinitions() if _, err := crd.Create(context.TODO(), &obj, metav1.CreateOptions{}); err != nil { - return err + if !apierrors.IsAlreadyExists(err) { + return err + } + klog.Infof("CRD %s already exists, skipping.", obj.Name) + return nil } + + klog.Infof("Create CRD %s successfully.", obj.Name) return nil } @@ -249,17 +257,18 @@ func initAPIService(clientSet *kubernetes.Clientset, restConfig *rest.Config, sy Kind: "Service", }, ObjectMeta: metav1.ObjectMeta{ - Name: "karmada-aggregated-apiserver", + Name: aggregatedApiserverServiceName, Namespace: systemNamespace, }, Spec: corev1.ServiceSpec{ Type: corev1.ServiceTypeExternalName, - ExternalName: fmt.Sprintf("karmada-aggregated-apiserver.%s.svc", systemNamespace), + ExternalName: fmt.Sprintf("%s.%s.svc", aggregatedApiserverServiceName, systemNamespace), }, } - if _, err := clientSet.CoreV1().Services(systemNamespace).Create(context.TODO(), aaService, metav1.CreateOptions{}); err != nil { + if err := util.CreateOrUpdateService(clientSet, aaService); err != nil { return err } + // new apiRegistrationClient apiRegistrationClient, err := apiclient.NewAPIRegistrationClient(restConfig) if err != nil { @@ -278,13 +287,13 @@ func initAPIService(clientSet *kubernetes.Clientset, restConfig *rest.Config, sy }, Spec: apiregistrationv1.APIServiceSpec{ InsecureSkipTLSVerify: true, - Group: "cluster.karmada.io", + Group: clusterv1alpha1.GroupName, GroupPriorityMinimum: 2000, Service: &apiregistrationv1.ServiceReference{ - Name: "karmada-aggregated-apiserver", - Namespace: systemNamespace, + Name: aaService.Name, + Namespace: aaService.Namespace, }, - Version: "v1alpha1", + Version: clusterv1alpha1.GroupVersion.Version, VersionPriority: 10, }, } diff --git a/pkg/karmadactl/cmdinit/karmada/webhook_configuration.go b/pkg/karmadactl/cmdinit/karmada/webhook_configuration.go index 167e3dce5..c155a541b 100644 --- a/pkg/karmadactl/cmdinit/karmada/webhook_configuration.go +++ b/pkg/karmadactl/cmdinit/karmada/webhook_configuration.go @@ -6,6 +6,7 @@ import ( "fmt" admissionregistrationv1 "k8s.io/api/admissionregistration/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" "k8s.io/klog/v2" @@ -168,8 +169,14 @@ func createValidatingWebhookConfiguration(c kubernetes.Interface, staticYaml str } if _, err := c.AdmissionregistrationV1().ValidatingWebhookConfigurations().Create(context.TODO(), &obj, metav1.CreateOptions{}); err != nil { - return err + if !apierrors.IsAlreadyExists(err) { + return err + } + klog.Infof("ValidatingWebhookConfiguration %s already exists, skipping.", obj.Name) + return nil } + klog.Infof("Create ValidatingWebhookConfiguration %s successfully.", obj.Name) + return nil } @@ -182,7 +189,13 @@ func createMutatingWebhookConfiguration(c kubernetes.Interface, staticYaml strin } if _, err := c.AdmissionregistrationV1().MutatingWebhookConfigurations().Create(context.TODO(), &obj, metav1.CreateOptions{}); err != nil { - return err + if !apierrors.IsAlreadyExists(err) { + return err + } + klog.Infof("MutatingWebhookConfiguration %s already exists, skipping.", obj.Name) + return nil } + + klog.Infof("Create MutatingWebhookConfiguration %s successfully.", obj.Name) return nil } diff --git a/pkg/karmadactl/cmdinit/kubernetes/deploy.go b/pkg/karmadactl/cmdinit/kubernetes/deploy.go index ab20bac76..7bd0fe4cf 100644 --- a/pkg/karmadactl/cmdinit/kubernetes/deploy.go +++ b/pkg/karmadactl/cmdinit/kubernetes/deploy.go @@ -23,6 +23,7 @@ import ( "github.com/karmada-io/karmada/pkg/karmadactl/cmdinit/karmada" "github.com/karmada-io/karmada/pkg/karmadactl/cmdinit/options" "github.com/karmada-io/karmada/pkg/karmadactl/cmdinit/utils" + "github.com/karmada-io/karmada/pkg/karmadactl/util" "github.com/karmada-io/karmada/pkg/karmadactl/util/apiclient" ) @@ -176,7 +177,7 @@ func initializeDirectory(path string) error { return err } } - if err := os.MkdirAll(path, os.FileMode(0755)); err != nil { + if err := os.MkdirAll(path, os.FileMode(0o755)); err != nil { return fmt.Errorf("failed to create directory: %s, error: %v", path, err) } @@ -187,7 +188,7 @@ func initializeDirectory(path string) error { func (i *CommandInitOption) genCerts() error { notAfter := time.Now().Add(cert.Duration365d).UTC() - var etcdServerCertDNS = []string{ + etcdServerCertDNS := []string{ "localhost", } for number := int32(0); number < i.EtcdReplicas; number++ { @@ -200,7 +201,7 @@ func (i *CommandInitOption) genCerts() error { etcdServerCertConfig := cert.NewCertConfig("karmada-etcd-server", []string{}, etcdServerAltNames, ¬After) etcdClientCertCfg := cert.NewCertConfig("karmada-etcd-client", []string{}, certutil.AltNames{}, ¬After) - var karmadaDNS = []string{ + karmadaDNS := []string{ "localhost", "kubernetes", "kubernetes.default", @@ -441,7 +442,7 @@ func (i *CommandInitOption) RunInit(parentCommand string) error { } // Create ns - if err := i.CreateNamespace(); err != nil { + if err := util.CreateOrUpdateNamespace(i.KubeClientSet, util.NewNamespace(i.Namespace)); err != nil { return fmt.Errorf("create namespace %s failed: %v", i.Namespace, err) } diff --git a/pkg/karmadactl/cmdinit/kubernetes/namespace.go b/pkg/karmadactl/cmdinit/kubernetes/namespace.go deleted file mode 100644 index 13a54e665..000000000 --- a/pkg/karmadactl/cmdinit/kubernetes/namespace.go +++ /dev/null @@ -1,38 +0,0 @@ -package kubernetes - -import ( - "context" - - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/klog/v2" -) - -// CreateNamespace namespace IfNotExist -func (i *CommandInitOption) CreateNamespace() error { - namespaceClient := i.KubeClientSet.CoreV1().Namespaces() - namespaceList, err := namespaceClient.List(context.TODO(), metav1.ListOptions{}) - if err != nil { - return err - } - - for _, nsList := range namespaceList.Items { - if i.Namespace == nsList.Name { - klog.Infof("Namespace %s already exists.", i.Namespace) - return nil - } - } - - n := &corev1.Namespace{ - ObjectMeta: metav1.ObjectMeta{ - Name: i.Namespace, - }, - } - - _, err = namespaceClient.Create(context.TODO(), n, metav1.CreateOptions{}) - if err != nil { - return err - } - klog.Infof("Create Namespace '%s' successfully.", i.Namespace) - return nil -} diff --git a/pkg/karmadactl/util/idempotency.go b/pkg/karmadactl/util/idempotency.go index d49030d41..fc2c322ee 100644 --- a/pkg/karmadactl/util/idempotency.go +++ b/pkg/karmadactl/util/idempotency.go @@ -9,6 +9,7 @@ import ( rbacv1 "k8s.io/api/rbac/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" kubeclient "k8s.io/client-go/kubernetes" "k8s.io/klog/v2" apiregistrationv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1" @@ -158,3 +159,58 @@ func CreateOrUpdateConfigMap(client *kubeclient.Clientset, cm *corev1.ConfigMap) return nil } + +// NewNamespace generates a new Namespace by given name. +func NewNamespace(name string) *corev1.Namespace { + return &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + } +} + +// CreateOrUpdateNamespace creates a Namespaces if the target resource doesn't exist. If the resource exists already, this function will update the resource instead. +func CreateOrUpdateNamespace(client kubeclient.Interface, ns *corev1.Namespace) error { + if _, err := client.CoreV1().Namespaces().Create(context.TODO(), ns, metav1.CreateOptions{}); err != nil { + if !apierrors.IsAlreadyExists(err) { + return fmt.Errorf("unable to create Namespace: %v", err) + } + + existNs, err := client.CoreV1().Namespaces().Get(context.TODO(), ns.Name, metav1.GetOptions{}) + if err != nil { + return err + } + + ns.ResourceVersion = existNs.ResourceVersion + + if _, err := client.CoreV1().Namespaces().Update(context.TODO(), ns, metav1.UpdateOptions{}); err != nil { + return fmt.Errorf("unable to update Namespace: %v", err) + } + } + klog.Infof("Namespace %s has been created or updated.", ns.ObjectMeta.Name) + + return nil +} + +// CreateOrUpdateService creates a Service if the target resource doesn't exist. If the resource exists already, this function will update the resource instead. +func CreateOrUpdateService(client kubernetes.Interface, svc *corev1.Service) error { + if _, err := client.CoreV1().Services(svc.Namespace).Create(context.TODO(), svc, metav1.CreateOptions{}); err != nil { + if !apierrors.IsAlreadyExists(err) { + return fmt.Errorf("unable to create Service: %v", err) + } + + existSvc, err := client.CoreV1().Services(svc.Namespace).Get(context.TODO(), svc.Name, metav1.GetOptions{}) + if err != nil { + return err + } + + svc.ResourceVersion = existSvc.ResourceVersion + + if _, err := client.CoreV1().Services(svc.ObjectMeta.Namespace).Update(context.TODO(), svc, metav1.UpdateOptions{}); err != nil { + return fmt.Errorf("unable to update Service: %v", err) + } + } + klog.Infof("Service %s/%s has been created or updated.", svc.ObjectMeta.Namespace, svc.ObjectMeta.Name) + + return nil +}