| /* |
| * 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() |
| } |