cmd/utils.go (121 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 cmd import ( "encoding/json" "fmt" "io/ioutil" "strings" "github.com/apache/openwhisk-wskdeploy/wskderrors" "github.com/apache/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 }