функция bash с третьим аргументом является массивом - PullRequest
1 голос
/ 22 мая 2019

Я пытаюсь написать 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, что: эй, возьмите все аргументы из третьего, а затем добавьте --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:

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

Обновление от 22 мая 2019 года:

После ответа Денниса Уильямсона ниже.Я пробовал:

  • Передача параметров в режиме 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
  • Passв виде строки:
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
  • Передача без ParameterKey и ParameterValue:
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
  • Передать без ParameterKey и ParameterValue и в виде строки.Получил ошибку:
arameter validation failed:
Unknown parameter in Parameters[0]: "PARAM_NAME", must be one of: ParameterKey, ParameterValue, UsePreviousValue, ResolvedValue

Я попробовал ответ Алекса Харви и получил это:

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

Ответы [ 5 ]

3 голосов
/ 22 мая 2019

Исходя из ответа LeBlue и быстрого прочтения документов , похоже, что вам нужно построить аргумент в --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 голос
/ 22 мая 2019

Я подозреваю, что расширение параметра неверно, поскольку --parameters, вероятно, должен иметь один аргумент. Либо заключите в кавычки все аргументы cloudformation_create, которые должны заканчиваться значением для флага --parameters:

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

или переписать функцию, чтобы не развернуть в несколько аргументов с помощью "$*" (объединить каждый аргумент в один)

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
1 голос
/ 22 мая 2019

Я не уверен, что ответ на ваш вопрос, но, возможно, это поможет вам.

$ # - это число параметров.

$ @ будет включать все параметры, и вы можете передать это.

#!/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
0 голосов
/ 22 мая 2019

Прежде всего, спасибо всем за помощь.

Я понял проблему (и моя ошибка ):

AWS вернул ошибку с Requires capabilities : [CAPABILITY_NAMED_IAM], и моя функция имеет [CAPABILITY_IAM].Зависит от шаблона с параметрами, связанными с созданием IAM, требуется [CAPABILITY_NAMED_IAM] или [CAPABILITY_IAM].Я нашел ответ здесь полезным.

Так что в моем случае функция bash хороша, для шаблона, который я пытался создать, мне нужно передать --capabilities CAPABILITY_NAMED_IAM.Я попробовал, и это работает.

0 голосов
/ 22 мая 2019

Я бы написал так:

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, так что вы можете простоиспользуйте $@ как обычно.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...