refactor: retrying mutate function in case of conflict error

This commit is contained in:
Dario Tranchitella
2022-07-09 10:49:43 +02:00
parent c47875345d
commit a2541bfc00
16 changed files with 67 additions and 23 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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