具有第三个arg的bash函数是一个数组

时间:2019-05-21 21:22:48

标签: bash amazon-web-services amazon-cloudformation

我正在尝试编写一个执行以下操作的bash函数:

  • 如果没有第三个参数,请运行命令。
  • 如果有第三个参数,请从第三个参数中获取每个参数并运行命令。

我遇到的问题是--capabilities CAPABILITY_IAM语句中命令else的最后一位,如果我有多个参数,我不想一直传递。

An error occurred (InsufficientCapabilitiesException) when calling the CreateStack operation: Requires capabilities : [CAPABILITY_NAMED_IAM]
// that means I need to pass in --capabilities CAPABILITY_IAM

有没有办法告诉bash:嘿,从第3个参数中获取所有arg,然后在其后添加--capabilities CAPABILITY_IAM?像在JavaScript中一样,我可以这样做:

function allTogetherNow(a, b, ...c) {
  console.log(`${a}, ${b}, ${c}. Can I have a little more?`);
}

allTogetherNow('one', 'two', 'three', 'four')

这是我的职能:

cloudformation_create() {
    if [ -z "$3" ]; then
        aws cloudformation create-stack --stack-name "$1" --template-body file://"$2" --capabilities CAPABILITY_IAM
    else
        aws cloudformation create-stack --stack-name "$1" --template-body file://"$2" --parameters "${@:3}" --capabilities CAPABILITY_IAM
    fi
}

如果我不使用bash函数,则第3个参数等等看起来像这样:

aws cloudformation create-stack --stack-name MY_STACK_NAME --template-body file://MY_FILE_NAME --parameters ParameterKey=KeyPairName,ParameterValue=TestKey ParameterKey=SubnetIDs,ParameterValue=SubnetID1 --capabilities CAPABILITY_IAM
  

2019年5月22日更新:

按照丹尼斯·威廉姆森的回答。我尝试过:

  • 以AWS方式传递参数:
cloudformation_create STACK_NAME FILE_NAME ParameterKey=KeyPairName,ParameterValue=TestKey ParameterKey=SubnetIDs,ParameterValue=SubnetID1

错误:

An error occurred (ValidationError) when calling the CreateStack operation: Parameters: [...] must have values
  • 作为字符串传递:
cloudformation_create STACK_NAME FILE_NAME "ParameterKey=KeyPairName,ParameterValue=TestKey ParameterKey=SubnetIDs,ParameterValue=SubnetID1"

错误:

An error occurred (ValidationError) when calling the CreateStack operation: ParameterValue for ... is required
  • 在没有ParameterKeyParameterValue的情况下通过:
cloudformation_create STACK_NAME FILE_NAME KeyPairName=TestKey SubnetIDs=SubnetID1

错误:

Parameter validation failed:
Unknown parameter in Parameters[0]: "PARAM_NAME", must be one of: ParameterKey, ParameterValue, UsePreviousValue, ResolvedValue
// list of all the params with the above error
  • 不带ParameterKeyParameterValue并以字符串形式传入。出现错误:
arameter validation failed:
Unknown parameter in Parameters[0]: "PARAM_NAME", must be one of: ParameterKey, ParameterValue, UsePreviousValue, ResolvedValue

我尝试了Alex Harvey的答案并得到了:

An error occurred (ValidationError) when calling the CreateStack operation: Template format error: unsupported structure.

5 个答案:

答案 0 :(得分:3)

基于LeBlue的答案和对docs的快速阅读,看来您需要根据函数的参数来构建--parameters的参数:

cloudformation_create () {
local IFS=,
local parameters="${*:3}"

#if block not shown
aws cloud_formation ... --parameters "$parameters" ...

这假定您的函数被这样调用:

cloudformation_create foo bar baz=123 qux=456

也就是说,使用键,已经形成了值对。

上面的代码段通过将IFS设置为逗号来工作。在引号内使用$*会使其中包含的元素使用IFS的第一个字符进行连接。如果您需要在函数的另一部分中使用分词功能,则可能需要保存IFS的当前值,然后再进行更改,然后在加入分配后将其恢复。

结果,$parameters的扩展名为baz=123,qux=456

答案 1 :(得分:1)

我不确定是否能回答您的问题,但也许会对您有所帮助。

$#是参数的数量。

$ @将包含所有参数,您可以传递它。

#!/bin/bash

foo()
{
    echo "params in foo: " $#
    echo "p1: " $1
    echo "p2: " $2
    echo "p3: " $3
}

echo "number of paramters: " $#

foo $@ 3   # pass params and add one to the end

致电:

./test.sh 1 2

输出:

number of paramters:  2
params in foo:  3
p1:  1
p2:  2
p3:  3

答案 2 :(得分:1)

我怀疑参数扩展错误,因为--parameters可能需要一个 参数。 引用cloudformation_create的所有需要​​结束的参数作为--parameters标志的值:

cloudformation_create "the-stack" "the-filename" "all the parameters"

或将函数重写为 not "$*"扩展为多个参数(将每个arg合并为一个)

cloudformation_create () {
    ...
    else
        aws cloudformation ... --parameters "${*:3}" --capabilities CAPABILITY_IAM
    fi
}

这会将所有值保留为一个字符串/参数,两者都将转换为:

aws cloudformation  ... --parameters "all other parameters" --capabilities CAPABILITY_IAM

与您的版本相反:

aws cloudformation ... --parameters "all" "other" "parameters" --capabilities CAPABILITY_IAM

答案 3 :(得分:0)

我会这样写:

cloudformation_create() {
  local stack_name=$1
  local template_body=$2
  shift 2 ; local parameters="$@"

  local command=(aws cloudformation create-stack 
    --stack-name "$stack_name"
    --template-body "file://$template_body")

  [ ! -z "$parameters" ] && \
    command+=(--parameters "$parameters")

  command+=(--capabilities CAPABILITY_IAM)

  ${command[@]}
}

注意:

  • 呼叫shift 2会将$3旋转到$1,这样您就可以照常使用$@

答案 4 :(得分:0)

首先,感谢大家的帮助。

我已经意识到了这个问题(并且我的错误):

AWS用Requires capabilities : [CAPABILITY_NAMED_IAM]返回了错误,我的函数有[CAPABILITY_IAM]。 取决于模板以及与创建IAM相关的参数,需要[CAPABILITY_NAMED_IAM][CAPABILITY_IAM]。我发现答案here很有帮助。

因此,对于我而言,bash函数很好,对于我尝试创建的模板,我需要传递--capabilities CAPABILITY_NAMED_IAM。我已经尝试过了,而且效果很好。