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 }