github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/controllers/apps/configuration/configconstraint_controller.go (about)

     1  /*
     2  Copyright (C) 2022-2023 ApeCloud Co., Ltd
     3  
     4  This file is part of KubeBlocks project
     5  
     6  This program is free software: you can redistribute it and/or modify
     7  it under the terms of the GNU Affero General Public License as published by
     8  the Free Software Foundation, either version 3 of the License, or
     9  (at your option) any later version.
    10  
    11  This program is distributed in the hope that it will be useful
    12  but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14  GNU Affero General Public License for more details.
    15  
    16  You should have received a copy of the GNU Affero General Public License
    17  along with this program.  If not, see <http://www.gnu.org/licenses/>.
    18  */
    19  
    20  package configuration
    21  
    22  import (
    23  	"context"
    24  	"time"
    25  
    26  	corev1 "k8s.io/api/core/v1"
    27  	"k8s.io/apimachinery/pkg/runtime"
    28  	"k8s.io/client-go/tools/record"
    29  	ctrl "sigs.k8s.io/controller-runtime"
    30  	"sigs.k8s.io/controller-runtime/pkg/client"
    31  	"sigs.k8s.io/controller-runtime/pkg/log"
    32  
    33  	appsv1alpha1 "github.com/1aal/kubeblocks/apis/apps/v1alpha1"
    34  	cfgcore "github.com/1aal/kubeblocks/pkg/configuration/core"
    35  	"github.com/1aal/kubeblocks/pkg/constant"
    36  	intctrlutil "github.com/1aal/kubeblocks/pkg/controllerutil"
    37  )
    38  
    39  // ConfigConstraintReconciler reconciles a ConfigConstraint object
    40  type ConfigConstraintReconciler struct {
    41  	client.Client
    42  	Scheme   *runtime.Scheme
    43  	Recorder record.EventRecorder
    44  }
    45  
    46  // +kubebuilder:rbac:groups=apps.kubeblocks.io,resources=configconstraints,verbs=get;list;watch;create;update;patch;delete
    47  // +kubebuilder:rbac:groups=apps.kubeblocks.io,resources=configconstraints/status,verbs=get;update;patch
    48  // +kubebuilder:rbac:groups=apps.kubeblocks.io,resources=configconstraints/finalizers,verbs=update
    49  
    50  // Reconcile is part of the main kubernetes reconciliation loop which aims to
    51  // move the current state of the cluster closer to the desired state.
    52  // TODO(user): Modify the Reconcile function to compare the state specified by
    53  // the ConfigConstraint object against the actual cluster state, and then
    54  // perform operations to make the cluster state reflect the state specified by
    55  // the user.
    56  //
    57  // For more details, check Reconcile and its Result here:
    58  // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.11.2/pkg/reconcile
    59  func (r *ConfigConstraintReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
    60  	reqCtx := intctrlutil.RequestCtx{
    61  		Ctx:      ctx,
    62  		Req:      req,
    63  		Log:      log.FromContext(ctx).WithName("ConfigConstraintReconcile").WithValues("ConfigConstraint", req.NamespacedName.Name),
    64  		Recorder: r.Recorder,
    65  	}
    66  
    67  	configConstraint := &appsv1alpha1.ConfigConstraint{}
    68  	if err := r.Client.Get(reqCtx.Ctx, reqCtx.Req.NamespacedName, configConstraint); err != nil {
    69  		return intctrlutil.CheckedRequeueWithError(err, reqCtx.Log, "")
    70  	}
    71  
    72  	res, err := intctrlutil.HandleCRDeletion(reqCtx, r, configConstraint, constant.ConfigurationTemplateFinalizerName, func() (*ctrl.Result, error) {
    73  		recordEvent := func() {
    74  			r.Recorder.Event(configConstraint, corev1.EventTypeWarning, "ExistsReferencedResources",
    75  				"cannot be deleted because of existing referencing of ClusterDefinition or ClusterVersion.")
    76  		}
    77  		if configConstraint.Status.Phase != appsv1alpha1.CCDeletingPhase {
    78  			err := updateConfigConstraintStatus(r.Client, reqCtx, configConstraint, appsv1alpha1.CCDeletingPhase)
    79  			// if fail to update ConfigConstraint status, return error,
    80  			// so that it can be retried
    81  			if err != nil {
    82  				return nil, err
    83  			}
    84  		}
    85  		if res, err := intctrlutil.ValidateReferenceCR(reqCtx, r.Client, configConstraint,
    86  			cfgcore.GenerateConstraintsUniqLabelKeyWithConfig(configConstraint.GetName()),
    87  			recordEvent, &appsv1alpha1.ClusterDefinitionList{},
    88  			&appsv1alpha1.ClusterVersionList{}); res != nil || err != nil {
    89  			return res, err
    90  		}
    91  		return nil, nil
    92  	})
    93  	if res != nil {
    94  		return *res, err
    95  	}
    96  
    97  	if configConstraint.Status.ObservedGeneration == configConstraint.Generation && configConstraint.Status.IsConfigConstraintTerminalPhases() {
    98  		return intctrlutil.Reconciled()
    99  	}
   100  
   101  	if ok, err := checkConfigConstraint(reqCtx, configConstraint); !ok || err != nil {
   102  		return intctrlutil.RequeueAfter(time.Second, reqCtx.Log, "ValidateConfigurationTemplate")
   103  	}
   104  
   105  	// Automatically convert cue to openAPISchema.
   106  	if err := updateConfigSchema(configConstraint, r.Client, ctx); err != nil {
   107  		return intctrlutil.CheckedRequeueWithError(err, reqCtx.Log, "failed to generate openAPISchema")
   108  	}
   109  
   110  	err = updateConfigConstraintStatus(r.Client, reqCtx, configConstraint, appsv1alpha1.CCAvailablePhase)
   111  	if err != nil {
   112  		return intctrlutil.CheckedRequeueWithError(err, reqCtx.Log, "")
   113  	}
   114  	intctrlutil.RecordCreatedEvent(r.Recorder, configConstraint)
   115  	return ctrl.Result{}, nil
   116  }
   117  
   118  // SetupWithManager sets up the controller with the Manager.
   119  func (r *ConfigConstraintReconciler) SetupWithManager(mgr ctrl.Manager) error {
   120  	return ctrl.NewControllerManagedBy(mgr).
   121  		For(&appsv1alpha1.ConfigConstraint{}).
   122  		// for other resource
   123  		Owns(&corev1.ConfigMap{}).
   124  		Complete(r)
   125  }