Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.
Exemple de macro : Création et utilisation d'une macro
L'exemple suivant passe en revue le processus d'utilisation des macros, de la définition de la macro dans un modèle jusqu'à l'utilisation de la macro dans un modèle, en passant par la création d'une fonction Lambda pour la macro.
Dans cet exemple, nous créons une macro simple qui insère la chaîne spécifiée à la place du contenu cible spécifié dans le modèle traité. Ensuite, nous l'utiliserons pour insérer un champ WaitHandleCondition
vide dans l'emplacement spécifié dans le modèle traité.
Exemple de macro : Modèle de définition de macro
Avant d'utiliser une macro, nous devons d'abord effectuer deux opérations : créer la fonction Lambda qui exécute le traitement du modèle souhaité, puis rendre cette fonction Lambda accessible CloudFormation en créant une définition de macro.
Note
Nous examinerons le code de la fonction Lambda plus loin dans cette rubrique.
L'exemple de modèle suivant contient la définition de notre exemple de macro. Pour rendre la macro disponible dans un CloudFormation compte spécifique, nous créons une pile à partir du modèle. La définition de macro spécifie le nom de la macro, une brève description et fait référence à ARN la fonction Lambda qui est appelée CloudFormation lorsque cette macro est utilisée dans un modèle. (Nous n'avons pas inclus de LogRoleARNpropriété LogGroupNameor pour la journalisation des erreurs.) Pour plus d'informations, consultez AWS: : CloudFormation : :Macro.
Dans cet exemple, supposons que la pile créée à partir de ce modèle est nommée JavaMacroFunc. Comme la Name
propriété de la macro est définie sur le nom de la pile, la macro résultante est également JavaMacroFuncnommée.
AWSTemplateFormatVersion: 2010-09-09 Resources: Macro: Type: AWS::CloudFormation::Macro Properties: Name:
!Sub '${AWS::StackName}'
Description:Adds a blank WaitConditionHandle named WaitHandle
FunctionName:'arn:aws:lambda:us-east-1:012345678910:function:JavaMacroFunc'
Exemple de macro : Modèle d'utilisation de macro
Pour utiliser notre macro dans ce cas, nous allons l'inclure dans un modèle à l'aide de la fonction intrinsèque Fn::Transform.
Lorsque nous créons une pile à l'aide du modèle ci-dessous, CloudFormation appelle notre exemple de macro. La fonction Lambda sous-jacente remplace une chaîne spécifiée par une autre chaîne spécifiée. Dans ce cas, le résultat est qu'un champ vide AWS: CloudFormation : : : WaitConditionHandle est inséré dans le modèle traité.
Notez ce qui suit :
-
La macro à invoquer est spécifiée comme telle JavaMacroFunc, comme indiqué dans l'exemple de définition de macro précédent.
-
Deux paramètres sont transmis à cette macro,
target
etreplacement
, qui représentent la chaîne cible et sa valeur de remplacement souhaitée. -
La macro peut fonctionner sur le contenu du nœud
Type
, carType
est un frère de la fonctionFn::Transform
référençant la macro. -
Le résultat AWS: CloudFormation : : WaitConditionHandle est nommé
2a
. -
Le modèle contient également un paramètre de modèle,
ExampleParameter
, auquel la macro a également accès (mais n'utilise pas dans ce cas).
Parameters: ExampleParameter: Type: String Default: 'SampleMacro' Resources: 2a: Fn::Transform: Name: "JavaMacroFunc" Parameters: replacement: 'AWS::CloudFormation::WaitConditionHandle' target: '$$REPLACEMENT$$' Type: '$$REPLACEMENT$$'
Exemple de macro : Demander un mappage d'événement
Lors du CloudFormation traitement de notre exemple de modèle lors de la création de la pile, il transmet le mappage d'événements suivant à la fonction Lambda référencée dans la définition de la JavaMacroFuncmacro.
fragment
contient JSON le fragment de modèle que la macro peut traiter. Ce fragment comprend les frères de l'appel de fonction Fn::Transform
, mais pas l'appel de fonction lui-même. params
Contient également la JSON représentation des paramètres de la macro. Dans ce cas, replacement et target. De même, templateParameterValues
contient des éléments JSON représentant les paramètres spécifiés pour le modèle dans son ensemble.
-
region
us-east-1
-
accountId
012345678910
-
fragment
{ "Type": "$$REPLACEMENT$$" }
-
transformId
012345678910::JavaMacroFunc
-
params
{ "replacement": "AWS::CloudFormation::WaitConditionHandle", "target": "$$REPLACEMENT$$" }
-
requestId
5dba79b5-f117-4de0-9ce4-d40363bfb6ab
-
templateParameterValues
{ "ExampleParameter": "SampleMacro" }
Exemple de macro : Code de la fonction Lambda
Voici le code réel de la fonction Lambda sous-jacente à l'JavaMacroFuncexemple de macro. La fonction parcourt le fragment de modèle inclus dans la réponse (qu'elle soit dans un format de chaîne, de liste ou de mappage), à la recherche de la chaîne cible spécifiée. Si elle trouve la chaîne cible spécifiée, la fonction Lambda remplace la chaîne cible par la chaîne de remplacement spécifiée. Sinon, la fonction laisse le fragment de modèle inchangé. La fonction renvoie ensuite une carte des propriétés attendues, décrites en détail ci-dessous, à CloudFormation.
package com.macroexample.lambda.demo; import java.util.List; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; public class LambdaFunctionHandler implements RequestHandler<Map<String, Object>, Map<String, Object>> { private static final String REPLACEMENT = "replacement"; private static final String TARGET = "target"; private static final String PARAMS = "params"; private static final String FRAGMENT = "fragment"; private static final String REQUESTID = "requestId"; private static final String STATUS = "status"; private static final String SUCCESS = "SUCCESS"; private static final String FAILURE = "FAILURE"; @Override public Map<String, Object> handleRequest(Map<String, Object> event, Context context) { // TODO: implement your handler final Map<String, Object> responseMap = new HashMap<String, Object>(); responseMap.put(REQUESTID, event.get(REQUESTID)); responseMap.put(STATUS, FAILURE); try { if (!event.containsKey(PARAMS)) { throw new RuntimeException("Params are required"); } final Map<String, Object> params = (Map<String, Object>) event.get(PARAMS); if (!params.containsKey(REPLACEMENT) || !params.containsKey(TARGET)) { throw new RuntimeException("replacement or target under Params are required"); } final String replacement = (String) params.get(REPLACEMENT); final String target = (String) params.get(TARGET); final Object fragment = event.getOrDefault(FRAGMENT, new HashMap<String, Object>()); final Object retFragment; if (fragment instanceof String) { retFragment = iterateAndReplace(replacement, target, (String) fragment); } else if (fragment instanceof List) { retFragment = iterateAndReplace(replacement, target, (List<Object>) fragment); } else if (fragment instanceof Map) { retFragment = iterateAndReplace(replacement, target, (Map<String, Object>) fragment); } else { retFragment = fragment; } responseMap.put(STATUS, SUCCESS); responseMap.put(FRAGMENT, retFragment); return responseMap; } catch (Exception e) { e.printStackTrace(); context.getLogger().log(e.getMessage()); return responseMap; } } private Map<String, Object> iterateAndReplace(final String replacement, final String target, final Map<String, Object> fragment) { final Map<String, Object> retFragment = new HashMap<String, Object>(); final List<String> replacementKeys = new ArrayList<>(); fragment.forEach((k, v) -> { if (v instanceof String) { retFragment.put(k, iterateAndReplace(replacement, target, (String)v)); } else if (v instanceof List) { retFragment.put(k, iterateAndReplace(replacement, target, (List<Object>)v)); } else if (v instanceof Map ) { retFragment.put(k, iterateAndReplace(replacement, target, (Map<String, Object>) v)); } else { retFragment.put(k, v); } }); return retFragment; } private List<Object> iterateAndReplace(final String replacement, final String target, final List<Object> fragment) { final List<Object> retFragment = new ArrayList<>(); fragment.forEach(o -> { if (o instanceof String) { retFragment.add(iterateAndReplace(replacement, target, (String) o)); } else if (o instanceof List) { retFragment.add(iterateAndReplace(replacement, target, (List<Object>) o)); } else if (o instanceof Map) { retFragment.add(iterateAndReplace(replacement, target, (Map<String, Object>) o)); } else { retFragment.add(o); } }); return retFragment; } private String iterateAndReplace(final String replacement, final String target, final String fragment) { System.out.println(replacement + " == " + target + " == " + fragment ); if (fragment != null AND_AND fragment.equals(target)) return replacement; return fragment; } }
Exemple de macro : Réponse de la fonction Lambda
Voici le mappage auquel la fonction Lambda retourne CloudFormation pour être traitée. Les requestId
correspondances envoyées depuis CloudFormation et une status
valeur de SUCCESS
indiquent que la fonction Lambda a traité avec succès le fragment de modèle inclus dans la demande. Dans cette réponse, fragment
contient le JSON contenu à insérer dans le modèle traité à la place de l'extrait de modèle d'origine.
-
requestId
5dba79b5-f117-4de0-9ce4-d40363bfb6ab
-
status
SUCCESS
-
fragment
{ "Type": "AWS::CloudFormation::WaitConditionHandle" }
Exemple de macro : Modèle traité obtenu
Après avoir CloudFormation reçu une réponse positive de la part de la fonction Lambda, elle insère le fragment de modèle renvoyé dans le modèle traité.
Vous trouverez ci-dessous le modèle traité obtenu pour notre exemple. L'appel de fonction Fn::Transform
intrinsèque qui faisait référence à la JavaMacroFuncmacro n'est plus inclus. Le fragment de modèle renvoyé par la fonction Lambda est inclus dans l'emplacement approprié, de sorte que le contenu "Type": "$$REPLACEMENT$$"
a été remplacé par "Type":
"AWS::CloudFormation::WaitConditionHandle"
.
{ "Parameters": { "ExampleParameter": { "Default": "SampleMacro", "Type": "String" } }, "Resources": { "2a": { "Type": "AWS::CloudFormation::WaitConditionHandle" } } }
Exemples supplémentaires de macros
Outre cette procédure pas à pas dans ce guide, vous trouverez des exemples de macros, notamment du code source et des modèles, dans notre GitHub référentiel