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 <skitt@redhat.com>
This commit is contained in:
Stephen Kitt 2024-12-19 11:23:27 +01:00
parent 29101e9774
commit efdb735750
No known key found for this signature in database
GPG Key ID: 1CC5FA453662A71D
12 changed files with 50 additions and 145 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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