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

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