controller_ref_manager.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576
  1. /*
  2. Copyright 2016 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package controller
  14. import (
  15. "encoding/json"
  16. "fmt"
  17. "sync"
  18. apps "k8s.io/api/apps/v1"
  19. v1 "k8s.io/api/core/v1"
  20. "k8s.io/apimachinery/pkg/api/errors"
  21. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  22. "k8s.io/apimachinery/pkg/labels"
  23. "k8s.io/apimachinery/pkg/runtime/schema"
  24. "k8s.io/apimachinery/pkg/types"
  25. utilerrors "k8s.io/apimachinery/pkg/util/errors"
  26. "k8s.io/klog"
  27. )
  28. type BaseControllerRefManager struct {
  29. Controller metav1.Object
  30. Selector labels.Selector
  31. canAdoptErr error
  32. canAdoptOnce sync.Once
  33. CanAdoptFunc func() error
  34. }
  35. func (m *BaseControllerRefManager) CanAdopt() error {
  36. m.canAdoptOnce.Do(func() {
  37. if m.CanAdoptFunc != nil {
  38. m.canAdoptErr = m.CanAdoptFunc()
  39. }
  40. })
  41. return m.canAdoptErr
  42. }
  43. // ClaimObject tries to take ownership of an object for this controller.
  44. //
  45. // It will reconcile the following:
  46. // * Adopt orphans if the match function returns true.
  47. // * Release owned objects if the match function returns false.
  48. //
  49. // A non-nil error is returned if some form of reconciliation was attempted and
  50. // failed. Usually, controllers should try again later in case reconciliation
  51. // is still needed.
  52. //
  53. // If the error is nil, either the reconciliation succeeded, or no
  54. // reconciliation was necessary. The returned boolean indicates whether you now
  55. // own the object.
  56. //
  57. // No reconciliation will be attempted if the controller is being deleted.
  58. func (m *BaseControllerRefManager) ClaimObject(obj metav1.Object, match func(metav1.Object) bool, adopt, release func(metav1.Object) error) (bool, error) {
  59. controllerRef := metav1.GetControllerOfNoCopy(obj)
  60. if controllerRef != nil {
  61. if controllerRef.UID != m.Controller.GetUID() {
  62. // Owned by someone else. Ignore.
  63. return false, nil
  64. }
  65. if match(obj) {
  66. // We already own it and the selector matches.
  67. // Return true (successfully claimed) before checking deletion timestamp.
  68. // We're still allowed to claim things we already own while being deleted
  69. // because doing so requires taking no actions.
  70. return true, nil
  71. }
  72. // Owned by us but selector doesn't match.
  73. // Try to release, unless we're being deleted.
  74. if m.Controller.GetDeletionTimestamp() != nil {
  75. return false, nil
  76. }
  77. if err := release(obj); err != nil {
  78. // If the pod no longer exists, ignore the error.
  79. if errors.IsNotFound(err) {
  80. return false, nil
  81. }
  82. // Either someone else released it, or there was a transient error.
  83. // The controller should requeue and try again if it's still stale.
  84. return false, err
  85. }
  86. // Successfully released.
  87. return false, nil
  88. }
  89. // It's an orphan.
  90. if m.Controller.GetDeletionTimestamp() != nil || !match(obj) {
  91. // Ignore if we're being deleted or selector doesn't match.
  92. return false, nil
  93. }
  94. if obj.GetDeletionTimestamp() != nil {
  95. // Ignore if the object is being deleted
  96. return false, nil
  97. }
  98. // Selector matches. Try to adopt.
  99. if err := adopt(obj); err != nil {
  100. // If the pod no longer exists, ignore the error.
  101. if errors.IsNotFound(err) {
  102. return false, nil
  103. }
  104. // Either someone else claimed it first, or there was a transient error.
  105. // The controller should requeue and try again if it's still orphaned.
  106. return false, err
  107. }
  108. // Successfully adopted.
  109. return true, nil
  110. }
  111. type PodControllerRefManager struct {
  112. BaseControllerRefManager
  113. controllerKind schema.GroupVersionKind
  114. podControl PodControlInterface
  115. }
  116. // NewPodControllerRefManager returns a PodControllerRefManager that exposes
  117. // methods to manage the controllerRef of pods.
  118. //
  119. // The CanAdopt() function can be used to perform a potentially expensive check
  120. // (such as a live GET from the API server) prior to the first adoption.
  121. // It will only be called (at most once) if an adoption is actually attempted.
  122. // If CanAdopt() returns a non-nil error, all adoptions will fail.
  123. //
  124. // NOTE: Once CanAdopt() is called, it will not be called again by the same
  125. // PodControllerRefManager instance. Create a new instance if it makes
  126. // sense to check CanAdopt() again (e.g. in a different sync pass).
  127. func NewPodControllerRefManager(
  128. podControl PodControlInterface,
  129. controller metav1.Object,
  130. selector labels.Selector,
  131. controllerKind schema.GroupVersionKind,
  132. canAdopt func() error,
  133. ) *PodControllerRefManager {
  134. return &PodControllerRefManager{
  135. BaseControllerRefManager: BaseControllerRefManager{
  136. Controller: controller,
  137. Selector: selector,
  138. CanAdoptFunc: canAdopt,
  139. },
  140. controllerKind: controllerKind,
  141. podControl: podControl,
  142. }
  143. }
  144. // ClaimPods tries to take ownership of a list of Pods.
  145. //
  146. // It will reconcile the following:
  147. // * Adopt orphans if the selector matches.
  148. // * Release owned objects if the selector no longer matches.
  149. //
  150. // Optional: If one or more filters are specified, a Pod will only be claimed if
  151. // all filters return true.
  152. //
  153. // A non-nil error is returned if some form of reconciliation was attempted and
  154. // failed. Usually, controllers should try again later in case reconciliation
  155. // is still needed.
  156. //
  157. // If the error is nil, either the reconciliation succeeded, or no
  158. // reconciliation was necessary. The list of Pods that you now own is returned.
  159. func (m *PodControllerRefManager) ClaimPods(pods []*v1.Pod, filters ...func(*v1.Pod) bool) ([]*v1.Pod, error) {
  160. var claimed []*v1.Pod
  161. var errlist []error
  162. match := func(obj metav1.Object) bool {
  163. pod := obj.(*v1.Pod)
  164. // Check selector first so filters only run on potentially matching Pods.
  165. if !m.Selector.Matches(labels.Set(pod.Labels)) {
  166. return false
  167. }
  168. for _, filter := range filters {
  169. if !filter(pod) {
  170. return false
  171. }
  172. }
  173. return true
  174. }
  175. adopt := func(obj metav1.Object) error {
  176. return m.AdoptPod(obj.(*v1.Pod))
  177. }
  178. release := func(obj metav1.Object) error {
  179. return m.ReleasePod(obj.(*v1.Pod))
  180. }
  181. for _, pod := range pods {
  182. ok, err := m.ClaimObject(pod, match, adopt, release)
  183. if err != nil {
  184. errlist = append(errlist, err)
  185. continue
  186. }
  187. if ok {
  188. claimed = append(claimed, pod)
  189. }
  190. }
  191. return claimed, utilerrors.NewAggregate(errlist)
  192. }
  193. // AdoptPod sends a patch to take control of the pod. It returns the error if
  194. // the patching fails.
  195. func (m *PodControllerRefManager) AdoptPod(pod *v1.Pod) error {
  196. if err := m.CanAdopt(); err != nil {
  197. return fmt.Errorf("can't adopt Pod %v/%v (%v): %v", pod.Namespace, pod.Name, pod.UID, err)
  198. }
  199. // Note that ValidateOwnerReferences() will reject this patch if another
  200. // OwnerReference exists with controller=true.
  201. patchBytes, err := ownerRefControllerPatch(m.Controller, m.controllerKind, pod.UID)
  202. if err != nil {
  203. return err
  204. }
  205. return m.podControl.PatchPod(pod.Namespace, pod.Name, patchBytes)
  206. }
  207. // ReleasePod sends a patch to free the pod from the control of the controller.
  208. // It returns the error if the patching fails. 404 and 422 errors are ignored.
  209. func (m *PodControllerRefManager) ReleasePod(pod *v1.Pod) error {
  210. klog.V(2).Infof("patching pod %s_%s to remove its controllerRef to %s/%s:%s",
  211. pod.Namespace, pod.Name, m.controllerKind.GroupVersion(), m.controllerKind.Kind, m.Controller.GetName())
  212. patchBytes, err := deleteOwnerRefStrategicMergePatch(pod.UID, m.Controller.GetUID())
  213. if err != nil {
  214. return err
  215. }
  216. err = m.podControl.PatchPod(pod.Namespace, pod.Name, patchBytes)
  217. if err != nil {
  218. if errors.IsNotFound(err) {
  219. // If the pod no longer exists, ignore it.
  220. return nil
  221. }
  222. if errors.IsInvalid(err) {
  223. // Invalid error will be returned in two cases: 1. the pod
  224. // has no owner reference, 2. the uid of the pod doesn't
  225. // match, which means the pod is deleted and then recreated.
  226. // In both cases, the error can be ignored.
  227. // TODO: If the pod has owner references, but none of them
  228. // has the owner.UID, server will silently ignore the patch.
  229. // Investigate why.
  230. return nil
  231. }
  232. }
  233. return err
  234. }
  235. // ReplicaSetControllerRefManager is used to manage controllerRef of ReplicaSets.
  236. // Three methods are defined on this object 1: Classify 2: AdoptReplicaSet and
  237. // 3: ReleaseReplicaSet which are used to classify the ReplicaSets into appropriate
  238. // categories and accordingly adopt or release them. See comments on these functions
  239. // for more details.
  240. type ReplicaSetControllerRefManager struct {
  241. BaseControllerRefManager
  242. controllerKind schema.GroupVersionKind
  243. rsControl RSControlInterface
  244. }
  245. // NewReplicaSetControllerRefManager returns a ReplicaSetControllerRefManager that exposes
  246. // methods to manage the controllerRef of ReplicaSets.
  247. //
  248. // The CanAdopt() function can be used to perform a potentially expensive check
  249. // (such as a live GET from the API server) prior to the first adoption.
  250. // It will only be called (at most once) if an adoption is actually attempted.
  251. // If CanAdopt() returns a non-nil error, all adoptions will fail.
  252. //
  253. // NOTE: Once CanAdopt() is called, it will not be called again by the same
  254. // ReplicaSetControllerRefManager instance. Create a new instance if it
  255. // makes sense to check CanAdopt() again (e.g. in a different sync pass).
  256. func NewReplicaSetControllerRefManager(
  257. rsControl RSControlInterface,
  258. controller metav1.Object,
  259. selector labels.Selector,
  260. controllerKind schema.GroupVersionKind,
  261. canAdopt func() error,
  262. ) *ReplicaSetControllerRefManager {
  263. return &ReplicaSetControllerRefManager{
  264. BaseControllerRefManager: BaseControllerRefManager{
  265. Controller: controller,
  266. Selector: selector,
  267. CanAdoptFunc: canAdopt,
  268. },
  269. controllerKind: controllerKind,
  270. rsControl: rsControl,
  271. }
  272. }
  273. // ClaimReplicaSets tries to take ownership of a list of ReplicaSets.
  274. //
  275. // It will reconcile the following:
  276. // * Adopt orphans if the selector matches.
  277. // * Release owned objects if the selector no longer matches.
  278. //
  279. // A non-nil error is returned if some form of reconciliation was attempted and
  280. // failed. Usually, controllers should try again later in case reconciliation
  281. // is still needed.
  282. //
  283. // If the error is nil, either the reconciliation succeeded, or no
  284. // reconciliation was necessary. The list of ReplicaSets that you now own is
  285. // returned.
  286. func (m *ReplicaSetControllerRefManager) ClaimReplicaSets(sets []*apps.ReplicaSet) ([]*apps.ReplicaSet, error) {
  287. var claimed []*apps.ReplicaSet
  288. var errlist []error
  289. match := func(obj metav1.Object) bool {
  290. return m.Selector.Matches(labels.Set(obj.GetLabels()))
  291. }
  292. adopt := func(obj metav1.Object) error {
  293. return m.AdoptReplicaSet(obj.(*apps.ReplicaSet))
  294. }
  295. release := func(obj metav1.Object) error {
  296. return m.ReleaseReplicaSet(obj.(*apps.ReplicaSet))
  297. }
  298. for _, rs := range sets {
  299. ok, err := m.ClaimObject(rs, match, adopt, release)
  300. if err != nil {
  301. errlist = append(errlist, err)
  302. continue
  303. }
  304. if ok {
  305. claimed = append(claimed, rs)
  306. }
  307. }
  308. return claimed, utilerrors.NewAggregate(errlist)
  309. }
  310. // AdoptReplicaSet sends a patch to take control of the ReplicaSet. It returns
  311. // the error if the patching fails.
  312. func (m *ReplicaSetControllerRefManager) AdoptReplicaSet(rs *apps.ReplicaSet) error {
  313. if err := m.CanAdopt(); err != nil {
  314. return fmt.Errorf("can't adopt ReplicaSet %v/%v (%v): %v", rs.Namespace, rs.Name, rs.UID, err)
  315. }
  316. // Note that ValidateOwnerReferences() will reject this patch if another
  317. // OwnerReference exists with controller=true.
  318. patchBytes, err := ownerRefControllerPatch(m.Controller, m.controllerKind, rs.UID)
  319. if err != nil {
  320. return err
  321. }
  322. return m.rsControl.PatchReplicaSet(rs.Namespace, rs.Name, patchBytes)
  323. }
  324. // ReleaseReplicaSet sends a patch to free the ReplicaSet from the control of the Deployment controller.
  325. // It returns the error if the patching fails. 404 and 422 errors are ignored.
  326. func (m *ReplicaSetControllerRefManager) ReleaseReplicaSet(replicaSet *apps.ReplicaSet) error {
  327. klog.V(2).Infof("patching ReplicaSet %s_%s to remove its controllerRef to %s/%s:%s",
  328. replicaSet.Namespace, replicaSet.Name, m.controllerKind.GroupVersion(), m.controllerKind.Kind, m.Controller.GetName())
  329. patchBytes, err := deleteOwnerRefStrategicMergePatch(replicaSet.UID, m.Controller.GetUID())
  330. if err != nil {
  331. return err
  332. }
  333. err = m.rsControl.PatchReplicaSet(replicaSet.Namespace, replicaSet.Name, patchBytes)
  334. if err != nil {
  335. if errors.IsNotFound(err) {
  336. // If the ReplicaSet no longer exists, ignore it.
  337. return nil
  338. }
  339. if errors.IsInvalid(err) {
  340. // Invalid error will be returned in two cases: 1. the ReplicaSet
  341. // has no owner reference, 2. the uid of the ReplicaSet doesn't
  342. // match, which means the ReplicaSet is deleted and then recreated.
  343. // In both cases, the error can be ignored.
  344. return nil
  345. }
  346. }
  347. return err
  348. }
  349. // RecheckDeletionTimestamp returns a CanAdopt() function to recheck deletion.
  350. //
  351. // The CanAdopt() function calls getObject() to fetch the latest value,
  352. // and denies adoption attempts if that object has a non-nil DeletionTimestamp.
  353. func RecheckDeletionTimestamp(getObject func() (metav1.Object, error)) func() error {
  354. return func() error {
  355. obj, err := getObject()
  356. if err != nil {
  357. return fmt.Errorf("can't recheck DeletionTimestamp: %v", err)
  358. }
  359. if obj.GetDeletionTimestamp() != nil {
  360. return fmt.Errorf("%v/%v has just been deleted at %v", obj.GetNamespace(), obj.GetName(), obj.GetDeletionTimestamp())
  361. }
  362. return nil
  363. }
  364. }
  365. // ControllerRevisionControllerRefManager is used to manage controllerRef of ControllerRevisions.
  366. // Three methods are defined on this object 1: Classify 2: AdoptControllerRevision and
  367. // 3: ReleaseControllerRevision which are used to classify the ControllerRevisions into appropriate
  368. // categories and accordingly adopt or release them. See comments on these functions
  369. // for more details.
  370. type ControllerRevisionControllerRefManager struct {
  371. BaseControllerRefManager
  372. controllerKind schema.GroupVersionKind
  373. crControl ControllerRevisionControlInterface
  374. }
  375. // NewControllerRevisionControllerRefManager returns a ControllerRevisionControllerRefManager that exposes
  376. // methods to manage the controllerRef of ControllerRevisions.
  377. //
  378. // The canAdopt() function can be used to perform a potentially expensive check
  379. // (such as a live GET from the API server) prior to the first adoption.
  380. // It will only be called (at most once) if an adoption is actually attempted.
  381. // If canAdopt() returns a non-nil error, all adoptions will fail.
  382. //
  383. // NOTE: Once canAdopt() is called, it will not be called again by the same
  384. // ControllerRevisionControllerRefManager instance. Create a new instance if it
  385. // makes sense to check canAdopt() again (e.g. in a different sync pass).
  386. func NewControllerRevisionControllerRefManager(
  387. crControl ControllerRevisionControlInterface,
  388. controller metav1.Object,
  389. selector labels.Selector,
  390. controllerKind schema.GroupVersionKind,
  391. canAdopt func() error,
  392. ) *ControllerRevisionControllerRefManager {
  393. return &ControllerRevisionControllerRefManager{
  394. BaseControllerRefManager: BaseControllerRefManager{
  395. Controller: controller,
  396. Selector: selector,
  397. CanAdoptFunc: canAdopt,
  398. },
  399. controllerKind: controllerKind,
  400. crControl: crControl,
  401. }
  402. }
  403. // ClaimControllerRevisions tries to take ownership of a list of ControllerRevisions.
  404. //
  405. // It will reconcile the following:
  406. // * Adopt orphans if the selector matches.
  407. // * Release owned objects if the selector no longer matches.
  408. //
  409. // A non-nil error is returned if some form of reconciliation was attempted and
  410. // failed. Usually, controllers should try again later in case reconciliation
  411. // is still needed.
  412. //
  413. // If the error is nil, either the reconciliation succeeded, or no
  414. // reconciliation was necessary. The list of ControllerRevisions that you now own is
  415. // returned.
  416. func (m *ControllerRevisionControllerRefManager) ClaimControllerRevisions(histories []*apps.ControllerRevision) ([]*apps.ControllerRevision, error) {
  417. var claimed []*apps.ControllerRevision
  418. var errlist []error
  419. match := func(obj metav1.Object) bool {
  420. return m.Selector.Matches(labels.Set(obj.GetLabels()))
  421. }
  422. adopt := func(obj metav1.Object) error {
  423. return m.AdoptControllerRevision(obj.(*apps.ControllerRevision))
  424. }
  425. release := func(obj metav1.Object) error {
  426. return m.ReleaseControllerRevision(obj.(*apps.ControllerRevision))
  427. }
  428. for _, h := range histories {
  429. ok, err := m.ClaimObject(h, match, adopt, release)
  430. if err != nil {
  431. errlist = append(errlist, err)
  432. continue
  433. }
  434. if ok {
  435. claimed = append(claimed, h)
  436. }
  437. }
  438. return claimed, utilerrors.NewAggregate(errlist)
  439. }
  440. // AdoptControllerRevision sends a patch to take control of the ControllerRevision. It returns the error if
  441. // the patching fails.
  442. func (m *ControllerRevisionControllerRefManager) AdoptControllerRevision(history *apps.ControllerRevision) error {
  443. if err := m.CanAdopt(); err != nil {
  444. return fmt.Errorf("can't adopt ControllerRevision %v/%v (%v): %v", history.Namespace, history.Name, history.UID, err)
  445. }
  446. // Note that ValidateOwnerReferences() will reject this patch if another
  447. // OwnerReference exists with controller=true.
  448. patchBytes, err := ownerRefControllerPatch(m.Controller, m.controllerKind, history.UID)
  449. if err != nil {
  450. return err
  451. }
  452. return m.crControl.PatchControllerRevision(history.Namespace, history.Name, patchBytes)
  453. }
  454. // ReleaseControllerRevision sends a patch to free the ControllerRevision from the control of its controller.
  455. // It returns the error if the patching fails. 404 and 422 errors are ignored.
  456. func (m *ControllerRevisionControllerRefManager) ReleaseControllerRevision(history *apps.ControllerRevision) error {
  457. klog.V(2).Infof("patching ControllerRevision %s_%s to remove its controllerRef to %s/%s:%s",
  458. history.Namespace, history.Name, m.controllerKind.GroupVersion(), m.controllerKind.Kind, m.Controller.GetName())
  459. patchBytes, err := deleteOwnerRefStrategicMergePatch(history.UID, m.Controller.GetUID())
  460. if err != nil {
  461. return err
  462. }
  463. err = m.crControl.PatchControllerRevision(history.Namespace, history.Name, patchBytes)
  464. if err != nil {
  465. if errors.IsNotFound(err) {
  466. // If the ControllerRevision no longer exists, ignore it.
  467. return nil
  468. }
  469. if errors.IsInvalid(err) {
  470. // Invalid error will be returned in two cases: 1. the ControllerRevision
  471. // has no owner reference, 2. the uid of the ControllerRevision doesn't
  472. // match, which means the ControllerRevision is deleted and then recreated.
  473. // In both cases, the error can be ignored.
  474. return nil
  475. }
  476. }
  477. return err
  478. }
  479. type objectForDeleteOwnerRefStrategicMergePatch struct {
  480. Metadata objectMetaForMergePatch `json:"metadata"`
  481. }
  482. type objectMetaForMergePatch struct {
  483. UID types.UID `json:"uid"`
  484. OwnerReferences []map[string]string `json:"ownerReferences"`
  485. }
  486. func deleteOwnerRefStrategicMergePatch(dependentUID types.UID, ownerUIDs ...types.UID) ([]byte, error) {
  487. var pieces []map[string]string
  488. for _, ownerUID := range ownerUIDs {
  489. pieces = append(pieces, map[string]string{"$patch": "delete", "uid": string(ownerUID)})
  490. }
  491. patch := objectForDeleteOwnerRefStrategicMergePatch{
  492. Metadata: objectMetaForMergePatch{
  493. UID: dependentUID,
  494. OwnerReferences: pieces,
  495. },
  496. }
  497. patchBytes, err := json.Marshal(&patch)
  498. if err != nil {
  499. return nil, err
  500. }
  501. return patchBytes, nil
  502. }
  503. type objectForAddOwnerRefPatch struct {
  504. Metadata objectMetaForPatch `json:"metadata"`
  505. }
  506. type objectMetaForPatch struct {
  507. OwnerReferences []metav1.OwnerReference `json:"ownerReferences"`
  508. UID types.UID `json:"uid"`
  509. }
  510. func ownerRefControllerPatch(controller metav1.Object, controllerKind schema.GroupVersionKind, uid types.UID) ([]byte, error) {
  511. blockOwnerDeletion := true
  512. isController := true
  513. addControllerPatch := objectForAddOwnerRefPatch{
  514. Metadata: objectMetaForPatch{
  515. UID: uid,
  516. OwnerReferences: []metav1.OwnerReference{
  517. {
  518. APIVersion: controllerKind.GroupVersion().String(),
  519. Kind: controllerKind.Kind,
  520. Name: controller.GetName(),
  521. UID: controller.GetUID(),
  522. Controller: &isController,
  523. BlockOwnerDeletion: &blockOwnerDeletion,
  524. },
  525. },
  526. },
  527. }
  528. patchBytes, err := json.Marshal(&addControllerPatch)
  529. if err != nil {
  530. return nil, err
  531. }
  532. return patchBytes, nil
  533. }