@@ -17,12 +17,14 @@ limitations under the License.
17
17
package controllers
18
18
19
19
import (
20
+ "bytes"
20
21
"context"
21
22
"fmt"
23
+ appsv1 "k8s.io/api/apps/v1"
24
+ "text/template"
22
25
"time"
23
26
24
27
"gopkg.in/yaml.v3"
25
- appsv1 "k8s.io/api/apps/v1"
26
28
v1 "k8s.io/api/core/v1"
27
29
"k8s.io/apimachinery/pkg/runtime"
28
30
"k8s.io/apimachinery/pkg/types"
@@ -89,6 +91,7 @@ func (r *InspectorReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
89
91
if err := r .Update (ctx , & inspector ); err != nil {
90
92
return ctrl.Result {}, err
91
93
}
94
+ return ctrl.Result {Requeue : true }, nil
92
95
}
93
96
} else {
94
97
// The object is being deleted
@@ -100,6 +103,10 @@ func (r *InspectorReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
100
103
return ctrl.Result {}, err
101
104
}
102
105
106
+ if err := r .configureSherlock (ctx , & inspector , false ); err != nil {
107
+ return ctrl.Result {}, err
108
+ }
109
+
103
110
// remove our finalizer from the list and update it.
104
111
controllerutil .RemoveFinalizer (& inspector , finalizerName )
105
112
if err := r .Update (ctx , & inspector ); err != nil {
@@ -110,13 +117,80 @@ func (r *InspectorReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
110
117
// Stop reconciliation as the item is being deleted
111
118
return ctrl.Result {}, nil
112
119
}
120
+
121
+ scrapePoints , err := r .configureGazer (ctx , & inspector )
122
+ if err != nil {
123
+ return ctrl.Result {}, err
124
+ }
125
+
126
+ if err := r .configureSherlock (ctx , & inspector , true ); err != nil {
127
+ return ctrl.Result {}, err
128
+ }
129
+
130
+ // Update local status
131
+ var MonitoredIPs []string
132
+ for k := range scrapePoints {
133
+ MonitoredIPs = append (MonitoredIPs , k )
134
+ }
135
+ inspector .Status .MonitoredIPs = MonitoredIPs
136
+ inspector .Status .Status = lazykoalav1alpha1 .Running
137
+
138
+ if err := r .Status ().Update (ctx , & inspector ); err != nil {
139
+ return ctrl.Result {}, err
140
+ }
141
+
142
+ return ctrl.Result {RequeueAfter : time .Minute }, nil
143
+ }
144
+
145
+ func (r * InspectorReconciler ) removeMonitoredIPs (inspector * lazykoalav1alpha1.Inspector ) error {
146
+ // --------------------- START OF GAZER CONFIG --------------------- //
147
+ // Get the Gazer config file
148
+ var configMap v1.ConfigMap
149
+ if err := r .Get (context .Background (), types.NamespacedName {
150
+ Namespace : "lazy-koala" ,
151
+ Name : "gazer-config" ,
152
+ }, & configMap ); err != nil {
153
+ return err
154
+ }
155
+
156
+ // Phase the config.yaml
157
+ configData := make (map [string ]ScrapePoint )
158
+ if err := yaml .Unmarshal ([]byte (configMap .Data ["config.yaml" ]), & configData ); err != nil {
159
+ return err
160
+ }
161
+
162
+ // Remove all the existing scrape points created from this Inspector
163
+ for _ , ip := range inspector .Status .MonitoredIPs {
164
+ if _ , ok := configData [ip ]; ok {
165
+ delete (configData , ip )
166
+ }
167
+ }
168
+
169
+ // Encode the config.yaml
170
+ encodedConfig , err := yaml .Marshal (& configData )
171
+ if err != nil {
172
+ return err
173
+ }
174
+
175
+ // Patch the config file
176
+ configMap .Data ["config.yaml" ] = string (encodedConfig )
177
+ if err := r .Update (context .Background (), & configMap ); err != nil {
178
+ return err
179
+ }
180
+
181
+ return nil
182
+ }
183
+
184
+ func (r * InspectorReconciler ) configureGazer (ctx context.Context , inspector * lazykoalav1alpha1.Inspector ) (map [string ]ScrapePoint , error ) {
185
+ logger := log .FromContext (ctx )
186
+
113
187
// Get the intended deployment
114
188
var deploymentRef appsv1.Deployment
115
189
if err := r .Get (ctx , types.NamespacedName {
116
190
Namespace : inspector .Spec .Namespace ,
117
191
Name : inspector .Spec .DeploymentRef ,
118
192
}, & deploymentRef ); err != nil {
119
- return ctrl. Result {} , err
193
+ return nil , err
120
194
}
121
195
122
196
scrapePoints := make (map [string ]ScrapePoint )
@@ -127,7 +201,7 @@ func (r *InspectorReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
127
201
var podList v1.PodList
128
202
if err := r .List (ctx , & podList , & selector ); client .IgnoreNotFound (err ) != nil {
129
203
logger .Error (err , fmt .Sprintf ("failed to pods for deployment %s" , deploymentRef .ObjectMeta .Name ))
130
- return ctrl. Result {} , err
204
+ return nil , err
131
205
}
132
206
133
207
// Create Scrape point for each pod
@@ -147,7 +221,7 @@ func (r *InspectorReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
147
221
Namespace : inspector .Spec .Namespace ,
148
222
Name : inspector .Spec .ServiceRef ,
149
223
}, & serviceRef ); err != nil {
150
- return ctrl. Result {} , err
224
+ return nil , err
151
225
}
152
226
153
227
scrapePoints [serviceRef .Spec .ClusterIP ] = ScrapePoint {
@@ -159,91 +233,89 @@ func (r *InspectorReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
159
233
}
160
234
161
235
// Get the Gazer config file
162
- var configMap v1.ConfigMap
236
+ var gazerConfigMap v1.ConfigMap
163
237
if err := r .Get (ctx , types.NamespacedName {
164
238
Namespace : "lazy-koala" ,
165
239
Name : "gazer-config" ,
166
- }, & configMap ); err != nil {
167
- return ctrl. Result {} , err
240
+ }, & gazerConfigMap ); err != nil {
241
+ return nil , err
168
242
}
169
243
170
244
// Phase the config.yaml
171
- configData := make (map [string ]ScrapePoint )
172
- if err := yaml .Unmarshal ([]byte (configMap .Data ["config.yaml" ]), & configData ); err != nil {
173
- return ctrl. Result {} , err
245
+ gazerData := make (map [string ]ScrapePoint )
246
+ if err := yaml .Unmarshal ([]byte (gazerConfigMap .Data ["config.yaml" ]), & gazerData ); err != nil {
247
+ return nil , err
174
248
}
175
249
176
250
// Remove all the existing scrape points created from this Inspector
177
251
for _ , ip := range inspector .Status .MonitoredIPs {
178
- if _ , ok := configData [ip ]; ok {
179
- delete (configData , ip )
252
+ if _ , ok := gazerData [ip ]; ok {
253
+ delete (gazerData , ip )
180
254
}
181
255
}
182
256
183
257
// Add the new scrape points
184
258
for k , v := range scrapePoints {
185
- configData [k ] = v
259
+ gazerData [k ] = v
186
260
}
187
261
188
262
// Encode the config.yaml
189
- encodedConfig , err := yaml .Marshal (& configData )
263
+ encodedConfig , err := yaml .Marshal (& gazerData )
190
264
if err != nil {
191
- return ctrl. Result {} , err
265
+ return nil , err
192
266
}
193
267
194
268
// Patch the config file
195
- configMap .Data ["config.yaml" ] = string (encodedConfig )
196
- if err := r .Update (ctx , & configMap ); err != nil {
197
- return ctrl. Result {} , err
269
+ gazerConfigMap .Data ["config.yaml" ] = string (encodedConfig )
270
+ if err := r .Update (ctx , & gazerConfigMap ); err != nil {
271
+ return nil , err
198
272
}
199
273
200
- // Update local status
201
- var MonitoredIPs []string
202
- for k := range scrapePoints {
203
- MonitoredIPs = append (MonitoredIPs , k )
204
- }
205
- inspector .Status .MonitoredIPs = MonitoredIPs
206
- inspector .Status .Status = lazykoalav1alpha1 .Running
207
-
208
- if err := r .Status ().Update (ctx , & inspector ); err != nil {
209
- return ctrl.Result {}, err
210
- }
211
-
212
- return ctrl.Result {RequeueAfter : time .Minute }, nil
274
+ return scrapePoints , nil
213
275
}
214
276
215
- func (r * InspectorReconciler ) removeMonitoredIPs ( inspector * lazykoalav1alpha1.Inspector ) error {
216
- // Get the Gazer config file
217
- var configMap v1.ConfigMap
218
- if err := r .Get (context . Background () , types.NamespacedName {
277
+ func (r * InspectorReconciler ) configureSherlock ( ctx context. Context , inspector * lazykoalav1alpha1.Inspector , append bool ) error {
278
+ // Get the Sherlock config file
279
+ var sherlockConfigMap v1.ConfigMap
280
+ if err := r .Get (ctx , types.NamespacedName {
219
281
Namespace : "lazy-koala" ,
220
- Name : "gazer -config" ,
221
- }, & configMap ); err != nil {
282
+ Name : "sherlock -config" ,
283
+ }, & sherlockConfigMap ); err != nil {
222
284
return err
223
285
}
224
286
225
- // Phase the config .yaml
226
- configData := make ( map [ string ] ScrapePoint )
227
- if err := yaml .Unmarshal ([]byte (configMap .Data ["config .yaml" ]), & configData ); err != nil {
287
+ // Phase the services .yaml
288
+ var sherlockServiceList [] string
289
+ if err := yaml .Unmarshal ([]byte (sherlockConfigMap .Data ["services .yaml" ]), & sherlockServiceList ); err != nil {
228
290
return err
229
291
}
230
292
231
- // Remove all the existing scrape points created from this Inspector
232
- for _ , ip := range inspector .Status .MonitoredIPs {
233
- if _ , ok := configData [ip ]; ok {
234
- delete (configData , ip )
235
- }
293
+ if append {
294
+ sherlockServiceList = AppendIfMissing (sherlockServiceList , inspector .Spec .DeploymentRef )
295
+ } else {
296
+ sherlockServiceList = RemoveIfExists (sherlockServiceList , inspector .Spec .DeploymentRef )
236
297
}
237
298
238
- // Encode the config.yaml
239
- encodedConfig , err := yaml . Marshal ( & configData )
299
+ // Generate the Servings Config
300
+ servingsConfig , err := createServingsConfig ( sherlockServiceList )
240
301
if err != nil {
241
302
return err
242
303
}
243
304
244
- // Patch the config file
245
- configMap .Data ["config.yaml" ] = string (encodedConfig )
246
- if err := r .Update (context .Background (), & configMap ); err != nil {
305
+ if err := r .Update (ctx , & sherlockConfigMap ); err != nil {
306
+ return err
307
+ }
308
+
309
+ // Encode the services.yaml
310
+ encodedSherlockConfig , err := yaml .Marshal (& sherlockServiceList )
311
+ if err != nil {
312
+ return err
313
+ }
314
+
315
+ sherlockConfigMap .Data ["services.yaml" ] = string (encodedSherlockConfig )
316
+ sherlockConfigMap .Data ["models.config" ] = servingsConfig
317
+
318
+ if err := r .Update (ctx , & sherlockConfigMap ); err != nil {
247
319
return err
248
320
}
249
321
return nil
@@ -265,3 +337,44 @@ func eventFilter() predicate.Predicate {
265
337
},
266
338
}
267
339
}
340
+
341
+ func AppendIfMissing (slice []string , item string ) []string {
342
+ for _ , ele := range slice {
343
+ if ele == item {
344
+ return slice
345
+ }
346
+ }
347
+ return append (slice , item )
348
+ }
349
+
350
+ func RemoveIfExists (slice []string , item string ) []string {
351
+ for i , other := range slice {
352
+ if other == item {
353
+ return append (slice [:i ], slice [i + 1 :]... )
354
+ }
355
+ }
356
+ return slice
357
+ }
358
+
359
+ func createServingsConfig (service []string ) (string , error ) {
360
+ tmpl := template .New ("config" )
361
+
362
+ tmpl , err := tmpl .Parse (`model_config_list {
363
+ {{range .}}
364
+ config {
365
+ name: '{{.}}'
366
+ base_path: '/models/{{.}}/'
367
+ model_platform: 'tensorflow'
368
+ }
369
+ {{end}}
370
+ }` )
371
+ if err != nil {
372
+ return "" , err
373
+ }
374
+ buf := new (bytes.Buffer )
375
+ err = tmpl .Execute (buf , service )
376
+ if err != nil {
377
+ return "" , err
378
+ }
379
+ return fmt .Sprintf ("%+v" , buf ), nil
380
+ }
0 commit comments