Fix MutatingWebhookConfig and ValidateWebhookConfig aren't updated

Signed-off-by: lonelyCZ <chengzhe@zju.edu.cn>
This commit is contained in:
lonelyCZ 2022-11-18 20:30:14 +08:00
parent 594ad9f44b
commit a239d538d1
8 changed files with 121 additions and 87 deletions

View File

@ -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)
}

View File

@ -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,

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}
klog.Infof("Create ValidatingWebhookConfiguration %s successfully.", obj.Name)
obj.ResourceVersion = existVwc.ResourceVersion
if _, err := c.AdmissionregistrationV1().ValidatingWebhookConfigurations().Update(context.TODO(), &obj, metav1.UpdateOptions{}); err != nil {
return err
}
}
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
existMwc, err := c.AdmissionregistrationV1().MutatingWebhookConfigurations().Get(context.TODO(), obj.Name, metav1.GetOptions{})
if err != nil {
return err
}
klog.Infof("Create MutatingWebhookConfiguration %s successfully.", obj.Name)
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
}

View File

@ -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)
}
}

View File

@ -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
}

View File

@ -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) {