1
16
17 package internal
18
19 import (
20 "fmt"
21
22 "k8s.io/apimachinery/pkg/api/meta"
23 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
24 "k8s.io/apimachinery/pkg/runtime"
25 )
26
27 type lastAppliedUpdater struct {
28 fieldManager Manager
29 }
30
31 var _ Manager = &lastAppliedUpdater{}
32
33
34
35 func NewLastAppliedUpdater(fieldManager Manager) Manager {
36 return &lastAppliedUpdater{
37 fieldManager: fieldManager,
38 }
39 }
40
41
42 func (f *lastAppliedUpdater) Update(liveObj, newObj runtime.Object, managed Managed, manager string) (runtime.Object, Managed, error) {
43 return f.fieldManager.Update(liveObj, newObj, managed, manager)
44 }
45
46
47 func (f *lastAppliedUpdater) Apply(liveObj, newObj runtime.Object, managed Managed, manager string, force bool) (runtime.Object, Managed, error) {
48 liveObj, managed, err := f.fieldManager.Apply(liveObj, newObj, managed, manager, force)
49 if err != nil {
50 return liveObj, managed, err
51 }
52
53
54
55
56
57
58 if manager == "kubectl" && hasLastApplied(liveObj) {
59 lastAppliedValue, err := buildLastApplied(newObj)
60 if err != nil {
61 return nil, nil, fmt.Errorf("failed to build last-applied annotation: %v", err)
62 }
63 err = SetLastApplied(liveObj, lastAppliedValue)
64 if err != nil {
65 return nil, nil, fmt.Errorf("failed to set last-applied annotation: %v", err)
66 }
67 }
68 return liveObj, managed, err
69 }
70
71 func hasLastApplied(obj runtime.Object) bool {
72 var accessor, err = meta.Accessor(obj)
73 if err != nil {
74 panic(fmt.Sprintf("couldn't get accessor: %v", err))
75 }
76 var annotations = accessor.GetAnnotations()
77 if annotations == nil {
78 return false
79 }
80 lastApplied, ok := annotations[LastAppliedConfigAnnotation]
81 return ok && len(lastApplied) > 0
82 }
83
84 func buildLastApplied(obj runtime.Object) (string, error) {
85 obj = obj.DeepCopyObject()
86
87 var accessor, err = meta.Accessor(obj)
88 if err != nil {
89 panic(fmt.Sprintf("couldn't get accessor: %v", err))
90 }
91
92
93 var annotations = accessor.GetAnnotations()
94 delete(annotations, LastAppliedConfigAnnotation)
95 accessor.SetAnnotations(annotations)
96
97 lastApplied, err := runtime.Encode(unstructured.UnstructuredJSONScheme, obj)
98 if err != nil {
99 return "", fmt.Errorf("couldn't encode object into last applied annotation: %v", err)
100 }
101 return string(lastApplied), nil
102 }
103
View as plain text