1
16
17 package garbagecollector
18
19 import (
20 "context"
21 "encoding/json"
22 "fmt"
23
24 "k8s.io/apimachinery/pkg/api/errors"
25 "k8s.io/apimachinery/pkg/api/meta"
26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27 "k8s.io/apimachinery/pkg/runtime"
28 "k8s.io/apimachinery/pkg/types"
29 "k8s.io/kubernetes/pkg/controller/garbagecollector/metaonly"
30 )
31
32
33
34 func (gc *GarbageCollector) getMetadata(apiVersion, kind, namespace, name string) (metav1.Object, error) {
35 apiResource, _, err := gc.apiResource(apiVersion, kind)
36 if err != nil {
37 return nil, err
38 }
39 gc.dependencyGraphBuilder.monitorLock.RLock()
40 defer gc.dependencyGraphBuilder.monitorLock.RUnlock()
41 m, ok := gc.dependencyGraphBuilder.monitors[apiResource]
42 if !ok || m == nil {
43
44 return gc.metadataClient.Resource(apiResource).Namespace(namespace).Get(context.TODO(), name, metav1.GetOptions{})
45 }
46 key := name
47 if len(namespace) != 0 {
48 key = namespace + "/" + name
49 }
50 raw, exist, err := m.store.GetByKey(key)
51 if err != nil {
52 return nil, err
53 }
54 if !exist {
55
56 return gc.metadataClient.Resource(apiResource).Namespace(namespace).Get(context.TODO(), name, metav1.GetOptions{})
57 }
58 obj, ok := raw.(runtime.Object)
59 if !ok {
60 return nil, fmt.Errorf("expect a runtime.Object, got %v", raw)
61 }
62 return meta.Accessor(obj)
63 }
64
65 type objectForFinalizersPatch struct {
66 ObjectMetaForFinalizersPatch `json:"metadata"`
67 }
68
69
70 type ObjectMetaForFinalizersPatch struct {
71 ResourceVersion string `json:"resourceVersion"`
72 Finalizers []string `json:"finalizers"`
73 }
74
75 type objectForPatch struct {
76 ObjectMetaForPatch `json:"metadata"`
77 }
78
79
80 type ObjectMetaForPatch struct {
81 ResourceVersion string `json:"resourceVersion"`
82 OwnerReferences []metav1.OwnerReference `json:"ownerReferences"`
83 }
84
85
86
87 type jsonMergePatchFunc func(*node) ([]byte, error)
88
89
90
91 func (gc *GarbageCollector) patch(item *node, smp []byte, jmp jsonMergePatchFunc) (*metav1.PartialObjectMetadata, error) {
92 smpResult, err := gc.patchObject(item.identity, smp, types.StrategicMergePatchType)
93 if err == nil {
94 return smpResult, nil
95 }
96 if !errors.IsUnsupportedMediaType(err) {
97 return nil, err
98 }
99
100 patch, err := jmp(item)
101 if err != nil {
102 return nil, err
103 }
104 return gc.patchObject(item.identity, patch, types.MergePatchType)
105 }
106
107
108 func (gc *GarbageCollector) deleteOwnerRefJSONMergePatch(item *node, ownerUIDs ...types.UID) ([]byte, error) {
109 accessor, err := gc.getMetadata(item.identity.APIVersion, item.identity.Kind, item.identity.Namespace, item.identity.Name)
110 if err != nil {
111 return nil, err
112 }
113 expectedObjectMeta := ObjectMetaForPatch{}
114 expectedObjectMeta.ResourceVersion = accessor.GetResourceVersion()
115 refs := accessor.GetOwnerReferences()
116 for _, ref := range refs {
117 var skip bool
118 for _, ownerUID := range ownerUIDs {
119 if ref.UID == ownerUID {
120 skip = true
121 break
122 }
123 }
124 if !skip {
125 expectedObjectMeta.OwnerReferences = append(expectedObjectMeta.OwnerReferences, ref)
126 }
127 }
128 return json.Marshal(objectForPatch{expectedObjectMeta})
129 }
130
131
132
133 func (n *node) unblockOwnerReferencesStrategicMergePatch() ([]byte, error) {
134 var dummy metaonly.MetadataOnlyObject
135 var blockingRefs []metav1.OwnerReference
136 falseVar := false
137 for _, owner := range n.owners {
138 if owner.BlockOwnerDeletion != nil && *owner.BlockOwnerDeletion {
139 ref := owner
140 ref.BlockOwnerDeletion = &falseVar
141 blockingRefs = append(blockingRefs, ref)
142 }
143 }
144 dummy.ObjectMeta.SetOwnerReferences(blockingRefs)
145 dummy.ObjectMeta.UID = n.identity.UID
146 return json.Marshal(dummy)
147 }
148
149
150
151 func (gc *GarbageCollector) unblockOwnerReferencesJSONMergePatch(n *node) ([]byte, error) {
152 accessor, err := gc.getMetadata(n.identity.APIVersion, n.identity.Kind, n.identity.Namespace, n.identity.Name)
153 if err != nil {
154 return nil, err
155 }
156 expectedObjectMeta := ObjectMetaForPatch{}
157 expectedObjectMeta.ResourceVersion = accessor.GetResourceVersion()
158 var expectedOwners []metav1.OwnerReference
159 falseVar := false
160 for _, owner := range n.owners {
161 owner.BlockOwnerDeletion = &falseVar
162 expectedOwners = append(expectedOwners, owner)
163 }
164 expectedObjectMeta.OwnerReferences = expectedOwners
165 return json.Marshal(objectForPatch{expectedObjectMeta})
166 }
167
View as plain text