@@ -3,6 +3,7 @@ package flagdproxy
3
3
import (
4
4
"context"
5
5
"fmt"
6
+ "reflect"
6
7
7
8
"github.com/go-logr/logr"
8
9
"github.com/open-feature/open-feature-operator/common/types"
@@ -28,6 +29,8 @@ type FlagdProxyHandler struct {
28
29
Log logr.Logger
29
30
}
30
31
32
+ type CreateUpdateFunc func (ctx context.Context , obj client.Object ) error
33
+
31
34
type FlagdProxyConfiguration struct {
32
35
Port int
33
36
ManagementPort int
@@ -62,43 +65,58 @@ func (f *FlagdProxyHandler) Config() *FlagdProxyConfiguration {
62
65
return f .config
63
66
}
64
67
68
+ func (f * FlagdProxyHandler ) createObject (ctx context.Context , obj client.Object ) error {
69
+ return f .Client .Create (ctx , obj )
70
+ }
71
+
72
+ func (f * FlagdProxyHandler ) updateObject (ctx context.Context , obj client.Object ) error {
73
+ return f .Client .Update (ctx , obj )
74
+ }
75
+
65
76
func (f * FlagdProxyHandler ) HandleFlagdProxy (ctx context.Context ) error {
66
- exists , err := f .doesFlagdProxyExist (ctx )
77
+ exists , deployment , err := f .doesFlagdProxyExist (ctx )
67
78
if err != nil {
68
79
return err
69
80
}
70
- if ! exists {
71
- return f .deployFlagdProxy (ctx )
72
- }
73
- return nil
74
- }
75
81
76
- func (f * FlagdProxyHandler ) deployFlagdProxy (ctx context.Context ) error {
77
- ownerReferences := []metav1.OwnerReference {}
78
82
ownerReference , err := f .getOwnerReference (ctx )
79
83
if err != nil {
80
- f .Log .Error (err , "unable to create owner reference for open-feature-operator, not appending" )
81
- } else {
82
- ownerReferences = append (ownerReferences , ownerReference )
84
+ return err
85
+ }
86
+ newDeployment := f .newFlagdProxyManifest (ownerReference )
87
+ newService := f .newFlagdProxyServiceManifest (ownerReference )
88
+
89
+ if ! exists {
90
+ f .Log .Info ("flagd-proxy Deployment does not exist, creating" )
91
+ return f .deployFlagdProxy (ctx , f .createObject , newDeployment , newService )
83
92
}
93
+ // flagd-proxy exists, need to check if we should update it
94
+ if f .shouldUpdateFlagdProxy (deployment , newDeployment ) {
95
+ f .Log .Info ("flagd-proxy Deployment out of sync, updating" )
96
+ return f .deployFlagdProxy (ctx , f .updateObject , newDeployment , newService )
97
+ }
98
+ f .Log .Info ("flagd-proxy Deployment up-to-date" )
99
+ return nil
100
+ }
84
101
102
+ func (f * FlagdProxyHandler ) deployFlagdProxy (ctx context.Context , createUpdateFunc CreateUpdateFunc , deployment * appsV1.Deployment , service * corev1.Service ) error {
85
103
f .Log .Info ("deploying the flagd-proxy" )
86
- if err := f . Client . Create (ctx , f . newFlagdProxyManifest ( ownerReferences ) ); err != nil && ! errors .IsAlreadyExists (err ) {
104
+ if err := createUpdateFunc (ctx , deployment ); err != nil && ! errors .IsAlreadyExists (err ) {
87
105
return err
88
106
}
89
107
f .Log .Info ("deploying the flagd-proxy service" )
90
- if err := f . Client . Create (ctx , f . newFlagdProxyServiceManifest ( ownerReferences ) ); err != nil && ! errors .IsAlreadyExists (err ) {
108
+ if err := createUpdateFunc (ctx , service ); err != nil && ! errors .IsAlreadyExists (err ) {
91
109
return err
92
110
}
93
111
return nil
94
112
}
95
113
96
- func (f * FlagdProxyHandler ) newFlagdProxyServiceManifest (ownerReferences [] metav1.OwnerReference ) * corev1.Service {
114
+ func (f * FlagdProxyHandler ) newFlagdProxyServiceManifest (ownerReference * metav1.OwnerReference ) * corev1.Service {
97
115
return & corev1.Service {
98
116
ObjectMeta : metav1.ObjectMeta {
99
117
Name : FlagdProxyServiceName ,
100
118
Namespace : f .config .Namespace ,
101
- OwnerReferences : ownerReferences ,
119
+ OwnerReferences : []metav1. OwnerReference { * ownerReference } ,
102
120
},
103
121
Spec : corev1.ServiceSpec {
104
122
Selector : map [string ]string {
@@ -116,7 +134,7 @@ func (f *FlagdProxyHandler) newFlagdProxyServiceManifest(ownerReferences []metav
116
134
}
117
135
}
118
136
119
- func (f * FlagdProxyHandler ) newFlagdProxyManifest (ownerReferences [] metav1.OwnerReference ) * appsV1.Deployment {
137
+ func (f * FlagdProxyHandler ) newFlagdProxyManifest (ownerReference * metav1.OwnerReference ) * appsV1.Deployment {
120
138
replicas := int32 (1 )
121
139
args := []string {
122
140
"start" ,
@@ -135,7 +153,7 @@ func (f *FlagdProxyHandler) newFlagdProxyManifest(ownerReferences []metav1.Owner
135
153
"app.kubernetes.io/managed-by" : ManagedByAnnotationValue ,
136
154
"app.kubernetes.io/version" : f .config .Tag ,
137
155
},
138
- OwnerReferences : ownerReferences ,
156
+ OwnerReferences : []metav1. OwnerReference { * ownerReference } ,
139
157
},
140
158
Spec : appsV1.DeploymentSpec {
141
159
Replicas : & replicas ,
@@ -178,31 +196,53 @@ func (f *FlagdProxyHandler) newFlagdProxyManifest(ownerReferences []metav1.Owner
178
196
}
179
197
}
180
198
181
- func (f * FlagdProxyHandler ) doesFlagdProxyExist (ctx context.Context ) (bool , error ) {
199
+ func (f * FlagdProxyHandler ) doesFlagdProxyExist (ctx context.Context ) (bool , * appsV1. Deployment , error ) {
182
200
d := & appsV1.Deployment {}
183
201
err := f .Client .Get (ctx , client.ObjectKey {Name : FlagdProxyDeploymentName , Namespace : f .config .Namespace }, d )
184
202
if err != nil {
185
203
if errors .IsNotFound (err ) {
186
204
// does not exist, is not ready, no error
187
- return false , nil
205
+ return false , nil , nil
188
206
}
189
207
// does not exist, is not ready, is in error
190
- return false , err
208
+ return false , nil , err
191
209
}
192
- // exists, at least one replica ready, no error
193
- return true , nil
210
+ return true , d , nil
194
211
}
195
212
196
- func (f * FlagdProxyHandler ) getOwnerReference (ctx context.Context ) (metav1.OwnerReference , error ) {
213
+ func (f * FlagdProxyHandler ) shouldUpdateFlagdProxy (old , new * appsV1.Deployment ) bool {
214
+ if ! isDeployedByOFO (old ) {
215
+ f .Log .Info ("flagd-proxy Deployment not managed by OFO" )
216
+ return false
217
+ }
218
+ return ! reflect .DeepEqual (old .Spec , new .Spec )
219
+ }
220
+
221
+ func (f * FlagdProxyHandler ) getOperatorDeployment (ctx context.Context ) (* appsV1.Deployment , error ) {
197
222
d := & appsV1.Deployment {}
198
223
if err := f .Client .Get (ctx , client.ObjectKey {Name : f .config .OperatorDeploymentName , Namespace : f .config .Namespace }, d ); err != nil {
199
- return metav1. OwnerReference {} , fmt .Errorf ("unable to fetch operator deployment to create owner reference : %w" , err )
224
+ return nil , fmt .Errorf ("unable to fetch operator deployment: %w" , err )
200
225
}
201
- return metav1.OwnerReference {
202
- UID : d .GetUID (),
203
- Name : d .GetName (),
204
- APIVersion : d .APIVersion ,
205
- Kind : d .Kind ,
226
+ return d , nil
227
+
228
+ }
229
+
230
+ func (f * FlagdProxyHandler ) getOwnerReference (ctx context.Context ) (* metav1.OwnerReference , error ) {
231
+ operatorDeployment , err := f .getOperatorDeployment (ctx )
232
+ if err != nil {
233
+ f .Log .Error (err , "unable to create owner reference for open-feature-operator" )
234
+ return nil , err
235
+ }
236
+
237
+ return & metav1.OwnerReference {
238
+ UID : operatorDeployment .GetUID (),
239
+ Name : operatorDeployment .GetName (),
240
+ APIVersion : operatorDeployment .APIVersion ,
241
+ Kind : operatorDeployment .Kind ,
206
242
}, nil
243
+ }
207
244
245
+ func isDeployedByOFO (d * appsV1.Deployment ) bool {
246
+ val , ok := d .Labels ["app.kubernetes.io/managed-by" ]
247
+ return ok && val == ManagedByAnnotationValue
208
248
}
0 commit comments