github.com/lablabs/operator-sdk@v0.8.2/pkg/ansible/operator/operator.go (about) 1 // Copyright 2018 The Operator-SDK Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package operator 16 17 import ( 18 "errors" 19 "fmt" 20 "math/rand" 21 "os" 22 "strconv" 23 "strings" 24 "time" 25 26 "k8s.io/apimachinery/pkg/runtime/schema" 27 28 "github.com/operator-framework/operator-sdk/pkg/ansible/controller" 29 "github.com/operator-framework/operator-sdk/pkg/ansible/flags" 30 "github.com/operator-framework/operator-sdk/pkg/ansible/proxy/controllermap" 31 "github.com/operator-framework/operator-sdk/pkg/ansible/runner" 32 33 "sigs.k8s.io/controller-runtime/pkg/manager" 34 logf "sigs.k8s.io/controller-runtime/pkg/runtime/log" 35 "sigs.k8s.io/controller-runtime/pkg/runtime/signals" 36 ) 37 38 // Run - A blocking function which starts a controller-runtime manager 39 // It starts an Operator by reading in the values in `./watches.yaml`, adds a controller 40 // to the manager, and finally running the manager. 41 func Run(done chan error, mgr manager.Manager, f *flags.AnsibleOperatorFlags, cMap *controllermap.ControllerMap) { 42 watches, err := runner.NewFromWatches(f.WatchesFile) 43 if err != nil { 44 logf.Log.WithName("manager").Error(err, "Failed to get watches") 45 done <- err 46 return 47 } 48 rand.Seed(time.Now().Unix()) 49 c := signals.SetupSignalHandler() 50 51 for gvk, runner := range watches { 52 53 // if the WORKER_* environment variable is set, use that value. 54 // Otherwise, use the value from the CLI. This is definitely 55 // counter-intuitive but it allows the operator admin adjust the 56 // number of workers based on their cluster resources. While the 57 // author may use the CLI option to specify a suggested 58 // configuration for the operator. 59 maxWorkers := getMaxWorkers(gvk, f.MaxWorkers) 60 61 o := controller.Options{ 62 GVK: gvk, 63 Runner: runner, 64 ManageStatus: runner.GetManageStatus(), 65 MaxWorkers: maxWorkers, 66 } 67 applyFlagsToControllerOptions(f, &o) 68 if d, ok := runner.GetReconcilePeriod(); ok { 69 o.ReconcilePeriod = d 70 } 71 ctr := controller.Add(mgr, o) 72 if ctr == nil { 73 done <- errors.New("failed to add controller") 74 return 75 } 76 cMap.Store(o.GVK, &controllermap.Contents{Controller: *ctr, 77 WatchDependentResources: runner.GetWatchDependentResources(), 78 WatchClusterScopedResources: runner.GetWatchClusterScopedResources(), 79 OwnerWatchMap: controllermap.NewWatchMap(), 80 AnnotationWatchMap: controllermap.NewWatchMap(), 81 }) 82 } 83 done <- mgr.Start(c) 84 } 85 86 func getMaxWorkers(gvk schema.GroupVersionKind, defvalue int) int { 87 envvar := formatEnvVar(gvk.Kind, gvk.Group) 88 maxWorkers, err := strconv.Atoi(os.Getenv(envvar)) 89 if err != nil { 90 // we don't care why we couldn't parse it just use one. 91 // maybe we should log that we are defaulting to 1. 92 logf.Log.WithName("manager").V(0).Info(fmt.Sprintf("Using default value for workers %d", defvalue)) 93 return defvalue 94 } 95 96 return maxWorkers 97 } 98 99 func formatEnvVar(kind string, group string) string { 100 envvar := fmt.Sprintf("WORKER_%s_%s", kind, group) 101 return strings.ToUpper(strings.Replace(envvar, ".", "_", -1)) 102 } 103 104 func applyFlagsToControllerOptions(f *flags.AnsibleOperatorFlags, o *controller.Options) { 105 o.ReconcilePeriod = f.ReconcilePeriod 106 }