|
| 1 | +/* |
| 2 | +Copyright 2022 The Kubernetes Authors. |
| 3 | +
|
| 4 | +Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | +you may not use this file except in compliance with the License. |
| 6 | +You may obtain a copy of the License at |
| 7 | +
|
| 8 | + http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | +
|
| 10 | +Unless required by applicable law or agreed to in writing, software |
| 11 | +distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | +See the License for the specific language governing permissions and |
| 14 | +limitations under the License. |
| 15 | +*/ |
| 16 | + |
| 17 | +package controllers |
| 18 | + |
| 19 | +import ( |
| 20 | + "context" |
| 21 | + "fmt" |
| 22 | + "strings" |
| 23 | + |
| 24 | + ctrl "sigs.k8s.io/controller-runtime" |
| 25 | + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" |
| 26 | + |
| 27 | + infrav1 "sigs.k8s.io/cluster-api-provider-cloudstack/api/v1beta3" |
| 28 | + csCtrlrUtils "sigs.k8s.io/cluster-api-provider-cloudstack/controllers/utils" |
| 29 | +) |
| 30 | + |
| 31 | +const CksClusterFinalizer = "ckscluster.infrastructure.cluster.x-k8s.io" |
| 32 | + |
| 33 | +// RBAC permissions for CloudStackCluster. |
| 34 | +// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=cloudstackclusters,verbs=get;list;watch;create;update;patch;delete |
| 35 | +// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=cloudstackclusters/status,verbs=create;get;update;patch |
| 36 | +// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=cloudstackclusters/finalizers,verbs=update |
| 37 | + |
| 38 | +// CksClusterReconciliationRunner is a ReconciliationRunner with extensions specific to CloudStackClusters. |
| 39 | +// The runner does the actual reconciliation. |
| 40 | +type CksClusterReconciliationRunner struct { |
| 41 | + *csCtrlrUtils.ReconciliationRunner |
| 42 | + FailureDomains *infrav1.CloudStackFailureDomainList |
| 43 | + ReconciliationSubject *infrav1.CloudStackCluster |
| 44 | +} |
| 45 | + |
| 46 | +// CksClusterReconciler is the k8s controller manager's interface to reconcile a CloudStackCluster. |
| 47 | +// This is primarily to adapt to k8s. |
| 48 | +type CksClusterReconciler struct { |
| 49 | + csCtrlrUtils.ReconcilerBase |
| 50 | +} |
| 51 | + |
| 52 | +// Initialize a new CloudStackCluster reconciliation runner with concrete types and initialized member fields. |
| 53 | +func NewCksClusterReconciliationRunner() *CksClusterReconciliationRunner { |
| 54 | + // Set concrete type and init pointers. |
| 55 | + runner := &CksClusterReconciliationRunner{ReconciliationSubject: &infrav1.CloudStackCluster{}} |
| 56 | + runner.FailureDomains = &infrav1.CloudStackFailureDomainList{} |
| 57 | + // Setup the base runner. Initializes pointers and links reconciliation methods. |
| 58 | + runner.ReconciliationRunner = csCtrlrUtils.NewRunner(runner, runner.ReconciliationSubject, "CKSClusterController") |
| 59 | + runner.CSCluster = runner.ReconciliationSubject |
| 60 | + return runner |
| 61 | +} |
| 62 | + |
| 63 | +// Reconcile is the method k8s will call upon a reconciliation request. |
| 64 | +func (reconciler *CksClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request) (retRes ctrl.Result, retErr error) { |
| 65 | + r := NewCksClusterReconciliationRunner() |
| 66 | + r.UsingBaseReconciler(reconciler.ReconcilerBase).ForRequest(req).WithRequestCtx(ctx) |
| 67 | + r.WithAdditionalCommonStages(r.GetFailureDomains(r.FailureDomains)) |
| 68 | + return r.RunBaseReconciliationStages() |
| 69 | +} |
| 70 | + |
| 71 | +// Reconcile actually reconciles the CloudStackCluster. |
| 72 | +func (r *CksClusterReconciliationRunner) Reconcile() (res ctrl.Result, reterr error) { |
| 73 | + if r.CSCluster.Spec.SyncWithACS { |
| 74 | + // Prevent premature deletion. |
| 75 | + controllerutil.AddFinalizer(r.ReconciliationSubject, CksClusterFinalizer) |
| 76 | + |
| 77 | + if len(r.FailureDomains.Items) == 0 { |
| 78 | + return r.RequeueWithMessage("No failure domains found") |
| 79 | + } |
| 80 | + |
| 81 | + res, err := r.AsFailureDomainUser(&r.FailureDomains.Items[0].Spec)() |
| 82 | + if r.ShouldReturn(res, err) { |
| 83 | + return res, err |
| 84 | + } |
| 85 | + |
| 86 | + r.Log.Info("Creating entry with CKS") |
| 87 | + err = r.CSUser.GetOrCreateUnmanagedCluster(r.CAPICluster, r.ReconciliationSubject, &r.FailureDomains.Items[0].Spec) |
| 88 | + if err != nil { |
| 89 | + if strings.Contains(err.Error(), "Kubernetes Service plugin is disabled") { |
| 90 | + r.Log.Info("Kubernetes Service plugin is disabled on CloudStack. Skipping ExternalManaged kubernetes cluster creation") |
| 91 | + return ctrl.Result{}, nil |
| 92 | + } |
| 93 | + r.Log.Info(fmt.Sprintf("Failed creating ExternalManaged kubernetes cluster on CloudStack. Error: %s", err.Error())) |
| 94 | + return r.RequeueWithMessage(fmt.Sprintf("Syncing VMs with CloudStack failed. error: %s", err.Error())) |
| 95 | + } |
| 96 | + } |
| 97 | + return ctrl.Result{}, nil |
| 98 | +} |
| 99 | + |
| 100 | +// ReconcileDelete cleans up resources used by the cluster and finally removes the CloudStackCluster's finalizers. |
| 101 | +func (r *CksClusterReconciliationRunner) ReconcileDelete() (ctrl.Result, error) { |
| 102 | + res, err := r.AsFailureDomainUser(&r.FailureDomains.Items[0].Spec)() |
| 103 | + if r.ShouldReturn(res, err) { |
| 104 | + return res, err |
| 105 | + } |
| 106 | + err = r.CSUser.DeleteUnmanagedCluster(r.ReconciliationSubject) |
| 107 | + if err != nil { |
| 108 | + if strings.Contains(err.Error(), " not found") { |
| 109 | + return ctrl.Result{}, nil |
| 110 | + } |
| 111 | + return r.RequeueWithMessage(fmt.Sprintf("Deleting unmanaged kubernetes cluster on CloudStack failed. error: %s", err.Error())) |
| 112 | + } |
| 113 | + controllerutil.RemoveFinalizer(r.ReconciliationSubject, CksClusterFinalizer) |
| 114 | + return ctrl.Result{}, nil |
| 115 | +} |
| 116 | + |
| 117 | +// SetupWithManager sets up the controller with the Manager. |
| 118 | +func (reconciler *CksClusterReconciler) SetupWithManager(mgr ctrl.Manager) error { |
| 119 | + return ctrl.NewControllerManagedBy(mgr). |
| 120 | + For(&infrav1.CloudStackCluster{}). |
| 121 | + Complete(reconciler) |
| 122 | +} |
0 commit comments