mirror of
https://github.com/clastix/kamaji.git
synced 2026-04-15 06:56:47 +00:00
refactor: retrying mutate function in case of conflict error
This commit is contained in:
@@ -64,8 +64,8 @@ func (r *APIServerCertificate) GetTmpDirectory() string {
|
||||
return r.TmpDirectory
|
||||
}
|
||||
|
||||
func (r *APIServerCertificate) CreateOrUpdate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
|
||||
return controllerutil.CreateOrUpdate(ctx, r.Client, r.resource, r.mutate(ctx, tenantControlPlane))
|
||||
func (r *APIServerCertificate) CreateOrUpdate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (res controllerutil.OperationResult, err error) {
|
||||
return utilities.CreateOrUpdateWithConflict(ctx, r.Client, r.resource, r.mutate(ctx, tenantControlPlane))
|
||||
}
|
||||
|
||||
func (r *APIServerCertificate) GetName() string {
|
||||
|
||||
@@ -64,8 +64,8 @@ func (r *APIServerKubeletClientCertificate) GetTmpDirectory() string {
|
||||
return r.TmpDirectory
|
||||
}
|
||||
|
||||
func (r *APIServerKubeletClientCertificate) CreateOrUpdate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
|
||||
return controllerutil.CreateOrUpdate(ctx, r.Client, r.resource, r.mutate(ctx, tenantControlPlane))
|
||||
func (r *APIServerKubeletClientCertificate) CreateOrUpdate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (res controllerutil.OperationResult, err error) {
|
||||
return utilities.CreateOrUpdateWithConflict(ctx, r.Client, r.resource, r.mutate(ctx, tenantControlPlane))
|
||||
}
|
||||
|
||||
func (r *APIServerKubeletClientCertificate) GetName() string {
|
||||
|
||||
@@ -65,7 +65,7 @@ func (r *CACertificate) GetTmpDirectory() string {
|
||||
}
|
||||
|
||||
func (r *CACertificate) CreateOrUpdate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
|
||||
return controllerutil.CreateOrUpdate(ctx, r.Client, r.resource, r.mutate(ctx, tenantControlPlane))
|
||||
return utilities.CreateOrUpdateWithConflict(ctx, r.Client, r.resource, r.mutate(ctx, tenantControlPlane))
|
||||
}
|
||||
|
||||
func (r *CACertificate) GetName() string {
|
||||
|
||||
@@ -59,7 +59,7 @@ func (r *ETCDCACertificatesResource) Define(ctx context.Context, tenantControlPl
|
||||
}
|
||||
|
||||
func (r *ETCDCACertificatesResource) CreateOrUpdate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
|
||||
return controllerutil.CreateOrUpdate(ctx, r.Client, r.resource, r.mutate(ctx, tenantControlPlane))
|
||||
return utilities.CreateOrUpdateWithConflict(ctx, r.Client, r.resource, r.mutate(ctx, tenantControlPlane))
|
||||
}
|
||||
|
||||
func (r *ETCDCACertificatesResource) GetName() string {
|
||||
|
||||
@@ -56,7 +56,7 @@ func (r *ETCDCertificatesResource) Define(ctx context.Context, tenantControlPlan
|
||||
}
|
||||
|
||||
func (r *ETCDCertificatesResource) CreateOrUpdate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
|
||||
return controllerutil.CreateOrUpdate(ctx, r.Client, r.resource, r.mutate(ctx, tenantControlPlane))
|
||||
return utilities.CreateOrUpdateWithConflict(ctx, r.Client, r.resource, r.mutate(ctx, tenantControlPlane))
|
||||
}
|
||||
|
||||
func (r *ETCDCertificatesResource) GetName() string {
|
||||
|
||||
@@ -65,7 +65,7 @@ func (r *FrontProxyClientCertificate) GetTmpDirectory() string {
|
||||
}
|
||||
|
||||
func (r *FrontProxyClientCertificate) CreateOrUpdate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
|
||||
return controllerutil.CreateOrUpdate(ctx, r.Client, r.resource, r.mutate(ctx, tenantControlPlane))
|
||||
return utilities.CreateOrUpdateWithConflict(ctx, r.Client, r.resource, r.mutate(ctx, tenantControlPlane))
|
||||
}
|
||||
|
||||
func (r *FrontProxyClientCertificate) GetName() string {
|
||||
|
||||
@@ -66,7 +66,7 @@ func (r *FrontProxyCACertificate) GetTmpDirectory() string {
|
||||
}
|
||||
|
||||
func (r *FrontProxyCACertificate) CreateOrUpdate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
|
||||
return controllerutil.CreateOrUpdate(ctx, r.Client, r.resource, r.mutate(ctx, tenantControlPlane))
|
||||
return utilities.CreateOrUpdateWithConflict(ctx, r.Client, r.resource, r.mutate(ctx, tenantControlPlane))
|
||||
}
|
||||
|
||||
func (r *FrontProxyCACertificate) GetName() string {
|
||||
|
||||
@@ -73,17 +73,19 @@ func (r *KubernetesDeploymentResource) Define(ctx context.Context, tenantControl
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *KubernetesDeploymentResource) CreateOrUpdate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
|
||||
func (r *KubernetesDeploymentResource) mutate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) controllerutil.MutateFn {
|
||||
maxSurge := intstr.FromString("100%")
|
||||
|
||||
maxUnavailable := intstr.FromInt(0)
|
||||
|
||||
address, err := tenantControlPlane.GetControlPlaneAddress(ctx, r.Client)
|
||||
if err != nil {
|
||||
return controllerutil.OperationResultNone, errors.Wrap(err, "cannot create TenantControlPlane Deployment")
|
||||
return func() error {
|
||||
return errors.Wrap(err, "cannot create TenantControlPlane Deployment")
|
||||
}
|
||||
}
|
||||
|
||||
return controllerutil.CreateOrUpdate(ctx, r.Client, r.resource, func() error {
|
||||
return func() error {
|
||||
labels := utilities.MergeMaps(r.resource.GetLabels(), tenantControlPlane.Spec.ControlPlane.Deployment.AdditionalMetadata.Labels)
|
||||
r.resource.SetLabels(labels)
|
||||
|
||||
@@ -500,7 +502,11 @@ func (r *KubernetesDeploymentResource) CreateOrUpdate(ctx context.Context, tenan
|
||||
}
|
||||
|
||||
return controllerutil.SetControllerReference(tenantControlPlane, r.resource, r.Client.Scheme())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (r *KubernetesDeploymentResource) CreateOrUpdate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
|
||||
return utilities.CreateOrUpdateWithConflict(ctx, r.Client, r.resource, r.mutate(ctx, tenantControlPlane))
|
||||
}
|
||||
|
||||
func (r *KubernetesDeploymentResource) GetName() string {
|
||||
|
||||
@@ -73,8 +73,8 @@ func (r *KubernetesIngressResource) Define(ctx context.Context, tenantControlPla
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *KubernetesIngressResource) CreateOrUpdate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
|
||||
return controllerutil.CreateOrUpdate(ctx, r.Client, r.resource, func() error {
|
||||
func (r *KubernetesIngressResource) mutate(tenantControlPlane *kamajiv1alpha1.TenantControlPlane) controllerutil.MutateFn {
|
||||
return func() error {
|
||||
labels := utilities.MergeMaps(r.resource.GetLabels(), tenantControlPlane.Spec.ControlPlane.Ingress.AdditionalMetadata.Labels)
|
||||
r.resource.SetLabels(labels)
|
||||
|
||||
@@ -131,7 +131,11 @@ func (r *KubernetesIngressResource) CreateOrUpdate(ctx context.Context, tenantCo
|
||||
}
|
||||
|
||||
return controllerutil.SetControllerReference(tenantControlPlane, r.resource, r.Client.Scheme())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (r *KubernetesIngressResource) CreateOrUpdate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
|
||||
return utilities.CreateOrUpdateWithConflict(ctx, r.Client, r.resource, r.mutate(tenantControlPlane))
|
||||
}
|
||||
|
||||
func (r *KubernetesIngressResource) GetName() string {
|
||||
|
||||
@@ -62,11 +62,15 @@ func (r *KubernetesServiceResource) Define(ctx context.Context, tenantControlPla
|
||||
}
|
||||
|
||||
func (r *KubernetesServiceResource) CreateOrUpdate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
|
||||
return utilities.CreateOrUpdateWithConflict(ctx, r.Client, r.resource, r.mutate(ctx, tenantControlPlane))
|
||||
}
|
||||
|
||||
func (r *KubernetesServiceResource) mutate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) controllerutil.MutateFn {
|
||||
// We don't need to check error here: in case of dynamic external IP, the Service must be created in advance.
|
||||
// After that, the specific cloud controller-manager will provide an IP that will be then used.
|
||||
address, _ := tenantControlPlane.GetControlPlaneAddress(ctx, r.Client)
|
||||
|
||||
return controllerutil.CreateOrUpdate(ctx, r.Client, r.resource, func() error {
|
||||
return func() error {
|
||||
var servicePort corev1.ServicePort
|
||||
if len(r.resource.Spec.Ports) > 0 {
|
||||
servicePort = r.resource.Spec.Ports[0]
|
||||
@@ -109,7 +113,7 @@ func (r *KubernetesServiceResource) CreateOrUpdate(ctx context.Context, tenantCo
|
||||
}
|
||||
|
||||
return controllerutil.SetControllerReference(tenantControlPlane, r.resource, r.Client.Scheme())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (r *KubernetesServiceResource) GetName() string {
|
||||
|
||||
@@ -71,7 +71,7 @@ func (r *KubeadmConfigResource) CreateOrUpdate(ctx context.Context, tenantContro
|
||||
return controllerutil.OperationResultNone, err
|
||||
}
|
||||
|
||||
return controllerutil.CreateOrUpdate(ctx, r.Client, r.resource, r.mutate(tenantControlPlane, address))
|
||||
return utilities.CreateOrUpdateWithConflict(ctx, r.Client, r.resource, r.mutate(tenantControlPlane, address))
|
||||
}
|
||||
|
||||
func (r *KubeadmConfigResource) GetName() string {
|
||||
|
||||
@@ -102,7 +102,7 @@ func (r *KubeconfigResource) getKubeconfigStatus(tenantControlPlane *kamajiv1alp
|
||||
}
|
||||
|
||||
func (r *KubeconfigResource) CreateOrUpdate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
|
||||
return controllerutil.CreateOrUpdate(ctx, r.Client, r.resource, r.mutate(ctx, tenantControlPlane))
|
||||
return utilities.CreateOrUpdateWithConflict(ctx, r.Client, r.resource, r.mutate(ctx, tenantControlPlane))
|
||||
}
|
||||
|
||||
func (r *KubeconfigResource) mutate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) controllerutil.MutateFn {
|
||||
|
||||
@@ -64,7 +64,7 @@ func (r *SACertificate) GetTmpDirectory() string {
|
||||
}
|
||||
|
||||
func (r *SACertificate) CreateOrUpdate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
|
||||
return controllerutil.CreateOrUpdate(ctx, r.Client, r.resource, r.mutate(ctx, tenantControlPlane))
|
||||
return utilities.CreateOrUpdateWithConflict(ctx, r.Client, r.resource, r.mutate(ctx, tenantControlPlane))
|
||||
}
|
||||
|
||||
func (r *SACertificate) GetName() string {
|
||||
|
||||
@@ -62,7 +62,7 @@ func (r *SQLCertificate) GetClient() client.Client {
|
||||
}
|
||||
|
||||
func (r *SQLCertificate) CreateOrUpdate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
|
||||
return controllerutil.CreateOrUpdate(ctx, r.Client, r.resource, r.mutate(ctx, tenantControlPlane))
|
||||
return utilities.CreateOrUpdateWithConflict(ctx, r.Client, r.resource, r.mutate(ctx, tenantControlPlane))
|
||||
}
|
||||
|
||||
func (r *SQLCertificate) GetName() string {
|
||||
|
||||
@@ -62,7 +62,7 @@ func (r *SQLStorageConfig) GetClient() client.Client {
|
||||
}
|
||||
|
||||
func (r *SQLStorageConfig) CreateOrUpdate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
|
||||
return controllerutil.CreateOrUpdate(ctx, r.Client, r.resource, r.mutate(ctx, tenantControlPlane))
|
||||
return utilities.CreateOrUpdateWithConflict(ctx, r.Client, r.resource, r.mutate(ctx, tenantControlPlane))
|
||||
}
|
||||
|
||||
func (r *SQLStorageConfig) GetName() string {
|
||||
|
||||
30
internal/utilities/create_or_update_conflict.go
Normal file
30
internal/utilities/create_or_update_conflict.go
Normal file
@@ -0,0 +1,30 @@
|
||||
// Copyright 2022 Clastix Labs
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package utilities
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
k8stypes "k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/client-go/util/retry"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||
)
|
||||
|
||||
// CreateOrUpdateWithConflict is a helper function that wraps the RetryOnConflict around the CreateOrUpdate function:
|
||||
// this allows to fetch from the cache the latest modified object an try to apply the changes defined in the MutateFn
|
||||
// without enqueuing back the request in order to get the latest changes of the resource.
|
||||
func CreateOrUpdateWithConflict(ctx context.Context, client client.Client, resource client.Object, f controllerutil.MutateFn) (res controllerutil.OperationResult, err error) {
|
||||
err = retry.RetryOnConflict(retry.DefaultRetry, func() (scopeErr error) {
|
||||
if scopeErr = client.Get(ctx, k8stypes.NamespacedName{Namespace: resource.GetNamespace(), Name: resource.GetName()}, resource); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res, scopeErr = controllerutil.CreateOrUpdate(ctx, client, resource, f)
|
||||
|
||||
return scopeErr
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user