diff --git a/internal/controller/deployment_controller.go b/internal/controller/deployment_controller.go index dbeeaffc9..1766d3d4e 100644 --- a/internal/controller/deployment_controller.go +++ b/internal/controller/deployment_controller.go @@ -16,6 +16,7 @@ package controller import ( "context" + "encoding/json" "errors" "fmt" "time" @@ -31,7 +32,9 @@ import ( apimeta "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/dynamic" "k8s.io/client-go/rest" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" @@ -57,7 +60,6 @@ type DeploymentReconciler struct { func (r *DeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { l := log.FromContext(ctx).WithValues("DeploymentController", req.NamespacedName) l.Info("Reconciling Deployment") - deployment := &hmc.Deployment{} if err := r.Get(ctx, req.NamespacedName, deployment); err != nil { if apierrors.IsNotFound(err) { @@ -87,6 +89,63 @@ func (r *DeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Request) return r.Update(ctx, l, deployment) } +func (r *DeploymentReconciler) setStatusFromClusterStatus(ctx context.Context, l logr.Logger, deployment *hmc.Deployment) (bool, error) { + dc, err := dynamic.NewForConfig(r.Config) + if err != nil { + return true, fmt.Errorf("failed to create client configuration: %v", err) + } + + resourceId := schema.GroupVersionResource{ + Group: "cluster.x-k8s.io", + Version: "v1beta1", + Resource: "clusters", + } + + list, err := dc.Resource(resourceId).Namespace(deployment.Namespace).Get(ctx, deployment.Name, metav1.GetOptions{}) + if apierrors.IsNotFound(err) { + l.Info("Cluster not found, ignoring since object must be deleted or not yet created") + return true, nil + } + + if err != nil { + return true, fmt.Errorf("failed to get cluster information for deployment: %s : %v", deployment.Name, err) + } + + requeue := true + if statusField, ok := list.Object["status"]; ok { + if statusMap, ok := statusField.(map[string]interface{}); ok { + if conditionsField, ok := statusMap["conditions"]; ok { + bytes, err := json.Marshal(conditionsField) + if err != nil { + return true, fmt.Errorf("failed to get deserialize cluster information for deployment: %s : %v", + deployment.Name, err) + } + var conditions []metav1.Condition + err = json.Unmarshal(bytes, &conditions) + if err != nil { + return true, fmt.Errorf("failed to get serialize cluster information for deployment: %s : %v", + deployment.Name, err) + } + + allConditionsComplete := true + for _, condition := range conditions { + if condition.Status != "True" { + allConditionsComplete = false + } + + if condition.Reason == "" && condition.Status == "True" { + condition.Reason = "Succeeded" + } + apimeta.SetStatusCondition(deployment.GetConditions(), condition) + } + requeue = !allConditionsComplete + } + } + } + + return requeue, nil +} + func (r *DeploymentReconciler) Update(ctx context.Context, l logr.Logger, deployment *hmc.Deployment) (result ctrl.Result, err error) { finalizersUpdated := controllerutil.AddFinalizer(deployment, hmc.DeploymentFinalizer) if finalizersUpdated { @@ -224,6 +283,20 @@ func (r *DeploymentReconciler) Update(ctx context.Context, l logr.Logger, deploy Message: hrReadyCondition.Message, }) } + + requeue, err := r.setStatusFromClusterStatus(ctx, l, deployment) + if err != nil { + if requeue { + return ctrl.Result{RequeueAfter: 10 * time.Second}, err + } else { + return ctrl.Result{}, err + } + } + + if requeue { + return ctrl.Result{RequeueAfter: 10 * time.Second}, nil + } + if !fluxconditions.IsReady(hr) { return ctrl.Result{RequeueAfter: 10 * time.Second}, nil } diff --git a/templates/hmc/templates/rbac/roles.yaml b/templates/hmc/templates/rbac/roles.yaml index 7cad5c226..85fce3122 100644 --- a/templates/hmc/templates/rbac/roles.yaml +++ b/templates/hmc/templates/rbac/roles.yaml @@ -5,6 +5,13 @@ metadata: labels: {{- include "hmc.labels" . | nindent 4 }} rules: +- apiGroups: + - cluster.x-k8s.io + resources: + - clusters + verbs: + - get + - list - apiGroups: - helm.toolkit.fluxcd.io resources: