...
1
16
17 package managedfields
18
19 import (
20 "fmt"
21
22 "k8s.io/apimachinery/pkg/api/meta"
23 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
24 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
25 "k8s.io/apimachinery/pkg/runtime/schema"
26 "k8s.io/apimachinery/pkg/util/managedfields/internal"
27 "sigs.k8s.io/structured-merge-diff/v4/fieldpath"
28 )
29
30 var (
31 scaleGroupVersion = schema.GroupVersion{Group: "autoscaling", Version: "v1"}
32 replicasPathInScale = fieldpath.MakePathOrDie("spec", "replicas")
33 )
34
35
36
37 type ResourcePathMappings map[string]fieldpath.Path
38
39
40
41 type ScaleHandler struct {
42 parentEntries []metav1.ManagedFieldsEntry
43 groupVersion schema.GroupVersion
44 mappings ResourcePathMappings
45 }
46
47
48 func NewScaleHandler(parentEntries []metav1.ManagedFieldsEntry, groupVersion schema.GroupVersion, mappings ResourcePathMappings) *ScaleHandler {
49 return &ScaleHandler{
50 parentEntries: parentEntries,
51 groupVersion: groupVersion,
52 mappings: mappings,
53 }
54 }
55
56
57
58
59
60
61
62 func (h *ScaleHandler) ToSubresource() ([]metav1.ManagedFieldsEntry, error) {
63 managed, err := internal.DecodeManagedFields(h.parentEntries)
64 if err != nil {
65 return nil, err
66 }
67
68 f := fieldpath.ManagedFields{}
69 t := map[string]*metav1.Time{}
70 for manager, versionedSet := range managed.Fields() {
71 path, ok := h.mappings[string(versionedSet.APIVersion())]
72
73 if !ok || path == nil {
74 continue
75 }
76
77 if versionedSet.Set().Has(path) {
78 newVersionedSet := fieldpath.NewVersionedSet(
79 fieldpath.NewSet(replicasPathInScale),
80 fieldpath.APIVersion(scaleGroupVersion.String()),
81 versionedSet.Applied(),
82 )
83
84 f[manager] = newVersionedSet
85 t[manager] = managed.Times()[manager]
86 }
87 }
88
89 return managedFieldsEntries(internal.NewManaged(f, t))
90 }
91
92
93
94 func (h *ScaleHandler) ToParent(scaleEntries []metav1.ManagedFieldsEntry) ([]metav1.ManagedFieldsEntry, error) {
95 decodedParentEntries, err := internal.DecodeManagedFields(h.parentEntries)
96 if err != nil {
97 return nil, err
98 }
99 parentFields := decodedParentEntries.Fields()
100
101 decodedScaleEntries, err := internal.DecodeManagedFields(scaleEntries)
102 if err != nil {
103 return nil, err
104 }
105 scaleFields := decodedScaleEntries.Fields()
106
107 f := fieldpath.ManagedFields{}
108 t := map[string]*metav1.Time{}
109
110 for manager, versionedSet := range parentFields {
111
112 path, ok := h.mappings[string(versionedSet.APIVersion())]
113
114 if !ok {
115 continue
116 }
117
118
119
120
121 if path == nil || !versionedSet.Set().Has(path) {
122 f[manager] = versionedSet
123 t[manager] = decodedParentEntries.Times()[manager]
124 continue
125 }
126
127 if _, ok := scaleFields[manager]; !ok {
128
129 newSet := versionedSet.Set().Difference(fieldpath.NewSet(path))
130
131 if !newSet.Empty() {
132 newVersionedSet := fieldpath.NewVersionedSet(
133 newSet,
134 versionedSet.APIVersion(),
135 versionedSet.Applied(),
136 )
137 f[manager] = newVersionedSet
138 t[manager] = decodedParentEntries.Times()[manager]
139 }
140 } else {
141
142 f[manager] = versionedSet
143 t[manager] = decodedParentEntries.Times()[manager]
144 delete(scaleFields, manager)
145 }
146 }
147
148 for manager, versionedSet := range scaleFields {
149 if !versionedSet.Set().Has(replicasPathInScale) {
150 continue
151 }
152 newVersionedSet := fieldpath.NewVersionedSet(
153 fieldpath.NewSet(h.mappings[h.groupVersion.String()]),
154 fieldpath.APIVersion(h.groupVersion.String()),
155 versionedSet.Applied(),
156 )
157 f[manager] = newVersionedSet
158 t[manager] = decodedParentEntries.Times()[manager]
159 }
160
161 return managedFieldsEntries(internal.NewManaged(f, t))
162 }
163
164 func managedFieldsEntries(entries internal.ManagedInterface) ([]metav1.ManagedFieldsEntry, error) {
165 obj := &unstructured.Unstructured{Object: map[string]interface{}{}}
166 if err := internal.EncodeObjectManagedFields(obj, entries); err != nil {
167 return nil, err
168 }
169 accessor, err := meta.Accessor(obj)
170 if err != nil {
171 panic(fmt.Sprintf("couldn't get accessor: %v", err))
172 }
173 return accessor.GetManagedFields(), nil
174 }
175
View as plain text