Contoh makro pengganti string sederhana - AWS CloudFormation

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

Contoh makro pengganti string sederhana

Contoh berikut memandu Anda melalui proses menggunakan makro, dari mendefinisikan makro dalam template, hingga membuat fungsi Lambda untuk makro, dan kemudian menggunakan makro dalam template.

Dalam contoh ini, kita membuat makro sederhana yang menyisipkan string yang ditentukan di tempat konten target yang ditentukan dalam templat yang diproses. Kemudian kita akan menggunakannya untuk menyisipkan WaitHandleCondition kosong di lokasi yang ditentukan dalam templat yang diproses.

Membuat makro

Sebelum menggunakan makro, pertama-tama kita harus menyelesaikan dua hal: membuat fungsi Lambda yang melakukan pemrosesan template yang diinginkan, dan kemudian membuat fungsi Lambda itu tersedia dengan membuat definisi CloudFormation makro.

Contoh template berikut berisi definisi untuk contoh makro kita. Untuk membuat makro tersedia secara spesifik Akun AWS, buat tumpukan dari template. Definisi makro menentukan nama makro, deskripsi singkat, dan referensi fungsi Lambda ARN yang CloudFormation dipanggil ketika makro ini digunakan dalam template. (Kami belum menyertakan LogRoleARN properti LogGroupName atau untuk pencatatan kesalahan.)

Dalam contoh ini, asumsikan bahwa tumpukan yang dibuat dari template ini diberi namaJavaMacroFunc. Karena Name properti makro diatur ke nama tumpukan, makro yang dihasilkan dinamai JavaMacroFunc juga.

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'

Menggunakan makro

Untuk menggunakan makro kami, kami memasukkannya ke dalam template menggunakan fungsi Fn::Transform intrinsik.

Ketika kita membuat tumpukan menggunakan template di bawah ini, CloudFormation memanggil contoh makro kita. Fungsi Lambda yang mendasari menggantikan satu string tertentu dengan string lain yang ditentukan. Dalam hal ini, hasilnya kosong AWS::CloudFormation::WaitConditionHandle dimasukkan ke dalam template yang diproses.

Parameters: ExampleParameter: Type: String Default: 'SampleMacro' Resources: 2a: Fn::Transform: Name: "JavaMacroFunc" Parameters: replacement: 'AWS::CloudFormation::WaitConditionHandle' target: '$$REPLACEMENT$$' Type: '$$REPLACEMENT$$'
  • Makro untuk memanggil ditentukan sebagaiJavaMacroFunc, yang berasal dari contoh definisi makro sebelumnya.

  • Makro melewati dua parameter, target dan replacement, yang mewakili string target dan nilai penggantian yang diinginkan.

  • Makro dapat beroperasi pada konten simpul Type karena merupakan Type saudara dari fungsi Fn::Transform yang mereferensikan makro.

  • Hasilnya AWS::CloudFormation::WaitConditionHandle dinamai2a.

  • Template juga berisi parameter template, ExampleParameter, yang juga dapat diakses oleh makro (tetapi tidak digunakan dalam hal ini).

Data masukan Lambda

Saat CloudFormation memproses contoh template kami selama pembuatan tumpukan, ia meneruskan pemetaan peristiwa berikut ke fungsi Lambda yang direferensikan dalam JavaMacroFunc definisi makro.

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

fragmentberisi JSON mewakili fragmen template yang dapat diproses oleh makro. Fragmen ini terdiri dari saudara dari panggilan fungsi Fn::Transform, tetapi bukan fungsi panggilan itu sendiri. Juga, params berisi JSON mewakili parameter makro. Dalam hal ini, penggantian dan target. Demikian pula, templateParameterValues berisi JSON mewakili parameter yang ditentukan untuk template secara keseluruhan.

Kode fungsi Lambda

Berikut ini adalah kode aktual untuk fungsi Lambda yang mendasari JavaMacroFunc contoh makro. Ini mengulangi fragmen templat yang disertakan dalam respons (baik dalam format string, daftar, maupun peta), mencari string target yang ditentukan. Jika menemukan string target yang ditentukan, fungsi Lambda menggantikan string target dengan string pengganti yang ditentukan. Jika tidak, fungsi membiarkan fragmen template tidak berubah. Kemudian, fungsi mengembalikan peta properti yang diharapkan, dibahas secara rinci di bawah ini, ke 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; } }

Respon fungsi Lambda

Berikut ini adalah pemetaan yang fungsi Lambda kembali CloudFormation untuk diproses.

  • requestId : 5dba79b5-f117-4de0-9ce4-d40363bfb6ab

  • status : SUCCESS

  • fragment :

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

requestIdPencocokan yang dikirim dari CloudFormation, dan status nilai SUCCESS menunjukkan bahwa fungsi Lambda berhasil memproses fragmen template yang disertakan dalam permintaan. Dalam tanggapan ini, fragment berisi JSON mewakili konten untuk dimasukkan ke dalam template yang diproses sebagai pengganti cuplikan template asli.

Template yang diproses yang dihasilkan

Setelah CloudFormation menerima respons yang berhasil dari fungsi Lambda, ia menyisipkan fragmen template yang dikembalikan ke dalam template yang diproses.

Di bawah ini adalah templat yang diproses yang dihasilkan untuk contoh kita. Panggilan fungsi Fn::Transform intrinsik yang mereferensikan JavaMacroFunc makro tidak lagi disertakan. Fragmen template yang dikembalikan oleh fungsi Lambda disertakan di lokasi yang sesuai, dengan hasil bahwa "Type": "$$REPLACEMENT$$" konten telah diganti. "Type": "AWS::CloudFormation::WaitConditionHandle"

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