github.com/circl-dev/go-swagger@v0.31.0/generator/templates/cli/cli.gotmpl (about)

     1  // Code generated by go-swagger; DO NOT EDIT.
     2  
     3  
     4  {{ if .Copyright -}}// {{ comment .Copyright -}}{{ end }}
     5  
     6  
     7  package {{ .GenOpts.CliPackage }}
     8  
     9  // This file was generated by the swagger tool.
    10  // Editing this file might prove futile when you re-run the swagger generate command
    11  
    12  import (
    13      {{ imports .DefaultImports }}
    14      {{ imports .Imports }}
    15  
    16      "github.com/spf13/cobra"
    17  	"github.com/spf13/viper"
    18  	"github.com/circl-dev/runtime"
    19  	"github.com/go-openapi/swag"
    20  	httptransport "github.com/circl-dev/runtime/client"
    21  	homedir "github.com/mitchellh/go-homedir"
    22  )
    23  
    24  // debug flag indicating that cli should output debug logs
    25  var debug bool
    26  // config file location
    27  var configFile string
    28  // dry run flag
    29  var dryRun bool
    30  
    31  // name of the executable
    32  var exeName string = filepath.Base(os.Args[0])
    33  
    34  // logDebugf writes debug log to stdout
    35  func logDebugf(format string, v ...interface{}) {
    36  	if !debug{
    37  		return
    38  	}
    39  	log.Printf(format, v...)
    40  }
    41  
    42  {{/*TODO: make this a swagger cli option*/}}
    43  // depth of recursion to construct model flags
    44  var maxDepth int = 5
    45  
    46  // makeClient constructs a client object
    47  func makeClient(cmd *cobra.Command, args []string) (*client.{{ pascalize .Name }}, error) {
    48  	hostname := viper.GetString("hostname")
    49  	scheme := viper.GetString("scheme")
    50  
    51  	r := httptransport.New(hostname, client.DefaultBasePath, []string{scheme})
    52  	r.SetDebug(debug)
    53  
    54  	{{- /* user might define custom mediatype xxx/json and there is no registered ones to handle. */}}
    55  	// set custom producer and consumer to use the default ones
    56  	{{ range .Consumes }}
    57  		{{ range .AllSerializers }}
    58  			{{- if stringContains .MediaType "json" }}
    59  		r.Consumers["{{ .MediaType }}"] = runtime.JSONConsumer()
    60  			{{- else }}
    61  		// warning: consumes {{ .MediaType }} is not supported by go-swagger cli yet
    62  			{{- end }}
    63  		{{- end }}
    64  	{{ end }}
    65  	{{ range .Produces }}
    66  		{{- range .AllSerializers }}
    67  			{{- if stringContains .MediaType "json" }}
    68  		r.Producers["{{ .MediaType }}"] = runtime.JSONProducer()
    69  			{{- else }}
    70  		// warning: produces {{ .MediaType }} is not supported by go-swagger cli yet
    71  			{{- end }}
    72  		{{- end }}
    73  	{{ end }}
    74  
    75  	{{- if .SecurityDefinitions }}
    76  	auth, err := makeAuthInfoWriter(cmd)
    77  	if err != nil {
    78  		return nil, err
    79  	}
    80  	r.DefaultAuthentication = auth
    81  	{{ end }}
    82  	appCli := client.New(r, strfmt.Default)
    83  	logDebugf("Server url: %v://%v", scheme, hostname)
    84  	return appCli, nil
    85  }
    86  
    87  // MakeRootCmd returns the root cmd
    88  func MakeRootCmd() (*cobra.Command, error) {
    89  	cobra.OnInitialize(initViperConfigs)
    90  
    91  	// Use executable name as the command name
    92  	rootCmd := &cobra.Command{
    93  		Use: exeName,
    94  	}
    95  	{{/*note: viper binded flag value must be retrieved from viper rather than cmd*/}}
    96  	// register basic flags
    97  	rootCmd.PersistentFlags().String("hostname", client.DefaultHost, "hostname of the service")
    98  	viper.BindPFlag("hostname", rootCmd.PersistentFlags().Lookup("hostname"))
    99  	rootCmd.PersistentFlags().String("scheme", client.DefaultSchemes[0], fmt.Sprintf("Choose from: %v", client.DefaultSchemes))
   100  	viper.BindPFlag("scheme", rootCmd.PersistentFlags().Lookup("scheme"))
   101  
   102  	// configure debug flag
   103  	rootCmd.PersistentFlags().BoolVar(&debug, "debug", false, "output debug logs")
   104  	// configure config location
   105  	rootCmd.PersistentFlags().StringVar(&configFile, "config", "", "config file path")
   106  	// configure dry run flag
   107  	rootCmd.PersistentFlags().BoolVar(&dryRun, "dry-run", false, "do not send the request to server")
   108  
   109  	// register security flags
   110  	{{- if .SecurityDefinitions }}
   111  	if err := registerAuthInoWriterFlags(rootCmd); err != nil{
   112  		return nil, err
   113  	}
   114  	{{- end }}
   115  	// add all operation groups
   116  {{- range .OperationGroups -}}
   117  	{{- $operationGroupCmdVarName := printf "operationGroup%vCmd" (pascalize .Name) }}
   118  	{{ $operationGroupCmdVarName }}, err := makeOperationGroup{{ pascalize .Name }}Cmd()
   119  	if err != nil {
   120  		return nil, err
   121  	}
   122  	rootCmd.AddCommand({{ $operationGroupCmdVarName }})
   123  {{ end }}
   124  
   125  	// add cobra completion
   126  	rootCmd.AddCommand(makeGenCompletionCmd())
   127  
   128  	return rootCmd, nil
   129  }
   130  
   131  // initViperConfigs initialize viper config using config file in '$HOME/.config/<cli name>/config.<json|yaml...>'
   132  // currently hostname, scheme and auth tokens can be specified in this config file.
   133  func initViperConfigs() {
   134  	if configFile != "" {
   135  		// use user specified config file location
   136  		viper.SetConfigFile(configFile)
   137  	}else{
   138  		// look for default config
   139  		// Find home directory.
   140  		home, err := homedir.Dir()
   141  		cobra.CheckErr(err)
   142  
   143  		// Search config in home directory with name ".cobra" (without extension).
   144  		viper.AddConfigPath(path.Join(home, ".config", exeName))
   145  		viper.SetConfigName("config")
   146  	}
   147  
   148  	if err := viper.ReadInConfig(); err != nil {
   149  		logDebugf("Error: loading config file: %v", err)
   150  		return
   151  	}
   152  	logDebugf("Using config file: %v", viper.ConfigFileUsed())
   153  }
   154  
   155  {{- if .SecurityDefinitions }}
   156  {{- /*youyuan: rework this since spec may define multiple auth schemes.
   157  	cli needs to detect which one user passed rather than add all of them.*/}}
   158  // registerAuthInoWriterFlags registers all flags needed to perform authentication
   159  func registerAuthInoWriterFlags(cmd *cobra.Command) error {
   160  {{- range .SecurityDefinitions }}
   161  		/*{{.Name}} {{.Description}}*/
   162  		{{- if .IsBasicAuth }}
   163  	cmd.PersistentFlags().String("username", "", "username for basic auth")
   164  	viper.BindPFlag("username", cmd.PersistentFlags().Lookup("username"))
   165  	cmd.PersistentFlags().String("password", "", "password for basic auth")
   166  	viper.BindPFlag("password", cmd.PersistentFlags().Lookup("password"))
   167  		{{- end }}
   168      	{{- if .IsAPIKeyAuth }}
   169  	cmd.PersistentFlags().String("{{.Name}}", "", `{{.Description}}`)
   170  	viper.BindPFlag("{{.Name}}", cmd.PersistentFlags().Lookup("{{.Name}}"))
   171      	{{- end }}
   172  		{{- if .IsOAuth2 }}
   173  	// oauth2: let user provide the token in a flag, rather than implement the logic to fetch the token.
   174  	cmd.PersistentFlags().String("oauth2-token", "", `{{.Description}}`)
   175  	viper.BindPFlag("oauth2-token", cmd.PersistentFlags().Lookup("oauth2-token"))
   176      	{{- end }}
   177  {{- end }}
   178  	return nil
   179  }
   180  
   181  // makeAuthInfoWriter retrieves cmd flags and construct an auth info writer
   182  func makeAuthInfoWriter(cmd *cobra.Command) (runtime.ClientAuthInfoWriter, error) {
   183  	auths := []runtime.ClientAuthInfoWriter{}
   184  {{- range .SecurityDefinitions }}
   185  	/*{{.Name}} {{.Description}}*/
   186  	{{- if .IsBasicAuth }}
   187  	if viper.IsSet("username") {
   188  		usr := viper.GetString("username")
   189  		if !viper.IsSet("password"){
   190  			return nil, fmt.Errorf("Basic Auth password for user [%v] is not provided.", usr)
   191  		}
   192  		pwd := viper.GetString("password")
   193  		auths = append(auths, httptransport.BasicAuth(usr,pwd))
   194      }
   195  	{{- end }}
   196      {{- if .IsAPIKeyAuth }}
   197  	if viper.IsSet("{{.Name}}") {
   198  		{{ pascalize .Name }}Key := viper.GetString("{{.Name}}")
   199  		auths = append(auths, httptransport.APIKeyAuth("{{.Name}}", "{{.In}}", {{ pascalize .Name }}Key))
   200      }
   201  	{{- end }}
   202  	{{- if .IsOAuth2 }}
   203  	if viper.IsSet("oauth2-token") {
   204  		// oauth2 workflow for generated CLI is not ideal.
   205  		// If you have suggestions on how to support it, raise an issue here: https://github.com/circl-dev/go-swagger/issues
   206  		// This will be added to header: "Authorization: Bearer {oauth2-token value}"
   207  		token := viper.GetString("oauth2-token")
   208  		auths = append(auths, httptransport.BearerToken(token))
   209      }
   210      {{- end }}
   211  {{- end }}
   212  	if len(auths) == 0 {
   213  		logDebugf("Warning: No auth params detected.")
   214  		return nil, nil
   215  	}
   216  	// compose all auths together
   217  	return httptransport.Compose(auths...), nil
   218  }
   219  {{- end }}
   220  
   221  {{ range .OperationGroups -}}
   222  func makeOperationGroup{{ pascalize .Name }}Cmd() (*cobra.Command, error) {
   223  	{{- $operationGroupCmdVarName := printf "operationGroup%vCmd" (pascalize .Name) }}
   224  	{{ $operationGroupCmdVarName }} := &cobra.Command{
   225  		Use:   "{{ .Name }}",
   226  		Long:  `{{ .Description }}`,
   227  	}
   228  {{ range .Operations }}
   229  	{{- $operationCmdVarName := printf "operation%vCmd" (pascalize .Name) }}
   230  	{{ $operationCmdVarName }}, err := makeOperation{{pascalize .Package}}{{ pascalize .Name }}Cmd()
   231  	if err != nil {
   232  		return nil, err
   233  	}
   234  	{{ $operationGroupCmdVarName }}.AddCommand({{ $operationCmdVarName }})
   235  {{ end }}
   236  	return {{ $operationGroupCmdVarName }}, nil
   237  }
   238  {{ end }} {{/*operation group*/}}