Contoh makro: Membuat dan menggunakan makro - AWS CloudFormation

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

Contoh makro: Membuat dan menggunakan makro

Contoh berikut berjalan melalui proses menggunakan makro, dari mendefinisikan makro dalam template, untuk 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.

Contoh makro: Templat definisi 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.

catatan

Kita akan memeriksa kode aktual untuk fungsi Lambda nanti dalam topik ini.

Contoh template berikut berisi definisi untuk contoh makro kita. Untuk membuat makro tersedia di CloudFormation akun tertentu, kami membuat 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 LogRoleARNproperti LogGroupNameatau untuk pencatatan kesalahan.) Untuk informasi lebih lanjut, lihat AWS::CloudFormation: :Makro.

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

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"

Contoh makro: Templat penggunaan makro

Untuk menggunakan makro kita dalam hal ini, kita akan memasukkannya ke dalam templat menggunakan fungsi intrinsik Fn::Transform.

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.

Perhatikan hal berikut:

  • Makro untuk memanggil ditentukan sebagai JavaMacroFunc, 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.

  • Hasil AWS::CloudFormation:: WaitConditionHandle diberi nama2a.

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

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

Contoh makro: Minta pemetaan peristiwa

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

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.

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

Contoh makro: Kode fungsi Lambda

Berikut ini adalah kode aktual untuk fungsi Lambda yang mendasari JavaMacroFunccontoh 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; } }

Contoh makro: Respons fungsi Lambda

Berikut ini adalah pemetaan yang fungsi Lambda kembali CloudFormation untuk diproses. 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.

  • requestId

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

  • status

    SUCCESS

  • fragment

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

Contoh makro: 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 JavaMacroFuncmakro 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" } } }

Contoh makro tambahan

Selain panduan ini dalam panduan ini, Anda dapat menemukan contoh makro, termasuk kode sumber dan templat, di repositori kami. GitHub Contoh-contoh ini disediakan 'sebagaimana adanya' untuk tujuan instruksional.