...
1
16
17 package managedfields
18
19 import (
20 "bytes"
21 "fmt"
22
23 "sigs.k8s.io/structured-merge-diff/v4/fieldpath"
24 "sigs.k8s.io/structured-merge-diff/v4/typed"
25
26 "k8s.io/apimachinery/pkg/api/meta"
27 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
28 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
29 "k8s.io/apimachinery/pkg/runtime"
30 )
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 func ExtractInto(object runtime.Object, objectType typed.ParseableType, fieldManager string, applyConfiguration interface{}, subresource string) error {
54 typedObj, err := toTyped(object, objectType)
55 if err != nil {
56 return fmt.Errorf("error converting obj to typed: %w", err)
57 }
58
59 accessor, err := meta.Accessor(object)
60 if err != nil {
61 return fmt.Errorf("error accessing metadata: %w", err)
62 }
63 fieldsEntry, ok := findManagedFields(accessor, fieldManager, subresource)
64 if !ok {
65 return nil
66 }
67 fieldset := &fieldpath.Set{}
68 err = fieldset.FromJSON(bytes.NewReader(fieldsEntry.FieldsV1.Raw))
69 if err != nil {
70 return fmt.Errorf("error marshalling FieldsV1 to JSON: %w", err)
71 }
72
73 u := typedObj.ExtractItems(fieldset.Leaves()).AsValue().Unstructured()
74 m, ok := u.(map[string]interface{})
75 if !ok {
76 return fmt.Errorf("unable to convert managed fields for %s to unstructured, expected map, got %T", fieldManager, u)
77 }
78
79
80
81 if _, ok := m["kind"]; !ok && object.GetObjectKind().GroupVersionKind().Kind != "" {
82 m["kind"] = object.GetObjectKind().GroupVersionKind().Kind
83 m["apiVersion"] = object.GetObjectKind().GroupVersionKind().GroupVersion().String()
84 }
85 if err := runtime.DefaultUnstructuredConverter.FromUnstructured(m, applyConfiguration); err != nil {
86 return fmt.Errorf("error extracting into obj from unstructured: %w", err)
87 }
88 return nil
89 }
90
91 func findManagedFields(accessor metav1.Object, fieldManager string, subresource string) (metav1.ManagedFieldsEntry, bool) {
92 objManagedFields := accessor.GetManagedFields()
93 for _, mf := range objManagedFields {
94 if mf.Manager == fieldManager && mf.Operation == metav1.ManagedFieldsOperationApply && mf.Subresource == subresource {
95 return mf, true
96 }
97 }
98 return metav1.ManagedFieldsEntry{}, false
99 }
100
101 func toTyped(obj runtime.Object, objectType typed.ParseableType) (*typed.TypedValue, error) {
102 switch o := obj.(type) {
103 case *unstructured.Unstructured:
104 return objectType.FromUnstructured(o.Object)
105 default:
106 return objectType.FromStructured(o)
107 }
108 }
109
View as plain text