Skip to content

Commit 45ac3f8

Browse files
committed
doc: Update existing resources with owner refs
Operator deployed resources created while dependent watches are disabled cannot have owner information retroactively injected by the proxy. This patch documents the process of adding that information to existing resources manually. Fixes #1977
1 parent e47857e commit 45ac3f8

File tree

3 files changed

+168
-1
lines changed

3 files changed

+168
-1
lines changed

doc/ansible/dev/advanced_options.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,12 @@ The ansible runner will keep information about the ansible run in the container.
4646
You may want to manage what your operator watches and the owner references. This means that your operator will need to understand how to clean up after itself when your CR is deleted. To disable these features you will need to edit your `build/Dockerfile` to include the line below.
4747

4848
**NOTE**: That if you use this feature there will be a warning that dependent watches is turned off but there will be no error.
49+
**WARNING**: Once a CR is deployed without owner reference injection, there is no automatic way to add those references.
4950

5051
```
5152
ENTRYPOINT ["/usr/local/bin/entrypoint", "--inject-owner-ref=false"]
5253
```
54+
55+
If you have created resources without owner reference injection, it is
56+
possible to manually to update resources following [this
57+
guide.](./retroactively-owned-resources.md)

doc/ansible/dev/dependent_watches.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,4 @@ This is an example of a watches file with the `watchDependentResources` field se
3030
manageStatus: False
3131
watchDependentResources: True
3232

33-
```
33+
```
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
# Owner References for Existing Resources
2+
3+
Owner references are automatically injected *only during creation of
4+
resources*. Enabling owner reference injection *will not update objects*
5+
created while [owner reference injection is
6+
disabled](./advanced_options.md#turning-off-dependent-watches-and-owner-reference-injection)
7+
.
8+
9+
This guide will demonstrate how to retroactively set owner references
10+
for existing resources.
11+
12+
### Owner References and Annotations
13+
14+
Dependent resources *within the same namespace as the owning CR* are
15+
tracked with the `ownerReference` field.
16+
17+
`ownerReference` structure:
18+
* apiVersion: {group}/{version}
19+
* kind: {kind}
20+
* name: {metadata.name}
21+
* uid: {metadata.uid}
22+
23+
**Example:**
24+
25+
```yaml
26+
27+
metadata:
28+
...(snip)
29+
ownerReferences:
30+
- apiVersion: cache.example.com/v1alpha1
31+
kind: Memcached
32+
name: example-memcached
33+
uid: ad834522-d9a5-4841-beac-991ff3798c00
34+
```
35+
36+
An `annotation` is used instead of an `ownerReference` if the dependent
37+
resource is in a different namespace than the CR or the dependent
38+
resource is a cluster level resource.
39+
40+
`annotation` structure:
41+
* operator-sdk/primary-resource: {metadata.namepace}/{metadata.name}
42+
* operator-sdk/primary-resource-type: {kind}.{group}
43+
44+
*Note: <group> must be determined by splitting the apiVersion field at the "/"*
45+
46+
```yaml
47+
metadata:
48+
annotations:
49+
operator-sdk/primary-resource: default/example-memcached
50+
operator-sdk/primary-resource-type: Memcached.cache.example.com
51+
```
52+
53+
A GET request to the owning resource will provide the necessary data to
54+
construct an `ownerReference` or an `annotation`.
55+
56+
`$ kubectl get memcacheds.cache.example.com -o yaml`
57+
58+
`kubectl edit` can be used to update the resources by hand.
59+
60+
### Migration Playbook
61+
62+
If you have many resources to update, it may be easier to use the
63+
following (unsupported) playbook.
64+
65+
#### vars.yml
66+
67+
Users will configure the playbook by providing a `vars.yml` file which will specify:
68+
* owning_resource
69+
* apiVersion
70+
* kind
71+
* name
72+
* namespace
73+
* resources_to_own (list): For each resource, specify:
74+
* name
75+
* namespace (if applicable)
76+
* apiVersion
77+
* kind
78+
79+
**Example File:**
80+
81+
```yaml
82+
owning_resource:
83+
apiVersion: cache.example.com/v1alpha1
84+
kind: Memcached
85+
name: example-memcached
86+
namespace: default
87+
88+
resources_to_own:
89+
- name: example-memcached-memcached
90+
namespace: default
91+
apiVersion: apps/v1
92+
kind: Deployment
93+
- name: example-memcached
94+
apiVersion: v1
95+
kind: Namespace
96+
```
97+
#### playbook.yml
98+
99+
```yaml
100+
- hosts: localhost
101+
102+
tasks:
103+
- name: Import user variables
104+
include_vars: vars.yml
105+
- name: Retrieve owning resource
106+
k8s_facts:
107+
api_version: "{{ owning_resource.apiVersion }}"
108+
kind: "{{ owning_resource.kind }}"
109+
name: "{{ owning_resource.name }}"
110+
namespace: "{{ owning_resource.namespace }}"
111+
register: extra_owner_data
112+
113+
- name: Ensure resources are owned
114+
include_tasks: each_resource.yml
115+
loop: "{{ resources_to_own }}"
116+
vars:
117+
to_be_owned: '{{ q("k8s",
118+
api_version=item.apiVersion,
119+
kind=item.kind,
120+
resource_name=item.name,
121+
namespace=item.namespace
122+
).0 }}'
123+
owner_reference:
124+
apiVersion: "{{ owning_resource.apiVersion }}"
125+
kind: "{{ owning_resource.kind }}"
126+
name: "{{ owning_resource.name }}"
127+
uid: "{{ extra_owner_data.resources[0].metadata.uid }}"
128+
```
129+
130+
#### `each_resource.yml`
131+
132+
``` yaml
133+
- name: Patch resource with owner reference
134+
when:
135+
- to_be_owned.metadata.namespace is defined
136+
- to_be_owned.metadata.namespace == owning_resource.namespace
137+
- (to_be_owned.metadata.ownerReferences is not defined) or
138+
(owner_reference not in to_be_owned.metadata.ownerReferences)
139+
k8s:
140+
state: present
141+
resource_definition:
142+
apiVersion: "{{ to_be_owned.apiVersion }}"
143+
kind: "{{ to_be_owned.kind }}"
144+
metadata:
145+
name: "{{ to_be_owned.metadata.name }}"
146+
namespace: "{{ to_be_owned.metadata.namespace }}"
147+
ownerReferences: "{{ (to_be_owned.metadata.ownerReferences | default([])) + [owner_reference] }}"
148+
149+
- name: Patch resource with owner annotation
150+
when: to_be_owned.namespace is not defined or to_be_owned.namespace != owning_resource.namespace
151+
k8s:
152+
state: present
153+
resource_definition:
154+
apiVersion: "{{ to_be_owned.apiVersion }}"
155+
kind: "{{ to_be_owned.kind }}"
156+
metadata:
157+
name: "{{ to_be_owned.metadata.name }}"
158+
namespace: "{{ to_be_owned.metadata.namespace | default(omit)}}"
159+
annotations:
160+
operator-sdk/primary-resource: "{{ owning_resource.namespace }}/{{ owning_resource.name }}"
161+
operator-sdk/primary-resource-type: "{{ owning_resource.kind }}.{{ owning_resource.apiVersion.split('/')[0] }}"
162+
```

0 commit comments

Comments
 (0)