Existe alguma maneira de definir atalhos para valores usados com frequência derivados dos parâmetros do modelo CloudFormation?
Por exemplo - eu tenho um script que cria uma pilha do Projeto Multi-AZ com o nome ELB project
e duas instâncias atrás do ELB chamado project-1
e project-2
. Eu só passo o ELBHostName
parâmetro para o modelo e depois o uso para construir:
"Fn::Join": [
".", [
{ "Fn::Join": [ "", [ { "Ref": "ELBHostName" }, "-1" ] ] },
{ "Ref": "EnvironmentVersioned" },
{ "Ref": "HostedZone" }
]
]
Essa construção ou muito semelhante é repetida várias vezes em todo o modelo - para criar o nome do host EC2, os registros do Route53, etc.
Em vez de repetir isso repetidamente, gostaria de atribuir a saída disso Fn::Join
a uma variável de algum tipo e me referir apenas a isso, assim como posso com a "Ref":
declaração.
Idealmente, algo como:
Var::HostNameFull = "Fn::Join": [ ... ]
...
{ "Name": { "Ref": "Var::HostNameFull" } }
ou algo igualmente simples.
Isso é possível com o Amazon CloudFormation?
Respostas:
Eu estava procurando a mesma funcionalidade. O uso de uma pilha aninhada como o SpoonMeiser sugeriu me veio à mente, mas então percebi que o que realmente precisava era de funções personalizadas. Felizmente, o CloudFormation permite o uso do AWS :: CloudFormation :: CustomResource que, com um pouco de trabalho, permite fazer exatamente isso. Isso parece um exagero para apenas variáveis (algo que eu diria que deveria estar no CloudFormation em primeiro lugar), mas faz o trabalho e, além disso, permite toda a flexibilidade de (faça a sua escolha em python / nó /Java). Deve-se notar que as funções lambda custam dinheiro, mas estamos falando de centavos aqui, a menos que você crie / exclua suas pilhas várias vezes por hora.
O primeiro passo é criar uma função lambda nesta página que não faça nada além de pegar o valor de entrada e copiá-lo para a saída. Poderíamos fazer com que a função lambda fizesse todo tipo de coisa maluca, mas uma vez que tenhamos a função de identidade, qualquer outra coisa será fácil. Como alternativa, poderíamos ter a função lambda sendo criada na própria pilha. Como eu uso muitas pilhas em uma conta, eu teria várias funções e funções restantes do lambda (e todas as pilhas precisam ser criadas com
--capabilities=CAPABILITY_IAM
, pois ela também precisa de uma função).Criar função lambda
index.handler
Em seguida, copie e cole o código abaixo no campo de código. A parte superior da função é o código do módulo python cfn-response , que só é instalado automaticamente se a função lambda for criada por meio do CloudFormation, por algum motivo estranho. A
handler
função é bastante auto-explicativa.Agora você pode testar a função lambda selecionando o botão "Teste" e selecione "Solicitação de criação do CloudFormation" como modelo de amostra. Você deve ver em seu log que as variáveis alimentadas a ele são retornadas.
Use variável no seu modelo CloudFormation
Agora que temos essa função lambda, podemos usá-la nos modelos do CloudFormation. Primeiro, anote a função lambda Arn (vá para a página inicial lambda , clique na função recém-criada, o Arn deve estar no canto superior direito, algo assim
arn:aws:lambda:region:12345:function:CloudFormationIdentity
).Agora, no seu modelo, na seção de recursos, especifique suas variáveis como:
Primeiro, eu especifico uma
Identity
variável que contém o Arn para a função lambda. Colocar isso em uma variável aqui significa que eu tenho que especificá-lo apenas uma vez. Eu faço todas as minhas variáveis do tipoCustom::Variable
. O CloudFormation permite que você use qualquer nome de tipo começando porCustom::
para recursos personalizados.Observe que a
Identity
variável contém o Arn para a função lambda duas vezes. Uma vez para especificar a função lambda a ser usada. A segunda vez como o valor da variável.Agora que tenho a
Identity
variável, posso definir novas variáveis usandoServiceToken: !GetAtt [Identity, Arn]
(acho que o código JSON deve ser algo como"ServiceToken": {"Fn::GetAtt": ["Identity", "Arn"]}
). Crio 2 novas variáveis, cada uma com 2 campos: Nome e Arn. No restante do meu modelo, eu posso usar!GetAtt [ClientBucketVar, Name]
ou!GetAtt [ClientBucketVar, Arn]
sempre que precisar.Palavra de cautela
Ao trabalhar com recursos personalizados, se a função lambda travar, você ficará preso por 1 a 2 horas, porque o CloudFormation aguarda uma resposta da função (travada) por uma hora antes de desistir. Portanto, pode ser bom especificar um tempo limite curto para a pilha ao desenvolver sua função lambda.
fonte
cloudformation-tool
gema), por isso empacoto a criação do lambda em o modelo e, em seguida, pode usá-lo diretamente em vez de criar oIdentity
recurso personalizado. Veja aqui o meu código: gist.github.com/guss77/2471e8789a644cac96992c4102936fb3Eu não tenho uma resposta, mas gostaria de salientar que você pode economizar muita dor usando
Fn::Sub
no lugar deFn::Join
Substitui
fonte
Não. Eu tentei, mas fiquei vazio. A maneira que fez sentido para mim foi criar uma entrada de Mapeamentos chamada "CustomVariables" e ter essa casa com todas as minhas variáveis. Ele funciona para Strings simples, mas você não pode usar Intrinsics (Refs, Fn :: Joins, etc.) dentro de Mappings .
Trabalho:
Não vai funcionar:
Isso é apenas um exemplo. Você não colocaria uma referência independente em uma variável.
fonte
Você pode usar uma pilha aninhada que resolve todas as suas variáveis em suas saídas e, em seguida, usar
Fn::GetAtt
para ler as saídas dessa pilhafonte
Você pode usar modelos aninhados nos quais "resolve" todas as suas variáveis no modelo externo e as passa para outro modelo.
fonte