Skip to content

Commit 2b9f050

Browse files
committed
✨ Add status resources for the helm charts
Adding status.resources Signed-off-by: janiskemper <[email protected]>
1 parent f5a34f9 commit 2b9f050

File tree

4 files changed

+97
-43
lines changed

4 files changed

+97
-43
lines changed

internal/controller/clusteraddon_controller.go

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -346,13 +346,16 @@ func (r *ClusterAddonReconciler) Reconcile(ctx context.Context, req reconcile.Re
346346
}
347347

348348
// Helm chart has been applied successfully
349-
// clusterAddon.Spec.Version = metadata.Versions.Components.ClusterAddon
350349
conditions.MarkTrue(clusterAddon, csov1alpha1.HelmChartAppliedCondition)
351350

352-
clusterAddon.Spec.ClusterStack = cluster.Spec.Topology.Class
351+
// remove the status resource if hook is finished
352+
clusterAddon.Status.Resources = make([]*csov1alpha1.Resource, 0)
353353

354354
// remove the helm chart status from the status.
355355
clusterAddon.Status.HelmChartStatus = make(map[string]csov1alpha1.HelmChartStatusConditions)
356+
357+
// update the latest cluster class
358+
clusterAddon.Spec.ClusterStack = cluster.Spec.Topology.Class
356359
clusterAddon.Status.Ready = true
357360

358361
return ctrl.Result{}, nil
@@ -372,7 +375,6 @@ func (r *ClusterAddonReconciler) Reconcile(ctx context.Context, req reconcile.Re
372375
if shouldRequeue {
373376
return reconcile.Result{RequeueAfter: 20 * time.Second}, nil
374377
}
375-
376378
}
377379

378380
if clusterAddon.Spec.Hook == "AfterControlPlaneInitialized" || clusterAddon.Spec.Hook == "BeforeClusterUpgrade" {
@@ -386,6 +388,9 @@ func (r *ClusterAddonReconciler) Reconcile(ctx context.Context, req reconcile.Re
386388
// remove the helm chart status from the status.
387389
clusterAddon.Status.HelmChartStatus = make(map[string]csov1alpha1.HelmChartStatusConditions)
388390

391+
// remove the status resource if hook is finished
392+
clusterAddon.Status.Resources = make([]*csov1alpha1.Resource, 0)
393+
389394
// store the release kubernetes version and current hook
390395
clusterAddon.Status.KubernetesVersion = releaseAsset.Meta.Versions.Kubernetes
391396
clusterAddon.Status.CurrentHook = clusterAddon.Spec.Hook
@@ -520,7 +525,7 @@ func (r *ClusterAddonReconciler) executeStage(ctx context.Context, stage cluster
520525

521526
check:
522527
switch in.clusterAddon.Status.HelmChartStatus[stage.HelmChartName] {
523-
case csov1alpha1.None:
528+
case csov1alpha1.None, csov1alpha1.WaitingForPreCondition:
524529
// If WaitForPreCondition is mentioned.
525530
if !reflect.DeepEqual(stage.WaitForPreCondition, clusteraddon.WaitForCondition{}) {
526531
// Evaluate the condition.
@@ -566,6 +571,9 @@ check:
566571
}
567572
logger.V(1).Info("finished applying helm chart", "clusterStack", in.clusterAddon.Spec.ClusterStack, "helm chart", stage.HelmChartName, "hook", in.clusterAddon.Spec.Hook)
568573

574+
// remove status resource if applied successfully
575+
in.clusterAddon.Status.Resources = make([]*csov1alpha1.Resource, 0)
576+
569577
in.clusterAddon.Status.HelmChartStatus[stage.HelmChartName] = csov1alpha1.WaitingForPostCondition
570578
goto check
571579

@@ -589,6 +597,9 @@ check:
589597
}
590598
logger.V(1).Info("finished deleting helm chart", "clusterStack", in.clusterAddon.Spec.ClusterStack, "helm chart", stage.HelmChartName, "hook", in.clusterAddon.Spec.Hook)
591599

600+
// remove status resource if deleted successfully
601+
in.clusterAddon.Status.Resources = make([]*csov1alpha1.Resource, 0)
602+
592603
in.clusterAddon.Status.HelmChartStatus[stage.HelmChartName] = csov1alpha1.WaitingForPostCondition
593604
goto check
594605
}
@@ -708,11 +719,13 @@ func helmTemplateAndApplyNewClusterStack(ctx context.Context, in templateAndAppl
708719
return false, fmt.Errorf("failed to template new helm chart: %w", err)
709720
}
710721

711-
shouldRequeue, err := in.kubeClient.ApplyNewClusterStack(ctx, oldHelmTemplate, newHelmTemplate)
722+
newResources, shouldRequeue, err := in.kubeClient.ApplyNewClusterStack(ctx, oldHelmTemplate, newHelmTemplate)
712723
if err != nil {
713724
return false, fmt.Errorf("failed to apply objects from cluster addon Helm chart: %w", err)
714725
}
715726

727+
in.clusterAddon.Status.Resources = newResources
728+
716729
return shouldRequeue, nil
717730
}
718731

@@ -728,11 +741,13 @@ func helmTemplateAndDeleteNewClusterStack(ctx context.Context, in templateAndApp
728741
return false, fmt.Errorf("failed to template new helm chart: %w", err)
729742
}
730743

731-
shouldRequeue, err := in.kubeClient.DeleteNewClusterStack(ctx, newHelmTemplate)
744+
newResources, shouldRequeue, err := in.kubeClient.DeleteNewClusterStack(ctx, newHelmTemplate)
732745
if err != nil {
733746
return false, fmt.Errorf("failed to delete objects from cluster addon Helm chart: %w", err)
734747
}
735748

749+
in.clusterAddon.Status.Resources = newResources
750+
736751
return shouldRequeue, nil
737752
}
738753

