@@ -478,43 +478,20 @@ func verifyAddonStatusInternal(cc *config.ClusterConfig, name string, val string
478478 return nil
479479}
480480
481- // Start enables the default addons for a profile, plus any additional
482- func Start (wg * sync.WaitGroup , cc * config.ClusterConfig , toEnable map [string ]bool , additional []string ) {
481+ // Enable tries to enable the default addons for a profile plus any additional, and returns a single slice of all successfully enabled addons via channel (thread-safe).
482+ // Since Enable is called asynchronously (so is not thread-safe for concurrent addons map updating/reading), to avoid race conditions,
483+ // ToEnable should be called synchronously before Enable to get complete list of addons to enable, and
484+ // UpdateConfig should be called synchronously after Enable to update the config with successfully enabled addons.
485+ func Enable (wg * sync.WaitGroup , cc * config.ClusterConfig , toEnable map [string ]bool , enabled chan <- []string ) {
483486 defer wg .Done ()
484487
485488 start := time .Now ()
486- klog .Infof ("enableAddons start: toEnable=%v, additional=%s" , toEnable , additional )
489+ klog .Infof ("enable addons start: toEnable=%v" , toEnable )
490+ var enabledAddons []string
487491 defer func () {
488- klog .Infof ("enableAddons completed in %s" , time .Since (start ))
492+ klog .Infof ("enable addons completed in %s: enabled=%v " , time .Since (start ), enabledAddons )
489493 }()
490494
491- // Get the default values of any addons not saved to our config
492- for name , a := range assets .Addons {
493- defaultVal := a .IsEnabled (cc )
494-
495- _ , exists := toEnable [name ]
496- if ! exists {
497- toEnable [name ] = defaultVal
498- }
499- }
500-
501- // Apply new addons
502- for _ , name := range additional {
503- isDeprecated , replacement , msg := Deprecations (name )
504- if isDeprecated && replacement == "" {
505- out .FailureT (msg )
506- continue
507- } else if isDeprecated {
508- out .Styled (style .Waiting , msg )
509- name = replacement
510- }
511- // if the specified addon doesn't exist, skip enabling
512- _ , e := isAddonValid (name )
513- if e {
514- toEnable [name ] = true
515- }
516- }
517-
518495 toEnableList := []string {}
519496 for k , v := range toEnable {
520497 if v {
@@ -525,8 +502,6 @@ func Start(wg *sync.WaitGroup, cc *config.ClusterConfig, toEnable map[string]boo
525502
526503 var awg sync.WaitGroup
527504
528- var enabledAddons []string
529-
530505 defer func () { // making it show after verifications (see #7613)
531506 register .Reg .SetStep (register .EnablingAddons )
532507 out .Step (style .AddonEnable , "Enabled addons: {{.addons}}" , out.V {"addons" : strings .Join (enabledAddons , ", " )})
@@ -544,10 +519,52 @@ func Start(wg *sync.WaitGroup, cc *config.ClusterConfig, toEnable map[string]boo
544519 }(a )
545520 }
546521
547- // Wait until all of the addons are enabled before updating the config (not thread safe)
522+ // Wait until all of the addons are enabled
548523 awg .Wait ()
549524
550- for _ , a := range enabledAddons {
525+ // send the slice of all successfully enabled addons to channel and close
526+ enabled <- enabledAddons
527+ close (enabled )
528+ }
529+
530+ // ToEnable returns the final list of addons to enable (not thread-safe).
531+ func ToEnable (cc * config.ClusterConfig , existing map [string ]bool , additional []string ) map [string ]bool {
532+ // start from existing
533+ enable := map [string ]bool {}
534+ for k , v := range existing {
535+ enable [k ] = v
536+ }
537+
538+ // Get the default values of any addons not saved to our config
539+ for name , a := range assets .Addons {
540+ if _ , exists := existing [name ]; ! exists {
541+ enable [name ] = a .IsEnabled (cc )
542+ }
543+ }
544+
545+ // Apply new addons
546+ for _ , name := range additional {
547+ isDeprecated , replacement , msg := Deprecations (name )
548+ if isDeprecated && replacement == "" {
549+ out .FailureT (msg )
550+ continue
551+ } else if isDeprecated {
552+ out .Styled (style .Waiting , msg )
553+ name = replacement
554+ }
555+ // if the specified addon doesn't exist, skip enabling
556+ if _ , e := isAddonValid (name ); e {
557+ enable [name ] = true
558+ }
559+ }
560+
561+ return enable
562+ }
563+
564+ // UpdateConfig tries to update config with all enabled addons (not thread-safe).
565+ // Any error will be logged and it will continue.
566+ func UpdateConfig (cc * config.ClusterConfig , enabled []string ) {
567+ for _ , a := range enabled {
551568 if err := Set (cc , a , "true" ); err != nil {
552569 klog .Errorf ("store failed: %v" , err )
553570 }
0 commit comments