github.com/thetreep/go-swagger@v0.0.0-20240223100711-35af64f14f01/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/thetreep/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*/}}