

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

# Beispiel für ein einfaches Makro zur Ersetzung von Strings
<a name="macros-example"></a>

Das folgende Beispiel führt Sie durch den Prozess der Verwendung von Makros, von der Definition des Makros in einer Vorlage über die Erstellung einer Lambda-Funktion für das Makro bis hin zur Verwendung des Makros in einer Vorlage.

In diesem Beispiel erstellen wir ein einfaches Makro, das die angegebene Zeichenfolge anstelle des angegebenen Zielinhalts in die verarbeitete Vorlage einfügt. Dann fügen wir damit ein leeres `WaitHandleCondition` an der angegebenen Stelle in der bearbeiteten Vorlage ein.

## Ein Makro erstellen
<a name="macros-example-definiton"></a>

Bevor wir ein Makro verwenden, müssen wir zunächst zwei Dinge erledigen: die Lambda-Funktion erstellen, die die gewünschte Vorlagenverarbeitung durchführt, und dann diese Lambda-Funktion verfügbar machen, CloudFormation indem wir eine Makrodefinition erstellen.

Die folgende Beispielvorlage enthält die Definition für unser Beispielmakro. Um das Makro in einem bestimmten Format verfügbar zu machen AWS-Konto, erstellen Sie einen Stack aus der Vorlage. Die Makrodefinition gibt den Makronamen und eine kurze Beschreibung an und verweist auf den ARN der Lambda-Funktion, die CloudFormation aufgerufen wird, wenn dieses Makro in einer Vorlage verwendet wird. (Wir haben keine `LogGroupName`- oder `LogRoleARN`-Eigenschaft für die Fehlerprotokollierung eingefügt). 

In diesem Beispiel nehmen wir an, dass der mit dieser Vorlage erstellte Stapel den Namen `JavaMacroFunc`trägt. Da die Makroeigenschaft `Name` auf den Stapelnamen gesetzt ist, heißt das resultierende Makro auch `JavaMacroFunc` .

```
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'
```

## Das Makro verwenden
<a name="macros-example-usage"></a>

Um unser Makro zu verwenden, fügen wir es in eine Vorlage ein, indem wir die intrinsische Funktion `Fn::Transform` verwenden.

 CloudFormation Ruft unser Beispielmakro auf, wenn wir mit der folgenden Vorlage einen Stack erstellen. Die zugrundeliegende Lambda-Funktion ersetzt eine angegebene Zeichenfolge durch eine andere angegebene Zeichenfolge. In diesem Fall ergibt sich daraus eine leere `AWS::CloudFormation::WaitConditionHandle`-Eigenschaft, die in die verarbeitete Vorlage eingefügt wird.

```
Parameters:
  ExampleParameter:
    Type: String
    Default: 'SampleMacro'

Resources:
  2a:
    Fn::Transform:
      Name: "JavaMacroFunc"
      Parameters:
        replacement: 'AWS::CloudFormation::WaitConditionHandle'
        target: '$$REPLACEMENT$$'
    Type: '$$REPLACEMENT$$'
```
+ Das aufzurufende Makro wird als `JavaMacroFunc`angegeben, das aus dem vorherigen Makrodefinitionsbeispiel stammt.
+ Dem Makro werden zwei Parameter, `target` und `replacement`, übergeben, die die Zielzeichenfolge und ihren gewünschten Ersatzwert darstellen.
+ Das Makro kann auf den Inhalt des `Type`-Knotens zugreifen, da `Type` ein Geschwisterelement der `Fn::Transform`-Funktion ist, das sich auf das Makro bezieht.
+ Die resultierende `AWS::CloudFormation::WaitConditionHandle`-Eigenschaft wird als `2a` benannt.
+ Die Vorlage enthält auch einen Vorlagenparameter (`ExampleParameter`), auf den das Makro ebenfalls Zugriff hat (in diesem Fall aber nicht verwendet wird).

## Lambda-Eingabedaten
<a name="macros-example-request"></a>

Wenn unsere Beispielvorlage während der Stack-Erstellung CloudFormation verarbeitet wird, übergibt sie die folgende Event-Mapping an die Lambda-Funktion, auf die in der `JavaMacroFunc` Makrodefinition verwiesen wird.
+ `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` enthält JSON, das das Vorlagenfragment darstellt, das das Makro verarbeiten kann. Dieses Fragment besteht aus den Geschwistern des `Fn::Transform`-Funktionsaufrufs, nicht aber aus dem Funktionsaufruf selbst. Außerdem enthält `params` JSON, das die Makroparameter repräsentiert. In diesem Fall Ersatz und Ziel. Ebenso enthält `templateParameterValues` JSON, das die für die gesamte Vorlage angegebenen Parameter repräsentiert.

## Code der Lambda-Funktion
<a name="macros-example-function"></a>

Im Folgenden finden Sie den eigentlichen Code für die Lambda-Funktion, die dem Beispielmakro `JavaMacroFunc` zugrunde liegt. Es durchläuft das in der Antwort enthaltene Vorlagenfragment (als Zeichenfolge, Liste oder Zuordnung) und sucht nach der angegebenen Zielzeichenfolge. Wenn die angegebene Zeichenfolge gefunden wird, ersetzt die Lambda-Funktion die Zielzeichenfolge durch die angegebene Ersatzzeichenfolge. Wenn nicht, lässt die Funktion das Vorlagenfragment unverändert. Anschließend gibt die Funktion eine Zuordnung der erwarteten Eigenschaften zurück, auf die weiter unten näher eingegangen wird. 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;
    }
}
```

## Antwort der Lambda-Funktion
<a name="macros-example-response"></a>

Im Folgenden finden Sie das Mapping, zu dem die Lambda-Funktion CloudFormation zur Verarbeitung zurückkehrt. 
+ `requestId` : `5dba79b5-f117-4de0-9ce4-d40363bfb6ab`
+ `status` : `SUCCESS`
+ `fragment` :

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

Die `requestId` Übereinstimmungen, die von gesendet wurden CloudFormation, und ein `status` Wert von `SUCCESS` bedeuten, dass die Lambda-Funktion das in der Anfrage enthaltene Vorlagenfragment erfolgreich verarbeitet hat. In dieser Antwort enthält `fragment` JSON, das den Inhalt darstellt, der anstelle des ursprünglichen Vorlagenausschnitts in die verarbeitete Vorlage eingefügt werden soll.

## Ergebnis der verarbeiteten Vorlage
<a name="macros-example-processed"></a>

Nachdem sie CloudFormation eine erfolgreiche Antwort von der Lambda-Funktion erhalten hat, fügt sie das zurückgegebene Vorlagenfragment in die verarbeitete Vorlage ein.

Nachfolgend sehen Sie die resultierende verarbeitete Vorlage für unser Beispiel. Der intrinsische Funktionsaufruf `Fn::Transform`, der auf das Makro `JavaMacroFunc` verwies, ist nicht mehr enthalten. Das von der Lambda-Funktion zurückgegebene Vorlagenfragment wird an der entsprechenden Stelle eingefügt, sodass der Inhalt `"Type": "$$REPLACEMENT$$"` durch `"Type": "AWS::CloudFormation::WaitConditionHandle"` ersetzt wurde.

```
{
    "Parameters": {
        "ExampleParameter": {
            "Default": "SampleMacro",
            "Type": "String"
        }
    },
    "Resources": {
        "2a": {
            "Type": "AWS::CloudFormation::WaitConditionHandle"
        }
    }
}
```