From efdb735750626308108568bb27a91f77b0bf305d Mon Sep 17 00:00:00 2001 From: Stephen Kitt Date: Thu, 19 Dec 2024 11:23:27 +0100 Subject: [PATCH] kubeadm: fix idempotency retain, address deprecation CreateOrRetain is supposed to operate on an object name which isn't necessarily the given object's name (for use in migrations), this restores that feature. Replace all uses of deprecated functions with their generic variants. Providing the context externally isn't useful right now, drop it from the new functions and use context.Background() where needed. Signed-off-by: Stephen Kitt --- cmd/kubeadm/app/discovery/token/token_test.go | 2 +- cmd/kubeadm/app/phases/addons/dns/dns.go | 19 +-- cmd/kubeadm/app/phases/addons/proxy/proxy.go | 12 +- .../bootstraptoken/clusterinfo/clusterinfo.go | 6 +- .../bootstraptoken/node/tlsbootstrap.go | 10 +- .../app/phases/bootstraptoken/node/token.go | 6 +- cmd/kubeadm/app/phases/copycerts/copycerts.go | 6 +- cmd/kubeadm/app/phases/kubelet/config.go | 6 +- .../app/phases/uploadconfig/uploadconfig.go | 6 +- cmd/kubeadm/app/util/apiclient/idempotency.go | 114 ++---------------- .../app/util/apiclient/idempotency_test.go | 6 +- cmd/kubeadm/test/resources/configmap.go | 2 +- 12 files changed, 50 insertions(+), 145 deletions(-) diff --git a/cmd/kubeadm/app/discovery/token/token_test.go b/cmd/kubeadm/app/discovery/token/token_test.go index 2ff433c65c4..908c5716610 100644 --- a/cmd/kubeadm/app/discovery/token/token_test.go +++ b/cmd/kubeadm/app/discovery/token/token_test.go @@ -303,7 +303,7 @@ type fakeConfigMap struct { } func (c *fakeConfigMap) createOrUpdate(client clientset.Interface) error { - return apiclient.CreateOrUpdateConfigMap(client, &v1.ConfigMap{ + return apiclient.CreateOrUpdate(client.CoreV1().ConfigMaps(metav1.NamespacePublic), &v1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: c.name, Namespace: metav1.NamespacePublic, diff --git a/cmd/kubeadm/app/phases/addons/dns/dns.go b/cmd/kubeadm/app/phases/addons/dns/dns.go index f41cf51002b..c84348fa578 100644 --- a/cmd/kubeadm/app/phases/addons/dns/dns.go +++ b/cmd/kubeadm/app/phases/addons/dns/dns.go @@ -189,9 +189,11 @@ func createCoreDNSAddon(deploymentBytes, serviceBytes, configBytes []byte, clien // Assume that migration is always possible, rely on migrateCoreDNSCorefile() to fail if not. canMigrateCorefile := true + configMapClient := client.CoreV1().ConfigMaps(coreDNSConfigMap.GetNamespace()) + if corefile == "" || migration.Default("", corefile) { // If the Corefile is empty or default, the latest default Corefile will be applied - if err := apiclient.CreateOrUpdateConfigMap(client, coreDNSConfigMap); err != nil { + if err := apiclient.CreateOrUpdate(configMapClient, coreDNSConfigMap); err != nil { return err } } else if corefileMigrationRequired { @@ -201,13 +203,13 @@ func createCoreDNSAddon(deploymentBytes, serviceBytes, configBytes []byte, clien // to ignore preflight check errors. canMigrateCorefile = false klog.Warningf("the CoreDNS Configuration was not migrated: %v. The existing CoreDNS Corefile configuration has been retained.", err) - if err := apiclient.CreateOrRetainConfigMap(client, coreDNSConfigMap, kubeadmconstants.CoreDNSConfigMap); err != nil { + if err := apiclient.CreateOrRetain(configMapClient, coreDNSConfigMap, kubeadmconstants.CoreDNSConfigMap); err != nil { return err } } } else { // If the Corefile is modified and doesn't require any migration, it'll be retained for the benefit of the user - if err := apiclient.CreateOrRetainConfigMap(client, coreDNSConfigMap, kubeadmconstants.CoreDNSConfigMap); err != nil { + if err := apiclient.CreateOrRetain(configMapClient, coreDNSConfigMap, kubeadmconstants.CoreDNSConfigMap); err != nil { return err } } @@ -218,7 +220,7 @@ func createCoreDNSAddon(deploymentBytes, serviceBytes, configBytes []byte, clien } // Create the Clusterroles for CoreDNS or update it in case it already exists - if err := apiclient.CreateOrUpdateClusterRole(client, coreDNSClusterRoles); err != nil { + if err := apiclient.CreateOrUpdate(client.RbacV1().ClusterRoles(), coreDNSClusterRoles); err != nil { return err } @@ -228,7 +230,7 @@ func createCoreDNSAddon(deploymentBytes, serviceBytes, configBytes []byte, clien } // Create the Clusterrolebindings for CoreDNS or update it in case it already exists - if err := apiclient.CreateOrUpdateClusterRoleBinding(client, coreDNSClusterRolesBinding); err != nil { + if err := apiclient.CreateOrUpdate(client.RbacV1().ClusterRoleBindings(), coreDNSClusterRolesBinding); err != nil { return err } @@ -238,7 +240,7 @@ func createCoreDNSAddon(deploymentBytes, serviceBytes, configBytes []byte, clien } // Create the ConfigMap for CoreDNS or update it in case it already exists - if err := apiclient.CreateOrUpdateServiceAccount(client, coreDNSServiceAccount); err != nil { + if err := apiclient.CreateOrUpdate(client.CoreV1().ServiceAccounts(coreDNSServiceAccount.GetNamespace()), coreDNSServiceAccount); err != nil { return err } @@ -248,13 +250,14 @@ func createCoreDNSAddon(deploymentBytes, serviceBytes, configBytes []byte, clien } // Create the deployment for CoreDNS or retain it in case the CoreDNS migration has failed during upgrade + deploymentsClient := client.AppsV1().Deployments(coreDNSDeployment.GetNamespace()) if !canMigrateCorefile { - if err := apiclient.CreateOrRetainDeployment(client, coreDNSDeployment, kubeadmconstants.CoreDNSDeploymentName); err != nil { + if err := apiclient.CreateOrRetain(deploymentsClient, coreDNSDeployment, kubeadmconstants.CoreDNSDeploymentName); err != nil { return err } } else { // Create the Deployment for CoreDNS or update it in case it already exists - if err := apiclient.CreateOrUpdateDeployment(client, coreDNSDeployment); err != nil { + if err := apiclient.CreateOrUpdate(deploymentsClient, coreDNSDeployment); err != nil { return err } } diff --git a/cmd/kubeadm/app/phases/addons/proxy/proxy.go b/cmd/kubeadm/app/phases/addons/proxy/proxy.go index 11aa9e5c1b5..ed50f0167cb 100644 --- a/cmd/kubeadm/app/phases/addons/proxy/proxy.go +++ b/cmd/kubeadm/app/phases/addons/proxy/proxy.go @@ -133,19 +133,19 @@ func printOrCreateKubeProxyObjects(cmByte []byte, dsByte []byte, client clientse // Create the objects if printManifest is false if !printManifest { - if err := apiclient.CreateOrUpdateServiceAccount(client, sa); err != nil { + if err := apiclient.CreateOrUpdate(client.CoreV1().ServiceAccounts(sa.GetNamespace()), sa); err != nil { return errors.Wrap(err, "error when creating kube-proxy service account") } - if err := apiclient.CreateOrUpdateClusterRoleBinding(client, crb); err != nil { + if err := apiclient.CreateOrUpdate(client.RbacV1().ClusterRoleBindings(), crb); err != nil { return err } - if err := apiclient.CreateOrUpdateRole(client, role); err != nil { + if err := apiclient.CreateOrUpdate(client.RbacV1().Roles(role.GetNamespace()), role); err != nil { return err } - if err := apiclient.CreateOrUpdateRoleBinding(client, rb); err != nil { + if err := apiclient.CreateOrUpdate(client.RbacV1().RoleBindings(rb.GetNamespace()), rb); err != nil { return err } @@ -243,7 +243,7 @@ func createKubeProxyConfigMap(cfg *kubeadmapi.ClusterConfiguration, localEndpoin } // Create the ConfigMap for kube-proxy or update it in case it already exists - return []byte(""), apiclient.CreateOrUpdateConfigMap(client, kubeproxyConfigMap) + return []byte(""), apiclient.CreateOrUpdate(client.CoreV1().ConfigMaps(kubeproxyConfigMap.GetNamespace()), kubeproxyConfigMap) } func createKubeProxyAddon(cfg *kubeadmapi.ClusterConfiguration, client clientset.Interface, printManifest bool) ([]byte, error) { @@ -269,5 +269,5 @@ func createKubeProxyAddon(cfg *kubeadmapi.ClusterConfiguration, client clientset *env = append(*env, kubeadmutil.MergeKubeadmEnvVars(kubeadmutil.GetProxyEnvVars(nil))...) // Create the DaemonSet for kube-proxy or update it in case it already exists - return []byte(""), apiclient.CreateOrUpdateDaemonSet(client, kubeproxyDaemonSet) + return []byte(""), apiclient.CreateOrUpdate(client.AppsV1().DaemonSets(kubeproxyDaemonSet.GetNamespace()), kubeproxyDaemonSet) } diff --git a/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo/clusterinfo.go b/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo/clusterinfo.go index fd1097dae7f..143f3dc6ae8 100644 --- a/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo/clusterinfo.go +++ b/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo/clusterinfo.go @@ -69,7 +69,7 @@ func CreateBootstrapConfigMapIfNotExists(client clientset.Interface, kubeconfig // Create or update the ConfigMap in the kube-public namespace klog.V(1).Infoln("[bootstrap-token] creating/updating ConfigMap in kube-public namespace") - return apiclient.CreateOrUpdateConfigMap(client, &v1.ConfigMap{ + return apiclient.CreateOrUpdate(client.CoreV1().ConfigMaps(metav1.NamespacePublic), &v1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: bootstrapapi.ConfigMapClusterInfo, Namespace: metav1.NamespacePublic, @@ -83,7 +83,7 @@ func CreateBootstrapConfigMapIfNotExists(client clientset.Interface, kubeconfig // CreateClusterInfoRBACRules creates the RBAC rules for exposing the cluster-info ConfigMap in the kube-public namespace to unauthenticated users func CreateClusterInfoRBACRules(client clientset.Interface) error { klog.V(1).Infoln("creating the RBAC rules for exposing the cluster-info ConfigMap in the kube-public namespace") - err := apiclient.CreateOrUpdateRole(client, &rbac.Role{ + err := apiclient.CreateOrUpdate(client.RbacV1().Roles(metav1.NamespacePublic), &rbac.Role{ ObjectMeta: metav1.ObjectMeta{ Name: BootstrapSignerClusterRoleName, Namespace: metav1.NamespacePublic, @@ -101,7 +101,7 @@ func CreateClusterInfoRBACRules(client clientset.Interface) error { return err } - return apiclient.CreateOrUpdateRoleBinding(client, &rbac.RoleBinding{ + return apiclient.CreateOrUpdate(client.RbacV1().RoleBindings(metav1.NamespacePublic), &rbac.RoleBinding{ ObjectMeta: metav1.ObjectMeta{ Name: BootstrapSignerClusterRoleName, Namespace: metav1.NamespacePublic, diff --git a/cmd/kubeadm/app/phases/bootstraptoken/node/tlsbootstrap.go b/cmd/kubeadm/app/phases/bootstraptoken/node/tlsbootstrap.go index 19a3eb63c94..72154c9ecde 100644 --- a/cmd/kubeadm/app/phases/bootstraptoken/node/tlsbootstrap.go +++ b/cmd/kubeadm/app/phases/bootstraptoken/node/tlsbootstrap.go @@ -31,7 +31,7 @@ import ( func AllowBootstrapTokensToPostCSRs(client clientset.Interface) error { fmt.Println("[bootstrap-token] Configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials") - return apiclient.CreateOrUpdateClusterRoleBinding(client, &rbac.ClusterRoleBinding{ + return apiclient.CreateOrUpdate(client.RbacV1().ClusterRoleBindings(), &rbac.ClusterRoleBinding{ ObjectMeta: metav1.ObjectMeta{ Name: constants.NodeKubeletBootstrap, }, @@ -53,7 +53,7 @@ func AllowBootstrapTokensToPostCSRs(client clientset.Interface) error { func AllowBootstrapTokensToGetNodes(client clientset.Interface) error { fmt.Println("[bootstrap-token] Configured RBAC rules to allow Node Bootstrap tokens to get nodes") - if err := apiclient.CreateOrUpdateClusterRole(client, &rbac.ClusterRole{ + if err := apiclient.CreateOrUpdate(client.RbacV1().ClusterRoles(), &rbac.ClusterRole{ ObjectMeta: metav1.ObjectMeta{ Name: constants.GetNodesClusterRoleName, }, @@ -68,7 +68,7 @@ func AllowBootstrapTokensToGetNodes(client clientset.Interface) error { return err } - return apiclient.CreateOrUpdateClusterRoleBinding(client, &rbac.ClusterRoleBinding{ + return apiclient.CreateOrUpdate(client.RbacV1().ClusterRoleBindings(), &rbac.ClusterRoleBinding{ ObjectMeta: metav1.ObjectMeta{ Name: constants.GetNodesClusterRoleName, }, @@ -91,7 +91,7 @@ func AutoApproveNodeBootstrapTokens(client clientset.Interface) error { fmt.Println("[bootstrap-token] Configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token") // Always create this kubeadm-specific binding though - return apiclient.CreateOrUpdateClusterRoleBinding(client, &rbac.ClusterRoleBinding{ + return apiclient.CreateOrUpdate(client.RbacV1().ClusterRoleBindings(), &rbac.ClusterRoleBinding{ ObjectMeta: metav1.ObjectMeta{ Name: constants.NodeAutoApproveBootstrapClusterRoleBinding, }, @@ -113,7 +113,7 @@ func AutoApproveNodeBootstrapTokens(client clientset.Interface) error { func AutoApproveNodeCertificateRotation(client clientset.Interface) error { fmt.Println("[bootstrap-token] Configured RBAC rules to allow certificate rotation for all node client certificates in the cluster") - return apiclient.CreateOrUpdateClusterRoleBinding(client, &rbac.ClusterRoleBinding{ + return apiclient.CreateOrUpdate(client.RbacV1().ClusterRoleBindings(), &rbac.ClusterRoleBinding{ ObjectMeta: metav1.ObjectMeta{ Name: constants.NodeAutoApproveCertificateRotationClusterRoleBinding, }, diff --git a/cmd/kubeadm/app/phases/bootstraptoken/node/token.go b/cmd/kubeadm/app/phases/bootstraptoken/node/token.go index ea3d77e085e..66484c1184e 100644 --- a/cmd/kubeadm/app/phases/bootstraptoken/node/token.go +++ b/cmd/kubeadm/app/phases/bootstraptoken/node/token.go @@ -40,10 +40,12 @@ func CreateNewTokens(client clientset.Interface, tokens []bootstraptokenv1.Boots // UpdateOrCreateTokens attempts to update a token with the given ID, or create if it does not already exist. func UpdateOrCreateTokens(client clientset.Interface, failIfExists bool, tokens []bootstraptokenv1.BootstrapToken) error { + secretsClient := client.CoreV1().Secrets(metav1.NamespaceSystem) + for _, token := range tokens { secretName := bootstraputil.BootstrapTokenSecretName(token.Token.ID) - secret, err := client.CoreV1().Secrets(metav1.NamespaceSystem).Get(context.TODO(), secretName, metav1.GetOptions{}) + secret, err := secretsClient.Get(context.Background(), secretName, metav1.GetOptions{}) if secret != nil && err == nil && failIfExists { return errors.Errorf("a token with id %q already exists", token.Token.ID) } @@ -56,7 +58,7 @@ func UpdateOrCreateTokens(client clientset.Interface, failIfExists bool, tokens kubeadmconstants.KubernetesAPICallRetryInterval, kubeadmapi.GetActiveTimeouts().KubernetesAPICall.Duration, true, func(_ context.Context) (bool, error) { - if err := apiclient.CreateOrUpdateSecret(client, updatedOrNewSecret); err != nil { + if err := apiclient.CreateOrUpdate(secretsClient, updatedOrNewSecret); err != nil { lastError = errors.Wrapf(err, "failed to create or update bootstrap token with name %s", secretName) return false, nil } diff --git a/cmd/kubeadm/app/phases/copycerts/copycerts.go b/cmd/kubeadm/app/phases/copycerts/copycerts.go index 866677c06e1..a62404df589 100644 --- a/cmd/kubeadm/app/phases/copycerts/copycerts.go +++ b/cmd/kubeadm/app/phases/copycerts/copycerts.go @@ -106,7 +106,7 @@ func UploadCerts(client clientset.Interface, cfg *kubeadmapi.InitConfiguration, return err } - err = apiclient.CreateOrUpdateSecret(client, &v1.Secret{ + err = apiclient.CreateOrUpdate(client.CoreV1().Secrets(metav1.NamespaceSystem), &v1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: kubeadmconstants.KubeadmCertsSecret, Namespace: metav1.NamespaceSystem, @@ -122,7 +122,7 @@ func UploadCerts(client clientset.Interface, cfg *kubeadmapi.InitConfiguration, } func createRBAC(client clientset.Interface) error { - err := apiclient.CreateOrUpdateRole(client, &rbac.Role{ + err := apiclient.CreateOrUpdate(client.RbacV1().Roles(metav1.NamespaceSystem), &rbac.Role{ ObjectMeta: metav1.ObjectMeta{ Name: kubeadmconstants.KubeadmCertsClusterRoleName, Namespace: metav1.NamespaceSystem, @@ -140,7 +140,7 @@ func createRBAC(client clientset.Interface) error { return err } - return apiclient.CreateOrUpdateRoleBinding(client, &rbac.RoleBinding{ + return apiclient.CreateOrUpdate(client.RbacV1().RoleBindings(metav1.NamespaceSystem), &rbac.RoleBinding{ ObjectMeta: metav1.ObjectMeta{ Name: kubeadmconstants.KubeadmCertsClusterRoleName, Namespace: metav1.NamespaceSystem, diff --git a/cmd/kubeadm/app/phases/kubelet/config.go b/cmd/kubeadm/app/phases/kubelet/config.go index 865acafcda4..5005d443bbf 100644 --- a/cmd/kubeadm/app/phases/kubelet/config.go +++ b/cmd/kubeadm/app/phases/kubelet/config.go @@ -151,7 +151,7 @@ func CreateConfigMap(cfg *kubeadmapi.ClusterConfiguration, client clientset.Inte componentconfigs.SignConfigMap(configMap) } - if err := apiclient.CreateOrUpdateConfigMap(client, configMap); err != nil { + if err := apiclient.CreateOrUpdate(client.CoreV1().ConfigMaps(configMap.GetNamespace()), configMap); err != nil { return err } @@ -163,7 +163,7 @@ func CreateConfigMap(cfg *kubeadmapi.ClusterConfiguration, client clientset.Inte // createConfigMapRBACRules creates the RBAC rules for exposing the base kubelet ConfigMap in the kube-system namespace to unauthenticated users func createConfigMapRBACRules(client clientset.Interface) error { - if err := apiclient.CreateOrUpdateRole(client, &rbac.Role{ + if err := apiclient.CreateOrUpdate(client.RbacV1().Roles(metav1.NamespaceSystem), &rbac.Role{ ObjectMeta: metav1.ObjectMeta{ Name: kubeadmconstants.KubeletBaseConfigMapRole, Namespace: metav1.NamespaceSystem, @@ -180,7 +180,7 @@ func createConfigMapRBACRules(client clientset.Interface) error { return err } - return apiclient.CreateOrUpdateRoleBinding(client, &rbac.RoleBinding{ + return apiclient.CreateOrUpdate(client.RbacV1().RoleBindings(metav1.NamespaceSystem), &rbac.RoleBinding{ ObjectMeta: metav1.ObjectMeta{ Name: kubeadmconstants.KubeletBaseConfigMapRole, Namespace: metav1.NamespaceSystem, diff --git a/cmd/kubeadm/app/phases/uploadconfig/uploadconfig.go b/cmd/kubeadm/app/phases/uploadconfig/uploadconfig.go index 9a430753388..25e4f22017b 100644 --- a/cmd/kubeadm/app/phases/uploadconfig/uploadconfig.go +++ b/cmd/kubeadm/app/phases/uploadconfig/uploadconfig.go @@ -59,7 +59,7 @@ func UploadConfiguration(cfg *kubeadmapi.InitConfiguration, client clientset.Int return err } - err = apiclient.CreateOrMutateConfigMap(client, &v1.ConfigMap{ + err = apiclient.CreateOrMutate(client.CoreV1().ConfigMaps(metav1.NamespaceSystem), &v1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: kubeadmconstants.KubeadmConfigConfigMap, Namespace: metav1.NamespaceSystem, @@ -78,7 +78,7 @@ func UploadConfiguration(cfg *kubeadmapi.InitConfiguration, client clientset.Int } // Ensure that the NodesKubeadmConfigClusterRoleName exists - err = apiclient.CreateOrUpdateRole(client, &rbac.Role{ + err = apiclient.CreateOrUpdate(client.RbacV1().Roles(metav1.NamespaceSystem), &rbac.Role{ ObjectMeta: metav1.ObjectMeta{ Name: NodesKubeadmConfigClusterRoleName, Namespace: metav1.NamespaceSystem, @@ -99,7 +99,7 @@ func UploadConfiguration(cfg *kubeadmapi.InitConfiguration, client clientset.Int // Binds the NodesKubeadmConfigClusterRoleName to all the bootstrap tokens // that are members of the system:bootstrappers:kubeadm:default-node-token group // and to all nodes - return apiclient.CreateOrUpdateRoleBinding(client, &rbac.RoleBinding{ + return apiclient.CreateOrUpdate(client.RbacV1().RoleBindings(metav1.NamespaceSystem), &rbac.RoleBinding{ ObjectMeta: metav1.ObjectMeta{ Name: NodesKubeadmConfigClusterRoleName, Namespace: metav1.NamespaceSystem, diff --git a/cmd/kubeadm/app/util/apiclient/idempotency.go b/cmd/kubeadm/app/util/apiclient/idempotency.go index cf4d218239d..e524e47c416 100644 --- a/cmd/kubeadm/app/util/apiclient/idempotency.go +++ b/cmd/kubeadm/app/util/apiclient/idempotency.go @@ -23,9 +23,7 @@ import ( "github.com/pkg/errors" - apps "k8s.io/api/apps/v1" v1 "k8s.io/api/core/v1" - rbac "k8s.io/api/rbac/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -57,9 +55,9 @@ type kubernetesObject interface { // CreateOrUpdate creates a runtime object if the target resource doesn't exist. // If the resource exists already, this function will update the resource instead. -func CreateOrUpdate[T kubernetesObject](ctx context.Context, client kubernetesInterface[T], obj T) error { +func CreateOrUpdate[T kubernetesObject](client kubernetesInterface[T], obj T) error { var lastError error - err := wait.PollUntilContextTimeout(ctx, + err := wait.PollUntilContextTimeout(context.Background(), apiCallRetryInterval, kubeadmapi.GetActiveTimeouts().KubernetesAPICall.Duration, true, func(_ context.Context) (bool, error) { // This uses a background context for API calls to avoid confusing callers that don't @@ -83,21 +81,13 @@ func CreateOrUpdate[T kubernetesObject](ctx context.Context, client kubernetesIn return lastError } -// CreateOrUpdateConfigMap creates a ConfigMap if the target resource doesn't exist. -// If the resource exists already, this function will update the resource instead. -// -// Deprecated: use CreateOrUpdate() instead. -func CreateOrUpdateConfigMap(client clientset.Interface, cm *v1.ConfigMap) error { - return CreateOrUpdate(context.Background(), client.CoreV1().ConfigMaps(cm.ObjectMeta.Namespace), cm) -} - // CreateOrMutate tries to create the provided object. If the resource exists already, the latest version will be fetched from // the cluster and mutator callback will be called on it, then an Update of the mutated object will be performed. This function is resilient // to conflicts, and a retry will be issued if the object was modified on the server between the refresh and the update (while the mutation was // taking place). -func CreateOrMutate[T kubernetesObject](ctx context.Context, client kubernetesInterface[T], obj T, mutator objectMutator[T]) error { +func CreateOrMutate[T kubernetesObject](client kubernetesInterface[T], obj T, mutator objectMutator[T]) error { var lastError error - err := wait.PollUntilContextTimeout(ctx, + err := wait.PollUntilContextTimeout(context.Background(), apiCallRetryInterval, kubeadmapi.GetActiveTimeouts().KubernetesAPICall.Duration, true, func(_ context.Context) (bool, error) { // This uses a background context for API calls to avoid confusing callers that don't @@ -119,16 +109,6 @@ func CreateOrMutate[T kubernetesObject](ctx context.Context, client kubernetesIn return lastError } -// CreateOrMutateConfigMap tries to create the ConfigMap provided as cm. If the resource exists already, the latest version will be fetched from -// the cluster and mutator callback will be called on it, then an Update of the mutated ConfigMap will be performed. This function is resilient -// to conflicts, and a retry will be issued if the ConfigMap was modified on the server between the refresh and the update (while the mutation was -// taking place). -// -// Deprecated: use CreateOrMutate() instead. -func CreateOrMutateConfigMap(client clientset.Interface, cm *v1.ConfigMap, mutator objectMutator[*v1.ConfigMap]) error { - return CreateOrMutate(context.Background(), client.CoreV1().ConfigMaps(cm.ObjectMeta.Namespace), cm, mutator) -} - // mutate takes an Object Meta (namespace and name), retrieves the resource from the server and tries to mutate it // by calling to the mutator callback, then an Update of the mutated object will be performed. This function is resilient // to conflicts, and a retry will be issued if the object was modified on the server between the refresh and the update (while the mutation was @@ -147,15 +127,15 @@ func mutate[T kubernetesObject](ctx context.Context, client kubernetesInterface[ // CreateOrRetain creates a runtime object if the target resource doesn't exist. // If the resource exists already, this function will retain the resource instead. -func CreateOrRetain[T kubernetesObject](ctx context.Context, client kubernetesInterface[T], obj T) error { +func CreateOrRetain[T kubernetesObject](client kubernetesInterface[T], obj T, name string) error { var lastError error - err := wait.PollUntilContextTimeout(ctx, + err := wait.PollUntilContextTimeout(context.Background(), apiCallRetryInterval, kubeadmapi.GetActiveTimeouts().KubernetesAPICall.Duration, true, func(_ context.Context) (bool, error) { // This uses a background context for API calls to avoid confusing callers that don't // expect context-related errors. ctx := context.Background() - if _, err := client.Get(ctx, obj.GetName(), metav1.GetOptions{}); err != nil { + if _, err := client.Get(ctx, name, metav1.GetOptions{}); err != nil { if !apierrors.IsNotFound(err) { lastError = errors.Wrapf(err, "unable to get %T", obj) return false, nil @@ -173,86 +153,6 @@ func CreateOrRetain[T kubernetesObject](ctx context.Context, client kubernetesIn return lastError } -// CreateOrRetainConfigMap creates a ConfigMap if the target resource doesn't exist. -// If the resource exists already, this function will retain the resource instead. -// -// Deprecated: use CreateOrRetain() instead. -func CreateOrRetainConfigMap(client clientset.Interface, cm *v1.ConfigMap, configMapName string) error { - return CreateOrRetain(context.Background(), client.CoreV1().ConfigMaps(cm.Namespace), cm) -} - -// CreateOrUpdateSecret creates a Secret if the target resource doesn't exist. -// If the resource exists already, this function will update the resource instead. -// -// Deprecated: use CreateOrUpdate() instead. -func CreateOrUpdateSecret(client clientset.Interface, secret *v1.Secret) error { - return CreateOrUpdate(context.Background(), client.CoreV1().Secrets(secret.Namespace), secret) -} - -// CreateOrUpdateServiceAccount creates a ServiceAccount if the target resource doesn't exist. -// If the resource exists already, this function will update the resource instead. -// -// Deprecated: use CreateOrUpdate() instead. -func CreateOrUpdateServiceAccount(client clientset.Interface, sa *v1.ServiceAccount) error { - return CreateOrUpdate(context.Background(), client.CoreV1().ServiceAccounts(sa.Namespace), sa) -} - -// CreateOrUpdateDeployment creates a Deployment if the target resource doesn't exist. -// If the resource exists already, this function will update the resource instead. -// -// Deprecated: use CreateOrUpdate() instead. -func CreateOrUpdateDeployment(client clientset.Interface, deploy *apps.Deployment) error { - return CreateOrUpdate(context.Background(), client.AppsV1().Deployments(deploy.Namespace), deploy) -} - -// CreateOrRetainDeployment creates a Deployment if the target resource doesn't exist. -// If the resource exists already, this function will retain the resource instead. -// -// Deprecated: use CreateOrRetain() instead. -func CreateOrRetainDeployment(client clientset.Interface, deploy *apps.Deployment, deployName string) error { - return CreateOrRetain(context.Background(), client.AppsV1().Deployments(deploy.Namespace), deploy) -} - -// CreateOrUpdateDaemonSet creates a DaemonSet if the target resource doesn't exist. -// If the resource exists already, this function will update the resource instead. -// -// Deprecated: use CreateOrUpdate() instead. -func CreateOrUpdateDaemonSet(client clientset.Interface, ds *apps.DaemonSet) error { - return CreateOrUpdate(context.Background(), client.AppsV1().DaemonSets(ds.Namespace), ds) -} - -// CreateOrUpdateRole creates a Role if the target resource doesn't exist. -// If the resource exists already, this function will update the resource instead. -// -// Deprecated: use CreateOrUpdate() instead. -func CreateOrUpdateRole(client clientset.Interface, role *rbac.Role) error { - return CreateOrUpdate(context.Background(), client.RbacV1().Roles(role.Namespace), role) -} - -// CreateOrUpdateRoleBinding creates a RoleBinding if the target resource doesn't exist. -// If the resource exists already, this function will update the resource instead. -// -// Deprecated: use CreateOrUpdate() instead. -func CreateOrUpdateRoleBinding(client clientset.Interface, roleBinding *rbac.RoleBinding) error { - return CreateOrUpdate(context.Background(), client.RbacV1().RoleBindings(roleBinding.Namespace), roleBinding) -} - -// CreateOrUpdateClusterRole creates a ClusterRole if the target resource doesn't exist. -// If the resource exists already, this function will update the resource instead. -// -// Deprecated: use CreateOrUpdate() instead. -func CreateOrUpdateClusterRole(client clientset.Interface, clusterRole *rbac.ClusterRole) error { - return CreateOrUpdate(context.Background(), client.RbacV1().ClusterRoles(), clusterRole) -} - -// CreateOrUpdateClusterRoleBinding creates a ClusterRoleBinding if the target resource doesn't exist. -// If the resource exists already, this function will update the resource instead. -// -// Deprecated: use CreateOrUpdate() instead. -func CreateOrUpdateClusterRoleBinding(client clientset.Interface, clusterRoleBinding *rbac.ClusterRoleBinding) error { - return CreateOrUpdate(context.Background(), client.RbacV1().ClusterRoleBindings(), clusterRoleBinding) -} - // PatchNodeOnce executes patchFn on the node object found by the node name. func PatchNodeOnce(client clientset.Interface, nodeName string, patchFn func(*v1.Node), lastError *error) func(context.Context) (bool, error) { return func(_ context.Context) (bool, error) { diff --git a/cmd/kubeadm/app/util/apiclient/idempotency_test.go b/cmd/kubeadm/app/util/apiclient/idempotency_test.go index c2e7c0d94a3..ec0caf78465 100644 --- a/cmd/kubeadm/app/util/apiclient/idempotency_test.go +++ b/cmd/kubeadm/app/util/apiclient/idempotency_test.go @@ -112,7 +112,7 @@ func testCreateOrUpdate[T kubernetesObject](t *testing.T, resource, resources st t.Run(fmt.Sprintf(tc.nameFormat, resource), func(t *testing.T) { client := clientsetfake.NewSimpleClientset() tc.setupClient(client, resources) - err := CreateOrUpdate(context.Background(), clientBuilder(client, empty), empty) + err := CreateOrUpdate(clientBuilder(client, empty), empty) if (err != nil) != tc.expectedError { t.Fatalf("expected error: %v, got %v, error: %v", tc.expectedError, err != nil, err) } @@ -205,7 +205,7 @@ func testCreateOrMutate[T kubernetesObject](t *testing.T, resource, resources st t.Run(fmt.Sprintf(tc.nameFormat, resource), func(t *testing.T) { client := clientsetfake.NewSimpleClientset() tc.setupClient(client) - err := CreateOrMutate[T](context.Background(), clientBuilder(client, empty), empty, tc.mutator) + err := CreateOrMutate[T](clientBuilder(client, empty), empty, tc.mutator) if (err != nil) != tc.expectedError { t.Fatalf("expected error: %v, got %v, error: %v", tc.expectedError, err != nil, err) } @@ -274,7 +274,7 @@ func testCreateOrRetain[T kubernetesObject](t *testing.T, resource, resources st t.Run(fmt.Sprintf(tc.nameFormat, resource), func(t *testing.T) { client := clientsetfake.NewSimpleClientset() tc.setupClient(client) - err := CreateOrRetain[T](context.Background(), clientBuilder(client, empty), empty) + err := CreateOrRetain[T](clientBuilder(client, empty), empty, resource) if (err != nil) != tc.expectedError { t.Fatalf("expected error: %v, got %v, error: %v", tc.expectedError, err != nil, err) } diff --git a/cmd/kubeadm/test/resources/configmap.go b/cmd/kubeadm/test/resources/configmap.go index 00799cb32f0..33a2b6e9cf4 100644 --- a/cmd/kubeadm/test/resources/configmap.go +++ b/cmd/kubeadm/test/resources/configmap.go @@ -32,7 +32,7 @@ type FakeConfigMap struct { // Create creates a fake configmap using the provided client func (c *FakeConfigMap) Create(client clientset.Interface) error { - return apiclient.CreateOrUpdateConfigMap(client, &v1.ConfigMap{ + return apiclient.CreateOrUpdate(client.CoreV1().ConfigMaps(metav1.NamespaceSystem), &v1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: c.Name, Namespace: metav1.NamespaceSystem,