commands/commands.go (199 lines of code) (raw):

/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package commands import ( "errors" "net/http" "os" "runtime" "github.com/apache/openwhisk-cli/wski18n" "github.com/apache/openwhisk-client-go/whisk" "github.com/spf13/cobra" ) var Client *whisk.Client const DefaultOpenWhiskApiPath string = "/api" var UserAgent string = "OpenWhisk-CLI" var AdditionalHeaders http.Header func SetupClientConfig(cmd *cobra.Command, args []string) error { baseURL, err := whisk.GetURLBase(Properties.APIHost, DefaultOpenWhiskApiPath) // Determine if the parent command will require the API host to be set apiHostRequired := (cmd.Parent().Name() == "property" && cmd.Name() == "get" && (Flags.property.auth || Flags.property.cert || Flags.property.key || Flags.property.apihost || Flags.property.apiversion || Flags.property.cliversion)) || (cmd.Parent().Name() == "property" && cmd.Name() == "set" && (len(Flags.property.apihostSet) > 0 || len(Flags.property.apiversionSet) > 0 || len(Flags.Global.Auth) > 0)) || (cmd.Parent().Name() == "sdk" && cmd.Name() == "install" && len(args) > 0 && args[0] == "bashauto") // Display an error if the parent command requires an API host to be set, and the current API host is not valid if err != nil && !apiHostRequired { whisk.Debug(whisk.DbgError, "whisk.GetURLBase(%s, %s) error: %s\n", Properties.APIHost, DefaultOpenWhiskApiPath, err) errMsg := wski18n.T("The API host is not valid: {{.err}}", map[string]interface{}{"err": err}) whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE) return whiskErr } clientConfig := &whisk.Config{ Cert: Properties.Cert, Key: Properties.Key, AuthToken: Properties.Auth, Namespace: Properties.Namespace, BaseURL: baseURL, Version: Properties.APIVersion, Insecure: Flags.Global.Insecure, Host: Properties.APIHost, UserAgent: UserAgent + "/1.0 (" + Properties.CLIVersion + ") " + runtime.GOOS + " " + runtime.GOARCH, AdditionalHeaders: AdditionalHeaders, } if len(clientConfig.Host) == 0 { config, _ := whisk.GetDefaultConfig() clientConfig.Host = config.Host if len(clientConfig.Host) == 0 { clientConfig.Host = "openwhisk.ng.bluemix.net" } } // Setup client Client, err = whisk.NewClient(http.DefaultClient, clientConfig) if err != nil { whisk.Debug(whisk.DbgError, "whisk.NewClient(%#v, %#v) error: %s\n", http.DefaultClient, clientConfig, err) errMsg := wski18n.T("Unable to initialize server connection: {{.err}}", map[string]interface{}{"err": err}) whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE) return whiskErr } return nil } func init() {} func getKeyValueArgs(args []string, argIndex int, parsedArgs []string) ([]string, []string, error) { var whiskErr error var key string var value string if len(args)-1 >= argIndex+2 { key = args[argIndex+1] value = args[argIndex+2] parsedArgs = append(parsedArgs, getFormattedJSON(key, value)) args = append(args[:argIndex], args[argIndex+3:]...) } else { whisk.Debug(whisk.DbgError, "Arguments for '%s' must be a key/value pair; args: %s", args[argIndex], args) errMsg := wski18n.T("Arguments for '{{.arg}}' must be a key/value pair", map[string]interface{}{"arg": args[argIndex]}) whiskErr = whisk.MakeWskError(errors.New(errMsg), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE) } return parsedArgs, args, whiskErr } func getValueFromArgs(args []string, argIndex int, parsedArgs []string) ([]string, []string, error) { var whiskErr error if len(args)-1 >= argIndex+1 { parsedArgs = append(parsedArgs, args[argIndex+1]) args = append(args[:argIndex], args[argIndex+2:]...) } else { whisk.Debug(whisk.DbgError, "An argument must be provided for '%s'; args: %s", args[argIndex], args) errMsg := wski18n.T("An argument must be provided for '{{.arg}}'", map[string]interface{}{"arg": args[argIndex]}) whiskErr = whisk.MakeWskError(errors.New(errMsg), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE) } return parsedArgs, args, whiskErr } func parseArgs(args []string) ([]string, []string, []string, []string, []string, error) { var paramArgs []string var annotArgs []string var feedParamArgs []string var triggerParamArgs []string var whiskErr error i := 0 for i < len(args) { if args[i] == "-P" || args[i] == "--param-file" { paramArgs, args, whiskErr = getValueFromArgs(args, i, paramArgs) if whiskErr != nil { whisk.Debug(whisk.DbgError, "getValueFromArgs(%#v, %d) failed: %s\n", args, i, whiskErr) errMsg := wski18n.T("The parameter arguments are invalid: {{.err}}", map[string]interface{}{"err": whiskErr}) whiskErr = whisk.MakeWskError(errors.New(errMsg), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE) return nil, nil, nil, nil, nil, whiskErr } filename := paramArgs[len(paramArgs)-1] paramArgs[len(paramArgs)-1], whiskErr = ReadFile(filename) if whiskErr != nil { whisk.Debug(whisk.DbgError, "readFile(%s) error: %s\n", filename, whiskErr) return nil, nil, nil, nil, nil, whiskErr } } else if args[i] == "-A" || args[i] == "--annotation-file" { annotArgs, args, whiskErr = getValueFromArgs(args, i, annotArgs) if whiskErr != nil { whisk.Debug(whisk.DbgError, "getValueFromArgs(%#v, %d) failed: %s\n", args, i, whiskErr) errMsg := wski18n.T("The annotation arguments are invalid: {{.err}}", map[string]interface{}{"err": whiskErr}) whiskErr = whisk.MakeWskError(errors.New(errMsg), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE) return nil, nil, nil, nil, nil, whiskErr } filename := annotArgs[len(annotArgs)-1] annotArgs[len(annotArgs)-1], whiskErr = ReadFile(filename) if whiskErr != nil { whisk.Debug(whisk.DbgError, "readFile(%s) error: %s\n", filename, whiskErr) return nil, nil, nil, nil, nil, whiskErr } } else if args[i] == "-p" || args[i] == "--param" { paramArgs, args, whiskErr = getKeyValueArgs(args, i, paramArgs) if whiskErr != nil { whisk.Debug(whisk.DbgError, "getKeyValueArgs(%#v, %d) failed: %s\n", args, i, whiskErr) errMsg := wski18n.T("The parameter arguments are invalid: {{.err}}", map[string]interface{}{"err": whiskErr}) whiskErr = whisk.MakeWskError(errors.New(errMsg), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE) return nil, nil, nil, nil, nil, whiskErr } } else if args[i] == "-a" || args[i] == "--annotation" { annotArgs, args, whiskErr = getKeyValueArgs(args, i, annotArgs) if whiskErr != nil { whisk.Debug(whisk.DbgError, "getKeyValueArgs(%#v, %d) failed: %s\n", args, i, whiskErr) errMsg := wski18n.T("The annotation arguments are invalid: {{.err}}", map[string]interface{}{"err": whiskErr}) whiskErr = whisk.MakeWskError(errors.New(errMsg), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE) return nil, nil, nil, nil, nil, whiskErr } } else if args[i] == "-F" || args[i] == "--feed-param" { feedParamArgs, args, whiskErr = getKeyValueArgs(args, i, feedParamArgs) if whiskErr != nil { whisk.Debug(whisk.DbgError, "getKeyValueArgs(%#v, %d) failed: %s\n", args, i, whiskErr) whiskErr = whisk.MakeWskError(whiskErr, whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE) return nil, nil, nil, nil, nil, whiskErr } } else if args[i] == "-T" || args[i] == "--trigger-param" { triggerParamArgs, args, whiskErr = getKeyValueArgs(args, i, triggerParamArgs) if whiskErr != nil { whisk.Debug(whisk.DbgError, "getKeyValueArgs(%#v, %d) failed: %s\n", args, i, whiskErr) whiskErr = whisk.MakeWskError(whiskErr, whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE) return nil, nil, nil, nil, nil, whiskErr } } else { i++ } } whisk.Debug(whisk.DbgInfo, "Found param args '%s'.\n", paramArgs) whisk.Debug(whisk.DbgInfo, "Found annotations args '%s'.\n", annotArgs) whisk.Debug(whisk.DbgInfo, "Found feed param args '%s'.\n", feedParamArgs) whisk.Debug(whisk.DbgInfo, "Found trigger param args '%s'.\n", triggerParamArgs) whisk.Debug(whisk.DbgInfo, "Arguments with param args removed '%s'.\n", args) return args, paramArgs, annotArgs, feedParamArgs, triggerParamArgs, nil } func Execute() error { var err error whisk.Debug(whisk.DbgInfo, "wsk args: %#v\n", os.Args) os.Args, Flags.common.param, Flags.common.annotation, Flags.trigger.feedParam, Flags.trigger.triggerParam, err = parseArgs(os.Args) if err != nil { whisk.Debug(whisk.DbgError, "parseParams(%s) failed: %s\n", os.Args, err) errMsg := wski18n.T("Failed to parse arguments: {{.err}}", map[string]interface{}{"err": err}) whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE) return whiskErr } err = loadProperties() if err != nil { whisk.Debug(whisk.DbgError, "loadProperties() error: %s\n", err) errMsg := wski18n.T("Unable to access configuration properties: {{.err}}", map[string]interface{}{"err": err}) whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE) return whiskErr } return WskCmd.Execute() }