Skip to content

Commit 3b5f7b4

Browse files
authored
Merge pull request #23 from thschue/main
feat: clean up configmaps
2 parents 6884720 + 75e266e commit 3b5f7b4

File tree

6 files changed

+91
-38
lines changed

6 files changed

+91
-38
lines changed

Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ COPY main.go main.go
1616
COPY apis/ apis/
1717
COPY webhooks/ webhooks/
1818
COPY controllers/ controllers/
19+
COPY pkg/ pkg/
1920

2021
# Build
2122
RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -a -o manager main.go

config/manager/manager.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ spec:
3131
- /manager
3232
args:
3333
- --leader-elect
34-
image: controller:latest
34+
imagePullPolicy: Always
35+
image: controller:main
3536
name: manager
3637
securityContext:
3738
allowPrivilegeEscalation: false

controllers/featureflagconfiguration_controller.go

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package controllers
1919
import (
2020
"context"
2121
"github.com/go-logr/logr"
22+
"github.com/open-feature/open-feature-operator/pkg/utils"
2223
corev1 "k8s.io/api/core/v1"
2324
"k8s.io/apimachinery/pkg/api/errors"
2425
"k8s.io/client-go/tools/record"
@@ -83,15 +84,15 @@ func (r *FeatureFlagConfigurationReconciler) Reconcile(ctx context.Context, req
8384
// The object is not being deleted, so if it does not have our finalizer,
8485
// then lets add the finalizer and update the object. This is equivalent
8586
// registering our finalizer.
86-
if !ContainsString(ffconf.GetFinalizers(), finalizerName) {
87+
if !utils.ContainsString(ffconf.GetFinalizers(), finalizerName) {
8788
controllerutil.AddFinalizer(ffconf, finalizerName)
8889
if err := r.Update(ctx, ffconf); err != nil {
8990
return r.finishReconcile(err, false)
9091
}
9192
}
9293
} else {
9394
// The object is being deleted
94-
if ContainsString(ffconf.GetFinalizers(), finalizerName) {
95+
if utils.ContainsString(ffconf.GetFinalizers(), finalizerName) {
9596
controllerutil.RemoveFinalizer(ffconf, finalizerName)
9697
if err := r.Update(ctx, ffconf); err != nil {
9798
return ctrl.Result{}, err
@@ -116,8 +117,23 @@ func (r *FeatureFlagConfigurationReconciler) Reconcile(ctx context.Context, req
116117
}
117118
}
118119

119-
// Update ConfigMaps
120120
for _, cm := range ffConfigMapList {
121+
// Append OwnerReference if not set
122+
if !r.featureFlagResourceIsOwner(ffconf, cm) {
123+
r.Log.Info("Setting owner reference for " + cm.Name)
124+
cm.OwnerReferences = append(cm.OwnerReferences, utils.GetFfReference(ffconf))
125+
err := r.Client.Update(ctx, &cm)
126+
if err != nil {
127+
return r.finishReconcile(err, true)
128+
}
129+
} else if len(cm.OwnerReferences) == 1 {
130+
// Delete ConfigMap if the Controller is the only reference
131+
r.Log.Info("Deleting configmap " + cm.Name)
132+
err := r.Client.Delete(ctx, &cm)
133+
return r.finishReconcile(err, true)
134+
}
135+
// Update ConfigMap Spec
136+
r.Log.Info("Updating ConfigMap Spec " + cm.Name)
121137
cm.Data = map[string]string{
122138
"config.yaml": ffconf.Spec.FeatureFlagSpec,
123139
}
@@ -126,6 +142,7 @@ func (r *FeatureFlagConfigurationReconciler) Reconcile(ctx context.Context, req
126142
return r.finishReconcile(err, true)
127143
}
128144
}
145+
129146
return r.finishReconcile(nil, false)
130147
}
131148

@@ -137,15 +154,6 @@ func (r *FeatureFlagConfigurationReconciler) SetupWithManager(mgr ctrl.Manager)
137154
Complete(r)
138155
}
139156

140-
func ContainsString(slice []string, s string) bool {
141-
for _, item := range slice {
142-
if item == s {
143-
return true
144-
}
145-
}
146-
return false
147-
}
148-
149157
func (r *FeatureFlagConfigurationReconciler) finishReconcile(err error, requeueImmediate bool) (ctrl.Result, error) {
150158
if err != nil {
151159
interval := reconcileErrorInterval
@@ -162,3 +170,12 @@ func (r *FeatureFlagConfigurationReconciler) finishReconcile(err error, requeueI
162170
r.Log.Info("Finished Reconciling " + crdName)
163171
return ctrl.Result{Requeue: true, RequeueAfter: interval}, nil
164172
}
173+
174+
func (r *FeatureFlagConfigurationReconciler) featureFlagResourceIsOwner(ff *configv1alpha1.FeatureFlagConfiguration, cm corev1.ConfigMap) bool {
175+
for _, cmOwner := range cm.OwnerReferences {
176+
if cmOwner.UID == utils.GetFfReference(ff).UID {
177+
return true
178+
}
179+
}
180+
return false
181+
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,4 @@ require (
7373
sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect
7474
sigs.k8s.io/structured-merge-diff/v4 v4.2.0 // indirect
7575
sigs.k8s.io/yaml v1.3.0 // indirect
76-
)
76+
)

pkg/utils/utils.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package utils
2+
3+
import (
4+
configv1alpha1 "github.com/open-feature/open-feature-operator/apis/core/v1alpha1"
5+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
6+
)
7+
8+
func TrueVal() *bool {
9+
b := true
10+
return &b
11+
}
12+
13+
func FalseVal() *bool {
14+
b := false
15+
return &b
16+
}
17+
18+
func ContainsString(slice []string, s string) bool {
19+
for _, item := range slice {
20+
if item == s {
21+
return true
22+
}
23+
}
24+
return false
25+
}
26+
27+
func GetFfReference(ff *configv1alpha1.FeatureFlagConfiguration) metav1.OwnerReference {
28+
return metav1.OwnerReference{
29+
APIVersion: ff.APIVersion,
30+
Kind: ff.Kind,
31+
Name: ff.Name,
32+
UID: ff.UID,
33+
Controller: TrueVal(),
34+
}
35+
}

webhooks/mutating_admission_webhook.go

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"fmt"
77
"github.com/go-logr/logr"
88
configv1alpha1 "github.com/open-feature/open-feature-operator/apis/core/v1alpha1"
9+
"github.com/open-feature/open-feature-operator/pkg/utils"
910
corev1 "k8s.io/api/core/v1"
1011
"k8s.io/apimachinery/pkg/api/errors"
1112
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -28,7 +29,6 @@ type PodMutator struct {
2829

2930
// PodMutator adds an annotation to every incoming pods.
3031
func (m *PodMutator) Handle(ctx context.Context, req admission.Request) admission.Response {
31-
3232
pod := &corev1.Pod{}
3333
err := m.decoder.Decode(req, pod)
3434
if err != nil {
@@ -57,24 +57,25 @@ func (m *PodMutator) Handle(ctx context.Context, req admission.Request) admissio
5757
// Check for ConfigMap and create it if it doesn't exist
5858
cm := corev1.ConfigMap{}
5959
if err := m.Client.Get(ctx, client.ObjectKey{Name: val, Namespace: req.Namespace}, &cm); errors.IsNotFound(err) {
60-
err := m.CreateConfigMap(ctx, val, req.Namespace, pod)
60+
err := m.createConfigMap(ctx, val, req.Namespace, pod)
6161
if err != nil {
6262
m.Log.V(1).Info(fmt.Sprintf("failed to create config map %s error: %s", val, err.Error()))
6363
return admission.Errored(http.StatusInternalServerError, err)
6464
}
6565
}
6666

67-
if !CheckOwnerReference(pod, cm) {
67+
// Add owner reference of the pod's owner
68+
if !podOwnerIsOwner(pod, cm) {
6869
reference := pod.OwnerReferences[0]
69-
reference.Controller = m.falseVal()
70+
reference.Controller = utils.FalseVal()
7071
cm.OwnerReferences = append(cm.OwnerReferences, reference)
7172
err := m.Client.Update(ctx, &cm)
7273
if err != nil {
7374
m.Log.V(1).Info(fmt.Sprintf("failed to update owner reference for %s error: %s", val, err.Error()))
7475
}
7576
}
7677

77-
marshaledPod, err := m.InjectSidecar(pod, val)
78+
marshaledPod, err := m.injectSidecar(pod, val)
7879
if err != nil {
7980
return admission.Errored(http.StatusInternalServerError, err)
8081
}
@@ -91,50 +92,53 @@ func (m *PodMutator) InjectDecoder(d *admission.Decoder) error {
9192
return nil
9293
}
9394

94-
func CheckOwnerReference(pod *corev1.Pod, cm corev1.ConfigMap) bool {
95+
func podOwnerIsOwner(pod *corev1.Pod, cm corev1.ConfigMap) bool {
9596
for _, cmOwner := range cm.OwnerReferences {
9697
for _, podOwner := range pod.OwnerReferences {
97-
if cmOwner == podOwner {
98+
if cmOwner.UID == podOwner.UID {
9899
return true
99100
}
100101
}
101102
}
102103
return false
103104
}
104105

105-
func (m *PodMutator) CreateConfigMap(ctx context.Context, name string, namespace string, pod *corev1.Pod) error {
106+
func (m *PodMutator) createConfigMap(ctx context.Context, name string, namespace string, pod *corev1.Pod) error {
106107
m.Log.V(1).Info(fmt.Sprintf("Creating configmap %s", name))
107-
reference := pod.OwnerReferences[0]
108-
reference.Controller = m.falseVal()
108+
references := []metav1.OwnerReference{
109+
pod.OwnerReferences[0],
110+
}
111+
references[0].Controller = utils.FalseVal()
112+
ff := m.getFeatureFlag(ctx, name, namespace)
113+
if ff.Name != "" {
114+
references = append(references, utils.GetFfReference(&ff))
115+
}
109116

110-
spec := m.GetFeatureFlagSpec(ctx, name, namespace)
111117
cm := corev1.ConfigMap{
112118
ObjectMeta: metav1.ObjectMeta{
113119
Name: name,
114120
Namespace: namespace,
115121
Annotations: map[string]string{
116122
"openfeature.dev/featureflagconfiguration": name,
117123
},
118-
OwnerReferences: []metav1.OwnerReference{
119-
reference,
120-
},
124+
OwnerReferences: references,
121125
},
122126
Data: map[string]string{
123-
"config.yaml": spec.FeatureFlagSpec,
127+
"config.yaml": ff.Spec.FeatureFlagSpec,
124128
},
125129
}
126130
return m.Client.Create(ctx, &cm)
127131
}
128132

129-
func (m *PodMutator) GetFeatureFlagSpec(ctx context.Context, name string, namespace string) configv1alpha1.FeatureFlagConfigurationSpec {
133+
func (m *PodMutator) getFeatureFlag(ctx context.Context, name string, namespace string) configv1alpha1.FeatureFlagConfiguration {
130134
ffConfig := configv1alpha1.FeatureFlagConfiguration{}
131135
if err := m.Client.Get(ctx, client.ObjectKey{Name: name, Namespace: namespace}, &ffConfig); errors.IsNotFound(err) {
132-
return configv1alpha1.FeatureFlagConfigurationSpec{}
136+
return configv1alpha1.FeatureFlagConfiguration{}
133137
}
134-
return ffConfig.Spec
138+
return ffConfig
135139
}
136140

137-
func (m *PodMutator) InjectSidecar(pod *corev1.Pod, configMap string) ([]byte, error) {
141+
func (m *PodMutator) injectSidecar(pod *corev1.Pod, configMap string) ([]byte, error) {
138142
m.Log.V(1).Info(fmt.Sprintf("Creating sidecar for pod %s/%s", pod.Namespace, pod.Name))
139143
// Inject the agent
140144
pod.Spec.Volumes = append(pod.Spec.Volumes, corev1.Volume{
@@ -162,8 +166,3 @@ func (m *PodMutator) InjectSidecar(pod *corev1.Pod, configMap string) ([]byte, e
162166
})
163167
return json.Marshal(pod)
164168
}
165-
166-
func (m *PodMutator) falseVal() *bool {
167-
b := false
168-
return &b
169-
}

0 commit comments

Comments
 (0)