Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.
Esempio di semplice macro di sostituzione di stringhe
L'esempio seguente illustra il processo di utilizzo delle macro, dalla definizione della macro in un modello, alla creazione di una funzione Lambda per la macro e quindi all'utilizzo della macro in un modello.
In questo esempio, creeremo una macro semplice che inserisce la stringa specificata al posto del contenuto di destinazione specificato nel modello elaborato. Quindi la utilizzeremo per inserire un campo WaitHandleCondition
vuoto nella posizione specificata nel modello elaborato.
Creazione di una macro
Prima di utilizzare una macro, dobbiamo prima completare due operazioni: creare la funzione Lambda che esegue l'elaborazione del modello desiderata e quindi rendere disponibile tale funzione CloudFormation Lambda creando una definizione di macro.
L'esempio di modello seguente contiene la definizione del nostro esempio di macro. Per rendere disponibile la macro in uno specifico Account AWS, create uno stack dal modello. La definizione della macro specifica il nome della macro, una breve descrizione e fa riferimento alla ARN funzione Lambda CloudFormation che richiama quando questa macro viene utilizzata in un modello. (Non abbiamo incluso una LogRoleARN
proprietà LogGroupName
or per la registrazione degli errori.)
In questo esempio, supponiamo che lo stack creato da questo modello abbia un nome. JavaMacroFunc
Poiché la Name
proprietà macro è impostata sul nome dello stack, anche la macro risultante viene JavaMacroFunc
denominata.
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'
Utilizzo della macro
Per utilizzare la nostra macro, la includiamo in un modello utilizzando la funzione Fn::Transform
intrinseca.
Quando creiamo uno stack utilizzando il modello seguente, CloudFormation richiama la nostra macro di esempio. La funzione Lambda sottostante sostituisce una stringa specificata con un'altra stringa specificata. In questo caso, il risultato è una risorsa AWS::CloudFormation::WaitConditionHandle
vuota che viene inserita nel modello elaborato.
Parameters: ExampleParameter: Type: String Default: 'SampleMacro' Resources: 2a: Fn::Transform: Name: "JavaMacroFunc" Parameters: replacement: 'AWS::CloudFormation::WaitConditionHandle' target: '$$REPLACEMENT$$' Type: '$$REPLACEMENT$$'
-
La macro da richiamare è specificata come
JavaMacroFunc
, che proviene dal precedente esempio di definizione di macro. -
Alla macro vengono passati due parametri,
target
ereplacement
, che rappresentano la stringa di destinazione e il valore di sostituzione desiderato. -
La macro può funzionare sul contenuto del nodo
Type
in quantoType
è un elemento di pari livello della funzioneFn::Transform
che fa riferimento alla macro. -
La risorsa
AWS::CloudFormation::WaitConditionHandle
risultante è denominata2a
. -
Il modello contiene inoltre un parametro di modello,
ExampleParameter
, a cui la macro ha accesso (ma che non utilizza in questo caso).
Dati di input Lambda
Quando CloudFormation elabora il nostro modello di esempio durante la creazione dello stack, passa la seguente mappatura degli eventi alla funzione Lambda a cui si fa riferimento nella definizione della macro. JavaMacroFunc
-
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" }
fragment
contiene la JSON rappresentazione del frammento di modello che la macro può elaborare. Questo frammento comprende elementi di pari livello della chiamata di funzione Fn::Transform
, ma non la chiamata stessa. Inoltre, params
contiene la JSON rappresentazione dei parametri della macro. In questo caso, sostituzione e destinazione. Analogamente, templateParameterValues
contiene la JSON rappresentazione dei parametri specificati per l'intero modello.
Codice funzione Lambda
Di seguito è riportato il codice effettivo per la funzione Lambda alla base della macro di JavaMacroFunc
esempio. L'esempio esegue l'iterazione del frammento di modello incluso nella risposta (che sia in un formato di stringa, elenco o mappa), alla ricerca della stringa di destinazione specificata. Se trova la stringa di destinazione specificata, la funzione Lambda sostituisce la stringa di destinazione con la stringa di sostituzione specificata. In caso contrario, la funzione lascia il frammento di modello invariato. Quindi, la funzione restituisce una mappa delle proprietà previste, illustrate in dettaglio di seguito, a 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; } }
Risposta della funzione Lambda
Di seguito è riportata la mappatura a cui torna la funzione Lambda CloudFormation per l'elaborazione.
-
requestId
:5dba79b5-f117-4de0-9ce4-d40363bfb6ab
-
status
:SUCCESS
-
fragment
:{ "Type": "AWS::CloudFormation::WaitConditionHandle" }
Le requestId
corrispondenze inviate da CloudFormation e il status
valore di SUCCESS
indicano che la funzione Lambda ha elaborato correttamente il frammento di modello incluso nella richiesta. In questa risposta, fragment
contiene la JSON rappresentazione del contenuto da inserire nel modello elaborato al posto dello snippet di modello originale.
Modello elaborato risultante
Dopo aver CloudFormation ricevuto una risposta corretta dalla funzione Lambda, inserisce il frammento di modello restituito nel modello elaborato.
Di seguito è riportato il modello elaborato risultante per il nostro esempio. La chiamata alla funzione Fn::Transform
intrinseca che faceva riferimento alla macro non è più JavaMacroFunc
inclusa. Il frammento di modello restituito dalla funzione Lambda è incluso nella posizione appropriata, con il risultato che il contenuto "Type": "$$REPLACEMENT$$"
è stato sostituito con "Type": "AWS::CloudFormation::WaitConditionHandle"
.
{ "Parameters": { "ExampleParameter": { "Default": "SampleMacro", "Type": "String" } }, "Resources": { "2a": { "Type": "AWS::CloudFormation::WaitConditionHandle" } } }