Skip to content

Commit 80d6c2f

Browse files
committed
update parent before apply
1 parent c48fc46 commit 80d6c2f

File tree

5 files changed

+50
-19
lines changed

5 files changed

+50
-19
lines changed

applylib/applyset/applyset.go

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"context"
2121
"encoding/json"
2222
"fmt"
23+
"reflect"
2324
"sync"
2425

2526
"k8s.io/apimachinery/pkg/api/meta"
@@ -30,6 +31,7 @@ import (
3031
"k8s.io/apimachinery/pkg/util/sets"
3132
"k8s.io/client-go/dynamic"
3233
"k8s.io/klog/v2"
34+
"sigs.k8s.io/controller-runtime/pkg/client"
3335
kubectlapply "sigs.k8s.io/kubebuilder-declarative-pattern/applylib/third_party/forked/github.com/kubernetes/kubectl/pkg/cmd/apply"
3436
)
3537

@@ -45,6 +47,8 @@ import (
4547
type ApplySet struct {
4648
// client is the dynamic kubernetes client used to apply objects to the k8s cluster.
4749
client dynamic.Interface
50+
// ParentClient is the controller runtime client used to apply parent.
51+
parentClient client.Client
4852
// restMapper is used to map object kind to resources, and to know if objects are cluster-scoped.
4953
restMapper meta.RESTMapper
5054
// patchOptions holds the options used when applying, in particular the fieldManager
@@ -73,6 +77,8 @@ type ApplySet struct {
7377
type Options struct {
7478
// Client is the dynamic kubernetes client used to apply objects to the k8s cluster.
7579
Client dynamic.Interface
80+
// ParentClient is the controller runtime client used to apply parent.
81+
ParentClient client.Client
7682
// RESTMapper is used to map object kind to resources, and to know if objects are cluster-scoped.
7783
RESTMapper meta.RESTMapper
7884
// PatchOptions holds the options used when applying, in particular the fieldManager
@@ -90,6 +96,7 @@ func New(options Options) (*ApplySet, error) {
9096
kapplyset := kubectlapply.NewApplySet(parentRef, kubectlapply.ApplySetTooling{Name: options.Tooling}, options.RESTMapper)
9197
options.PatchOptions.FieldManager = kapplyset.FieldManager()
9298
a := &ApplySet{
99+
parentClient: options.ParentClient,
93100
client: options.Client,
94101
restMapper: options.RESTMapper,
95102
patchOptions: options.PatchOptions,
@@ -142,6 +149,7 @@ func (a *ApplySet) ApplyOnce(ctx context.Context) (*ApplyResults, error) {
142149
parentRef := &kubectlapply.ApplySetParentRef{Name: a.parent.Name(), Namespace: a.parent.Namespace(), RESTMapping: a.parent.RESTMapping()}
143150
kapplyset := kubectlapply.NewApplySet(parentRef, kubectlapply.ApplySetTooling{Name: a.tooling}, a.restMapper)
144151

152+
// Cache the current RESTMappings to avoid re-fetching the bad ones.
145153
restMappings := make(map[schema.GroupVersionKind]restMappingResult)
146154
for i := range trackers.items {
147155
tracker := &trackers.items[i]
@@ -160,15 +168,16 @@ func (a *ApplySet) ApplyOnce(ctx context.Context) (*ApplyResults, error) {
160168
}
161169

162170
// TODO: Check error is NotFound and not some transient error?
163-
// TODO: Make sure we don't prune if there were errors
164-
165171
restMapping := result.restMapping
166172
if restMapping != nil {
167173
// cache the GVK in kubectlapply. kubectlapply will use this to calculate
168174
// the latest parent "applyset.kubernetes.io/contains-group-resources" annotation after applying.
169175
kapplyset.AddResource(restMapping, obj.GetNamespace())
170176
}
171177
}
178+
if err := a.WithParent(ctx, kapplyset); err != nil {
179+
return results, fmt.Errorf("unable to update Parent %v", err)
180+
}
172181

173182
for i := range trackers.items {
174183
tracker := &trackers.items[i]
@@ -240,11 +249,9 @@ func (a *ApplySet) ApplyOnce(ctx context.Context) (*ApplyResults, error) {
240249
results.reportHealth(gvk, nn, tracker.isHealthy)
241250
}
242251

243-
if a.prune {
252+
// We want to be more cautions on pruning and only do it if all manifests are applied.
253+
if a.prune && results.applyFailCount == 0 {
244254
klog.V(4).Infof("Prune is enabled")
245-
if err := a.WithParent(kapplyset); err != nil {
246-
return results, err
247-
}
248255
err := func() error {
249256
pruneObjects, err := kapplyset.FindAllObjectsToPrune(ctx, a.client, visitedUids)
250257
if err != nil {
@@ -257,12 +264,12 @@ func (a *ApplySet) ApplyOnce(ctx context.Context) (*ApplyResults, error) {
257264
}()
258265
if err != nil {
259266
klog.Errorf("encounter error on pruning %v", err)
260-
if e := a.updateParentLabelsAndAnnotations(kapplyset, "superset"); e != nil {
267+
if e := a.updateParentLabelsAndAnnotations(ctx, kapplyset, "superset"); e != nil {
261268
return results, e
262269
}
263270
}
264271
}
265-
if err := a.updateParentLabelsAndAnnotations(kapplyset, "latest"); err != nil {
272+
if err := a.updateParentLabelsAndAnnotations(ctx, kapplyset, "latest"); err != nil {
266273
klog.Errorf("update parent failed %v", err)
267274
}
268275
return results, nil
@@ -297,17 +304,23 @@ func (a *ApplySet) updateManifestLabel(obj ApplyableObject, applysetLabels map[s
297304
// updateParentLabelsAndAnnotations updates the parent labels and annotations.
298305
// This method leverages the kubectlapply to build the parent labels and annotations, but avoid using the
299306
// `resource.NewHelper` and cmdutil to patch the parent.
300-
func (a *ApplySet) updateParentLabelsAndAnnotations(kapplyset *kubectlapply.ApplySet, mode kubectlapply.ApplySetUpdateMode) error {
307+
func (a *ApplySet) updateParentLabelsAndAnnotations(ctx context.Context, kapplyset *kubectlapply.ApplySet, mode kubectlapply.ApplySetUpdateMode) error {
301308
parent, err := meta.Accessor(a.parent.GetSubject())
302309
if err != nil {
303310
return err
304311
}
312+
313+
original, err := meta.Accessor(a.parent.GetSubject().DeepCopyObject())
314+
if err != nil {
315+
return err
316+
}
305317
partialParent := kapplyset.BuildParentPatch(mode)
306318
newAnnotations := mergeMap(partialParent.Annotations, parent.GetAnnotations())
307319
parent.SetAnnotations(newAnnotations)
308320
newLabels := mergeMap(partialParent.Labels, parent.GetLabels())
309321
parent.SetLabels(newLabels)
310-
return nil
322+
323+
return a.updateParent(ctx, original, parent)
311324
}
312325

313326
func (a *ApplySet) deleteObjects(ctx context.Context, pruneObjects []kubectlapply.PruneObject, results *ApplyResults) error {
@@ -331,8 +344,13 @@ func (a *ApplySet) deleteObjects(ctx context.Context, pruneObjects []kubectlappl
331344
return nil
332345
}
333346

334-
func (a *ApplySet) WithParent(kapplyset *kubectlapply.ApplySet) error {
335-
object, err := meta.Accessor(a.parent.GetSubject())
347+
func (a *ApplySet) WithParent(ctx context.Context, kapplyset *kubectlapply.ApplySet) error {
348+
parent := a.parent.GetSubject()
349+
object, err := meta.Accessor(parent)
350+
if err != nil {
351+
return err
352+
}
353+
original, err := meta.Accessor(parent.DeepCopyObject())
336354
if err != nil {
337355
return err
338356
}
@@ -356,5 +374,19 @@ func (a *ApplySet) WithParent(kapplyset *kubectlapply.ApplySet) error {
356374
object.SetLabels(labels)
357375
}
358376
// This is not a cluster fetch. It builds up the parents labels and annotations information in kapplyset.
359-
return kapplyset.FetchParent(a.parent.GetSubject())
377+
if err := kapplyset.FetchParent(a.parent.GetSubject()); err != nil {
378+
return err
379+
}
380+
381+
return a.updateParent(ctx, original, object)
382+
}
383+
384+
func (a *ApplySet) updateParent(ctx context.Context, original, current metav1.Object) error {
385+
if !reflect.DeepEqual(original.GetLabels(), current.GetLabels()) || !reflect.DeepEqual(original.GetAnnotations(), current.GetAnnotations()) {
386+
if err := a.parentClient.Update(ctx, current.(client.Object)); err != nil {
387+
return fmt.Errorf("error updating parent %v", err)
388+
}
389+
}
390+
klog.V(4).Infof("parent labels and annotations are not changed, skip updating")
391+
return nil
360392
}

applylib/third_party/forked/github.com/kubernetes/kubectl/pkg/cmd/apply/prune.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020

2121
"k8s.io/apimachinery/pkg/api/meta"
2222
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
23+
2324
// "k8s.io/cli-runtime/pkg/printers"
2425
"k8s.io/client-go/dynamic"
2526
)

pkg/patterns/declarative/pkg/applier/applylib.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ func (a *ApplySetApplier) Apply(ctx context.Context, opt ApplierOptions) error {
7373
Client: dynamicClient,
7474
Prune: opt.Prune,
7575
Tooling: tooling,
76+
ParentClient: opt.Client,
7677
}
7778
s, err := applyset.New(options)
7879
if err != nil {

pkg/patterns/declarative/pkg/applier/type.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"k8s.io/apimachinery/pkg/api/meta"
77
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
88
"k8s.io/client-go/rest"
9+
"sigs.k8s.io/controller-runtime/pkg/client"
910
"sigs.k8s.io/kubebuilder-declarative-pattern/applylib/applyset"
1011
"sigs.k8s.io/kubebuilder-declarative-pattern/pkg/patterns/declarative/pkg/manifest"
1112
)
@@ -37,4 +38,5 @@ type ApplierOptions struct {
3738
ExtraArgs []string
3839

3940
ParentRef applyset.Parent
41+
Client client.Client
4042
}

pkg/patterns/declarative/reconciler.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -202,12 +202,6 @@ func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (
202202
}
203203
}
204204

205-
if !reflect.DeepEqual(original.GetLabels(), instance.GetLabels()) || !reflect.DeepEqual(original.GetAnnotations(), instance.GetAnnotations()) {
206-
if err := r.client.Update(ctx, instance); err != nil {
207-
log.Error(err, "error updating spec")
208-
}
209-
}
210-
211205
if err := r.updateStatus(ctx, original, instance); err != nil {
212206
return result, err
213207
}
@@ -381,6 +375,7 @@ func (r *Reconciler) reconcileExists(ctx context.Context, name types.NamespacedN
381375
ExtraArgs: extraArgs,
382376
Force: true,
383377
CascadingStrategy: r.options.cascadingStrategy,
378+
Client: r.client,
384379
}
385380

386381
applyOperation := &ApplyOperation{

0 commit comments

Comments
 (0)