¿Hay alguna forma de definir accesos directos para los valores de uso frecuente derivados de los parámetros de la plantilla CloudFormation?
Por ejemplo: tengo un script que crea una pila de proyectos Multi-AZ con el nombre ELB project
y dos instancias detrás del ELB llamado project-1
y project-2
. Solo paso el ELBHostName
parámetro a la plantilla y luego lo uso para construir:
"Fn::Join": [
".", [
{ "Fn::Join": [ "", [ { "Ref": "ELBHostName" }, "-1" ] ] },
{ "Ref": "EnvironmentVersioned" },
{ "Ref": "HostedZone" }
]
]
Esta construcción o muy similar se repite muchas veces a lo largo de la plantilla, para crear el nombre de host EC2, los registros de Route53, etc.
En lugar de repetir eso una y otra vez, me gustaría asignar el resultado de eso Fn::Join
a una variable de algún tipo y solo referirme a eso, al igual que puedo con la "Ref":
declaración.
Idealmente algo como:
Var::HostNameFull = "Fn::Join": [ ... ]
...
{ "Name": { "Ref": "Var::HostNameFull" } }
o algo similarmente simple.
¿Es eso posible con Amazon CloudFormation?
Respuestas:
Estaba buscando la misma funcionalidad. El uso de una pila anidada como SpoonMeiser sugirió vino a mi mente, pero luego me di cuenta de que lo que realmente necesitaba eran funciones personalizadas. Afortunadamente, CloudFormation permite el uso de AWS :: CloudFormation :: CustomResource que, con un poco de trabajo, le permite a uno hacer exactamente eso. Esto se siente como una exageración solo para variables (algo que diría que debería haber estado en CloudFormation en primer lugar), pero hace el trabajo y, además, permite toda la flexibilidad de (elija Python / node /Java). Cabe señalar que las funciones lambda cuestan dinero, pero aquí estamos hablando de centavos a menos que cree / elimine sus pilas varias veces por hora.
El primer paso es hacer que una función lambda en esta página no haga nada más que tomar el valor de entrada y copiarlo a la salida. Podríamos hacer que la función lambda haga todo tipo de locuras, pero una vez que tenemos la función de identidad, cualquier otra cosa es fácil. Alternativamente, podríamos crear la función lambda en la pila misma. Como uso muchas pilas en 1 cuenta, tendría un montón de funciones y roles lambda sobrantes (y todas las pilas deben crearse
--capabilities=CAPABILITY_IAM
, ya que también necesita un rol.Crear función lambda
index.handler
Luego copie y pegue el código a continuación en el campo de código. La parte superior de la función es el código del módulo de python cfn-response , que solo se instala automáticamente si la función lambda se crea a través de CloudFormation, por alguna extraña razón. La
handler
función es bastante autoexplicativa.Ahora puede probar la función lambda seleccionando el botón "Prueba" y seleccione "Solicitud de creación de CloudFormation" como plantilla de muestra. Debería ver en su registro que se devuelven las variables alimentadas.
Usar variable en su plantilla de CloudFormation
Ahora que tenemos esta función lambda, podemos usarla en las plantillas de CloudFormation. Primero tome nota de la función lambda Arn (vaya a la página de inicio lambda , haga clic en la función recién creada, el Arn debe estar en la parte superior derecha, algo así como
arn:aws:lambda:region:12345:function:CloudFormationIdentity
).Ahora en su plantilla, en la sección de recursos, especifique sus variables como:
Primero especifico una
Identity
variable que contiene el Arn para la función lambda. Poner esto en una variable aquí, significa que solo tengo que especificarlo una vez. Hago todas mis variables de tipoCustom::Variable
. CloudFormation le permite usar cualquier tipo de nombre que comience conCustom::
recursos personalizados.Tenga en cuenta que la
Identity
variable contiene el Arn para la función lambda dos veces. Una vez para especificar la función lambda a utilizar. La segunda vez como el valor de la variable.Ahora que tengo la
Identity
variable, puedo definir nuevas variables usandoServiceToken: !GetAtt [Identity, Arn]
(creo que el código JSON debería ser algo así como"ServiceToken": {"Fn::GetAtt": ["Identity", "Arn"]}
). Creo 2 nuevas variables, cada una con 2 campos: Nombre y Arn. En el resto de mi plantilla puedo usar!GetAtt [ClientBucketVar, Name]
o!GetAtt [ClientBucketVar, Arn]
cuando lo necesite.Palabra de precaución
Al trabajar con recursos personalizados, si la función lambda se bloquea, está atascado entre 1 y 2 horas, porque CloudFormation espera una respuesta de la función (bloqueada) durante una hora antes de darse por vencido. Por lo tanto, podría ser bueno especificar un tiempo de espera corto para la pila mientras se desarrolla la función lambda.
fuente
cloudformation-tool
gema), así que empaco la creación lambda en la plantilla y luego puede usarla directamente en lugar de crear elIdentity
recurso personalizado. Vea aquí mi código: gist.github.com/guss77/2471e8789a644cac96992c4102936fb3No tengo una respuesta, pero quería señalar que puede ahorrarse mucho dolor al usarlo
Fn::Sub
en lugar deFn::Join
Reemplaza
fuente
No. Lo intenté, pero me quedé vacío. La forma que tenía sentido para mí era crear una entrada de asignaciones llamada "CustomVariables" y tener esa casa todas mis variables. Funciona para cadenas simples, pero no puede usar Intrinsics (Refs, Fn :: Joins, etc.) dentro de Mappings .
Trabajos:
No funcionará
Eso es solo un ejemplo. No pondrías una referencia independiente en una variable.
fuente
Podría usar una pila anidada que resuelva todas sus variables en sus salidas, y luego usarla
Fn::GetAtt
para leer las salidas de esa pilafuente
Puede usar plantillas anidadas en las que "resuelve" todas sus variables en la plantilla externa y las pasa a otra plantilla.
fuente