

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 una macro semplice di sostituzione delle stringhe
<a name="macros-example"></a>

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.

## Creazione di una macro
<a name="macros-example-definiton"></a>

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 all'ARN della funzione Lambda CloudFormation che viene richiamata quando questa macro viene utilizzata in un modello. (non abbiamo incluso una proprietà `LogGroupName` o `LogRoleARN` per la registrazione degli errori). 

In questo esempio, supponiamo che lo stack creato da questo modello sia denominato `JavaMacroFunc`. Poiché la proprietà `Name` della macro viene impostata sul nome dello stack, anche la macro risultante è denominata `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'
```

## Utilizzo della macro
<a name="macros-example-usage"></a>

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

Quando creiamo uno stack utilizzando il modello seguente, richiama la nostra macro di esempio. CloudFormation 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 invocare è specificata come `JavaMacroFunc`, ovvero la macro dell’esempio di definizione di macro precedente.
+ 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.
+ La risorsa `AWS::CloudFormation::WaitConditionHandle` risultante è denominata `2a`.
+ 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
<a name="macros-example-request"></a>

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

## Codice della funzione Lambda
<a name="macros-example-function"></a>

Di seguito è riportato il codice effettivo della funzione Lambda sottostante l’esempio di macro `JavaMacroFunc`. 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, discusse 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
<a name="macros-example-response"></a>

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 codice JSON che rappresenta il contenuto da inserire nel modello elaborato al posto del frammento del modello originale.

## Modello elaborato risultante
<a name="macros-example-processed"></a>

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 della funzione intrinseca `Fn::Transform` che faceva riferimento alla macro `JavaMacroFunc` non è più 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"
        }
    }
}
```