github.com/iter8-tools/iter8@v1.1.2/cmd/controllers.go (about)

     1  package cmd
     2  
     3  import (
     4  	"context"
     5  	"os"
     6  	"os/signal"
     7  	"syscall"
     8  
     9  	"github.com/iter8-tools/iter8/abn"
    10  	"github.com/iter8-tools/iter8/base/log"
    11  	"github.com/iter8-tools/iter8/controllers"
    12  	"github.com/iter8-tools/iter8/controllers/k8sclient"
    13  	"github.com/iter8-tools/iter8/metrics"
    14  	"github.com/spf13/cobra"
    15  	"google.golang.org/grpc"
    16  )
    17  
    18  // controllersDesc is the description of controllers cmd
    19  const controllersDesc = `
    20  Start Iter8 controllers.
    21  
    22  	$ iter8 controllers
    23  `
    24  
    25  // newControllersCmd creates the Iter8 controllers
    26  // when invoking this function for real, set stopCh to nil
    27  // this will block the controller from exiting until an os.Interrupt;
    28  // when invoking this function in a unit test, set stopCh to ctx.Done()
    29  // this will exit the controller when cancel() is called by the parent function;
    30  func newControllersCmd(stopCh <-chan struct{}, client k8sclient.Interface) *cobra.Command {
    31  	cmd := &cobra.Command{
    32  		Use:          "controllers",
    33  		Short:        "Start Iter8 controllers",
    34  		Long:         controllersDesc,
    35  		Args:         cobra.NoArgs,
    36  		SilenceUsage: true,
    37  		RunE: func(_ *cobra.Command, _ []string) error {
    38  			// createSigCh indicates if we should create sigCh (channel) that fires on interrupt
    39  			createSigCh := false
    40  
    41  			ctx, cancel := context.WithCancel(context.Background())
    42  			defer cancel()
    43  			// if stopCh is nil, create sigCh to exit this func on interrupt,
    44  			// and use ctx.Done() to clean up controllers when exiting;
    45  			// otherwise, simply use stopCh for both
    46  			if stopCh == nil {
    47  				stopCh = ctx.Done()
    48  				createSigCh = true
    49  			}
    50  
    51  			if client == nil {
    52  				var err error
    53  				client, err = k8sclient.New(settings)
    54  				if err != nil {
    55  					log.Logger.Error("could not obtain Kube client... ")
    56  					return err
    57  				}
    58  			}
    59  
    60  			if err := controllers.Start(stopCh, client); err != nil {
    61  				log.Logger.Error("controllers did not start... ")
    62  				return err
    63  			}
    64  			log.Logger.Debug("started controllers... ")
    65  
    66  			// launch gRPC server to respond to frontend requests
    67  			go func() {
    68  				err := abn.LaunchGRPCServer([]grpc.ServerOption{}, stopCh)
    69  				if err != nil {
    70  					log.Logger.Error("cound not start A/B/n service")
    71  				}
    72  			}()
    73  
    74  			// launch metrics HTTP server to respond to support Grafana visualization
    75  			go func() {
    76  				err := metrics.Start(stopCh)
    77  				if err != nil {
    78  					log.Logger.Error("count not start A/B/n metrics service")
    79  				}
    80  			}()
    81  
    82  			// if createSigCh, then block until there is an os.Interrupt
    83  			if createSigCh {
    84  				sigCh := make(chan os.Signal, 1)
    85  				signal.Notify(sigCh, syscall.SIGTERM, os.Interrupt)
    86  				<-sigCh
    87  				log.Logger.Warn("SIGTERM... ")
    88  			}
    89  
    90  			return nil
    91  		},
    92  	}
    93  	return cmd
    94  }