Esempio di macro: creazione e utilizzo di una macro - AWS CloudFormation

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 macro: creazione e utilizzo di una macro

L'esempio seguente descrive il processo di utilizzo di macro, dalla definizione dalla macro in un modello alla creazione di una funzione Lambda per la macro e 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.

Esempio di macro: modello di definizione di 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.

Nota

Esamineremo il codice effettivo della funzione Lambda successivamente in questo argomento.

L'esempio di modello seguente contiene la definizione del nostro esempio di macro. Per rendere disponibile la macro in un CloudFormation account specifico, creiamo uno stack a partire dal modello. La definizione della macro specifica il nome della macro, una breve descrizione e fa riferimento all'ARN della funzione Lambda CloudFormation che viene richiamata quando questa macro viene utilizzata in un modello. (Non abbiamo incluso una proprietà LogGroupNameo LogRoleARN per la registrazione degli errori.) Per ulteriori informazioni, vedere. AWS::CloudFormation::Macro

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 JavaMacroFuncdenominata.

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"

Esempio di macro: modello di utilizzo di macro

Per utilizzare la nostra macro in questo caso, la includeremo in un modello utilizzando la funzione intrinseca Fn::Transform.

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 è che un AWS::CloudFormation::WaitConditionHandle vuoto viene inserito nel modello elaborato.

Tieni presente quanto segue:

  • La macro da richiamare è specificata come JavaMacroFunc, che deriva dal precedente esempio di definizione di macro.

  • Alla macro vengono passati due parametri, target e replacement, che rappresentano la stringa di destinazione e il valore di sostituzione desiderato.

  • La macro può funzionare sul contenuto del nodo Type in quanto Type è un elemento di pari livello della funzione Fn::Transform che fa riferimento alla macro.

  • L'AWS::CloudFormation::WaitConditionHandle risultante viene denominato2a.

  • Il modello contiene inoltre un parametro di modello, ExampleParameter, a cui la macro ha accesso (ma che non utilizza in questo caso).

Parameters: ExampleParameter: Type: String Default: 'SampleMacro' Resources: 2a: Fn::Transform: Name: "JavaMacroFunc" Parameters: replacement: 'AWS::CloudFormation::WaitConditionHandle' target: '$$REPLACEMENT$$' Type: '$$REPLACEMENT$$'

Esempio di macro: mappatura di eventi di richiesta

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

fragment contiene codice JSON che rappresenta il 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 codice JSON che rappresenta i parametri di macro. In questo caso, sostituzione e destinazione. Analogamente, templateParameterValues contiene codice JSON che rappresenta i parametri specificati per il modello nel complesso.

  • 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" }

Esempio di macro: codice della funzione Lambda

Di seguito è riportato il codice effettivo per la funzione Lambda alla base della macro di JavaMacroFuncesempio. 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; } }

Esempio di macro: risposta della funzione Lambda

Di seguito è riportata la mappatura a cui torna la funzione Lambda AWS CloudFormation per l'elaborazione. 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 codice JSON che rappresenta il contenuto da inserire nel modello elaborato al posto del frammento del modello originale.

  • requestId

    5dba79b5-f117-4de0-9ce4-d40363bfb6ab

  • status

    SUCCESS

  • fragment

    { "Type": "AWS::CloudFormation::WaitConditionHandle" }

Esempio di macro: 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ù JavaMacroFuncinclusa. 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" } } }

Ulteriori esempi di macro

Oltre a questa procedura dettagliata riportata in questa guida, nel nostro repository puoi trovare macro di esempio, tra cui codice sorgente e modelli. GitHub Questi esempi vengono forniti "così come sono" per scopi didattici.