pkg/kube/fake/kube.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,10 @@ func (*kube) Delete(_ context.Context, _ []byte, _ []*csov1alpha1.Resource) (_ [
5050
return nil, false, nil
5151
}
5252

53-
func (*kube) ApplyNewClusterStack(_ context.Context, _, _ []byte) (_ bool, _ error) {
54-
return false, nil
53+
func (*kube) ApplyNewClusterStack(_ context.Context, _, _ []byte) (_ []*csov1alpha1.Resource, _ bool, _ error) {
54+
return nil, false, nil
5555
}
5656

57-
func (*kube) DeleteNewClusterStack(_ context.Context, _ []byte) (_ bool, _ error) {
58-
return false, nil
57+
func (*kube) DeleteNewClusterStack(_ context.Context, _ []byte) (_ []*csov1alpha1.Resource, _ bool, _ error) {
58+
return nil, false, nil
5959
}

pkg/kube/kube.go

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ type Client interface {
4040
Apply(ctx context.Context, template []byte, oldResources []*csov1alpha1.Resource, shouldDelete bool) (newResources []*csov1alpha1.Resource, shouldRequeue bool, err error)
4141
Delete(ctx context.Context, template []byte, oldResources []*csov1alpha1.Resource) (newResources []*csov1alpha1.Resource, shouldRequeue bool, err error)
4242

43-
ApplyNewClusterStack(ctx context.Context, oldTemplate, newTemplate []byte) (shouldRequeue bool, err error)
44-
DeleteNewClusterStack(ctx context.Context, template []byte) (shouldRequeue bool, err error)
43+
ApplyNewClusterStack(ctx context.Context, oldTemplate, newTemplate []byte) (newResources []*csov1alpha1.Resource, shouldRequeue bool, err error)
44+
DeleteNewClusterStack(ctx context.Context, template []byte) (newResources []*csov1alpha1.Resource, shouldRequeue bool, err error)
4545
}
4646

4747
// Factory creates new fake kube client factories.
@@ -67,24 +67,26 @@ func (*factory) NewClient(namespace string, resCfg *rest.Config) Client {
6767
}
6868
}
6969

70-
func (k *kube) ApplyNewClusterStack(ctx context.Context, oldTemplate, newTemplate []byte) (shouldRequeue bool, err error) {
70+
func (k *kube) ApplyNewClusterStack(ctx context.Context, oldTemplate, newTemplate []byte) (newResources []*csov1alpha1.Resource, shouldRequeue bool, err error) {
7171
logger := log.FromContext(ctx)
7272

7373
oldObjects, err := parseK8sYaml(oldTemplate)
7474
if err != nil {
75-
return false, fmt.Errorf("failed to parse old cluster stack template: %w", err)
75+
return nil, false, fmt.Errorf("failed to parse old cluster stack template: %w", err)
7676
}
7777

7878
newObjects, err := parseK8sYaml(newTemplate)
7979
if err != nil {
80-
return false, fmt.Errorf("failed to parse new cluster stack template: %w", err)
80+
return nil, false, fmt.Errorf("failed to parse new cluster stack template: %w", err)
8181
}
8282

8383
for _, newObject := range newObjects {
8484
if err := setLabel(newObject, ObjectLabelKeyOwned, ObjectLabelValueOwned); err != nil {
85-
return false, fmt.Errorf("error setting label: %w", err)
85+
return nil, false, fmt.Errorf("error setting label: %w", err)
8686
}
8787

88+
resource := csov1alpha1.NewResourceFromUnstructured(newObject)
89+
8890
// call the function and get dynamic.ResourceInterface
8991
// getDynamicResourceInterface
9092
dr, err := getDynamicResourceInterface(k.Namespace, k.RestConfig, newObject.GroupVersionKind())
@@ -97,50 +99,68 @@ func (k *kube) ApplyNewClusterStack(ctx context.Context, oldTemplate, newTemplat
9799

98100
if _, err := dr.Apply(ctx, newObject.GetName(), newObject, metav1.ApplyOptions{FieldManager: "kubectl", Force: true}); err != nil {
99101
reterr := fmt.Errorf("failed to apply object: %w", err)
102+
resource.Error = reterr.Error()
103+
resource.Status = csov1alpha1.ResourceStatusNotSynced
100104
logger.Error(reterr, "failed to apply object", "obj", newObject.GetObjectKind().GroupVersionKind(), "name", newObject.GetName(), "namespace", newObject.GetNamespace())
101105
shouldRequeue = true
102106
}
107+
108+
resource.Status = csov1alpha1.ResourceStatusSynced
109+
newResources = append(newResources, resource)
103110
}
104111

105112
for _, object := range resourcesToBeDeletedFromUnstructuredObjects(oldObjects, newObjects) {
113+
resource := csov1alpha1.NewResourceFromUnstructured(object)
114+
106115
dr, err := getDynamicResourceInterface(k.Namespace, k.RestConfig, object.GroupVersionKind())
107116
if err != nil {
108-
return false, fmt.Errorf("failed to get dynamic resource interface: %w", err)
117+
return nil, false, fmt.Errorf("failed to get dynamic resource interface: %w", err)
109118
}
110119

111120
if err := dr.Delete(ctx, object.GetName(), metav1.DeleteOptions{}); err != nil && !apierrors.IsNotFound(err) {
112121
reterr := fmt.Errorf("failed to delete object: %w", err)
113122
logger.Error(reterr, "failed to delete object", "obj", object.GroupVersionKind(), "namespacedName", fmt.Sprintf("%s/%s", object.GetNamespace(), object.GetName()))
114123
// append resource to status and requeue again to be able to retry deletion
124+
resource.Status = csov1alpha1.ResourceStatusNotSynced
125+
resource.Error = reterr.Error()
126+
newResources = append(newResources, resource)
115127
shouldRequeue = true
116128
}
117129
}
118130

119-
return shouldRequeue, nil
131+
return newResources, shouldRequeue, nil
120132
}
121133

122-
func (k *kube) DeleteNewClusterStack(ctx context.Context, template []byte) (shouldRequeue bool, err error) {
134+
func (k *kube) DeleteNewClusterStack(ctx context.Context, template []byte) (newResources []*csov1alpha1.Resource, shouldRequeue bool, err error) {
123135
objects, err := parseK8sYaml(template)
124136
if err != nil {
125-
return false, fmt.Errorf("failed to parse new cluster stack template: %w", err)
137+
return nil, false, fmt.Errorf("failed to parse new cluster stack template: %w", err)
126138
}
127139

128140
for _, object := range objects {
141+
resource := csov1alpha1.NewResourceFromUnstructured(object)
142+
129143
if err := setLabel(object, ObjectLabelKeyOwned, ObjectLabelValueOwned); err != nil {
130-
return false, fmt.Errorf("error setting label: %w", err)
144+
return nil, false, fmt.Errorf("error setting label: %w", err)
131145
}
132146

133147
dr, err := getDynamicResourceInterface(k.Namespace, k.RestConfig, object.GroupVersionKind())
134148
if err != nil {
135-
return false, fmt.Errorf("failed to get dynamic resource interface: %w", err)
149+
return nil, false, fmt.Errorf("failed to get dynamic resource interface: %w", err)
136150
}
137151

138-
if err := dr.Delete(ctx, object.GetName(), metav1.DeleteOptions{}); err != nil {
139-
return true, fmt.Errorf("failed to delete object %q: %w", object.GetObjectKind().GroupVersionKind(), err)
152+
if err := dr.Delete(ctx, object.GetName(), metav1.DeleteOptions{}); err != nil && !apierrors.IsNotFound(err) {
153+
reterr := fmt.Errorf("failed to delete object %q: %w", object.GetObjectKind().GroupVersionKind(), err)
154+
resource.Status = csov1alpha1.ResourceStatusNotSynced
155+
resource.Error = reterr.Error()
156+
shouldRequeue = true
140157
}
158+
159+
resource.Status = csov1alpha1.ResourceStatusSynced
160+
newResources = append(newResources, resource)
141161
}
142162

143-
return shouldRequeue, nil
163+
return newResources, shouldRequeue, nil
144164
}
145165

146166
func (k *kube) Apply(ctx context.Context, template []byte, oldResources []*csov1alpha1.Resource, shouldDelete bool) (newResources []*csov1alpha1.Resource, shouldRequeue bool, err error) {
@@ -192,6 +212,7 @@ func (k *kube) Apply(ctx context.Context, template []byte, oldResources []*csov1
192212
newResources = append(newResources, resource)
193213
}
194214

215+
// TODO: cleanup shouldDelete
195216
if shouldDelete {
196217
// make a diff between new objs and oldResources to find out
197218
// a) if an object is in oldResources and synced and not in new objs, then delete should be attempted

pkg/kube/mocks/Client.go

Lines changed: 36 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)