github.com/khulnasoft/cli@v0.0.0-20240402070845-01bcad7beefa/cli/flags/options.go (about)

     1  package flags
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path/filepath"
     7  
     8  	"github.com/docker/docker/client"
     9  	"github.com/khulnasoft-lab/go-connections/tlsconfig"
    10  	"github.com/khulnasoft/cli/cli/config"
    11  	"github.com/khulnasoft/cli/opts"
    12  	"github.com/sirupsen/logrus"
    13  	"github.com/spf13/pflag"
    14  )
    15  
    16  const (
    17  	// EnvEnableTLS is the name of the environment variable that can be used
    18  	// to enable TLS for client connections. When set to a non-empty value, TLS
    19  	// is enabled for API connections using TCP. For backward-compatibility, this
    20  	// environment-variable can only be used to enable TLS, not to disable.
    21  	//
    22  	// Note that TLS is always enabled implicitly if the "--tls-verify" option
    23  	// or "DOCKER_TLS_VERIFY" ([github.com/docker/docker/client.EnvTLSVerify])
    24  	// env var is set to, which could be to either enable or disable TLS certification
    25  	// validation. In both cases, TLS is enabled but, depending on the setting,
    26  	// with verification disabled.
    27  	EnvEnableTLS = "DOCKER_TLS"
    28  
    29  	// DefaultCaFile is the default filename for the CA pem file
    30  	DefaultCaFile = "ca.pem"
    31  	// DefaultKeyFile is the default filename for the key pem file
    32  	DefaultKeyFile = "key.pem"
    33  	// DefaultCertFile is the default filename for the cert pem file
    34  	DefaultCertFile = "cert.pem"
    35  	// FlagTLSVerify is the flag name for the TLS verification option
    36  	FlagTLSVerify = "tlsverify"
    37  	// FormatHelp describes the --format flag behavior for list commands
    38  	FormatHelp = `Format output using a custom template:
    39  'table':            Print output in table format with column headers (default)
    40  'table TEMPLATE':   Print output in table format using the given Go template
    41  'json':             Print in JSON format
    42  'TEMPLATE':         Print output using the given Go template.
    43  Refer to https://docs.docker.com/go/formatting/ for more information about formatting output with templates`
    44  	// InspectFormatHelp describes the --format flag behavior for inspect commands
    45  	InspectFormatHelp = `Format output using a custom template:
    46  'json':             Print in JSON format
    47  'TEMPLATE':         Print output using the given Go template.
    48  Refer to https://docs.docker.com/go/formatting/ for more information about formatting output with templates`
    49  )
    50  
    51  var (
    52  	dockerCertPath  = os.Getenv(client.EnvOverrideCertPath)
    53  	dockerTLSVerify = os.Getenv(client.EnvTLSVerify) != ""
    54  	dockerTLS       = os.Getenv(EnvEnableTLS) != ""
    55  )
    56  
    57  // ClientOptions are the options used to configure the client cli.
    58  type ClientOptions struct {
    59  	Debug      bool
    60  	Hosts      []string
    61  	LogLevel   string
    62  	TLS        bool
    63  	TLSVerify  bool
    64  	TLSOptions *tlsconfig.Options
    65  	Context    string
    66  	ConfigDir  string
    67  }
    68  
    69  // NewClientOptions returns a new ClientOptions.
    70  func NewClientOptions() *ClientOptions {
    71  	return &ClientOptions{}
    72  }
    73  
    74  // InstallFlags adds flags for the common options on the FlagSet
    75  func (o *ClientOptions) InstallFlags(flags *pflag.FlagSet) {
    76  	configDir := config.Dir()
    77  	if dockerCertPath == "" {
    78  		dockerCertPath = configDir
    79  	}
    80  
    81  	flags.StringVar(&o.ConfigDir, "config", configDir, "Location of client config files")
    82  	flags.BoolVarP(&o.Debug, "debug", "D", false, "Enable debug mode")
    83  	flags.StringVarP(&o.LogLevel, "log-level", "l", "info", `Set the logging level ("debug", "info", "warn", "error", "fatal")`)
    84  	flags.BoolVar(&o.TLS, "tls", dockerTLS, "Use TLS; implied by --tlsverify")
    85  	flags.BoolVar(&o.TLSVerify, FlagTLSVerify, dockerTLSVerify, "Use TLS and verify the remote")
    86  
    87  	o.TLSOptions = &tlsconfig.Options{
    88  		CAFile:   filepath.Join(dockerCertPath, DefaultCaFile),
    89  		CertFile: filepath.Join(dockerCertPath, DefaultCertFile),
    90  		KeyFile:  filepath.Join(dockerCertPath, DefaultKeyFile),
    91  	}
    92  	tlsOptions := o.TLSOptions
    93  	flags.Var(opts.NewQuotedString(&tlsOptions.CAFile), "tlscacert", "Trust certs signed only by this CA")
    94  	flags.Var(opts.NewQuotedString(&tlsOptions.CertFile), "tlscert", "Path to TLS certificate file")
    95  	flags.Var(opts.NewQuotedString(&tlsOptions.KeyFile), "tlskey", "Path to TLS key file")
    96  
    97  	// opts.ValidateHost is not used here, so as to allow connection helpers
    98  	hostOpt := opts.NewNamedListOptsRef("hosts", &o.Hosts, nil)
    99  	flags.VarP(hostOpt, "host", "H", "Daemon socket to connect to")
   100  	flags.StringVarP(&o.Context, "context", "c", "",
   101  		`Name of the context to use to connect to the daemon (overrides `+client.EnvOverrideHost+` env var and default context set with "docker context use")`)
   102  }
   103  
   104  // SetDefaultOptions sets default values for options after flag parsing is
   105  // complete
   106  func (o *ClientOptions) SetDefaultOptions(flags *pflag.FlagSet) {
   107  	// Regardless of whether the user sets it to true or false, if they
   108  	// specify --tlsverify at all then we need to turn on TLS
   109  	// TLSVerify can be true even if not set due to DOCKER_TLS_VERIFY env var, so we need
   110  	// to check that here as well
   111  	if flags.Changed(FlagTLSVerify) || o.TLSVerify {
   112  		o.TLS = true
   113  	}
   114  
   115  	if !o.TLS {
   116  		o.TLSOptions = nil
   117  	} else {
   118  		tlsOptions := o.TLSOptions
   119  		tlsOptions.InsecureSkipVerify = !o.TLSVerify
   120  
   121  		// Reset CertFile and KeyFile to empty string if the user did not specify
   122  		// the respective flags and the respective default files were not found.
   123  		if !flags.Changed("tlscert") {
   124  			if _, err := os.Stat(tlsOptions.CertFile); os.IsNotExist(err) {
   125  				tlsOptions.CertFile = ""
   126  			}
   127  		}
   128  		if !flags.Changed("tlskey") {
   129  			if _, err := os.Stat(tlsOptions.KeyFile); os.IsNotExist(err) {
   130  				tlsOptions.KeyFile = ""
   131  			}
   132  		}
   133  	}
   134  }
   135  
   136  // SetLogLevel sets the logrus logging level
   137  func SetLogLevel(logLevel string) {
   138  	if logLevel != "" {
   139  		lvl, err := logrus.ParseLevel(logLevel)
   140  		if err != nil {
   141  			fmt.Fprintf(os.Stderr, "Unable to parse logging level: %s\n", logLevel)
   142  			os.Exit(1)
   143  		}
   144  		logrus.SetLevel(lvl)
   145  	} else {
   146  		logrus.SetLevel(logrus.InfoLevel)
   147  	}
   148  }