@@ -3,6 +3,7 @@ package flagdproxy
33import (
44 "context"
55 "fmt"
6+ "reflect"
67
78 "github.com/go-logr/logr"
89 "github.com/open-feature/open-feature-operator/common/types"
@@ -28,6 +29,8 @@ type FlagdProxyHandler struct {
2829 Log logr.Logger
2930}
3031
32+ type CreateUpdateFunc func (ctx context.Context , obj client.Object ) error
33+
3134type FlagdProxyConfiguration struct {
3235 Port int
3336 ManagementPort int
@@ -62,43 +65,58 @@ func (f *FlagdProxyHandler) Config() *FlagdProxyConfiguration {
6265 return f .config
6366}
6467
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+
6576func (f * FlagdProxyHandler ) HandleFlagdProxy (ctx context.Context ) error {
66- exists , err := f .doesFlagdProxyExist (ctx )
77+ exists , deployment , err := f .doesFlagdProxyExist (ctx )
6778 if err != nil {
6879 return err
6980 }
70- if ! exists {
71- return f .deployFlagdProxy (ctx )
72- }
73- return nil
74- }
7581
76- func (f * FlagdProxyHandler ) deployFlagdProxy (ctx context.Context ) error {
77- ownerReferences := []metav1.OwnerReference {}
7882 ownerReference , err := f .getOwnerReference (ctx )
7983 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 )
8392 }
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+ }
84101
102+ func (f * FlagdProxyHandler ) deployFlagdProxy (ctx context.Context , createUpdateFunc CreateUpdateFunc , deployment * appsV1.Deployment , service * corev1.Service ) error {
85103 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 ) {
87105 return err
88106 }
89107 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 ) {
91109 return err
92110 }
93111 return nil
94112}
95113
96- func (f * FlagdProxyHandler ) newFlagdProxyServiceManifest (ownerReferences [] metav1.OwnerReference ) * corev1.Service {
114+ func (f * FlagdProxyHandler ) newFlagdProxyServiceManifest (ownerReference * metav1.OwnerReference ) * corev1.Service {
97115 return & corev1.Service {
98116 ObjectMeta : metav1.ObjectMeta {
99117 Name : FlagdProxyServiceName ,
100118 Namespace : f .config .Namespace ,
101- OwnerReferences : ownerReferences ,
119+ OwnerReferences : []metav1. OwnerReference { * ownerReference } ,
102120 },
103121 Spec : corev1.ServiceSpec {
104122 Selector : map [string ]string {
@@ -116,7 +134,7 @@ func (f *FlagdProxyHandler) newFlagdProxyServiceManifest(ownerReferences []metav
116134 }
117135}
118136
119- func (f * FlagdProxyHandler ) newFlagdProxyManifest (ownerReferences [] metav1.OwnerReference ) * appsV1.Deployment {
137+ func (f * FlagdProxyHandler ) newFlagdProxyManifest (ownerReference * metav1.OwnerReference ) * appsV1.Deployment {
120138 replicas := int32 (1 )
121139 args := []string {
122140 "start" ,
@@ -135,7 +153,7 @@ func (f *FlagdProxyHandler) newFlagdProxyManifest(ownerReferences []metav1.Owner
135153 "app.kubernetes.io/managed-by" : ManagedByAnnotationValue ,
136154 "app.kubernetes.io/version" : f .config .Tag ,
137155 },
138- OwnerReferences : ownerReferences ,
156+ OwnerReferences : []metav1. OwnerReference { * ownerReference } ,
139157 },
140158 Spec : appsV1.DeploymentSpec {
141159 Replicas : & replicas ,
@@ -178,31 +196,53 @@ func (f *FlagdProxyHandler) newFlagdProxyManifest(ownerReferences []metav1.Owner
178196 }
179197}
180198
181- func (f * FlagdProxyHandler ) doesFlagdProxyExist (ctx context.Context ) (bool , error ) {
199+ func (f * FlagdProxyHandler ) doesFlagdProxyExist (ctx context.Context ) (bool , * appsV1. Deployment , error ) {
182200 d := & appsV1.Deployment {}
183201 err := f .Client .Get (ctx , client.ObjectKey {Name : FlagdProxyDeploymentName , Namespace : f .config .Namespace }, d )
184202 if err != nil {
185203 if errors .IsNotFound (err ) {
186204 // does not exist, is not ready, no error
187- return false , nil
205+ return false , nil , nil
188206 }
189207 // does not exist, is not ready, is in error
190- return false , err
208+ return false , nil , err
191209 }
192- // exists, at least one replica ready, no error
193- return true , nil
210+ return true , d , nil
194211}
195212
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 ) {
197222 d := & appsV1.Deployment {}
198223 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 )
200225 }
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 ,
206242 }, nil
243+ }
207244
245+ func isDeployedByOFO (d * appsV1.Deployment ) bool {
246+ val , ok := d .Labels ["app.kubernetes.io/managed-by" ]
247+ return ok && val == ManagedByAnnotationValue
208248}
0 commit comments