github.imxd.top/operator-framework/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  }