github.com/verrazzano/verrazzano@v1.7.0/cluster-operator/controllers/quickcreate/ociocne/ociocne_controller.go (about)

     1  // Copyright (c) 2023, Oracle and/or its affiliates.
     2  // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
     3  
     4  package ociocne
     5  
     6  import (
     7  	"context"
     8  	_ "embed"
     9  	vmcv1alpha1 "github.com/verrazzano/verrazzano/cluster-operator/apis/clusters/v1alpha1"
    10  	"github.com/verrazzano/verrazzano/cluster-operator/controllers/quickcreate/controller"
    11  	"github.com/verrazzano/verrazzano/cluster-operator/controllers/quickcreate/controller/oci"
    12  	"github.com/verrazzano/verrazzano/cluster-operator/internal/capi"
    13  	"github.com/verrazzano/verrazzano/pkg/k8s/node"
    14  	apierrors "k8s.io/apimachinery/pkg/api/errors"
    15  	"k8s.io/apimachinery/pkg/runtime"
    16  	"k8s.io/apimachinery/pkg/types"
    17  	ctrl "sigs.k8s.io/controller-runtime"
    18  )
    19  
    20  const (
    21  	finalizerKey = "verrazzano.io/oci-ocne-cluster"
    22  )
    23  
    24  var (
    25  	//go:embed template/addons/addons.goyaml
    26  	addonsTemplate []byte
    27  	//go:embed template/cluster/cluster.goyaml
    28  	clusterTemplate []byte
    29  	//go:embed template/cluster/nodes.goyaml
    30  	nodesTemplate []byte
    31  	//go:embed template/cluster/ocne.goyaml
    32  	ocneTemplate []byte
    33  )
    34  
    35  type ClusterReconciler struct {
    36  	*controller.Base
    37  	Scheme            *runtime.Scheme
    38  	CredentialsLoader oci.CredentialsLoader
    39  	OCIClientGetter   func(credentials *oci.Credentials) (oci.Client, error)
    40  }
    41  
    42  func (r *ClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
    43  	q := &vmcv1alpha1.OCNEOCIQuickCreate{}
    44  	err := r.Get(ctx, req.NamespacedName, q)
    45  	// if cluster not found, no work to be done
    46  	if apierrors.IsNotFound(err) {
    47  		return ctrl.Result{}, nil
    48  	}
    49  	if err != nil {
    50  		return controller.RequeueDelay(), err
    51  	}
    52  	if err := r.SetNewResourceLogger(q); err != nil {
    53  		return controller.RequeueDelay(), err
    54  	}
    55  	return r.reconcile(ctx, q)
    56  }
    57  
    58  func (r *ClusterReconciler) reconcile(ctx context.Context, q *vmcv1alpha1.OCNEOCIQuickCreate) (ctrl.Result, error) {
    59  	// If quick create is completed, or being deleted, clean up the quick create
    60  	if !q.GetDeletionTimestamp().IsZero() || q.Status.Phase == vmcv1alpha1.QuickCreatePhaseComplete {
    61  		return ctrl.Result{}, r.Cleanup(ctx, q, finalizerKey)
    62  	}
    63  	// Add any finalizers if they are not present
    64  	if isMissingFinalizer(q) {
    65  		return r.SetFinalizers(ctx, q, finalizerKey)
    66  	}
    67  	return r.syncCluster(ctx, q)
    68  }
    69  
    70  func (r *ClusterReconciler) syncCluster(ctx context.Context, q *vmcv1alpha1.OCNEOCIQuickCreate) (ctrl.Result, error) {
    71  	ocne, err := NewProperties(ctx, r.Client, r.CredentialsLoader, r.OCIClientGetter, q)
    72  	if err != nil {
    73  		return controller.RequeueDelay(), err
    74  	}
    75  	// If provisioning has not successfully started, attempt to provisioning the cluster
    76  	if shouldProvision(q) {
    77  		if err := controller.ApplyTemplates(r.Client, ocne, q.Namespace, clusterTemplate, nodesTemplate, ocneTemplate); err != nil {
    78  			return controller.RequeueDelay(), err
    79  		}
    80  		q.Status = vmcv1alpha1.OCNEOCIQuickCreateStatus{
    81  			Phase: vmcv1alpha1.QuickCreatePhaseProvisioning,
    82  		}
    83  		r.Log.Oncef("provisioning OCNE OCI cluster: %s/%s", q.Namespace, q.Name)
    84  		return r.UpdateStatus(ctx, q)
    85  	}
    86  	// If OCI Network is loaded, update the quick create to completed phase
    87  	if ocne.HasOCINetwork() {
    88  		if err := controller.ApplyTemplates(r.Client, ocne, q.Namespace, addonsTemplate); err != nil {
    89  			return controller.RequeueDelay(), err
    90  		}
    91  		// If the cluster only has control plane nodes, set them for scheduling
    92  		if ocne.IsControlPlaneOnly() {
    93  			if err := r.setControlPlaneSchedulable(ctx, q); err != nil {
    94  				return controller.RequeueDelay(), nil
    95  			}
    96  		}
    97  		r.Log.Oncef("completed provisioning OCNE OCI cluster: %s/%s", q.Namespace, q.Name)
    98  		q.Status.Phase = vmcv1alpha1.QuickCreatePhaseComplete
    99  		return r.UpdateStatus(ctx, q)
   100  	}
   101  
   102  	r.Log.Progressf("waiting for OCNE OCI cluster infrastructure: %s/%s", q.Namespace, q.Name)
   103  	// Quick Create is not complete yet, requeue
   104  	return controller.RequeueDelay(), nil
   105  }
   106  
   107  func (r *ClusterReconciler) setControlPlaneSchedulable(ctx context.Context, q *vmcv1alpha1.OCNEOCIQuickCreate) error {
   108  	cli, err := capi.GetClusterClient(ctx, r.Client, types.NamespacedName{
   109  		Namespace: q.Namespace,
   110  		Name:      q.Name,
   111  	}, r.Scheme)
   112  	if err != nil {
   113  		return err
   114  	}
   115  	return node.SetControlPlaneScheduling(ctx, cli)
   116  }
   117  
   118  // SetupWithManager creates a new controller and adds it to the manager
   119  func (r *ClusterReconciler) SetupWithManager(mgr ctrl.Manager) error {
   120  	return ctrl.NewControllerManagedBy(mgr).
   121  		For(&vmcv1alpha1.OCNEOCIQuickCreate{}).
   122  		Complete(r)
   123  }