Skip to content

Commit ea6d221

Browse files
committed
Enable OwnerReference API for resources created by OperandConfig
Signed-off-by: Daniel Fan <[email protected]>
1 parent c96ea32 commit ea6d221

File tree

4 files changed

+165
-7
lines changed

4 files changed

+165
-7
lines changed

controllers/operandrequest/reconcile_operand.go

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -265,14 +265,14 @@ func (r *Reconciler) reconcileCRwithConfig(ctx context.Context, service *operato
265265
if err != nil && !apierrors.IsNotFound(err) {
266266
merr.Add(errors.Wrapf(err, "failed to get k8s resource %s/%s", k8sResNs, res.Name))
267267
} else if apierrors.IsNotFound(err) {
268-
if err := r.createK8sResource(ctx, k8sRes, res.Data, res.Labels, res.Annotations); err != nil {
268+
if err := r.createK8sResource(ctx, k8sRes, res.Data, res.Labels, res.Annotations, &res.OwnerReferences); err != nil {
269269
merr.Add(err)
270270
}
271271
} else {
272272
if res.Force {
273273
// Update k8s resource
274274
klog.V(3).Info("Found existing k8s resource: " + res.Name)
275-
if err := r.updateK8sResource(ctx, k8sRes, res.Data, res.Labels, res.Annotations); err != nil {
275+
if err := r.updateK8sResource(ctx, k8sRes, res.Data, res.Labels, res.Annotations, &res.OwnerReferences); err != nil {
276276
merr.Add(err)
277277
}
278278
} else {
@@ -939,7 +939,7 @@ func (r *Reconciler) checkCustomResource(ctx context.Context, requestInstance *o
939939
return nil
940940
}
941941

942-
func (r *Reconciler) createK8sResource(ctx context.Context, k8sResTemplate unstructured.Unstructured, k8sResConfig *runtime.RawExtension, newLabels, newAnnotations map[string]string) error {
942+
func (r *Reconciler) createK8sResource(ctx context.Context, k8sResTemplate unstructured.Unstructured, k8sResConfig *runtime.RawExtension, newLabels, newAnnotations map[string]string, ownerReferences *[]operatorv1alpha1.OwnerReference) error {
943943
kind := k8sResTemplate.GetKind()
944944
name := k8sResTemplate.GetName()
945945
namespace := k8sResTemplate.GetNamespace()
@@ -959,6 +959,9 @@ func (r *Reconciler) createK8sResource(ctx context.Context, k8sResTemplate unstr
959959
r.EnsureLabel(k8sResTemplate, map[string]string{constant.OpreqLabel: "true"})
960960
r.EnsureLabel(k8sResTemplate, newLabels)
961961
r.EnsureAnnotation(k8sResTemplate, newAnnotations)
962+
if err := r.setOwnerReferences(ctx, &k8sResTemplate, ownerReferences); err != nil {
963+
return errors.Wrap(err, "failed to set ownerReferences for k8s resource")
964+
}
962965

963966
// Create the k8s resource
964967
err := r.Create(ctx, &k8sResTemplate)
@@ -971,7 +974,7 @@ func (r *Reconciler) createK8sResource(ctx context.Context, k8sResTemplate unstr
971974
return nil
972975
}
973976

974-
func (r *Reconciler) updateK8sResource(ctx context.Context, existingK8sRes unstructured.Unstructured, k8sResConfig *runtime.RawExtension, newLabels, newAnnotations map[string]string) error {
977+
func (r *Reconciler) updateK8sResource(ctx context.Context, existingK8sRes unstructured.Unstructured, k8sResConfig *runtime.RawExtension, newLabels, newAnnotations map[string]string, ownerReferences *[]operatorv1alpha1.OwnerReference) error {
975978
kind := existingK8sRes.GetKind()
976979
apiversion := existingK8sRes.GetAPIVersion()
977980
name := existingK8sRes.GetName()
@@ -1023,7 +1026,7 @@ func (r *Reconciler) updateK8sResource(ctx context.Context, existingK8sRes unstr
10231026
if err := r.deleteK8sResource(ctx, existingK8sRes, namespace); err != nil {
10241027
return errors.Wrap(err, "failed to update k8s resource")
10251028
}
1026-
if err := r.createK8sResource(ctx, templatek8sRes, k8sResConfig, newLabels, newAnnotations); err != nil {
1029+
if err := r.createK8sResource(ctx, templatek8sRes, k8sResConfig, newLabels, newAnnotations, ownerReferences); err != nil {
10271030
return errors.Wrap(err, "failed to update k8s resource")
10281031
}
10291032
}
@@ -1076,6 +1079,9 @@ func (r *Reconciler) updateK8sResource(ctx context.Context, existingK8sRes unstr
10761079

10771080
r.EnsureAnnotation(existingK8sRes, newAnnotations)
10781081
r.EnsureLabel(existingK8sRes, newLabels)
1082+
if err := r.setOwnerReferences(ctx, &existingK8sRes, ownerReferences); err != nil {
1083+
return false, errors.Wrapf(err, "failed to set ownerReferences for k8s resource -- Kind: %s, NamespacedName: %s/%s", kind, namespace, name)
1084+
}
10791085

10801086
klog.V(2).Infof("updating k8s resource with apiversion: %s, kind: %s, %s/%s", apiversion, kind, namespace, name)
10811087

@@ -1279,3 +1285,32 @@ func (r *Reconciler) ResourceForKind(gvk schema.GroupVersionKind, namespace stri
12791285
}
12801286
return &mapping.Resource, nil
12811287
}
1288+
1289+
func (r *Reconciler) setOwnerReferences(ctx context.Context, controlledRes *unstructured.Unstructured, ownerReferences *[]operatorv1alpha1.OwnerReference) error {
1290+
if ownerReferences != nil {
1291+
for _, owner := range *ownerReferences {
1292+
ownerObj := unstructured.Unstructured{}
1293+
ownerObj.SetAPIVersion(owner.APIVersion)
1294+
ownerObj.SetKind(owner.Kind)
1295+
ownerObj.SetName(owner.Name)
1296+
1297+
if err := r.Reader.Get(ctx, types.NamespacedName{
1298+
Name: owner.Name,
1299+
Namespace: controlledRes.GetNamespace(),
1300+
}, &ownerObj); err != nil {
1301+
return errors.Wrapf(err, "failed to get owner object -- Kind: %s, NamespacedName: %s/%s", owner.Kind, controlledRes.GetNamespace(), owner.Name)
1302+
}
1303+
if owner.Controller != nil && *owner.Controller {
1304+
if err := controllerutil.SetControllerReference(&ownerObj, controlledRes, r.Scheme); err != nil {
1305+
return errors.Wrapf(err, "failed to set controller ownerReference for k8s resource -- Kind: %s, NamespacedName: %s/%s", controlledRes.GetKind(), controlledRes.GetNamespace(), controlledRes.GetName())
1306+
}
1307+
} else {
1308+
if err := controllerutil.SetOwnerReference(&ownerObj, controlledRes, r.Scheme); err != nil {
1309+
return errors.Wrapf(err, "failed to set ownerReference for k8s resource -- Kind: %s, NamespacedName: %s/%s", controlledRes.GetKind(), controlledRes.GetNamespace(), controlledRes.GetName())
1310+
}
1311+
}
1312+
klog.Infof("Set %s with name %s as Owner for k8s resource -- Kind: %s, NamespacedName: %s/%s", owner.Kind, owner.Name, controlledRes.GetKind(), controlledRes.GetNamespace(), controlledRes.GetName())
1313+
}
1314+
}
1315+
return nil
1316+
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
//
2+
// Copyright 2022 IBM Corporation
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
//
16+
17+
package operandrequest
18+
19+
import (
20+
"context"
21+
"testing"
22+
23+
operatorv1alpha1 "github.com/IBM/operand-deployment-lifecycle-manager/api/v1alpha1"
24+
deploy "github.com/IBM/operand-deployment-lifecycle-manager/controllers/operator"
25+
"github.com/stretchr/testify/assert"
26+
"github.com/stretchr/testify/mock"
27+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
28+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
29+
"k8s.io/apimachinery/pkg/types"
30+
"k8s.io/utils/pointer"
31+
"sigs.k8s.io/controller-runtime/pkg/client"
32+
"sigs.k8s.io/controller-runtime/pkg/client/fake"
33+
)
34+
35+
type MockReader struct {
36+
mock.Mock
37+
}
38+
39+
func (m *MockReader) Get(ctx context.Context, key client.ObjectKey, obj client.Object) error {
40+
args := m.Called(ctx, key, obj)
41+
return args.Error(0)
42+
}
43+
func (m *MockReader) List(ctx context.Context, list client.ObjectList, opts ...client.ListOption) error {
44+
args := m.Called(ctx, list, opts)
45+
return args.Error(0)
46+
}
47+
48+
func TestSetOwnerReferences(t *testing.T) {
49+
// Create a fake client
50+
client := fake.NewClientBuilder().Build()
51+
52+
// Create a mock reader
53+
reader := &MockReader{}
54+
55+
// Create a reconciler instance
56+
r := &Reconciler{
57+
ODLMOperator: &deploy.ODLMOperator{
58+
Client: client,
59+
Reader: reader,
60+
},
61+
}
62+
63+
// Create the controlled resource
64+
controlledRes := &unstructured.Unstructured{
65+
Object: map[string]interface{}{
66+
"apiVersion": "v1",
67+
"kind": "Pod",
68+
"metadata": map[string]interface{}{
69+
"name": "test-pod",
70+
"namespace": "test-namespace",
71+
},
72+
},
73+
}
74+
75+
// Create the owner references
76+
ownerReferences := []operatorv1alpha1.OwnerReference{
77+
{
78+
APIVersion: "v1",
79+
Kind: "Deployment",
80+
Name: "test-deployment",
81+
Controller: pointer.BoolPtr(true),
82+
},
83+
{
84+
APIVersion: "v1",
85+
Kind: "Service",
86+
Name: "test-service",
87+
Controller: pointer.BoolPtr(false),
88+
},
89+
}
90+
91+
// Mock the Get method of the reader
92+
reader.On("Get", mock.Anything, types.NamespacedName{Name: "test-deployment", Namespace: "test-namespace"}, mock.AnythingOfType("*unstructured.Unstructured")).Return(nil)
93+
reader.On("Get", mock.Anything, types.NamespacedName{Name: "test-service", Namespace: "test-namespace"}, mock.AnythingOfType("*unstructured.Unstructured")).Return(nil)
94+
95+
// Call the setOwnerReferences function
96+
err := r.setOwnerReferences(context.Background(), controlledRes, &ownerReferences)
97+
98+
// Assert that there are no errors
99+
assert.NoError(t, err)
100+
101+
// Assert that the owner references are set correctly
102+
expectedOwnerReferences := []metav1.OwnerReference{
103+
{
104+
APIVersion: "v1",
105+
Kind: "Deployment",
106+
Name: "test-deployment",
107+
Controller: pointer.BoolPtr(true),
108+
BlockOwnerDeletion: pointer.BoolPtr(true),
109+
},
110+
{
111+
APIVersion: "v1",
112+
Kind: "Service",
113+
Name: "test-service",
114+
},
115+
}
116+
assert.Equal(t, expectedOwnerReferences, controlledRes.GetOwnerReferences())
117+
}

go.mod

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@ require (
1515
github.com/operator-framework/api v0.6.2
1616
github.com/operator-framework/operator-lifecycle-manager v0.17.0
1717
github.com/pkg/errors v0.9.1
18+
github.com/stretchr/testify v1.9.0
1819
golang.org/x/mod v0.8.0
1920
k8s.io/api v0.24.3
2021
k8s.io/apiextensions-apiserver v0.24.2
2122
k8s.io/apimachinery v0.24.3
2223
k8s.io/client-go v0.24.3
2324
k8s.io/klog v1.0.0
25+
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9
2426
sigs.k8s.io/controller-runtime v0.12.3
2527
sigs.k8s.io/kubebuilder v1.0.9-0.20200805184228-f7a3b65dd250
2628
)
@@ -66,6 +68,7 @@ require (
6668
github.com/operator-framework/operator-registry v1.13.6 // indirect
6769
github.com/pelletier/go-toml v1.9.5 // indirect
6870
github.com/pelletier/go-toml/v2 v2.0.1 // indirect
71+
github.com/pmezard/go-difflib v1.0.0 // indirect
6972
github.com/prometheus/client_golang v1.12.2 // indirect
7073
github.com/prometheus/client_model v0.2.0 // indirect
7174
github.com/prometheus/common v0.32.1 // indirect
@@ -76,6 +79,7 @@ require (
7679
github.com/spf13/jwalterweatherman v1.1.0 // indirect
7780
github.com/spf13/pflag v1.0.5 // indirect
7881
github.com/spf13/viper v1.12.0 // indirect
82+
github.com/stretchr/objx v0.5.2 // indirect
7983
github.com/subosito/gotenv v1.3.0 // indirect
8084
go.uber.org/atomic v1.7.0 // indirect
8185
go.uber.org/multierr v1.6.0 // indirect
@@ -99,7 +103,6 @@ require (
99103
k8s.io/component-base v0.24.2 // indirect
100104
k8s.io/klog/v2 v2.60.1 // indirect
101105
k8s.io/kube-openapi v0.0.0-20220627174259-011e075b9cb8 // indirect
102-
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 // indirect
103106
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 // indirect
104107
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect
105108
sigs.k8s.io/yaml v1.3.0 // indirect

go.sum

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -917,6 +917,8 @@ github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag
917917
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
918918
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
919919
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
920+
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
921+
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
920922
github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
921923
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
922924
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
@@ -926,7 +928,8 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
926928
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
927929
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
928930
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
929-
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
931+
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
932+
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
930933
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
931934
github.com/subosito/gotenv v1.3.0 h1:mjC+YW8QpAdXibNi+vNWgzmgBH4+5l5dCXv8cNysBLI=
932935
github.com/subosito/gotenv v1.3.0/go.mod h1:YzJjq/33h7nrwdY+iHMhEOEEbW0ovIz0tB6t6PwAXzs=

0 commit comments

Comments
 (0)