diff --git a/pkg/karmadactl/cmdinit/bootstraptoken/agent/tlsbootstrap.go b/pkg/karmadactl/cmdinit/bootstraptoken/agent/tlsbootstrap.go index f181dec70..4e5671473 100644 --- a/pkg/karmadactl/cmdinit/bootstraptoken/agent/tlsbootstrap.go +++ b/pkg/karmadactl/cmdinit/bootstraptoken/agent/tlsbootstrap.go @@ -6,6 +6,7 @@ import ( "k8s.io/klog/v2" "github.com/karmada-io/karmada/pkg/karmadactl/cmdinit/utils" + cmdutil "github.com/karmada-io/karmada/pkg/karmadactl/util" ) const ( @@ -38,7 +39,7 @@ func AllowBootstrapTokensToPostCSRs(clientSet *kubernetes.Clientset) error { Name: KarmadaAgentBootstrapTokenAuthGroup, }, }, nil) - return utils.CreateIfNotExistClusterRoleBinding(clientSet, clusterRoleBinding) + return cmdutil.CreateOrUpdateClusterRoleBinding(clientSet, clusterRoleBinding) } // AutoApproveKarmadaAgentBootstrapTokens creates RBAC rules in a way that makes Karmada Agent Bootstrap Tokens' CSR auto-approved by the csrapprover controller @@ -52,7 +53,7 @@ func AutoApproveKarmadaAgentBootstrapTokens(clientSet *kubernetes.Clientset) err Name: KarmadaAgentBootstrapTokenAuthGroup, }, }, nil) - return utils.CreateIfNotExistClusterRoleBinding(clientSet, clusterRoleBinding) + return cmdutil.CreateOrUpdateClusterRoleBinding(clientSet, clusterRoleBinding) } // AutoApproveAgentCertificateRotation creates RBAC rules in a way that makes Agent certificate rotation CSR auto-approved by the csrapprover controller @@ -66,5 +67,5 @@ func AutoApproveAgentCertificateRotation(clientSet *kubernetes.Clientset) error Name: KarmadaAgentGroup, }, }, nil) - return utils.CreateIfNotExistClusterRoleBinding(clientSet, clusterRoleBinding) + return cmdutil.CreateOrUpdateClusterRoleBinding(clientSet, clusterRoleBinding) } diff --git a/pkg/karmadactl/cmdinit/bootstraptoken/clusterinfo/clusterinfo.go b/pkg/karmadactl/cmdinit/bootstraptoken/clusterinfo/clusterinfo.go index ef4316c57..51ac3f9d3 100644 --- a/pkg/karmadactl/cmdinit/bootstraptoken/clusterinfo/clusterinfo.go +++ b/pkg/karmadactl/cmdinit/bootstraptoken/clusterinfo/clusterinfo.go @@ -60,7 +60,7 @@ func CreateBootstrapConfigMapIfNotExists(clientSet *kubernetes.Clientset, file s // CreateClusterInfoRBACRules creates the RBAC rules for exposing the cluster-info ConfigMap in the kube-public namespace to unauthenticated users func CreateClusterInfoRBACRules(clientSet *kubernetes.Clientset) error { - klog.V(1).Infoln("creating the RBAC rules for exposing the cluster-info ConfigMap in the kube-public namespace") + klog.V(1).Info("creating the RBAC rules for exposing the cluster-info ConfigMap in the kube-public namespace") err := cmdutil.CreateOrUpdateRole(clientSet, &rbacv1.Role{ ObjectMeta: metav1.ObjectMeta{ Name: BootstrapSignerClusterRoleName, diff --git a/pkg/karmadactl/cmdinit/karmada/deploy.go b/pkg/karmadactl/cmdinit/karmada/deploy.go index 1068f4b4a..cdd1f7ba4 100644 --- a/pkg/karmadactl/cmdinit/karmada/deploy.go +++ b/pkg/karmadactl/cmdinit/karmada/deploy.go @@ -90,17 +90,18 @@ func InitKarmadaResources(dir, caBase64, systemNamespace string) error { // create webhook configuration // https://github.com/karmada-io/karmada/blob/master/artifacts/deploy/webhook-configuration.yaml klog.Info("Create MutatingWebhookConfiguration mutating-config.") - if err = createMutatingWebhookConfiguration(clientSet, mutatingConfig(caBase64, systemNamespace)); err != nil { + if err = createOrUpdateMutatingWebhookConfiguration(clientSet, mutatingConfig(caBase64, systemNamespace)); err != nil { klog.Exitln(err) } klog.Info("Create ValidatingWebhookConfiguration validating-config.") - if err = createValidatingWebhookConfiguration(clientSet, validatingConfig(caBase64, systemNamespace)); err != nil { + if err = createOrUpdateValidatingWebhookConfiguration(clientSet, validatingConfig(caBase64, systemNamespace)); err != nil { klog.Exitln(err) } // karmada-aggregated-apiserver - if err = initAPIService(clientSet, restConfig, systemNamespace); err != nil { + klog.Info("Create Service 'karmada-aggregated-apiserver' and APIService 'v1alpha1.cluster.karmada.io'.") + if err = initAggregatedAPIService(clientSet, restConfig, systemNamespace); err != nil { klog.Exitln(err) } @@ -250,7 +251,7 @@ func getName(str, start, end string) string { return str } -func initAPIService(clientSet *kubernetes.Clientset, restConfig *rest.Config, systemNamespace string) error { +func initAggregatedAPIService(clientSet *kubernetes.Clientset, restConfig *rest.Config, systemNamespace string) error { // https://github.com/karmada-io/karmada/blob/master/artifacts/deploy/karmada-aggregated-apiserver-apiservice.yaml aaService := &corev1.Service{ TypeMeta: metav1.TypeMeta{ @@ -299,7 +300,6 @@ func initAPIService(clientSet *kubernetes.Clientset, restConfig *rest.Config, sy }, } - klog.Infof("Create APIService '%s'", aaAPIServiceObjName) if err = cmdutil.CreateOrUpdateAPIService(apiRegistrationClient, aaAPIService); err != nil { return err } diff --git a/pkg/karmadactl/cmdinit/karmada/rbac.go b/pkg/karmadactl/cmdinit/karmada/rbac.go index 0d2e3f2a0..57b2cdab1 100644 --- a/pkg/karmadactl/cmdinit/karmada/rbac.go +++ b/pkg/karmadactl/cmdinit/karmada/rbac.go @@ -3,8 +3,10 @@ package karmada import ( rbacv1 "k8s.io/api/rbac/v1" "k8s.io/client-go/kubernetes" + "k8s.io/klog/v2" "github.com/karmada-io/karmada/pkg/karmadactl/cmdinit/utils" + cmdutil "github.com/karmada-io/karmada/pkg/karmadactl/util" ) const ( @@ -21,7 +23,7 @@ func grantProxyPermissionToAdmin(clientSet kubernetes.Interface) error { Verbs: []string{"*"}, }, }, nil) - err := utils.CreateIfNotExistClusterRole(clientSet, proxyAdminClusterRole) + err := cmdutil.CreateOrUpdateClusterRole(clientSet, proxyAdminClusterRole) if err != nil { return err } @@ -32,7 +34,9 @@ func grantProxyPermissionToAdmin(clientSet kubernetes.Interface) error { Kind: "User", Name: clusterProxyAdminUser, }}, nil) - err = utils.CreateIfNotExistClusterRoleBinding(clientSet, proxyAdminClusterRoleBinding) + + klog.V(1).Info("grant cluster proxy permission to 'system:admin'") + err = cmdutil.CreateOrUpdateClusterRoleBinding(clientSet, proxyAdminClusterRoleBinding) if err != nil { return err } @@ -40,7 +44,7 @@ func grantProxyPermissionToAdmin(clientSet kubernetes.Interface) error { return nil } -// grantAccessPermissionToAgent grants the limited access permmission to 'karmada-agent' +// grantAccessPermissionToAgent grants the limited access permission to 'karmada-agent' func grantAccessPermissionToAgent(clientSet kubernetes.Interface) error { clusterRole := utils.ClusterRoleFromRules(karmadaAgentAccessClusterRole, []rbacv1.PolicyRule{ { @@ -104,7 +108,7 @@ func grantAccessPermissionToAgent(clientSet kubernetes.Interface) error { Verbs: []string{"create", "patch", "update"}, }, }, nil) - err := utils.CreateIfNotExistClusterRole(clientSet, clusterRole) + err := cmdutil.CreateOrUpdateClusterRole(clientSet, clusterRole) if err != nil { return err } @@ -115,7 +119,9 @@ func grantAccessPermissionToAgent(clientSet kubernetes.Interface) error { Kind: rbacv1.GroupKind, Name: karmadaAgentGroup, }}, nil) - err = utils.CreateIfNotExistClusterRoleBinding(clientSet, clusterRoleBinding) + + klog.V(1).Info("grant the limited access permission to 'karmada-agent'") + err = cmdutil.CreateOrUpdateClusterRoleBinding(clientSet, clusterRoleBinding) if err != nil { return err } diff --git a/pkg/karmadactl/cmdinit/karmada/webhook_configuration.go b/pkg/karmadactl/cmdinit/karmada/webhook_configuration.go index c155a541b..85aa7b9f4 100644 --- a/pkg/karmadactl/cmdinit/karmada/webhook_configuration.go +++ b/pkg/karmadactl/cmdinit/karmada/webhook_configuration.go @@ -160,7 +160,7 @@ webhooks: timeoutSeconds: 3`, systemNamespace, caBundle) } -func createValidatingWebhookConfiguration(c kubernetes.Interface, staticYaml string) error { +func createOrUpdateValidatingWebhookConfiguration(c kubernetes.Interface, staticYaml string) error { obj := admissionregistrationv1.ValidatingWebhookConfiguration{} if err := json.Unmarshal(utils.StaticYamlToJSONByte(staticYaml), &obj); err != nil { @@ -172,15 +172,24 @@ func createValidatingWebhookConfiguration(c kubernetes.Interface, staticYaml str if !apierrors.IsAlreadyExists(err) { return err } - klog.Infof("ValidatingWebhookConfiguration %s already exists, skipping.", obj.Name) - return nil + + existVwc, err := c.AdmissionregistrationV1().ValidatingWebhookConfigurations().Get(context.TODO(), obj.Name, metav1.GetOptions{}) + if err != nil { + return err + } + + obj.ResourceVersion = existVwc.ResourceVersion + + if _, err := c.AdmissionregistrationV1().ValidatingWebhookConfigurations().Update(context.TODO(), &obj, metav1.UpdateOptions{}); err != nil { + return err + } } - klog.Infof("Create ValidatingWebhookConfiguration %s successfully.", obj.Name) + klog.Infof("ValidatingWebhookConfiguration %s has been created or updated successfully.", obj.Name) return nil } -func createMutatingWebhookConfiguration(c kubernetes.Interface, staticYaml string) error { +func createOrUpdateMutatingWebhookConfiguration(c kubernetes.Interface, staticYaml string) error { obj := admissionregistrationv1.MutatingWebhookConfiguration{} if err := json.Unmarshal(utils.StaticYamlToJSONByte(staticYaml), &obj); err != nil { @@ -192,10 +201,19 @@ func createMutatingWebhookConfiguration(c kubernetes.Interface, staticYaml strin 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) + existMwc, err := c.AdmissionregistrationV1().MutatingWebhookConfigurations().Get(context.TODO(), obj.Name, metav1.GetOptions{}) + if err != nil { + return err + } + + obj.ResourceVersion = existMwc.ResourceVersion + + if _, err := c.AdmissionregistrationV1().MutatingWebhookConfigurations().Update(context.TODO(), &obj, metav1.UpdateOptions{}); err != nil { + return err + } + } + klog.Infof("MutatingWebhookConfiguration %s has been created or updated successfully.", obj.Name) + return nil } diff --git a/pkg/karmadactl/cmdinit/karmada/webhook_configuration_test.go b/pkg/karmadactl/cmdinit/karmada/webhook_configuration_test.go index ae2be11c6..2f7050f7e 100644 --- a/pkg/karmadactl/cmdinit/karmada/webhook_configuration_test.go +++ b/pkg/karmadactl/cmdinit/karmada/webhook_configuration_test.go @@ -7,24 +7,24 @@ import ( "k8s.io/client-go/kubernetes/fake" ) -func Test_createValidatingWebhookConfiguration(t *testing.T) { +func Test_createOrUpdateValidatingWebhookConfiguration(t *testing.T) { client := fake.NewSimpleClientset() cfg := validatingConfig(base64.StdEncoding.EncodeToString([]byte("foo")), "bar") if cfg == "" { t.Errorf("validatingConfig() return = %v, want yaml config", cfg) } - if err := createValidatingWebhookConfiguration(client, cfg); err != nil { - t.Errorf("createValidatingWebhookConfiguration() return = %v, want no error", err) + if err := createOrUpdateValidatingWebhookConfiguration(client, cfg); err != nil { + t.Errorf("createOrUpdateValidatingWebhookConfiguration() return = %v, want no error", err) } } -func Test_createMutatingWebhookConfiguration(t *testing.T) { +func Test_createOrUpdateMutatingWebhookConfiguration(t *testing.T) { client := fake.NewSimpleClientset() cfg := mutatingConfig(base64.StdEncoding.EncodeToString([]byte("foo")), "bar") if cfg == "" { t.Errorf("mutatingConfig() return = %v, want yaml config", cfg) } - if err := createMutatingWebhookConfiguration(client, cfg); err != nil { - t.Errorf("createMutatingWebhookConfiguration() return = %v, want no error", err) + if err := createOrUpdateMutatingWebhookConfiguration(client, cfg); err != nil { + t.Errorf("createOrUpdateMutatingWebhookConfiguration() return = %v, want no error", err) } } diff --git a/pkg/karmadactl/cmdinit/utils/rbac.go b/pkg/karmadactl/cmdinit/utils/rbac.go index 1d102c82a..904dcdeed 100644 --- a/pkg/karmadactl/cmdinit/utils/rbac.go +++ b/pkg/karmadactl/cmdinit/utils/rbac.go @@ -1,14 +1,8 @@ package utils import ( - "context" - "fmt" - 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" - "k8s.io/klog/v2" ) // ClusterRoleFromRules ClusterRole Rules @@ -45,45 +39,3 @@ func ClusterRoleBindingFromSubjects(clusterRoleBindingName, clusterRoleName stri Subjects: sub, } } - -// CreateIfNotExistClusterRole create ClusterRole when it doesn't exist -func CreateIfNotExistClusterRole(clientSet kubernetes.Interface, role *rbacv1.ClusterRole) error { - clusterRoleClient := clientSet.RbacV1().ClusterRoles() - _, err := clusterRoleClient.Get(context.TODO(), role.Name, metav1.GetOptions{}) - if err != nil { - if apierrors.IsNotFound(err) { - _, err = clusterRoleClient.Create(context.TODO(), role, metav1.CreateOptions{}) - if err != nil { - return fmt.Errorf("create ClusterRole %s failed: %v", role.Name, err) - } - - klog.Infof("CreateClusterRole %s success.", role.Name) - return nil - } - return fmt.Errorf("get ClusterRole %s failed: %v", role.Name, err) - } - klog.Infof("CreateClusterRole %s already exists.", role.Name) - - return nil -} - -// CreateIfNotExistClusterRoleBinding create ClusterRoleBinding when it doesn't exist -func CreateIfNotExistClusterRoleBinding(clientSet kubernetes.Interface, binding *rbacv1.ClusterRoleBinding) error { - crbClient := clientSet.RbacV1().ClusterRoleBindings() - _, err := crbClient.Get(context.TODO(), binding.Name, metav1.GetOptions{}) - if err != nil { - if apierrors.IsNotFound(err) { - _, err = crbClient.Create(context.TODO(), binding, metav1.CreateOptions{}) - if err != nil { - return fmt.Errorf("create ClusterRoleBinding %s failed: %v", binding.Name, err) - } - - klog.Infof("CreateClusterRoleBinding %s success.", binding.Name) - return nil - } - return fmt.Errorf("get ClusterRoleBinding %s failed: %v", binding.Name, err) - } - klog.Infof("CreateClusterRoleBinding %s already exists.", binding.Name) - - return nil -} diff --git a/pkg/karmadactl/util/idempotency.go b/pkg/karmadactl/util/idempotency.go index f0ba77cc7..544a63b15 100644 --- a/pkg/karmadactl/util/idempotency.go +++ b/pkg/karmadactl/util/idempotency.go @@ -16,7 +16,8 @@ import ( aggregator "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset" ) -// CreateService creates a Service if the target resource doesn't exist. If the resource exists already, return directly +// CreateService creates a Service if the target resource doesn't exist. +// If the resource exists already, return directly func CreateService(client kubeclient.Interface, service *corev1.Service) error { if _, err := client.CoreV1().Services(service.ObjectMeta.Namespace).Create(context.TODO(), service, metav1.CreateOptions{}); err != nil { if !apierrors.IsAlreadyExists(err) { @@ -28,7 +29,8 @@ func CreateService(client kubeclient.Interface, service *corev1.Service) error { return nil } -// CreateOrUpdateSecret creates a Secret if the target resource doesn't exist. If the resource exists already, this function will update the resource instead. +// CreateOrUpdateSecret creates a Secret if the target resource doesn't exist. +// If the resource exists already, this function will update the resource instead. func CreateOrUpdateSecret(client kubeclient.Interface, secret *corev1.Secret) error { if _, err := client.CoreV1().Secrets(secret.Namespace).Create(context.TODO(), secret, metav1.CreateOptions{}); err != nil { if !apierrors.IsAlreadyExists(err) { @@ -49,7 +51,8 @@ func CreateOrUpdateSecret(client kubeclient.Interface, secret *corev1.Secret) er return nil } -// CreateOrUpdateDeployment creates a Deployment if the target resource doesn't exist. If the resource exists already, this function will update the resource instead. +// CreateOrUpdateDeployment creates a Deployment if the target resource doesn't exist. +// If the resource exists already, this function will update the resource instead. func CreateOrUpdateDeployment(client kubeclient.Interface, deploy *appsv1.Deployment) error { if _, err := client.AppsV1().Deployments(deploy.Namespace).Create(context.TODO(), deploy, metav1.CreateOptions{}); err != nil { if !apierrors.IsAlreadyExists(err) { @@ -70,7 +73,8 @@ func CreateOrUpdateDeployment(client kubeclient.Interface, deploy *appsv1.Deploy return nil } -// CreateOrUpdateAPIService creates a ApiService if the target resource doesn't exist. If the resource exists already, this function will update the resource instead. +// CreateOrUpdateAPIService creates a ApiService if the target resource doesn't exist. +// If the resource exists already, this function will update the resource instead. func CreateOrUpdateAPIService(apiRegistrationClient *aggregator.Clientset, apiservice *apiregistrationv1.APIService) error { if _, err := apiRegistrationClient.ApiregistrationV1().APIServices().Create(context.TODO(), apiservice, metav1.CreateOptions{}); err != nil { if !apierrors.IsAlreadyExists(err) { @@ -93,7 +97,8 @@ func CreateOrUpdateAPIService(apiRegistrationClient *aggregator.Clientset, apise return nil } -// CreateOrUpdateRole creates a Role if the target resource doesn't exist. If the resource exists already, this function will update the resource instead. +// CreateOrUpdateRole creates a Role if the target resource doesn't exist. +// If the resource exists already, this function will update the resource instead. func CreateOrUpdateRole(client kubeclient.Interface, role *rbacv1.Role) error { if _, err := client.RbacV1().Roles(role.ObjectMeta.Namespace).Create(context.TODO(), role, metav1.CreateOptions{}); err != nil { if !apierrors.IsAlreadyExists(err) { @@ -111,12 +116,13 @@ func CreateOrUpdateRole(client kubeclient.Interface, role *rbacv1.Role) error { return fmt.Errorf("unable to update RBAC role: %v", err) } } - klog.V(2).Infof("Role %s%s has been created or updated.", role.ObjectMeta.Namespace, role.ObjectMeta.Name) + klog.V(2).Infof("Role %s/%s has been created or updated.", role.ObjectMeta.Namespace, role.ObjectMeta.Name) return nil } -// CreateOrUpdateRoleBinding creates a RoleBinding if the target resource doesn't exist. If the resource exists already, this function will update the resource instead. +// CreateOrUpdateRoleBinding creates a RoleBinding if the target resource doesn't exist. +// If the resource exists already, this function will update the resource instead. func CreateOrUpdateRoleBinding(client kubeclient.Interface, roleBinding *rbacv1.RoleBinding) error { if _, err := client.RbacV1().RoleBindings(roleBinding.ObjectMeta.Namespace).Create(context.TODO(), roleBinding, metav1.CreateOptions{}); err != nil { if !apierrors.IsAlreadyExists(err) { @@ -139,7 +145,56 @@ func CreateOrUpdateRoleBinding(client kubeclient.Interface, roleBinding *rbacv1. return nil } -// CreateOrUpdateConfigMap creates a ConfigMap if the target resource doesn't exist. If the resource exists already, this function will update the resource instead. +// CreateOrUpdateClusterRole creates a ClusterRole if the target resource doesn't exist. +// If the resource exists already, this function will update the resource instead. +func CreateOrUpdateClusterRole(client kubeclient.Interface, clusterRole *rbacv1.ClusterRole) error { + if _, err := client.RbacV1().ClusterRoles().Create(context.TODO(), clusterRole, metav1.CreateOptions{}); err != nil { + if !apierrors.IsAlreadyExists(err) { + return fmt.Errorf("unable to create ClusterRole: %v", err) + } + + existClusterRole, err := client.RbacV1().ClusterRoles().Get(context.TODO(), clusterRole.Name, metav1.GetOptions{}) + if err != nil { + return err + } + + clusterRole.ResourceVersion = existClusterRole.ResourceVersion + + if _, err := client.RbacV1().ClusterRoles().Update(context.TODO(), clusterRole, metav1.UpdateOptions{}); err != nil { + return fmt.Errorf("unable to update ClusterRole: %v", err) + } + } + klog.V(2).Infof("ClusterRole %s has been created or updated.", clusterRole.Name) + + return nil +} + +// CreateOrUpdateClusterRoleBinding creates a ClusterRoleBinding if the target resource doesn't exist. +// If the resource exists already, this function will update the resource instead. +func CreateOrUpdateClusterRoleBinding(client kubernetes.Interface, clusterRoleBinding *rbacv1.ClusterRoleBinding) error { + if _, err := client.RbacV1().ClusterRoleBindings().Create(context.TODO(), clusterRoleBinding, metav1.CreateOptions{}); err != nil { + if !apierrors.IsAlreadyExists(err) { + return fmt.Errorf("unable to create ClusterRoleBinding: %v", err) + } + + existCrb, err := client.RbacV1().ClusterRoleBindings().Get(context.TODO(), clusterRoleBinding.Name, metav1.GetOptions{}) + if err != nil { + return err + } + + clusterRoleBinding.ResourceVersion = existCrb.ResourceVersion + + if _, err := client.RbacV1().ClusterRoleBindings().Update(context.TODO(), clusterRoleBinding, metav1.UpdateOptions{}); err != nil { + return fmt.Errorf("unable to update ClusterRolebinding: %v", err) + } + } + klog.V(2).Infof("ClusterRolebinding %s has been created or updated.", clusterRoleBinding.Name) + + return nil +} + +// CreateOrUpdateConfigMap creates a ConfigMap if the target resource doesn't exist. +// If the resource exists already, this function will update the resource instead. func CreateOrUpdateConfigMap(client *kubeclient.Clientset, cm *corev1.ConfigMap) error { if _, err := client.CoreV1().ConfigMaps(cm.ObjectMeta.Namespace).Create(context.TODO(), cm, metav1.CreateOptions{}); err != nil { if !apierrors.IsAlreadyExists(err) { @@ -171,7 +226,8 @@ func NewNamespace(name string) *corev1.Namespace { } } -// CreateOrUpdateNamespace creates a Namespaces if the target resource doesn't exist. If the resource exists already, this function will update the resource instead. +// 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) { @@ -194,7 +250,8 @@ func CreateOrUpdateNamespace(client kubeclient.Interface, ns *corev1.Namespace) 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. +// 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) {