@@ -57,30 +57,29 @@ import (
57
57
/*
58
58
Example call for tilt up:
59
59
--tools kustomize,envsubst
60
- --cert-manager
61
- --kustomize-builds clusterctl.crd:./cmd/clusterctl/config/crd/
62
- --kustomize-builds observability.tools:./hack/observability/
63
- --providers core:.
64
- --providers kubeadm-bootstrap:./bootstrap/kubeadm
65
- --providers kubeadm-control-plane:./controlplane/kubeadm
66
- --providers docker:./test/infrastructure/docker
67
60
*/
68
61
69
62
var (
70
63
rootPath string
71
64
tiltBuildPath string
72
65
73
- toolsFlag = pflag .StringSlice ("tools" , []string {}, "list of tools to be created; each value should correspond to a make target" )
74
- certManagerFlag = pflag .Bool ("cert-manager" , false , "prepare cert-manager" )
75
- kustomizeBuildsFlag = pflag .StringSlice ("kustomize-builds" , []string {}, "list of kustomize build to be run; each value should be in the form name:path" )
76
- providersBuildsFlag = pflag .StringSlice ("providers" , []string {}, "list of providers to be installed; each value should be in the form name:path" )
77
- allowK8SContextsFlag = pflag .StringSlice ("allow-k8s-contexts" , []string {}, "Specifies that Tilt is allowed to run against the specified k8s context name; Kind is automatically allowed" )
78
66
tiltSettingsFileFlag = pflag .String ("tilt-settings-file" , "./tilt-settings.yaml" , "Path to a tilt-settings.(json|yaml) file" )
67
+ toolsFlag = pflag .StringSlice ("tools" , []string {}, "list of tools to be created; each value should correspond to a make target" )
79
68
)
80
69
81
70
type tiltSettings struct {
82
- Debug map [string ]debugConfig `json:"debug,omitempty"`
83
- ExtraArgs map [string ]extraArgs `json:"extra_args,omitempty"`
71
+ Debug map [string ]debugConfig `json:"debug,omitempty"`
72
+ ExtraArgs map [string ]extraArgs `json:"extra_args,omitempty"`
73
+ DeployCertManager bool `json:"deploy_cert_manager,omitempty"`
74
+ DeployObservability []string `json:"deploy_observability,omitempty"`
75
+ EnableProviders []string `json:"enable_providers,omitempty"`
76
+ AllowedContexts []string `json:"allowed_contexts,omitempty"`
77
+ ProviderRepos []string `json:"provider_repos,omitempty"`
78
+ }
79
+
80
+ type providerSettings struct {
81
+ Name string `json:"name,omitempty"`
82
+ Context * string `json:"context"`
84
83
}
85
84
86
85
type debugConfig struct {
@@ -118,9 +117,6 @@ func main() {
118
117
start := time .Now ()
119
118
120
119
pflag .Parse ()
121
- if err := allowK8sConfig (); err != nil {
122
- klog .Exit (fmt .Sprintf ("[main] tilt-prepare can't start: %v" , err ))
123
- }
124
120
125
121
ctx := ctrl .SetupSignalHandler ()
126
122
@@ -129,6 +125,10 @@ func main() {
129
125
klog .Exit (fmt .Sprintf ("[main] failed to read tilt settings: %v" , err ))
130
126
}
131
127
128
+ if err := allowK8sConfig (ts ); err != nil {
129
+ klog .Exit (fmt .Sprintf ("[main] tilt-prepare can't start: %v" , err ))
130
+ }
131
+
132
132
// Execute a first group of tilt prepare tasks, building all the tools required in subsequent steps/by tilt.
133
133
if err := tiltTools (ctx ); err != nil {
134
134
klog .Exit (fmt .Sprintf ("[main] failed to prepare tilt tools: %v" , err ))
@@ -187,7 +187,7 @@ func setDebugDefaults(ts *tiltSettings) {
187
187
}
188
188
189
189
// allowK8sConfig mimics allow_k8s_contexts; only kind is enabled by default but more can be added.
190
- func allowK8sConfig () error {
190
+ func allowK8sConfig (ts * tiltSettings ) error {
191
191
config , err := clientcmd .NewDefaultClientConfigLoadingRules ().Load ()
192
192
if err != nil {
193
193
return errors .Wrap (err , "failed to load Kubeconfig" )
@@ -204,7 +204,7 @@ func allowK8sConfig() error {
204
204
return nil
205
205
}
206
206
207
- allowed := sets .NewString (* allowK8SContextsFlag ... )
207
+ allowed := sets .NewString (ts . AllowedContexts ... )
208
208
if ! allowed .Has (config .CurrentContext ) {
209
209
return errors .Errorf ("context %s is not allowed" , config .CurrentContext )
210
210
}
@@ -227,41 +227,123 @@ func tiltTools(ctx context.Context) error {
227
227
func tiltResources (ctx context.Context , ts * tiltSettings ) error {
228
228
tasks := map [string ]taskFunction {}
229
229
230
+ // Note: we are creating clusterctl CRDs using kustomize (vs using clusterctl) because we want to create
231
+ // a dependency between these resources and provider resources.
232
+ tasks ["clusterctl.crd" ] = kustomizeTask ("./cmd/clusterctl/config/crd/" , "clusterctl.crd.yaml" )
233
+
230
234
// If required, all the task to install cert manager.
231
235
// NOTE: strictly speaking cert-manager is not a resource, however it is a dependency for most of the actual resources
232
236
// and running this is the same task group of the kustomize/provider tasks gives the maximum benefits in terms of reducing the total elapsed time.
233
- if * certManagerFlag {
237
+ if ts . DeployCertManager {
234
238
tasks ["cert-manager-cainjector" ] = preLoadImageTask (fmt .Sprintf ("quay.io/jetstack/cert-manager-cainjector:%s" , config .CertManagerDefaultVersion ))
235
239
tasks ["cert-manager-webhook" ] = preLoadImageTask (fmt .Sprintf ("quay.io/jetstack/cert-manager-webhook:%s" , config .CertManagerDefaultVersion ))
236
240
tasks ["cert-manager-controller" ] = preLoadImageTask (fmt .Sprintf ("quay.io/jetstack/cert-manager-controller:%s" , config .CertManagerDefaultVersion ))
237
241
tasks ["cert-manager" ] = certManagerTask ()
238
242
}
239
243
240
- // Add a kustomize task for each name/path defined using the --kustomize-build flag.
241
- for _ , k := range * kustomizeBuildsFlag {
242
- values := strings .Split (k , ":" )
243
- if len (values ) != 2 {
244
- return errors .Errorf ("[resources] failed to parse --kustomize-build flag %s: value should be in the form of name:path" , k )
245
- }
246
- name := values [0 ]
247
- path := values [1 ]
244
+ // Add a kustomize task for each tool configured via deploy_observability.
245
+ for _ , tool := range ts .DeployObservability {
246
+ name := fmt .Sprintf ("%s.observability" , tool )
247
+ path := fmt .Sprintf ("./hack/observability/%s/" , tool )
248
248
tasks [name ] = kustomizeTask (path , fmt .Sprintf ("%s.yaml" , name ))
249
249
}
250
250
251
- // Add a provider task for each name/path defined using the --provider flag.
252
- for _ , p := range * providersBuildsFlag {
253
- pValues := strings .Split (p , ":" )
254
- if len (pValues ) != 2 {
255
- return errors .Errorf ("[resources] failed to parse --provider flag %s: value should be in the form of name:path" , p )
251
+ providerPaths := map [string ]string {"core" : "." ,
252
+ "kubeadm-bootstrap" : "bootstrap/kubeadm" ,
253
+ "kubeadm-control-plane" : "controlplane/kubeadm" ,
254
+ "docker" : "test/infrastructure/docker" ,
255
+ }
256
+
257
+ // Add all the provider paths to the providerpaths map
258
+ for _ , p := range ts .ProviderRepos {
259
+ providerContexts , err := loadProviders (p )
260
+ if err != nil {
261
+ return err
262
+ }
263
+
264
+ for name , path := range providerContexts {
265
+ providerPaths [name ] = path
266
+ }
267
+ }
268
+
269
+ enableCore := false
270
+ for _ , providerName := range ts .EnableProviders {
271
+ if providerName == "core" {
272
+ enableCore = true
273
+ }
274
+ }
275
+ if ! enableCore {
276
+ ts .EnableProviders = append (ts .EnableProviders , "core" )
277
+ }
278
+
279
+ // Add the provider task for each of the enabled provider
280
+ for _ , providerName := range ts .EnableProviders {
281
+ path , ok := providerPaths [providerName ]
282
+ if ! ok {
283
+ return errors .Errorf ("failed to obtain path for the provider %s" , providerName )
256
284
}
257
- name := pValues [0 ]
258
- path := pValues [1 ]
259
- tasks [name ] = providerTask (name , fmt .Sprintf ("%s/config/default" , path ), ts )
285
+ tasks [providerName ] = providerTask (providerName , fmt .Sprintf ("%s/config/default" , path ), ts )
260
286
}
261
287
262
288
return runTaskGroup (ctx , "resources" , tasks )
263
289
}
264
290
291
+ func loadProviders (r string ) (map [string ]string , error ) {
292
+ var contextPath string
293
+ providerData , err := readProviderSettings (r )
294
+ if err != nil {
295
+ return nil , err
296
+ }
297
+
298
+ providerContexts := map [string ]string {}
299
+ for _ , p := range providerData {
300
+ if p .Context != nil {
301
+ contextPath = r + "/" + * p .Context
302
+ } else {
303
+ contextPath = r
304
+ }
305
+ providerContexts [p .Name ] = contextPath
306
+ }
307
+ return providerContexts , nil
308
+ }
309
+
310
+ func readProviderSettings (path string ) ([]providerSettings , error ) {
311
+ path , err := checkProviderFileFormat (path )
312
+ if err != nil {
313
+ return nil , err
314
+ }
315
+
316
+ content , err := os .ReadFile (path ) //nolint:gosec
317
+ if err != nil {
318
+ return nil , err
319
+ }
320
+
321
+ ps := []providerSettings {}
322
+ // providerSettings file can be an array and this is done to detect arrays
323
+ if strings .HasPrefix (string (content ), "[" ) || strings .HasPrefix (string (content ), "-" ) {
324
+ if err := yaml .Unmarshal (content , & ps ); err != nil {
325
+ return nil , errors .Wrap (err , fmt .Sprintf ("failed to read provider path %s tilt file" , path ))
326
+ }
327
+ } else {
328
+ p := providerSettings {}
329
+ if err := yaml .Unmarshal (content , & p ); err != nil {
330
+ return nil , errors .Wrap (err , fmt .Sprintf ("failed to read provider path %s tilt file" , path ))
331
+ }
332
+ ps = append (ps , p )
333
+ }
334
+ return ps , nil
335
+ }
336
+
337
+ func checkProviderFileFormat (path string ) (string , error ) {
338
+ if _ , err := os .Stat (path + "/tilt-provider.yaml" ); err == nil {
339
+ return path + "/tilt-provider.yaml" , nil
340
+ }
341
+ if _ , err := os .Stat (path + "/tilt-provider.json" ); err == nil {
342
+ return path + "/tilt-provider.json" , nil
343
+ }
344
+ return "" , fmt .Errorf ("unable to find a tilt settings file under %s" , path )
345
+ }
346
+
265
347
type taskFunction func (ctx context.Context , prefix string , errors chan error )
266
348
267
349
// runTaskGroup executes a group of task in parallel handling an error channel.
0 commit comments