| /* |
| * 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 cmd |
| |
| import ( |
| "encoding/json" |
| "fmt" |
| "io/ioutil" |
| "strings" |
| |
| "github.com/apache/incubator-openwhisk-wskdeploy/wskderrors" |
| "github.com/apache/incubator-openwhisk-wskdeploy/wski18n" |
| ) |
| |
| const ( |
| FLAG_CONFIG = "config" |
| FLAG_PROJECT = "project" |
| FLAG_PROJECT_SHORT = "p" |
| FLAG_MANIFEST = "manifest" |
| FLAG_MANIFEST_SHORT = "m" |
| FLAG_DEPLOYMENT = "deployment" |
| FLAG_DEPLOYMENT_SHORT = "d" |
| FLAG_STRICT = "strict" |
| FLAG_STRICT_SHORT = "s" |
| FLAG_PREVIEW = "preview" |
| FLAG_VERBOSE = "verbose" |
| FLAG_VERBOSE_SHORT = "v" |
| FLAG_API_HOST = "apihost" |
| FLAG_NAMESPACE = "namespace" |
| FLAG_NAMESPACE_SHORT = "n" |
| FLAG_AUTH = "auth" |
| FLAG_AUTH_SHORT = "u" |
| FLAG_APIVERSION = "apiversion" |
| FLAG_KEY = "key" |
| FLAG_KEY_SHORT = "k" |
| FLAG_CERT = "cert" |
| FLAG_CERT_SHORT = "c" |
| FLAG_MANAGED = "managed" |
| FLAG_PROJECTNAME = "projectname" |
| FLAG_TRACE = "trace" |
| FLAG_TRACE_SHORT = "t" |
| FLAG_PARAM = "param" |
| FLAG_PARAMFILE = "param-file" |
| FLAG_PARAMFILE_SHORT = "P" |
| SHORT_CMD = "-" |
| LONG_CMD = SHORT_CMD + SHORT_CMD |
| ) |
| |
| // parse key value pairs from --param |
| // read parameters from param JSON file specified in --param-file |
| func parseArgsForParams(args []string) ([]string, []string, error) { |
| var paramArgs []string |
| var err error |
| |
| i := 0 |
| |
| // iterate over the list of input arguments |
| // append key value pair of --param <parameter name> <parameter value> as a string |
| // in case of --param-file, read parameter file, append each JSON "key: value" pair as a string |
| for i < len(args) { |
| // when arg is -P or --param-file, open and read the specified JSON file |
| if args[i] == SHORT_CMD+FLAG_PARAMFILE_SHORT || args[i] == LONG_CMD+FLAG_PARAMFILE { |
| // Command line parser library Cobra, assigns value of --param-file to utils.Flags.ParamFile |
| // but at this point of execution, we still don't have utils.Flags.ParamFile assigned any value |
| // and that's the reason, we have to explicitly parse the argument list to get the file name |
| paramArgs, args, err = getValueFromArgs(args, i, paramArgs) |
| if err != nil { |
| return nil, nil, err |
| } |
| filename := paramArgs[len(paramArgs)-1] |
| // drop the argument (--param-file) and its value from the argument list after retrieving filename |
| // read file content as a single string and append it to the list of params |
| file, readErr := ioutil.ReadFile(filename) |
| if readErr != nil { |
| err = wskderrors.NewCommandError(FLAG_PARAMFILE+"/"+FLAG_PARAMFILE_SHORT, |
| wski18n.T(wski18n.ID_ERR_INVALID_PARAM_FILE_X_file_X, |
| map[string]interface{}{ |
| wski18n.KEY_PATH: filename, |
| wski18n.KEY_ARG: FLAG_PARAMFILE + "/" + FLAG_PARAMFILE_SHORT, |
| wski18n.KEY_ERR: readErr})) |
| return nil, nil, err |
| } |
| paramArgs[len(paramArgs)-1] = string(file) |
| // --param can appear multiple times in a single invocation of whisk deploy |
| // for example, wskdeploy -m manifest.yaml --param key1 value1 --param key2 value2 |
| // parse key value map for each --param from the argument list |
| // drop each --param and key value map from the argument list after reading the map |
| // append key value as a string to the list of params |
| } else if args[i] == LONG_CMD+FLAG_PARAM { |
| paramArgs, args, err = getKeyValueArgs(args, i, paramArgs) |
| if err != nil { |
| return nil, nil, err |
| } |
| } else { |
| i++ |
| } |
| } |
| return args, paramArgs, nil |
| } |
| |
| func getValueFromArgs(args []string, argIndex int, parsedArgs []string) ([]string, []string, error) { |
| var err error |
| // check if parameter argument has any value |
| if len(args)-1 >= argIndex+1 { |
| // update arguments list and parameter list |
| // append param value (JSON file name) to list of parameters |
| parsedArgs = append(parsedArgs, args[argIndex+1]) |
| // drop the parameter (--param-file) and its value (JSON file name) from the argument list |
| args = append(args[:argIndex], args[argIndex+2:]...) |
| } else { |
| err = wskderrors.NewCommandError(args[argIndex], |
| wski18n.T(wski18n.ID_ERR_ARG_MISSING_VALUE_X_arg_X, |
| map[string]interface{}{wski18n.KEY_ARG: args[argIndex]})) |
| } |
| return parsedArgs, args, err |
| } |
| |
| func getKeyValueArgs(args []string, argIndex int, parsedArgs []string) ([]string, []string, error) { |
| var err error |
| var key string |
| var value string |
| // check if parameter argument has a key/value pair specified |
| if len(args)-1 >= argIndex+2 { |
| key = args[argIndex+1] |
| value = args[argIndex+2] |
| // append key/value pairs to list of parameters |
| // drop those pairs from the argument list |
| parsedArgs = append(parsedArgs, getFormattedJSON(key, value)) |
| args = append(args[:argIndex], args[argIndex+3:]...) |
| } else { |
| err = wskderrors.NewCommandError(args[argIndex], |
| wski18n.T(wski18n.ID_ERR_ARG_MISSING_KEY_VALUE_X_arg_X, |
| map[string]interface{}{wski18n.KEY_ARG: args[argIndex]})) |
| } |
| return parsedArgs, args, err |
| } |
| |
| func getFormattedJSON(key string, value string) string { |
| var res string |
| key = getEscapedJSON(key) |
| if isValidJSON(value) { |
| res = fmt.Sprintf("{\"%s\": %s}", key, value) |
| } else { |
| res = fmt.Sprintf("{\"%s\": \"%s\"}", key, value) |
| } |
| return res |
| } |
| |
| func isValidJSON(value string) bool { |
| var jsonInterface interface{} |
| err := json.Unmarshal([]byte(value), &jsonInterface) |
| return err == nil |
| } |
| |
| func getEscapedJSON(value string) string { |
| value = strings.Replace(value, "\\", "\\\\", -1) |
| value = strings.Replace(value, "\"", "\\\"", -1) |
| return value |
| } |