github.com/openshift/installer@v1.4.17/cmd/openshift-install/main.go (about)

     1  package main
     2  
     3  import (
     4  	"context"
     5  	"flag"
     6  	"io"
     7  	"os"
     8  	"path/filepath"
     9  
    10  	"github.com/pkg/errors"
    11  	"github.com/sirupsen/logrus"
    12  	"github.com/spf13/cobra"
    13  	terminal "golang.org/x/term"
    14  	"k8s.io/klog"
    15  	klogv2 "k8s.io/klog/v2"
    16  	ctrl "sigs.k8s.io/controller-runtime"
    17  	"sigs.k8s.io/controller-runtime/pkg/manager/signals"
    18  
    19  	"github.com/openshift/installer/cmd/openshift-install/command"
    20  	"github.com/openshift/installer/pkg/clusterapi"
    21  )
    22  
    23  func main() {
    24  	// This attempts to configure klog (used by vendored Kubernetes code) not
    25  	// to log anything.
    26  	// Handle k8s.io/klog
    27  	var fs flag.FlagSet
    28  	klog.InitFlags(&fs)
    29  	fs.Set("stderrthreshold", "4")
    30  	klog.SetOutput(io.Discard)
    31  	// Handle k8s.io/klog/v2
    32  	var fsv2 flag.FlagSet
    33  	klogv2.InitFlags(&fsv2)
    34  	fsv2.Set("stderrthreshold", "4")
    35  	klogv2.SetOutput(io.Discard)
    36  
    37  	ctrl.SetLogger(klogv2.Background())
    38  
    39  	installerMain()
    40  }
    41  
    42  func installerMain() {
    43  	rootCmd := newRootCmd()
    44  
    45  	// Perform a graceful shutdown upon interrupt or at exit.
    46  	ctx := handleInterrupt(signals.SetupSignalHandler())
    47  	logrus.RegisterExitHandler(shutdown)
    48  
    49  	for _, subCmd := range []*cobra.Command{
    50  		newCreateCmd(ctx),
    51  		newDestroyCmd(),
    52  		newWaitForCmd(),
    53  		newGatherCmd(ctx),
    54  		newAnalyzeCmd(),
    55  		newVersionCmd(),
    56  		newGraphCmd(),
    57  		newCoreOSCmd(),
    58  		newCompletionCmd(),
    59  		newExplainCmd(),
    60  		newAgentCmd(ctx),
    61  		newListFeaturesCmd(),
    62  		newImageBasedCmd(ctx),
    63  	} {
    64  		rootCmd.AddCommand(subCmd)
    65  	}
    66  
    67  	if err := rootCmd.Execute(); err != nil {
    68  		logrus.Fatalf("Error executing openshift-install: %v", err)
    69  	}
    70  }
    71  
    72  func newRootCmd() *cobra.Command {
    73  	cmd := &cobra.Command{
    74  		Use:              filepath.Base(os.Args[0]),
    75  		Short:            "Creates OpenShift clusters",
    76  		Long:             "",
    77  		PersistentPreRun: runRootCmd,
    78  		SilenceErrors:    true,
    79  		SilenceUsage:     true,
    80  	}
    81  	cmd.PersistentFlags().StringVar(&command.RootOpts.Dir, "dir", ".", "assets directory")
    82  	cmd.PersistentFlags().StringVar(&command.RootOpts.LogLevel, "log-level", "info", "log level (e.g. \"debug | info | warn | error\")")
    83  	return cmd
    84  }
    85  
    86  func runRootCmd(cmd *cobra.Command, args []string) {
    87  	logrus.SetOutput(io.Discard)
    88  	logrus.SetLevel(logrus.TraceLevel)
    89  
    90  	level, err := logrus.ParseLevel(command.RootOpts.LogLevel)
    91  	if err != nil {
    92  		level = logrus.InfoLevel
    93  	}
    94  
    95  	logrus.AddHook(command.NewFileHookWithNewlineTruncate(os.Stderr, level, &logrus.TextFormatter{
    96  		// Setting ForceColors is necessary because logrus.TextFormatter determines
    97  		// whether or not to enable colors by looking at the output of the logger.
    98  		// In this case, the output is io.Discard, which is not a terminal.
    99  		// Overriding it here allows the same check to be done, but against the
   100  		// hook's output instead of the logger's output.
   101  		ForceColors:            terminal.IsTerminal(int(os.Stderr.Fd())),
   102  		DisableTimestamp:       true,
   103  		DisableLevelTruncation: true,
   104  		DisableQuote:           true,
   105  	}))
   106  
   107  	if err != nil {
   108  		logrus.Fatal(errors.Wrap(err, "invalid log-level"))
   109  	}
   110  }
   111  
   112  // handleInterrupt executes a graceful shutdown then exits in
   113  // the case of a user interrupt. It returns a new context that
   114  // will be cancelled upon interrupt.
   115  func handleInterrupt(signalCtx context.Context) context.Context {
   116  	ctx, cancel := context.WithCancel(context.Background())
   117  
   118  	// If the context from the signal handler is done,
   119  	// an interrupt has been received, so shutdown & exit.
   120  	go func() {
   121  		<-signalCtx.Done()
   122  		logrus.Warn("Received interrupt signal")
   123  		shutdown()
   124  		cancel()
   125  		logrus.Exit(exitCodeInterrupt)
   126  	}()
   127  
   128  	return ctx
   129  }
   130  
   131  func shutdown() {
   132  	clusterapi.System().Teardown()
   133  }