@mavogel/awscdk-rootmail 0.0.289 → 0.0.291

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/.jsii +594 -89
  2. package/.prettierrc +0 -0
  3. package/API.md +49 -5
  4. package/CONTRIBUTING.md +13 -2
  5. package/README.md +8 -0
  6. package/integ-tests/functions/cleanup-handler.ts +2 -2
  7. package/integ-tests/functions/close-opsitem-handler.ts +5 -7
  8. package/integ-tests/functions/send-email-handler.ts +3 -5
  9. package/integ-tests/integ.rootmail-custom-santa.ts +2 -20
  10. package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/RootmailIntegTestStack.assets.json +15 -15
  11. package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/RootmailIntegTestStack.template.json +435 -65
  12. package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/SetupTestIntegStackDefaultTestDeployAssert6EB6FF77.assets.json +6 -6
  13. package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/SetupTestIntegStackDefaultTestDeployAssert6EB6FF77.template.json +137 -5
  14. package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/asset.2819175352ad1ce0dae768e83fc328fb70fb5f10b4a8ff0ccbcb791f02b0716d/index.js +1 -0
  15. package/integ-tests/{integ.rootmail-filter-subject.ts.snapshot/asset.d2b520d86fd9d964c83dc0d5ce2e4456dbde5fa7ae0c791a71865cbdfe2fb855 → integ.rootmail-custom-santa.ts.snapshot/asset.2b86f8b255c50c6eba274c368849bab1c7a3747c30ef5df4c96f8dea8fffa21e}/index.js +3 -3
  16. package/integ-tests/{integ.rootmail-filter-subject.ts.snapshot/asset.9ac6d29f0cc4b20ec46e4c186d9a6f6448c7ea11b689e70a5dda69671a9d6848 → integ.rootmail-custom-santa.ts.snapshot/asset.b01091642674a865788c271ec84db9d88a8dfbe14d4d95583aca8814cfa848b9}/index.js +63 -60
  17. package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/asset.bdc104ed9cab1b5b6421713c8155f0b753380595356f710400609664d3635eca/cfn-response.js +1 -0
  18. package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/asset.bdc104ed9cab1b5b6421713c8155f0b753380595356f710400609664d3635eca/framework.js +3 -0
  19. package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/asset.bdc104ed9cab1b5b6421713c8155f0b753380595356f710400609664d3635eca/outbound.js +1 -0
  20. package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/asset.bdc104ed9cab1b5b6421713c8155f0b753380595356f710400609664d3635eca/util.js +1 -0
  21. package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/{asset.53e8368959effe94a6e51bef9c7c5bf0eaf5c4d64eece81632ca62aa34517978.bundle → asset.f692c9f68e4daba2abc99103efd3518bced1e9d7a2a89847b9b5d5473c64f1bd.bundle}/index.js +22701 -24111
  22. package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/integ.json +2 -2
  23. package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/manifest.json +35 -3
  24. package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/tree.json +782 -424
  25. package/integ-tests/integ.rootmail-filter-subject.ts +2 -20
  26. package/integ-tests/integ.rootmail-filter-subject.ts.snapshot/RootmailIntegTestStack.assets.json +15 -15
  27. package/integ-tests/integ.rootmail-filter-subject.ts.snapshot/RootmailIntegTestStack.template.json +435 -65
  28. package/integ-tests/integ.rootmail-filter-subject.ts.snapshot/SetupTestIntegStackDefaultTestDeployAssert6EB6FF77.assets.json +6 -6
  29. package/integ-tests/integ.rootmail-filter-subject.ts.snapshot/SetupTestIntegStackDefaultTestDeployAssert6EB6FF77.template.json +137 -5
  30. package/integ-tests/integ.rootmail-filter-subject.ts.snapshot/asset.2819175352ad1ce0dae768e83fc328fb70fb5f10b4a8ff0ccbcb791f02b0716d/index.js +1 -0
  31. package/integ-tests/{integ.rootmail-custom-santa.ts.snapshot/asset.d2b520d86fd9d964c83dc0d5ce2e4456dbde5fa7ae0c791a71865cbdfe2fb855 → integ.rootmail-filter-subject.ts.snapshot/asset.2b86f8b255c50c6eba274c368849bab1c7a3747c30ef5df4c96f8dea8fffa21e}/index.js +3 -3
  32. package/integ-tests/{integ.rootmail-custom-santa.ts.snapshot/asset.9ac6d29f0cc4b20ec46e4c186d9a6f6448c7ea11b689e70a5dda69671a9d6848 → integ.rootmail-filter-subject.ts.snapshot/asset.b01091642674a865788c271ec84db9d88a8dfbe14d4d95583aca8814cfa848b9}/index.js +63 -60
  33. package/integ-tests/integ.rootmail-filter-subject.ts.snapshot/asset.bdc104ed9cab1b5b6421713c8155f0b753380595356f710400609664d3635eca/cfn-response.js +1 -0
  34. package/integ-tests/integ.rootmail-filter-subject.ts.snapshot/asset.bdc104ed9cab1b5b6421713c8155f0b753380595356f710400609664d3635eca/framework.js +3 -0
  35. package/integ-tests/integ.rootmail-filter-subject.ts.snapshot/asset.bdc104ed9cab1b5b6421713c8155f0b753380595356f710400609664d3635eca/outbound.js +1 -0
  36. package/integ-tests/integ.rootmail-filter-subject.ts.snapshot/asset.bdc104ed9cab1b5b6421713c8155f0b753380595356f710400609664d3635eca/util.js +1 -0
  37. package/integ-tests/integ.rootmail-filter-subject.ts.snapshot/{asset.53e8368959effe94a6e51bef9c7c5bf0eaf5c4d64eece81632ca62aa34517978.bundle → asset.f692c9f68e4daba2abc99103efd3518bced1e9d7a2a89847b9b5d5473c64f1bd.bundle}/index.js +22701 -24111
  38. package/integ-tests/integ.rootmail-filter-subject.ts.snapshot/integ.json +2 -2
  39. package/integ-tests/integ.rootmail-filter-subject.ts.snapshot/manifest.json +35 -3
  40. package/integ-tests/integ.rootmail-filter-subject.ts.snapshot/tree.json +782 -424
  41. package/integ-tests/integ.rootmail.ts +4 -30
  42. package/integ-tests/integ.rootmail.ts.snapshot/RootmailIntegTestStack.assets.json +18 -18
  43. package/integ-tests/integ.rootmail.ts.snapshot/RootmailIntegTestStack.template.json +437 -72
  44. package/integ-tests/integ.rootmail.ts.snapshot/SetupTestIntegStackDefaultTestDeployAssert6EB6FF77.assets.json +6 -6
  45. package/integ-tests/integ.rootmail.ts.snapshot/SetupTestIntegStackDefaultTestDeployAssert6EB6FF77.template.json +139 -7
  46. package/integ-tests/integ.rootmail.ts.snapshot/asset.2819175352ad1ce0dae768e83fc328fb70fb5f10b4a8ff0ccbcb791f02b0716d/index.js +1 -0
  47. package/integ-tests/integ.rootmail.ts.snapshot/{asset.d2b520d86fd9d964c83dc0d5ce2e4456dbde5fa7ae0c791a71865cbdfe2fb855 → asset.2b86f8b255c50c6eba274c368849bab1c7a3747c30ef5df4c96f8dea8fffa21e}/index.js +3 -3
  48. package/integ-tests/integ.rootmail.ts.snapshot/{asset.070f758ea9c89b8ceea9bb5141ea511633e1d72ab992b608da4efb3d6eeb2ba5 → asset.6ae1d1fcc0e69b0216c406dcb73136e88857dfc9a29784c57838e1fb0f9f7496}/index.js +5 -5
  49. package/integ-tests/integ.rootmail.ts.snapshot/{asset.adf960437fc6c552bee317e122c1e6839152590b199f7c44c0eee7bfbb744187 → asset.8621467f8f2410fb7445cc07fab37b2e996e541b6f7acb8549df9e88e1def73c}/index.js +63 -60
  50. package/integ-tests/integ.rootmail.ts.snapshot/asset.bdc104ed9cab1b5b6421713c8155f0b753380595356f710400609664d3635eca/cfn-response.js +1 -0
  51. package/integ-tests/integ.rootmail.ts.snapshot/asset.bdc104ed9cab1b5b6421713c8155f0b753380595356f710400609664d3635eca/framework.js +3 -0
  52. package/integ-tests/integ.rootmail.ts.snapshot/asset.bdc104ed9cab1b5b6421713c8155f0b753380595356f710400609664d3635eca/outbound.js +1 -0
  53. package/integ-tests/integ.rootmail.ts.snapshot/asset.bdc104ed9cab1b5b6421713c8155f0b753380595356f710400609664d3635eca/util.js +1 -0
  54. package/integ-tests/integ.rootmail.ts.snapshot/{asset.53e8368959effe94a6e51bef9c7c5bf0eaf5c4d64eece81632ca62aa34517978.bundle → asset.f692c9f68e4daba2abc99103efd3518bced1e9d7a2a89847b9b5d5473c64f1bd.bundle}/index.js +22701 -24111
  55. package/integ-tests/integ.rootmail.ts.snapshot/integ.json +2 -2
  56. package/integ-tests/integ.rootmail.ts.snapshot/manifest.json +35 -3
  57. package/integ-tests/integ.rootmail.ts.snapshot/tree.json +798 -445
  58. package/lib/hosted-zone-dkim-propagation.js +1 -11
  59. package/lib/hosted-zone-dkim-verification-records.js +1 -6
  60. package/lib/rootmail-autowire-dns.js +1 -11
  61. package/lib/rootmail.d.ts +15 -1
  62. package/lib/rootmail.js +5 -2
  63. package/lib/ses-receipt-ruleset-activation.js +1 -11
  64. package/lib/ses-receive.d.ts +12 -0
  65. package/lib/ses-receive.js +5 -7
  66. package/node_modules/@aws-sdk/client-cloudwatch-logs/package.json +2 -2
  67. package/node_modules/@aws-sdk/client-route-53/package.json +2 -2
  68. package/node_modules/@aws-sdk/client-s3/package.json +2 -2
  69. package/node_modules/@aws-sdk/client-ses/package.json +2 -2
  70. package/node_modules/@aws-sdk/client-ssm/package.json +2 -2
  71. package/node_modules/@aws-sdk/credential-provider-ini/dist-types/fromIni.d.ts +5 -0
  72. package/node_modules/@aws-sdk/credential-provider-ini/dist-types/ts3.4/fromIni.d.ts +1 -0
  73. package/node_modules/@aws-sdk/credential-provider-ini/package.json +1 -1
  74. package/node_modules/@aws-sdk/credential-provider-node/package.json +2 -2
  75. package/node_modules/cdk-nag/.jsii +3 -3
  76. package/node_modules/cdk-nag/lib/ignore-suppression-conditions.js +5 -5
  77. package/node_modules/cdk-nag/lib/nag-logger.js +2 -2
  78. package/node_modules/cdk-nag/lib/nag-pack.js +1 -1
  79. package/node_modules/cdk-nag/lib/nag-rules.js +1 -1
  80. package/node_modules/cdk-nag/lib/nag-suppressions.js +1 -1
  81. package/node_modules/cdk-nag/lib/packs/aws-solutions.js +1 -1
  82. package/node_modules/cdk-nag/lib/packs/hipaa-security.js +1 -1
  83. package/node_modules/cdk-nag/lib/packs/nist-800-53-r4.js +1 -1
  84. package/node_modules/cdk-nag/lib/packs/nist-800-53-r5.js +1 -1
  85. package/node_modules/cdk-nag/lib/packs/pci-dss-321.js +1 -1
  86. package/node_modules/cdk-nag/package.json +2 -2
  87. package/package.json +31 -27
  88. package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/asset.5cc92ed0cea39e2b8de2dbc527dfb5980a3af9564bd1084d840b9787c7d0467e/index.d.ts +0 -14
  89. package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/asset.5cc92ed0cea39e2b8de2dbc527dfb5980a3af9564bd1084d840b9787c7d0467e/index.js +0 -1
  90. package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/asset.f2d30cfc360482320a52a4fcde8a70f3569df79ab30be24650fda58eb60052cf/cfn-response.js +0 -1
  91. package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/asset.f2d30cfc360482320a52a4fcde8a70f3569df79ab30be24650fda58eb60052cf/framework.js +0 -3
  92. package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/asset.f2d30cfc360482320a52a4fcde8a70f3569df79ab30be24650fda58eb60052cf/outbound.js +0 -1
  93. package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/asset.f2d30cfc360482320a52a4fcde8a70f3569df79ab30be24650fda58eb60052cf/util.js +0 -1
  94. package/integ-tests/integ.rootmail-filter-subject.ts.snapshot/asset.5cc92ed0cea39e2b8de2dbc527dfb5980a3af9564bd1084d840b9787c7d0467e/index.d.ts +0 -14
  95. package/integ-tests/integ.rootmail-filter-subject.ts.snapshot/asset.5cc92ed0cea39e2b8de2dbc527dfb5980a3af9564bd1084d840b9787c7d0467e/index.js +0 -1
  96. package/integ-tests/integ.rootmail-filter-subject.ts.snapshot/asset.f2d30cfc360482320a52a4fcde8a70f3569df79ab30be24650fda58eb60052cf/cfn-response.js +0 -1
  97. package/integ-tests/integ.rootmail-filter-subject.ts.snapshot/asset.f2d30cfc360482320a52a4fcde8a70f3569df79ab30be24650fda58eb60052cf/framework.js +0 -3
  98. package/integ-tests/integ.rootmail-filter-subject.ts.snapshot/asset.f2d30cfc360482320a52a4fcde8a70f3569df79ab30be24650fda58eb60052cf/outbound.js +0 -1
  99. package/integ-tests/integ.rootmail-filter-subject.ts.snapshot/asset.f2d30cfc360482320a52a4fcde8a70f3569df79ab30be24650fda58eb60052cf/util.js +0 -1
  100. package/integ-tests/integ.rootmail.ts.snapshot/asset.5cc92ed0cea39e2b8de2dbc527dfb5980a3af9564bd1084d840b9787c7d0467e/index.d.ts +0 -14
  101. package/integ-tests/integ.rootmail.ts.snapshot/asset.5cc92ed0cea39e2b8de2dbc527dfb5980a3af9564bd1084d840b9787c7d0467e/index.js +0 -1
  102. package/integ-tests/integ.rootmail.ts.snapshot/asset.f2d30cfc360482320a52a4fcde8a70f3569df79ab30be24650fda58eb60052cf/cfn-response.js +0 -1
  103. package/integ-tests/integ.rootmail.ts.snapshot/asset.f2d30cfc360482320a52a4fcde8a70f3569df79ab30be24650fda58eb60052cf/framework.js +0 -3
  104. package/integ-tests/integ.rootmail.ts.snapshot/asset.f2d30cfc360482320a52a4fcde8a70f3569df79ab30be24650fda58eb60052cf/outbound.js +0 -1
  105. package/integ-tests/integ.rootmail.ts.snapshot/asset.f2d30cfc360482320a52a4fcde8a70f3569df79ab30be24650fda58eb60052cf/util.js +0 -1
  106. /package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/{asset.f2d30cfc360482320a52a4fcde8a70f3569df79ab30be24650fda58eb60052cf → asset.bdc104ed9cab1b5b6421713c8155f0b753380595356f710400609664d3635eca}/consts.js +0 -0
  107. /package/integ-tests/integ.rootmail-filter-subject.ts.snapshot/{asset.f2d30cfc360482320a52a4fcde8a70f3569df79ab30be24650fda58eb60052cf → asset.bdc104ed9cab1b5b6421713c8155f0b753380595356f710400609664d3635eca}/consts.js +0 -0
  108. /package/integ-tests/integ.rootmail.ts.snapshot/{asset.f2d30cfc360482320a52a4fcde8a70f3569df79ab30be24650fda58eb60052cf → asset.bdc104ed9cab1b5b6421713c8155f0b753380595356f710400609664d3635eca}/consts.js +0 -0
@@ -717,5 +717,5 @@ class PCIDSS321Checks extends nag_pack_1.NagPack {
717
717
  }
718
718
  exports.PCIDSS321Checks = PCIDSS321Checks;
719
719
  _a = JSII_RTTI_SYMBOL_1;
720
- PCIDSS321Checks[_a] = { fqn: "cdk-nag.PCIDSS321Checks", version: "2.35.8" };
720
+ PCIDSS321Checks[_a] = { fqn: "cdk-nag.PCIDSS321Checks", version: "2.35.13" };
721
721
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGNpLWRzcy0zMjEuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcGFja3MvcGNpLWRzcy0zMjEudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQTs7O0VBR0U7QUFFRiw2Q0FBMEM7QUFFMUMsMENBQW9EO0FBQ3BELDRDQUErQztBQUMvQywwQ0FLd0I7QUFDeEIsc0RBRzhCO0FBQzlCLG9EQUk2QjtBQUM3QixvREFHNkI7QUFDN0Isa0RBRzRCO0FBQzVCLHNDQUF1RDtBQUN2RCxzQ0FNc0I7QUFDdEIsc0NBQWdFO0FBQ2hFLHNDQUE0QztBQUM1QyxzQ0FRc0I7QUFDdEIsc0NBQWtEO0FBQ2xELHNDQU9zQjtBQUN0QixzQ0FBNEQ7QUFDNUQsNENBR3lCO0FBQ3pCLG9EQUs2QjtBQUM3QixzQ0FLc0I7QUFDdEIsZ0RBTTJCO0FBQzNCLG9DQVNxQjtBQUNyQixrREFJNEI7QUFDNUIsNERBQW9FO0FBQ3BFLHNDQUErQztBQUMvQyxzQ0FLc0I7QUFDdEIsc0NBQW1EO0FBRW5EOzs7R0FHRztBQUNILE1BQWEsZUFBZ0IsU0FBUSxrQkFBTztJQUMxQyxZQUFZLEtBQW9CO1FBQzlCLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNiLElBQUksQ0FBQyxRQUFRLEdBQUcsYUFBYSxDQUFDO0lBQ2hDLENBQUM7SUFDTSxLQUFLLENBQUMsSUFBZ0I7UUFDM0IsSUFBSSxJQUFJLFlBQVkseUJBQVcsRUFBRSxDQUFDO1lBQ2hDLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDdEIsSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzVCLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDM0IsSUFBSSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUMzQixJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzFCLElBQUksQ0FBQyxRQUFRLENBQUMs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SyxFQUFFLDJCQUFlLENBQUMsS0FBSztZQUM1QixJQUFJLEVBQUUseUNBQW1DO1lBQ3pDLElBQUksRUFBRSxJQUFJO1NBQ1gsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVEOzs7O09BSUc7SUFDSyxRQUFRLENBQUMsSUFBaUI7UUFDaEMsSUFBSSxDQUFDLFNBQVMsQ0FBQztZQUNiLElBQUksRUFBRSxnSUFBZ0k7WUFDdEksV0FBVyxFQUNULDJRQUEyUTtZQUM3USxLQUFLLEVBQUUsMkJBQWUsQ0FBQyxLQUFLO1lBQzVCLElBQUksRUFBRSx5QkFBbUI7WUFDekIsSUFBSSxFQUFFLElBQUk7U0FDWCxDQUFDLENBQUM7SUFDTCxDQUFDOztBQWh3QkgsMENBaXdCQyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG5Db3B5cmlnaHQgQW1hem9uLmNvbSwgSW5jLiBvciBpdHMgYWZmaWxpYXRlcy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cblNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG4qL1xuXG5pbXBvcnQgeyBDZm5SZXNvdXJjZSB9IGZyb20gJ2F3cy1jZGstbGliJztcbmltcG9ydCB7IElDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IE5hZ1BhY2ssIE5hZ1BhY2tQcm9wcyB9IGZyb20gJy4uL25hZy1wYWNrJztcbmltcG9ydCB7IE5hZ01lc3NhZ2VMZXZlbCB9IGZyb20gJy4uL25hZy1ydWxlcyc7XG5pbXBvcnQge1xuICBBUElHV0Fzc29jaWF0ZWRXaXRoV0FGLFxuICBBUElHV0NhY2hlRW5hYmxlZEFuZEVuY3J5cHRlZCxcbiAgQVBJR1dFeGVjdXRpb25Mb2dnaW5nRW5hYmxlZCxcbiAgQVBJR1dTU0xFbmFibGVkLFxufSBmcm9tICcuLi9ydWxlcy9hcGlndyc7XG5pbXBvcnQge1xuICBBdXRvU2NhbGluZ0dyb3VwRUxCSGVhbHRoQ2hlY2tSZXF1aXJlZCxcbiAgQXV0b1NjYWxpbmdMYXVuY2hDb25maWdQdWJsaWNJcERpc2FibGVkLFxufSBmcm9tICcuLi9ydWxlcy9hdXRvc2NhbGluZyc7XG5pbXBvcnQge1xuICBDbG91ZFRyYWlsQ2xvdWRXYXRjaExvZ3NFbmFibGVkLFxuICBDbG91ZFRyYWlsRW5jcnlwdGlvbkVuYWJsZWQsXG4gIENsb3VkVHJhaWxMb2dGaWxlVmFsaWRhdGlvbkVuYWJsZWQsXG59IGZyb20gJy4uL3J1bGVzL2Nsb3VkdHJhaWwnO1xuaW1wb3J0IHtcbiAgQ2xvdWRXYXRjaExvZ0dyb3VwRW5jcnlwdGVkLFxuICBDbG91ZFdhdGNoTG9nR3JvdXBSZXRlbnRpb25QZXJpb2QsXG59IGZyb20gJy4uL3J1bGVzL2Nsb3Vkd2F0Y2gnO1xuaW1wb3J0IHtcbiAgQ29kZUJ1aWxkUHJvamVjdEVudlZhckF3c0NyZWQsXG4gIENvZGVCdWlsZFByb2plY3RTb3VyY2VSZXBvVXJsLFxufSBmcm9tICcuLi9ydWxlcy9jb2RlYnVpbGQnO1xuaW1wb3J0IHsgRE1TUmVwbGljYXRpb25Ob3RQdWJsaWMgfSBmcm9tICcuLi9ydWxlcy9kbXMnO1xuaW1wb3J0IHtcbiAgRUMySW5zdGFuY2VOb1B1YmxpY0lwLFxuICBFQzJJbnN0YW5jZVByb2ZpbGVBdHRhY2hlZCxcbiAgRUMySW5zdGFuY2VzSW5WUEMsXG4gIEVDMlJlc3RyaWN0ZWRDb21tb25Qb3J0cyxcbiAgRUMyUmVzdHJpY3RlZFNTSCxcbn0gZnJvbSAnLi4vcnVsZXMvZWMyJztcbmltcG9ydCB7IEVDU1Rhc2tEZWZpbml0aW9uVXNlckZvckhvc3RNb2RlIH0gZnJvbSAnLi4vcnVsZXMvZWNzJztcbmltcG9ydCB7IEVGU0VuY3J5cHRlZCB9IGZyb20gJy4uL3J1bGVzL2Vmcyc7XG5pbXBvcnQge1xuICBBTEJIdHRwRHJvcEludmFsaWRIZWFkZXJFbmFibGVkLFxuICBBTEJIdHRwVG9IdHRwc1JlZGlyZWN0aW9uLFxuICBBTEJXQUZFbmFibGVkLFxuICBFTEJBQ01DZXJ0aWZpY2F0ZVJlcXVpcmVkLFxuICBFTEJMb2dnaW5nRW5hYmxlZCxcbiAgRUxCVGxzSHR0cHNMaXN0ZW5lcnNPbmx5LFxuICBFTEJ2MkFDTUNlcnRpZmljYXRlUmVxdWlyZWQsXG59IGZyb20gJy4uL3J1bGVzL2VsYic7XG5pbXBvcnQgeyBFTVJLZXJiZXJvc0VuYWJsZWQgfSBmcm9tICcuLi9ydWxlcy9lbXInO1xuaW1wb3J0IHtcbiAgSUFNR3JvdXBIYXNVc2VycyxcbiAgSUFNTm9JbmxpbmVQb2xpY3ksXG4gIElBTVBvbGljeU5vU3RhdGVtZW50c1dpdGhBZG1pbkFjY2VzcyxcbiAgSUFNUG9saWN5Tm9TdGF0ZW1lbnRzV2l0aEZ1bGxBY2Nlc3MsXG4gIElBTVVzZXJHcm91cE1lbWJlcnNoaXAsXG4gIElBTVVzZXJOb1BvbGljaWVzLFxufSBmcm9tICcuLi9ydWxlcy9pYW0nO1xuaW1wb3J0IHsgS01TQmFja2luZ0tleVJvdGF0aW9uRW5hYmxlZCB9IGZyb20gJy4uL3J1bGVzL2ttcyc7XG5pbXBvcnQge1xuICBMYW1iZGFGdW5jdGlvblB1YmxpY0FjY2Vzc1Byb2hpYml0ZWQsXG4gIExhbWJkYUluc2lkZVZQQyxcbn0gZnJvbSAnLi4vcnVsZXMvbGFtYmRhJztcbmltcG9ydCB7XG4gIE9wZW5TZWFyY2hFbmNyeXB0ZWRBdFJlc3QsXG4gIE9wZW5TZWFyY2hFcnJvckxvZ3NUb0Nsb3VkV2F0Y2gsXG4gIE9wZW5TZWFyY2hJblZQQ09ubHksXG4gIE9wZW5TZWFyY2hOb2RlVG9Ob2RlRW5jcnlwdGlvbixcbn0gZnJvbSAnLi4vcnVsZXMvb3BlbnNlYXJjaCc7XG5pbXBvcnQge1xuICBSRFNBdXRvbWF0aWNNaW5vclZlcnNpb25VcGdyYWRlRW5hYmxlZCxcbiAgUkRTSW5zdGFuY2VQdWJsaWNBY2Nlc3MsXG4gIFJEU0xvZ2dpbmdFbmFibGVkLFxuICBSRFNTdG9yYWdlRW5jcnlwdGVkLFxufSBmcm9tICcuLi9ydWxlcy9yZHMnO1xuaW1wb3J0IHtcbiAgUmVkc2hpZnRDbHVzdGVyQ29uZmlndXJhdGlvbixcbiAgUmVkc2hpZnRDbHVzdGVyTWFpbnRlbmFuY2VTZXR0aW5ncyxcbiAgUmVkc2hpZnRDbHVzdGVyUHVibGljQWNjZXNzLFxuICBSZWRzaGlmdEVuaGFuY2VkVlBDUm91dGluZ0VuYWJsZWQsXG4gIFJlZHNoaWZ0UmVxdWlyZVRsc1NTTCxcbn0gZnJvbSAnLi4vcnVsZXMvcmVkc2hpZnQnO1xuaW1wb3J0IHtcbiAgUzNCdWNrZXRMZXZlbFB1YmxpY0FjY2Vzc1Byb2hpYml0ZWQsXG4gIFMzQnVja2V0TG9nZ2luZ0VuYWJsZWQsXG4gIFMzQnVja2V0UHVibGljUmVhZFByb2hpYml0ZWQsXG4gIFMzQnVja2V0UHVibGljV3JpdGVQcm9oaWJpdGVkLFxuICBTM0J1Y2tldFJlcGxpY2F0aW9uRW5hYmxlZCxcbiAgUzNCdWNrZXRTU0xSZXF1ZXN0c09ubHksXG4gIFMzQnVja2V0VmVyc2lvbmluZ0VuYWJsZWQsXG4gIFMzRGVmYXVsdEVuY3J5cHRpb25LTVMsXG59IGZyb20gJy4uL3J1bGVzL3MzJztcbmltcG9ydCB7XG4gIFNhZ2VNYWtlckVuZHBvaW50Q29uZmlndXJhdGlvbktNU0tleUNvbmZpZ3VyZWQsXG4gIFNhZ2VNYWtlck5vdGVib29rSW5zdGFuY2VLTVNLZXlDb25maWd1cmVkLFxuICBTYWdlTWFrZXJOb3RlYm9va05vRGlyZWN0SW50ZXJuZXRBY2Nlc3MsXG59IGZyb20gJy4uL3J1bGVzL3NhZ2VtYWtlcic7XG5pbXBvcnQgeyBTZWNyZXRzTWFuYWdlclVzaW5nS01TS2V5IH0gZnJvbSAnLi4vcnVsZXMvc2VjcmV0c21hbmFnZXInO1xuaW1wb3J0IHsgU05TRW5jcnlwdGVkS01TIH0gZnJvbSAnLi4vcnVsZXMvc25zJztcbmltcG9ydCB7XG4gIFZQQ0RlZmF1bHRTZWN1cml0eUdyb3VwQ2xvc2VkLFxuICBWUENGbG93TG9nc0VuYWJsZWQsXG4gIFZQQ05vVW5yZXN0cmljdGVkUm91dGVUb0lHVyxcbiAgVlBDU3VibmV0QXV0b0Fzc2lnblB1YmxpY0lwRGlzYWJsZWQsXG59IGZyb20gJy4uL3J1bGVzL3ZwYyc7XG5pbXBvcnQgeyBXQUZ2MkxvZ2dpbmdFbmFibGVkIH0gZnJvbSAnLi4vcnVsZXMvd2FmJztcblxuLyoqXG4gKiBDaGVjayBmb3IgUENJIERTUyAzLjIuMSBjb21wbGlhbmNlLlxuICogQmFzZWQgb24gdGhlIFBDSSBEU1MgMy4yLjEgQVdTIG9wZXJhdGlvbmFsIGJlc3QgcHJhY3RpY2VzOiBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vY29uZmlnL2xhdGVzdC9kZXZlbG9wZXJndWlkZS9vcGVyYXRpb25hbC1iZXN0LXByYWN0aWNlcy1mb3ItcGNpLWRzcy5odG1sXG4gKi9cbmV4cG9ydCBjbGFzcyBQQ0lEU1MzMjFDaGVja3MgZXh0ZW5kcyBOYWdQYWNrIHtcbiAgY29uc3RydWN0b3IocHJvcHM/OiBOYWdQYWNrUHJvcHMpIHtcbiAgICBzdXBlcihwcm9wcyk7XG4gICAgdGhpcy5wYWNrTmFtZSA9ICdQQ0kuRFNTLjMyMSc7XG4gIH1cbiAgcHVibGljIHZpc2l0KG5vZGU6IElDb25zdHJ1Y3QpOiB2b2lkIHtcbiAgICBpZiAobm9kZSBpbnN0YW5jZW9mIENmblJlc291cmNlKSB7XG4gICAgICB0aGlzLmNoZWNrQVBJR1cobm9kZSk7XG4gICAgICB0aGlzLmNoZWNrQXV0b1NjYWxpbmcobm9kZSk7XG4gICAgICB0aGlzLmNoZWNrQ2xvdWRUcmFpbChub2RlKTtcbiAgICAgIHRoaXMuY2hlY2tDbG91ZFdhdGNoKG5vZGUpO1xuICAgICAgdGhpcy5jaGVja0NvZGVCdWlsZChub2RlKTtcbiAgICAgIHRoaXMuY2hlY2tETVMobm9kZSk7XG4gICAgICB0aGlzLmNoZWNrRUMyKG5vZGUpO1xuICAgICAgdGhpcy5jaGVja0VDUyhub2RlKTtcbiAgICAgIHRoaXMuY2hlY2tFRlMobm9kZSk7XG4gICAgICB0aGlzLmNoZWNrRUxCKG5vZGUpO1xuICAgICAgdGhpcy5jaGVja0VNUihub2RlKTtcbiAgICAgIHRoaXMuY2hlY2tJQU0obm9kZSk7XG4gICAgICB0aGlzLmNoZWNrS01TKG5vZGUpO1xuICAgICAgdGhpcy5jaGVja0xhbWJkYShub2RlKTtcbiAgICAgIHRoaXMuY2hlY2tPcGVuU2VhcmNoKG5vZGUpO1xuICAgICAgdGhpcy5jaGVja1JEUyhub2RlKTtcbiAgICAgIHRoaXMuY2hlY2tSZWRzaGlmdChub2RlKTtcbiAgICAgIHRoaXMuY2hlY2tTMyhub2RlKTtcbiAgICAgIHRoaXMuY2hlY2tTYWdlTWFrZXIobm9kZSk7XG4gICAgICB0aGlzLmNoZWNrU2VjcmV0c01hbmFnZXIobm9kZSk7XG4gICAgICB0aGlzLmNoZWNrU05TKG5vZGUpO1xuICAgICAgdGhpcy5jaGVja1ZQQyhub2RlKTtcbiAgICAgIHRoaXMuY2hlY2tXQUYobm9kZSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIEFQSSBHYXRld2F5IFJlc291cmNlc1xuICAgKiBAcGFyYW0gbm9kZSB0aGUgQ2ZuUmVzb3VyY2UgdG8gY2hlY2tcbiAgICogQHBhcmFtIGlnbm9yZXMgbGlzdCBvZiBpZ25vcmVzIGZvciB0aGUgcmVzb3VyY2VcbiAgICovXG4gIHByaXZhdGUgY2hlY2tBUElHVyhub2RlOiBDZm5SZXNvdXJjZSk6IHZvaWQge1xuICAgIHRoaXMuYXBwbHlSdWxlKHtcbiAgICAgIGluZm86ICdUaGUgUkVTVCBBUEkgc3RhZ2UgaXMgbm90IGFzc29jaWF0ZWQgd2l0aCBBV1MgV0FGdjIgd2ViIEFDTCAtIChDb250cm9sIElEOiA2LjYpLicsXG4gICAgICBleHBsYW5hdGlvbjpcbiAgICAgICAgJ0FXUyBXQUYgZW5hYmxlcyB5b3UgdG8gY29uZmlndXJlIGEgc2V0IG9mIHJ1bGVzIChjYWxsZWQgYSB3ZWIgYWNjZXNzIGNvbnRyb2wgbGlzdCAod2ViIEFDTCkpIHRoYXQgYWxsb3csIGJsb2NrLCBvciBjb3VudCB3ZWIgcmVxdWVzdHMgYmFzZWQgb24gY3VzdG9taXphYmxlIHdlYiBzZWN1cml0eSBydWxlcyBhbmQgY29uZGl0aW9ucyB0aGF0IHlvdSBkZWZpbmUuIEVuc3VyZSB5b3VyIEFtYXpvbiBBUEkgR2F0ZXdheSBzdGFnZSBpcyBhc3NvY2lhdGVkIHdpdGggYSBXQUYgV2ViIEFDTCB0byBwcm90ZWN0IGl0IGZyb20gbWFsaWNpb3VzIGF0dGFja3MuJyxcbiAgICAgIGxldmVsOiBOYWdNZXNzYWdlTGV2ZWwuRVJST1IsXG4gICAgICBydWxlOiBBUElHV0Fzc29jaWF0ZWRXaXRoV0FGLFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcbiAgICB0aGlzLmFwcGx5UnVsZSh7XG4gICAgICBpbmZvOiAnVGhlIEFQSSBHYXRld2F5IHN0YWdlIGRvZXMgbm90IGhhdmUgY2FjaGluZyBlbmFibGVkIGFuZCBlbmNyeXB0ZWQgZm9yIGFsbCBtZXRob2RzIC0gKENvbnRyb2wgSUQ6IDMuNCkuJyxcbiAgICAgIGV4cGxhbmF0aW9uOlxuICAgICAgICBcIlRvIGhlbHAgcHJvdGVjdCBkYXRhIGF0IHJlc3QsIGVuc3VyZSBlbmNyeXB0aW9uIGlzIGVuYWJsZWQgZm9yIHlvdXIgQVBJIEdhdGV3YXkgc3RhZ2UncyBjYWNoZS4gQmVjYXVzZSBzZW5zaXRpdmUgZGF0YSBjYW4gYmUgY2FwdHVyZWQgZm9yIHRoZSBBUEkgbWV0aG9kLCBlbmFibGUgZW5jcnlwdGlvbiBhdCByZXN0IHRvIGhlbHAgcHJvdGVjdCB0aGF0IGRhdGEuXCIsXG4gICAgICBsZXZlbDogTmFnTWVzc2FnZUxldmVsLkVSUk9SLFxuICAgICAgcnVsZTogQVBJR1dDYWNoZUVuYWJsZWRBbmRFbmNyeXB0ZWQsXG4gICAgICBub2RlOiBub2RlLFxuICAgIH0pO1xuICAgIHRoaXMuYXBwbHlSdWxlKHtcbiAgICAgIGluZm86ICdUaGUgQVBJIEdhdGV3YXkgc3RhZ2UgZG9lcyBub3QgaGF2ZSBleGVjdXRpb24gbG9nZ2luZyBlbmFibGVkIGZvciBhbGwgbWV0aG9kcyAtIChDb250cm9sIElEczogMTAuMSwgMTAuMy4xLCAxMC4zLjIsIDEwLjMuMywgMTAuMy40LCAxMC4zLjUsIDEwLjMuNiwgMTAuNS40KS4nLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgICdBUEkgR2F0ZXdheSBsb2dnaW5nIGRpc3BsYXlzIGRldGFpbGVkIHZpZXdzIG9mIHVzZXJzIHdobyBhY2Nlc3NlZCB0aGUgQVBJIGFuZCB0aGUgd2F5IHRoZXkgYWNjZXNzZWQgdGhlIEFQSS4gVGhpcyBpbnNpZ2h0IGVuYWJsZXMgdmlzaWJpbGl0eSBvZiB1c2VyIGFjdGl2aXRpZXMuJyxcbiAgICAgIGxldmVsOiBOYWdNZXNzYWdlTGV2ZWwuRVJST1IsXG4gICAgICBydWxlOiBBUElHV0V4ZWN1dGlvbkxvZ2dpbmdFbmFibGVkLFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcbiAgICB0aGlzLmFwcGx5UnVsZSh7XG4gICAgICBpbmZvOiAnVGhlIEFQSSBHYXRld2F5IFJFU1QgQVBJIHN0YWdlIGlzIG5vdCBjb25maWd1cmVkIHdpdGggU1NMIGNlcnRpZmljYXRlcyAtIChDb250cm9sIElEczogMi4zLCA0LjEsIDguMi4xKS4nLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgICdFbnN1cmUgQW1hem9uIEFQSSBHYXRld2F5IFJFU1QgQVBJIHN0YWdlcyBhcmUgY29uZmlndXJlZCB3aXRoIFNTTCBjZXJ0aWZpY2F0ZXMgdG8gYWxsb3cgYmFja2VuZCBzeXN0ZW1zIHRvIGF1dGhlbnRpY2F0ZSB0aGF0IHJlcXVlc3RzIG9yaWdpbmF0ZSBmcm9tIEFQSSBHYXRld2F5LicsXG4gICAgICBsZXZlbDogTmFnTWVzc2FnZUxldmVsLkVSUk9SLFxuICAgICAgcnVsZTogQVBJR1dTU0xFbmFibGVkLFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBBdXRvIFNjYWxpbmcgUmVzb3VyY2VzXG4gICAqIEBwYXJhbSBub2RlIHRoZSBDZm5SZXNvdXJjZSB0byBjaGVja1xuICAgKiBAcGFyYW0gaWdub3JlcyBsaXN0IG9mIGlnbm9yZXMgZm9yIHRoZSByZXNvdXJjZVxuICAgKi9cbiAgcHJpdmF0ZSBjaGVja0F1dG9TY2FsaW5nKG5vZGU6IENmblJlc291cmNlKTogdm9pZCB7XG4gICAgdGhpcy5hcHBseVJ1bGUoe1xuICAgICAgaW5mbzogJ1RoZSBBdXRvIFNjYWxpbmcgZ3JvdXAgKHdoaWNoIGlzIGFzc29jaWF0ZWQgd2l0aCBhIGxvYWQgYmFsYW5jZXIpIGRvZXMgbm90IHV0aWxpemUgRUxCIGhlYWx0aCBjaGVja3MgLSAoQ29udHJvbCBJRDogMi4yKS4nLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgICdUaGUgRWxhc3RpYyBMb2FkIEJhbGFuY2VyIChFTEIpIGhlYWx0aCBjaGVja3MgZm9yIEFtYXpvbiBFbGFzdGljIENvbXB1dGUgQ2xvdWQgKEFtYXpvbiBFQzIpIEF1dG8gU2NhbGluZyBncm91cHMgc3VwcG9ydCBtYWludGVuYW5jZSBvZiBhZGVxdWF0ZSBjYXBhY2l0eSBhbmQgYXZhaWxhYmlsaXR5LiBUaGUgbG9hZCBiYWxhbmNlciBwZXJpb2RpY2FsbHkgc2VuZHMgcGluZ3MsIGF0dGVtcHRzIGNvbm5lY3Rpb25zLCBvciBzZW5kcyByZXF1ZXN0cyB0byB0ZXN0IEFtYXpvbiBFQzIgaW5zdGFuY2VzIGhlYWx0aCBpbiBhbiBhdXRvLXNjYWxpbmcgZ3JvdXAuIElmIGFuIGluc3RhbmNlIGlzIG5vdCByZXBvcnRpbmcgYmFjaywgdHJhZmZpYyBpcyBzZW50IHRvIGEgbmV3IEFtYXpvbiBFQzIgaW5zdGFuY2UuJyxcbiAgICAgIGxldmVsOiBOYWdNZXNzYWdlTGV2ZWwuRVJST1IsXG4gICAgICBydWxlOiBBdXRvU2NhbGluZ0dyb3VwRUxCSGVhbHRoQ2hlY2tSZXF1aXJlZCxcbiAgICAgIG5vZGU6IG5vZGUsXG4gICAgfSk7XG4gICAgdGhpcy5hcHBseVJ1bGUoe1xuICAgICAgaW5mbzogJ1RoZSBBdXRvIFNjYWxpbmcgbGF1bmNoIGNvbmZpZ3VyYXRpb24gZG9lcyBub3QgaGF2ZSBwdWJsaWMgSVAgYWRkcmVzc2VzIGRpc2FibGVkIC0gKENvbnRyb2wgSURzOiAxLjIsIDEuMi4xLCAxLjMsIDEuMy4xLCAxLjMuMiwgMS4zLjQsIDEuMy42LCAyLjIuMikuJyxcbiAgICAgIGV4cGxhbmF0aW9uOlxuICAgICAgICAnSWYgeW91IGNvbmZpZ3VyZSB5b3VyIE5ldHdvcmsgSW50ZXJmYWNlcyB3aXRoIGEgcHVibGljIElQIGFkZHJlc3MsIHRoZW4gdGhlIGFzc29jaWF0ZWQgcmVzb3VyY2VzIHRvIHRob3NlIE5ldHdvcmsgSW50ZXJmYWNlcyBhcmUgcmVhY2hhYmxlIGZyb20gdGhlIGludGVybmV0LiBFQzIgcmVzb3VyY2VzIHNob3VsZCBub3QgYmUgcHVibGljbHkgYWNjZXNzaWJsZSwgYXMgdGhpcyBtYXkgYWxsb3cgdW5pbnRlbmRlZCBhY2Nlc3MgdG8geW91ciBhcHBsaWNhdGlvbnMgb3Igc2VydmVycy4nLFxuICAgICAgbGV2ZWw6IE5hZ01lc3NhZ2VMZXZlbC5FUlJPUixcbiAgICAgIHJ1bGU6IEF1dG9TY2FsaW5nTGF1bmNoQ29uZmlnUHVibGljSXBEaXNhYmxlZCxcbiAgICAgIG5vZGU6IG5vZGUsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgQ2xvdWRUcmFpbCBSZXNvdXJjZXNcbiAgICogQHBhcmFtIG5vZGUgdGhlIENmblJlc291cmNlIHRvIGNoZWNrXG4gICAqIEBwYXJhbSBpZ25vcmVzIGxpc3Qgb2YgaWdub3JlcyBmb3IgdGhlIHJlc291cmNlXG4gICAqL1xuICBwcml2YXRlIGNoZWNrQ2xvdWRUcmFpbChub2RlOiBDZm5SZXNvdXJjZSk6IHZvaWQge1xuICAgIHRoaXMuYXBwbHlSdWxlKHtcbiAgICAgIGluZm86ICdUaGUgdHJhaWwgZG9lcyBub3QgaGF2ZSBDbG91ZFdhdGNoIGxvZ3MgZW5hYmxlZCAtIChDb250cm9sIElEczogMi4yLCAxMC4xLCAxMC4yLjEsIDEwLjIuMiwgMTAuMi4zLCAxMC4yLjUsIDEwLjMuMSwgMTAuMy4yLCAxMC4zLjMsIDEwLjMuNCwgMTAuMy41LCAxMC4zLjYsIDEwLjUuMywgMTAuNS40KS4nLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgICdVc2UgQW1hem9uIENsb3VkV2F0Y2ggdG8gY2VudHJhbGx5IGNvbGxlY3QgYW5kIG1hbmFnZSBsb2cgZXZlbnQgYWN0aXZpdHkuIEluY2x1c2lvbiBvZiBBV1MgQ2xvdWRUcmFpbCBkYXRhIHByb3ZpZGVzIGRldGFpbHMgb2YgQVBJIGNhbGwgYWN0aXZpdHkgd2l0aGluIHlvdXIgQVdTIGFjY291bnQuJyxcbiAgICAgIGxldmVsOiBOYWdNZXNzYWdlTGV2ZWwuRVJST1IsXG4gICAgICBydWxlOiBDbG91ZFRyYWlsQ2xvdWRXYXRjaExvZ3NFbmFibGVkLFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcbiAgICB0aGlzLmFwcGx5UnVsZSh7XG4gICAgICBpbmZvOiAnVGhlIHRyYWlsIGRvZXMgbm90IGhhdmUgZW5jcnlwdGlvbiBlbmFibGVkIC0gKENvbnRyb2wgSURzOiAyLjIsIDMuNCwgMTAuNSkuJyxcbiAgICAgIGV4cGxhbmF0aW9uOlxuICAgICAgICAnQmVjYXVzZSBzZW5zaXRpdmUgZGF0YSBtYXkgZXhpc3QgYW5kIHRvIGhlbHAgcHJvdGVjdCBkYXRhIGF0IHJlc3QsIGVuc3VyZSBlbmNyeXB0aW9uIGlzIGVuYWJsZWQgZm9yIHlvdXIgQVdTIENsb3VkVHJhaWwgdHJhaWxzLicsXG4gICAgICBsZXZlbDogTmFnTWVzc2FnZUxldmVsLkVSUk9SLFxuICAgICAgcnVsZTogQ2xvdWRUcmFpbEVuY3J5cHRpb25FbmFibGVkLFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcbiAgICB0aGlzLmFwcGx5UnVsZSh7XG4gICAgICBpbmZvOiAnVGhlIHRyYWlsIGRvZXMgbm90IGhhdmUgbG9nIGZpbGUgdmFsaWRhdGlvbiBlbmFibGVkIC0gKENvbnRyb2wgSURzOiAyLjIsIDEwLjUuMiwgMTAuNSwgMTAuNS41LCAxMS41KS4nLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgICdVdGlsaXplIEFXUyBDbG91ZFRyYWlsIGxvZyBmaWxlIHZhbGlkYXRpb24gdG8gY2hlY2sgdGhlIGludGVncml0eSBvZiBDbG91ZFRyYWlsIGxvZ3MuIExvZyBmaWxlIHZhbGlkYXRpb24gaGVscHMgZGV0ZXJtaW5lIGlmIGEgbG9nIGZpbGUgd2FzIG1vZGlmaWVkIG9yIGRlbGV0ZWQgb3IgdW5jaGFuZ2VkIGFmdGVyIENsb3VkVHJhaWwgZGVsaXZlcmVkIGl0LiBUaGlzIGZlYXR1cmUgaXMgYnVpbHQgdXNpbmcgaW5kdXN0cnkgc3RhbmRhcmQgYWxnb3JpdGhtczogU0hBLTI1NiBmb3IgaGFzaGluZyBhbmQgU0hBLTI1NiB3aXRoIFJTQSBmb3IgZGlnaXRhbCBzaWduaW5nLiBUaGlzIG1ha2VzIGl0IGNvbXB1dGF0aW9uYWxseSBpbmZlYXNpYmxlIHRvIG1vZGlmeSwgZGVsZXRlIG9yIGZvcmdlIENsb3VkVHJhaWwgbG9nIGZpbGVzIHdpdGhvdXQgZGV0ZWN0aW9uLicsXG4gICAgICBsZXZlbDogTmFnTWVzc2FnZUxldmVsLkVSUk9SLFxuICAgICAgcnVsZTogQ2xvdWRUcmFpbExvZ0ZpbGVWYWxpZGF0aW9uRW5hYmxlZCxcbiAgICAgIG5vZGU6IG5vZGUsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgQ2xvdWRXYXRjaCBSZXNvdXJjZXNcbiAgICogQHBhcmFtIG5vZGUgdGhlIENmblJlc291cmNlIHRvIGNoZWNrXG4gICAqIEBwYXJhbSBpZ25vcmVzIGxpc3Qgb2YgaWdub3JlcyBmb3IgdGhlIHJlc291cmNlXG4gICAqL1xuICBwcml2YXRlIGNoZWNrQ2xvdWRXYXRjaChub2RlOiBDZm5SZXNvdXJjZSk6IHZvaWQge1xuICAgIHRoaXMuYXBwbHlSdWxlKHtcbiAgICAgIGluZm86ICdUaGUgQ2xvdWRXYXRjaCBMb2cgR3JvdXAgaXMgbm90IGVuY3J5cHRlZCB3aXRoIGFuIEFXUyBLTVMga2V5IC0gKENvbnRyb2wgSUQ6IDMuNCkuJyxcbiAgICAgIGV4cGxhbmF0aW9uOlxuICAgICAgICAnVG8gaGVscCBwcm90ZWN0IHNlbnNpdGl2ZSBkYXRhIGF0IHJlc3QsIGVuc3VyZSBlbmNyeXB0aW9uIGlzIGVuYWJsZWQgZm9yIHlvdXIgQW1hem9uIENsb3VkV2F0Y2ggTG9nIEdyb3Vwcy4nLFxuICAgICAgbGV2ZWw6IE5hZ01lc3NhZ2VMZXZlbC5FUlJPUixcbiAgICAgIHJ1bGU6IENsb3VkV2F0Y2hMb2dHcm91cEVuY3J5cHRlZCxcbiAgICAgIG5vZGU6IG5vZGUsXG4gICAgfSk7XG4gICAgdGhpcy5hcHBseVJ1bGUoe1xuICAgICAgaW5mbzogJ1RoZSBDbG91ZFdhdGNoIExvZyBHcm91cCBkb2VzIG5vdCBoYXZlIGFuIGV4cGxpY2l0IHJldGVudGlvbiBwZXJpb2QgY29uZmlndXJlZCAtIChDb250cm9sIElEczogMy4xLCAxMC43KS4nLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgICdFbnN1cmUgYSBtaW5pbXVtIGR1cmF0aW9uIG9mIGV2ZW50IGxvZyBkYXRhIGlzIHJldGFpbmVkIGZvciB5b3VyIGxvZyBncm91cHMgdG8gaGVscCB3aXRoIHRyb3VibGVzaG9vdGluZyBhbmQgZm9yZW5zaWNzIGludmVzdGlnYXRpb25zLiBUaGUgbGFjayBvZiBhdmFpbGFibGUgcGFzdCBldmVudCBsb2cgZGF0YSBtYWtlcyBpdCBkaWZmaWN1bHQgdG8gcmVjb25zdHJ1Y3QgYW5kIGlkZW50aWZ5IHBvdGVudGlhbGx5IG1hbGljaW91cyBldmVudHMuJyxcbiAgICAgIGxldmVsOiBOYWdNZXNzYWdlTGV2ZWwuRVJST1IsXG4gICAgICBydWxlOiBDbG91ZFdhdGNoTG9nR3JvdXBSZXRlbnRpb25QZXJpb2QsXG4gICAgICBub2RlOiBub2RlLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIENvZGVCdWlsZCBSZXNvdXJjZXNcbiAgICogQHBhcmFtIG5vZGUgdGhlIENmblJlc291cmNlIHRvIGNoZWNrXG4gICAqIEBwYXJhbSBpZ25vcmVzIGxpc3Qgb2YgaWdub3JlcyBmb3IgdGhlIHJlc291cmNlXG4gICAqL1xuICBwcml2YXRlIGNoZWNrQ29kZUJ1aWxkKG5vZGU6IENmblJlc291cmNlKTogdm9pZCB7XG4gICAgdGhpcy5hcHBseVJ1bGUoe1xuICAgICAgaW5mbzogJ1RoZSBDb2RlQnVpbGQgZW52aXJvbm1lbnQgc3RvcmVzIHNlbnNpdGl2ZSBjcmVkZW50aWFscyAoc3VjaCBhcyBBV1NfQUNDRVNTX0tFWV9JRCBhbmQvb3IgQVdTX1NFQ1JFVF9BQ0NFU1NfS0VZKSBhcyBwbGFpbnRleHQgZW52aXJvbm1lbnQgdmFyaWFibGVzIC0gKENvbnRyb2wgSUQ6IDguMi4xKS4nLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgICdEbyBub3Qgc3RvcmUgdGhlc2UgdmFyaWFibGVzIGluIGNsZWFyIHRleHQuIFN0b3JpbmcgdGhlc2UgdmFyaWFibGVzIGluIGNsZWFyIHRleHQgbGVhZHMgdG8gdW5pbnRlbmRlZCBkYXRhIGV4cG9zdXJlIGFuZCB1bmF1dGhvcml6ZWQgYWNjZXNzLicsXG4gICAgICBsZXZlbDogTmFnTWVzc2FnZUxldmVsLkVSUk9SLFxuICAgICAgcnVsZTogQ29kZUJ1aWxkUHJvamVjdEVudlZhckF3c0NyZWQsXG4gICAgICBub2RlOiBub2RlLFxuICAgIH0pO1xuICAgIHRoaXMuYXBwbHlSdWxlKHtcbiAgICAgIGluZm86ICdUaGUgQ29kZUJ1aWxkIHByb2plY3Qgd2hpY2ggdXRpbGl6ZXMgZWl0aGVyIGEgR2l0SHViIG9yIEJpdEJ1Y2tldCBzb3VyY2UgcmVwb3NpdG9yeSBkb2VzIG5vdCB1dGlsaXplIE9BdXRoIC0gKENvbnRyb2wgSUQ6IDguMi4xKS4nLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgICdPQXV0aCBpcyB0aGUgbW9zdCBzZWN1cmUgbWV0aG9kIG9mIGF1dGhlbnRpY2F0aW5nIHlvdXIgQ29kZUJ1aWxkIGFwcGxpY2F0aW9uLiBVc2UgT0F1dGggaW5zdGVhZCBvZiBwZXJzb25hbCBhY2Nlc3MgdG9rZW5zIG9yIGEgdXNlciBuYW1lIGFuZCBwYXNzd29yZCB0byBncmFudCBhdXRob3JpemF0aW9uIGZvciBhY2Nlc3NpbmcgR2l0SHViIG9yIEJpdGJ1Y2tldCByZXBvc2l0b3JpZXMuJyxcbiAgICAgIGxldmVsOiBOYWdNZXNzYWdlTGV2ZWwuRVJST1IsXG4gICAgICBydWxlOiBDb2RlQnVpbGRQcm9qZWN0U291cmNlUmVwb1VybCxcbiAgICAgIG5vZGU6IG5vZGUsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgRE1TIFJlc291cmNlc1xuICAgKiBAcGFyYW0gbm9kZSB0aGUgQ2ZuUmVzb3VyY2UgdG8gY2hlY2tcbiAgICogQHBhcmFtIGlnbm9yZXMgbGlzdCBvZiBpZ25vcmVzIGZvciB0aGUgcmVzb3VyY2VcbiAgICovXG4gIHByaXZhdGUgY2hlY2tETVMobm9kZTogQ2ZuUmVzb3VyY2UpIHtcbiAgICB0aGlzLmFwcGx5UnVsZSh7XG4gICAgICBpbmZvOiAnVGhlIERNUyByZXBsaWNhdGlvbiBpbnN0YW5jZSBpcyBwdWJsaWMgLSAoQ29udHJvbCBJRHM6IDEuMiwgMS4yLjEsIDEuMywgMS4zLjEsIDEuMy4yLCAxLjMuNCwgMS4zLjYsIDIuMi4yKS4nLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgICdETVMgcmVwbGljYXRpb24gaW5zdGFuY2VzIGNhbiBjb250YWluIHNlbnNpdGl2ZSBpbmZvcm1hdGlvbiBhbmQgYWNjZXNzIGNvbnRyb2wgaXMgcmVxdWlyZWQgZm9yIHN1Y2ggYWNjb3VudHMuJyxcbiAgICAgIGxldmVsOiBOYWdNZXNzYWdlTGV2ZWwuRVJST1IsXG4gICAgICBydWxlOiBETVNSZXBsaWNhdGlvbk5vdFB1YmxpYyxcbiAgICAgIG5vZGU6IG5vZGUsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgRUMyIFJlc291cmNlc1xuICAgKiBAcGFyYW0gbm9kZSB0aGUgQ2ZuUmVzb3VyY2UgdG8gY2hlY2tcbiAgICogQHBhcmFtIGlnbm9yZXMgbGlzdCBvZiBpZ25vcmVzIGZvciB0aGUgcmVzb3VyY2VcbiAgICovXG4gIHByaXZhdGUgY2hlY2tFQzIobm9kZTogQ2ZuUmVzb3VyY2UpOiB2b2lkIHtcbiAgICB0aGlzLmFwcGx5UnVsZSh7XG4gICAgICBpbmZvOiAnVGhlIEVDMiBpbnN0YW5jZSBpcyBhc3NvY2lhdGVkIHdpdGggYSBwdWJsaWMgSVAgYWRkcmVzcyAtIChDb250cm9sIElEczogMS4yLCAxLjIuMSwgMS4zLCAxLjMuMSwgMS4zLjIsIDEuMy40LCAxLjMuNiwgMi4yLjIpLicsXG4gICAgICBleHBsYW5hdGlvbjpcbiAgICAgICAgJ01hbmFnZSBhY2Nlc3MgdG8gdGhlIEFXUyBDbG91ZCBieSBlbnN1cmluZyBBbWF6b24gRWxhc3RpYyBDb21wdXRlIENsb3VkIChBbWF6b24gRUMyKSBpbnN0YW5jZXMgY2Fubm90IGJlIHB1YmxpY2x5IGFjY2Vzc2VkLiBBbWF6b24gRUMyIGluc3RhbmNlcyBjYW4gY29udGFpbiBzZW5zaXRpdmUgaW5mb3JtYXRpb24gYW5kIGFjY2VzcyBjb250cm9sIGlzIHJlcXVpcmVkIGZvciBzdWNoIGFjY291bnRzLicsXG4gICAgICBsZXZlbDogTmFnTWVzc2FnZUxldmVsLkVSUk9SLFxuICAgICAgcnVsZTogRUMySW5zdGFuY2VOb1B1YmxpY0lwLFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcbiAgICB0aGlzLmFwcGx5UnVsZSh7XG4gICAgICBpbmZvOiAnVGhlIEVDMiBpbnN0YW5jZSBkb2VzIG5vdCBoYXZlIGFuIGluc3RhbmNlIHByb2ZpbGUgYXR0YWNoZWQgLSAoQ29udHJvbCBJRHM6IDIuMiwgNy4xLjEsIDcuMi4xKS4nLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgICdFQzIgaW5zdGFuY2UgcHJvZmlsZXMgcGFzcyBhbiBJQU0gcm9sZSB0byBhbiBFQzIgaW5zdGFuY2UuIEF0dGFjaGluZyBhbiBpbnN0YW5jZSBwcm9maWxlIHRvIHlvdXIgaW5zdGFuY2VzIGNhbiBhc3Npc3Qgd2l0aCBsZWFzdCBwcml2aWxlZ2UgYW5kIHBlcm1pc3Npb25zIG1hbmFnZW1lbnQuJyxcbiAgICAgIGxldmVsOiBOYWdNZXNzYWdlTGV2ZWwuRVJST1IsXG4gICAgICBydWxlOiBFQzJJbnN0YW5jZVByb2ZpbGVBdHRhY2hlZCxcbiAgICAgIG5vZGU6IG5vZGUsXG4gICAgfSk7XG4gICAgdGhpcy5hcHBseVJ1bGUoe1xuICAgICAgaW5mbzogJ1RoZSBFQzIgaW5zdGFuY2UgaXMgbm90IHdpdGhpbiBhIFZQQyAtIChDb250cm9sIElEczogMS4yLCAxLjIuMSwgMS4zLCAxLjMuMSwgMS4zLjIsIDEuMy40LCAxLjMuNiwgMi4yLjIpLicsXG4gICAgICBleHBsYW5hdGlvbjpcbiAgICAgICAgJ0RlcGxveSBBbWF6b24gRWxhc3RpYyBDb21wdXRlIENsb3VkIChBbWF6b24gRUMyKSBpbnN0YW5jZXMgd2l0aGluIGFuIEFtYXpvbiBWaXJ0dWFsIFByaXZhdGUgQ2xvdWQgKEFtYXpvbiBWUEMpIHRvIGVuYWJsZSBzZWN1cmUgY29tbXVuaWNhdGlvbiBiZXR3ZWVuIGFuIGluc3RhbmNlIGFuZCBvdGhlciBzZXJ2aWNlcyB3aXRoaW4gdGhlIGFtYXpvbiBWUEMsIHdpdGhvdXQgcmVxdWlyaW5nIGFuIGludGVybmV0IGdhdGV3YXksIE5BVCBkZXZpY2UsIG9yIFZQTiBjb25uZWN0aW9uLiBBbGwgdHJhZmZpYyByZW1haW5zIHNlY3VyZWx5IHdpdGhpbiB0aGUgQVdTIENsb3VkLiBCZWNhdXNlIG9mIHRoZWlyIGxvZ2ljYWwgaXNvbGF0aW9uLCBkb21haW5zIHRoYXQgcmVzaWRlIHdpdGhpbiBhbkFtYXpvbiBWUEMgaGF2ZSBhbiBleHRyYSBsYXllciBvZiBzZWN1cml0eSB3aGVuIGNvbXBhcmVkIHRvIGRvbWFpbnMgdGhhdCB1c2UgcHVibGljIGVuZHBvaW50cy4gQXNzaWduIEFtYXpvbiBFQzIgaW5zdGFuY2VzIHRvIGFuIEFtYXpvbiBWUEMgdG8gcHJvcGVybHkgbWFuYWdlIGFjY2Vzcy4nLFxuICAgICAgbGV2ZWw6IE5hZ01lc3NhZ2VMZXZlbC5FUlJPUixcbiAgICAgIHJ1bGU6IEVDMkluc3RhbmNlc0luVlBDLFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcbiAgICB0aGlzLmFwcGx5UnVsZSh7XG4gICAgICBpbmZvOiAnVGhlIEVDMiBpbnN0YW5jZSBhbGxvd3MgdW5yZXN0cmljdGVkIGluYm91bmQgSVB2NCBUQ1AgdHJhZmZpYyBvbiBvbmUgb3IgbW9yZSBjb21tb24gcG9ydHMgKGJ5IGRlZmF1bHQgdGhlc2UgcG9ydHMgaW5jbHVkZSAyMCwgMjEsIDMzODksIDMzMDksIDMzMDYsIDQzMzMpIC0gKENvbnRyb2wgSURzOiAxLjIsIDEuMi4xLCAxLjMsIDEuMy4xLCAxLjMuMiwgMi4yLCAyLjIuMikuJyxcbiAgICAgIGV4cGxhbmF0aW9uOlxuICAgICAgICAnTm90IHJlc3RyaWN0aW5nIGFjY2VzcyB0byBwb3J0cyB0byB0cnVzdGVkIHNvdXJjZXMgY2FuIGxlYWQgdG8gYXR0YWNrcyBhZ2FpbnN0IHRoZSBhdmFpbGFiaWxpdHksIGludGVncml0eSBhbmQgY29uZmlkZW50aWFsaXR5IG9mIHN5c3RlbXMuIEJ5IGRlZmF1bHQsIGNvbW1vbiBwb3J0cyB3aGljaCBzaG91bGQgYmUgcmVzdHJpY3RlZCBpbmNsdWRlIHBvcnQgbnVtYmVycyAyMCwgMjEsIDMzODksIDMzMDYsIGFuZCA0MzMzLicsXG4gICAgICBsZXZlbDogTmFnTWVzc2FnZUxldmVsLkVSUk9SLFxuICAgICAgcnVsZTogRUMyUmVzdHJpY3RlZENvbW1vblBvcnRzLFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcbiAgICB0aGlzLmFwcGx5UnVsZSh7XG4gICAgICBpbmZvOiAnVGhlIFNlY3VyaXR5IEdyb3VwIGFsbG93cyB1bnJlc3RyaWN0ZWQgU1NIIGFjY2VzcyAtIChDb250cm9sIElEczogMS4yLCAxLjIuMSwgMS4zLCAxLjMuMSwgMS4zLjIsIDIuMiwgMi4yLjIpLicsXG4gICAgICBleHBsYW5hdGlvbjpcbiAgICAgICAgJ05vdCBhbGxvd2luZyBpbmdyZXNzIChvciByZW1vdGUpIHRyYWZmaWMgZnJvbSAwLjAuMC4wLzAgb3IgOjovMCB0byBwb3J0IDIyIG9uIHlvdXIgcmVzb3VyY2VzIGhlbHBzIHRvIHJlc3RyaWN0IHJlbW90ZSBhY2Nlc3MuJyxcbiAgICAgIGxldmVsOiBOYWdNZXNzYWdlTGV2ZWwuRVJST1IsXG4gICAgICBydWxlOiBFQzJSZXN0cmljdGVkU1NILFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBFQ1MgUmVzb3VyY2VzXG4gICAqIEBwYXJhbSBub2RlIHRoZSBDZm5SZXNvdXJjZSB0byBjaGVja1xuICAgKiBAcGFyYW0gaWdub3JlcyBsaXN0IG9mIGlnbm9yZXMgZm9yIHRoZSByZXNvdXJjZVxuICAgKi9cbiAgcHJpdmF0ZSBjaGVja0VDUyhub2RlOiBDZm5SZXNvdXJjZSk6IHZvaWQge1xuICAgIHRoaXMuYXBwbHlSdWxlKHtcbiAgICAgIGluZm86IFwiVGhlIEVDUyB0YXNrIGRlZmluaXRpb24gaXMgY29uZmlndXJlZCBmb3IgaG9zdCBuZXR3b3JraW5nIGFuZCBoYXMgYXQgbGVhc3Qgb25lIGNvbnRhaW5lciB3aXRoIGRlZmluaXRpb25zIHdpdGggJ3ByaXZpbGVnZWQnIHNldCB0byBmYWxzZSBvciBlbXB0eSBvciAndXNlcicgc2V0IHRvIHJvb3Qgb3IgZW1wdHkgLSAoQ29udHJvbCBJRDogNy4yLjEpLlwiLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgICdJZiBhIHRhc2sgZGVmaW5pdGlvbiBoYXMgZWxldmF0ZWQgcHJpdmlsZWdlcyBpdCBpcyBiZWNhdXNlIHlvdSBoYXZlIHNwZWNpZmljYWxseSBvcHRlZC1pbiB0byB0aG9zZSBjb25maWd1cmF0aW9ucy4gVGhpcyBydWxlIGNoZWNrcyBmb3IgdW5leHBlY3RlZCBwcml2aWxlZ2UgZXNjYWxhdGlvbiB3aGVuIGEgdGFzayBkZWZpbml0aW9uIGhhcyBob3N0IG5ldHdvcmtpbmcgZW5hYmxlZCBidXQgdGhlIGN1c3RvbWVyIGhhcyBub3Qgb3B0ZWQtaW4gdG8gZWxldmF0ZWQgcHJpdmlsZWdlcy4nLFxuICAgICAgbGV2ZWw6IE5hZ01lc3NhZ2VMZXZlbC5FUlJPUixcbiAgICAgIHJ1bGU6IEVDU1Rhc2tEZWZpbml0aW9uVXNlckZvckhvc3RNb2RlLFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBFRlMgUmVzb3VyY2VzXG4gICAqIEBwYXJhbSBub2RlIHRoZSBDZm5SZXNvdXJjZSB0byBjaGVja1xuICAgKiBAcGFyYW0gaWdub3JlcyBsaXN0IG9mIGlnbm9yZXMgZm9yIHRoZSByZXNvdXJjZVxuICAgKi9cbiAgcHJpdmF0ZSBjaGVja0VGUyhub2RlOiBDZm5SZXNvdXJjZSkge1xuICAgIHRoaXMuYXBwbHlSdWxlKHtcbiAgICAgIGluZm86ICdUaGUgRUZTIGRvZXMgbm90IGhhdmUgZW5jcnlwdGlvbiBhdCByZXN0IGVuYWJsZWQgLSAoQ29udHJvbCBJRHM6IDMuNCwgOC4yLjEpLicsXG4gICAgICBleHBsYW5hdGlvbjpcbiAgICAgICAgJ0JlY2F1c2Ugc2Vuc2l0aXZlIGRhdGEgY2FuIGV4aXN0IGFuZCB0byBoZWxwIHByb3RlY3QgZGF0YSBhdCByZXN0LCBlbnN1cmUgZW5jcnlwdGlvbiBpcyBlbmFibGVkIGZvciB5b3VyIEFtYXpvbiBFbGFzdGljIEZpbGUgU3lzdGVtIChFRlMpLicsXG4gICAgICBsZXZlbDogTmFnTWVzc2FnZUxldmVsLkVSUk9SLFxuICAgICAgcnVsZTogRUZTRW5jcnlwdGVkLFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBFbGFzdGljIExvYWQgQmFsYW5jZXIgUmVzb3VyY2VzXG4gICAqIEBwYXJhbSBub2RlIHRoZSBDZm5SZXNvdXJjZSB0byBjaGVja1xuICAgKiBAcGFyYW0gaWdub3JlcyBsaXN0IG9mIGlnbm9yZXMgZm9yIHRoZSByZXNvdXJjZVxuICAgKi9cbiAgcHJpdmF0ZSBjaGVja0VMQihub2RlOiBDZm5SZXNvdXJjZSk6IHZvaWQge1xuICAgIHRoaXMuYXBwbHlSdWxlKHtcbiAgICAgIGluZm86ICdUaGUgQUxCIGRvZXMgbm90IGhhdmUgaW52YWxpZCBIVFRQIGhlYWRlciBkcm9wcGluZyBlbmFibGVkIC0gKENvbnRyb2wgSURzOiA0LjEsIDguMi4xKS4nLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgICdFbnN1cmUgdGhhdCB5b3VyIEFwcGxpY2F0aW9uIExvYWQgQmFsYW5jZXJzIChBTEIpIGFyZSBjb25maWd1cmVkIHRvIGRyb3AgaHR0cCBoZWFkZXJzLiBCZWNhdXNlIHNlbnNpdGl2ZSBkYXRhIGNhbiBleGlzdCwgZW5hYmxlIGVuY3J5cHRpb24gaW4gdHJhbnNpdCB0byBoZWxwIHByb3RlY3QgdGhhdCBkYXRhLicsXG4gICAgICBsZXZlbDogTmFnTWVzc2FnZUxldmVsLkVSUk9SLFxuICAgICAgcnVsZTogQUxCSHR0cERyb3BJbnZhbGlkSGVhZGVyRW5hYmxlZCxcbiAgICAgIG5vZGU6IG5vZGUsXG4gICAgfSk7XG4gICAgdGhpcy5hcHBseVJ1bGUoe1xuICAgICAgaW5mbzogXCJUaGUgQUxCJ3MgSFRUUCBsaXN0ZW5lcnMgYXJlIG5vdCBjb25maWd1cmVkIHRvIHJlZGlyZWN0IHRvIEhUVFBTIC0gKENvbnRyb2wgSURzOiAyLjMsIDQuMSwgOC4yLjEpLlwiLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgICdUbyBoZWxwIHByb3RlY3QgZGF0YSBpbiB0cmFuc2l0LCBlbnN1cmUgdGhhdCB5b3VyIEFwcGxpY2F0aW9uIExvYWQgQmFsYW5jZXIgYXV0b21hdGljYWxseSByZWRpcmVjdHMgdW5lbmNyeXB0ZWQgSFRUUCByZXF1ZXN0cyB0byBIVFRQUy4gQmVjYXVzZSBzZW5zaXRpdmUgZGF0YSBjYW4gZXhpc3QsIGVuYWJsZSBlbmNyeXB0aW9uIGluIHRyYW5zaXQgdG8gaGVscCBwcm90ZWN0IHRoYXQgZGF0YS4nLFxuICAgICAgbGV2ZWw6IE5hZ01lc3NhZ2VMZXZlbC5FUlJPUixcbiAgICAgIHJ1bGU6IEFMQkh0dHBUb0h0dHBzUmVkaXJlY3Rpb24sXG4gICAgICBub2RlOiBub2RlLFxuICAgIH0pO1xuICAgIHRoaXMuYXBwbHlSdWxlKHtcbiAgICAgIGluZm86ICdUaGUgQUxCIGlzIG5vdCBhc3NvY2lhdGVkIHdpdGggQVdTIFdBRnYyIHdlYiBBQ0wgLSAoQ29udHJvbCBJRDogNi42KS4nLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgICdBIFdBRiBoZWxwcyB0byBwcm90ZWN0IHlvdXIgd2ViIGFwcGxpY2F0aW9ucyBvciBBUElzIGFnYWluc3QgY29tbW9uIHdlYiBleHBsb2l0cy4gVGhlc2Ugd2ViIGV4cGxvaXRzIG1heSBhZmZlY3QgYXZhaWxhYmlsaXR5LCBjb21wcm9taXNlIHNlY3VyaXR5LCBvciBjb25zdW1lIGV4Y2Vzc2l2ZSByZXNvdXJjZXMgd2l0aGluIHlvdXIgZW52aXJvbm1lbnQuJyxcbiAgICAgIGxldmVsOiBOYWdNZXNzYWdlTGV2ZWwuRVJST1IsXG4gICAgICBydWxlOiBBTEJXQUZFbmFibGVkLFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcbiAgICB0aGlzLmFwcGx5UnVsZSh7XG4gICAgICBpbmZvOiAnVGhlIENMQiBkb2VzIG5vdCB1dGlsaXplIGFuIFNTTCBjZXJ0aWZpY2F0ZSBwcm92aWRlZCBieSBBQ00gKEFtYXpvbiBDZXJ0aWZpY2F0ZSBNYW5hZ2VyKSAtIChDb250cm9sIElEczogNC4xLCA4LjIuMSkuJyxcbiAgICAgIGV4cGxhbmF0aW9uOlxuICAgICAgICAnQmVjYXVzZSBzZW5zaXRpdmUgZGF0YSBjYW4gZXhpc3QgYW5kIHRvIGhlbHAgcHJvdGVjdCBkYXRhIGF0IHRyYW5zaXQsIGVuc3VyZSBlbmNyeXB0aW9uIGlzIGVuYWJsZWQgZm9yIHlvdXIgRWxhc3RpYyBMb2FkIEJhbGFuY2luZy4gVXNlIEFXUyBDZXJ0aWZpY2F0ZSBNYW5hZ2VyIHRvIG1hbmFnZSwgcHJvdmlzaW9uIGFuZCBkZXBsb3kgcHVibGljIGFuZCBwcml2YXRlIFNTTC9UTFMgY2VydGlmaWNhdGVzIHdpdGggQVdTIHNlcnZpY2VzIGFuZCBpbnRlcm5hbCByZXNvdXJjZXMuJyxcbiAgICAgIGxldmVsOiBOYWdNZXNzYWdlTGV2ZWwuRVJST1IsXG4gICAgICBydWxlOiBFTEJBQ01DZXJ0aWZpY2F0ZVJlcXVpcmVkLFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcbiAgICB0aGlzLmFwcGx5UnVsZSh7XG4gICAgICBpbmZvOiAnVGhlIEVMQiBkb2VzIG5vdCBoYXZlIGxvZ2dpbmcgZW5hYmxlZCAtIChDb250cm9sIElEczogMTAuMSwgMTAuMy4xLCAxMC4zLjIsIDEwLjMuMywgMTAuMy40LCAxMC4zLjUsIDEwLjMuNiwgMTAuNS40KS4nLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgIFwiRWxhc3RpYyBMb2FkIEJhbGFuY2luZyBhY3Rpdml0eSBpcyBhIGNlbnRyYWwgcG9pbnQgb2YgY29tbXVuaWNhdGlvbiB3aXRoaW4gYW4gZW52aXJvbm1lbnQuIEVuc3VyZSBFTEIgbG9nZ2luZyBpcyBlbmFibGVkLiBUaGUgY29sbGVjdGVkIGRhdGEgcHJvdmlkZXMgZGV0YWlsZWQgaW5mb3JtYXRpb24gYWJvdXQgcmVxdWVzdHMgc2VudCB0byBUaGUgRUxCLiBFYWNoIGxvZyBjb250YWlucyBpbmZvcm1hdGlvbiBzdWNoIGFzIHRoZSB0aW1lIHRoZSByZXF1ZXN0IHdhcyByZWNlaXZlZCwgdGhlIGNsaWVudCdzIElQIGFkZHJlc3MsIGxhdGVuY2llcywgcmVxdWVzdCBwYXRocywgYW5kIHNlcnZlciByZXNwb25zZXMuXCIsXG4gICAgICBsZXZlbDogTmFnTWVzc2FnZUxldmVsLkVSUk9SLFxuICAgICAgcnVsZTogRUxCTG9nZ2luZ0VuYWJsZWQsXG4gICAgICBub2RlOiBub2RlLFxuICAgIH0pO1xuICAgIHRoaXMuYXBwbHlSdWxlKHtcbiAgICAgIGluZm86ICdUaGUgQ0xCIGRvZXMgbm90IHJlc3RyaWN0IGl0cyBsaXN0ZW5lcnMgdG8gb25seSB0aGUgU1NMIGFuZCBIVFRQUyBwcm90b2NvbHMgLSAoQ29udHJvbCBJRHM6IDIuMywgNC4xLCA4LjIuMSkuJyxcbiAgICAgIGV4cGxhbmF0aW9uOlxuICAgICAgICAnRW5zdXJlIHRoYXQgeW91ciBDbGFzc2ljIExvYWQgQmFsYW5jZXJzIChDTEJzKSBhcmUgY29uZmlndXJlZCB3aXRoIFNTTCBvciBIVFRQUyBsaXN0ZW5lcnMuIEJlY2F1c2Ugc2Vuc2l0aXZlIGRhdGEgY2FuIGV4aXN0LCBlbmFibGUgZW5jcnlwdGlvbiBpbiB0cmFuc2l0IHRvIGhlbHAgcHJvdGVjdCB0aGF0IGRhdGEuJyxcbiAgICAgIGxldmVsOiBOYWdNZXNzYWdlTGV2ZWwuRVJST1IsXG4gICAgICBydWxlOiBFTEJUbHNIdHRwc0xpc3RlbmVyc09ubHksXG4gICAgICBub2RlOiBub2RlLFxuICAgIH0pO1xuICAgIHRoaXMuYXBwbHlSdWxlKHtcbiAgICAgIGluZm86ICdUaGUgQUxCLCBOTEIsIG9yIEdMQiBsaXN0ZW5lciBkb2VzIG5vdCB1dGlsaXplIGFuIFNTTCBjZXJ0aWZpY2F0ZSBwcm92aWRlZCBieSBBQ00gKEFtYXpvbiBDZXJ0aWZpY2F0ZSBNYW5hZ2VyKSAtIChDb250cm9sIElEOiA0LjEpLicsXG4gICAgICBleHBsYW5hdGlvbjpcbiAgICAgICAgJ0JlY2F1c2Ugc2Vuc2l0aXZlIGRhdGEgY2FuIGV4aXN0IGFuZCB0byBoZWxwIHByb3RlY3QgZGF0YSBhdCB0cmFuc2l0LCBlbnN1cmUgZW5jcnlwdGlvbiBpcyBlbmFibGVkIGZvciB5b3VyIEVsYXN0aWMgTG9hZCBCYWxhbmNpbmcuIFVzZSBBV1MgQ2VydGlmaWNhdGUgTWFuYWdlciB0byBtYW5hZ2UsIHByb3Zpc2lvbiBhbmQgZGVwbG95IHB1YmxpYyBhbmQgcHJpdmF0ZSBTU0wvVExTIGNlcnRpZmljYXRlcyB3aXRoIEFXUyBzZXJ2aWNlcyBhbmQgaW50ZXJuYWwgcmVzb3VyY2VzLicsXG4gICAgICBsZXZlbDogTmFnTWVzc2FnZUxldmVsLkVSUk9SLFxuICAgICAgcnVsZTogRUxCdjJBQ01DZXJ0aWZpY2F0ZVJlcXVpcmVkLFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBFTVIgUmVzb3VyY2VzXG4gICAqIEBwYXJhbSBub2RlIHRoZSBDZm5SZXNvdXJjZSB0byBjaGVja1xuICAgKiBAcGFyYW0gaWdub3JlcyBsaXN0IG9mIGlnbm9yZXMgZm9yIHRoZSByZXNvdXJjZVxuICAgKi9cbiAgcHJpdmF0ZSBjaGVja0VNUihub2RlOiBDZm5SZXNvdXJjZSkge1xuICAgIHRoaXMuYXBwbHlSdWxlKHtcbiAgICAgIGluZm86ICdUaGUgQUxCLCBOTEIsIG9yIEdMQiBsaXN0ZW5lciBkb2VzIG5vdCB1dGlsaXplIGFuIFNTTCBjZXJ0aWZpY2F0ZSBwcm92aWRlZCBieSBBQ00gKEFtYXpvbiBDZXJ0aWZpY2F0ZSBNYW5hZ2VyKSAtIChDb250cm9sIElEOiA3LjIuMSkuJyxcbiAgICAgIGV4cGxhbmF0aW9uOlxuICAgICAgICAnQmVjYXVzZSBzZW5zaXRpdmUgZGF0YSBjYW4gZXhpc3QgYW5kIHRvIGhlbHAgcHJvdGVjdCBkYXRhIGF0IHRyYW5zaXQsIGVuc3VyZSBlbmNyeXB0aW9uIGlzIGVuYWJsZWQgZm9yIHlvdXIgRWxhc3RpYyBMb2FkIEJhbGFuY2luZy4gVXNlIEFXUyBDZXJ0aWZpY2F0ZSBNYW5hZ2VyIHRvIG1hbmFnZSwgcHJvdmlzaW9uIGFuZCBkZXBsb3kgcHVibGljIGFuZCBwcml2YXRlIFNTTC9UTFMgY2VydGlmaWNhdGVzIHdpdGggQVdTIHNlcnZpY2VzIGFuZCBpbnRlcm5hbCByZXNvdXJjZXMuJyxcbiAgICAgIGxldmVsOiBOYWdNZXNzYWdlTGV2ZWwuRVJST1IsXG4gICAgICBydWxlOiBFTVJLZXJiZXJvc0VuYWJsZWQsXG4gICAgICBub2RlOiBub2RlLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIElBTSBSZXNvdXJjZXNcbiAgICogQHBhcmFtIG5vZGUgdGhlIENmblJlc291cmNlIHRvIGNoZWNrXG4gICAqIEBwYXJhbSBpZ25vcmVzIGxpc3Qgb2YgaWdub3JlcyBmb3IgdGhlIHJlc291cmNlXG4gICAqL1xuICBwcml2YXRlIGNoZWNrSUFNKG5vZGU6IENmblJlc291cmNlKTogdm9pZCB7XG4gICAgdGhpcy5hcHBseVJ1bGUoe1xuICAgICAgaW5mbzogJ1RoZSBJQU0gR3JvdXAgZG9lcyBub3QgaGF2ZSBhdCBsZWFzdCBvbmUgSUFNIFVzZXIgLSAoQ29udHJvbCBJRHM6IDcuMS4yLMKgNy4xLjMswqA3LjIuMSzCoDcuMi4yKS4nLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgICdBV1MgSWRlbnRpdHkgYW5kIEFjY2VzcyBNYW5hZ2VtZW50IChJQU0pIGNhbiBoZWxwIHlvdSBpbmNvcnBvcmF0ZSB0aGUgcHJpbmNpcGxlcyBvZiBsZWFzdCBwcml2aWxlZ2UgYW5kIHNlcGFyYXRpb24gb2YgZHV0aWVzIHdpdGggYWNjZXNzIHBlcm1pc3Npb25zIGFuZCBhdXRob3JpemF0aW9ucywgYnkgZW5zdXJpbmcgdGhhdCBJQU0gZ3JvdXBzIGhhdmUgYXQgbGVhc3Qgb25lIElBTSB1c2VyLiBQbGFjaW5nIElBTSB1c2VycyBpbiBncm91cHMgYmFzZWQgb24gdGhlaXIgYXNzb2NpYXRlZCBwZXJtaXNzaW9ucyBvciBqb2IgZnVuY3Rpb24gaXMgb25lIHdheSB0byBpbmNvcnBvcmF0ZSBsZWFzdCBwcml2aWxlZ2UuJyxcbiAgICAgIGxldmVsOiBOYWdNZXNzYWdlTGV2ZWwuRVJST1IsXG4gICAgICBydWxlOiBJQU1Hcm91cEhhc1VzZXJzLFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcbiAgICB0aGlzLmFwcGx5UnVsZSh7XG4gICAgICBpbmZvOiAnVGhlIElBTSBHcm91cCwgVXNlciwgb3IgUm9sZSBjb250YWlucyBhbiBpbmxpbmUgcG9saWN5IC0gKENvbnRyb2wgSURzOiAyLjIsIDcuMS4yLCA3LjEuMywgNy4yLjEsIDcuMi4yKS4nLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgICdBV1MgcmVjb21tZW5kcyB0byB1c2UgbWFuYWdlZCBwb2xpY2llcyBpbnN0ZWFkIG9mIGlubGluZSBwb2xpY2llcy4gVGhlIG1hbmFnZWQgcG9saWNpZXMgYWxsb3cgcmV1c2FiaWxpdHksIHZlcnNpb25pbmcgYW5kIHJvbGxpbmcgYmFjaywgYW5kIGRlbGVnYXRpbmcgcGVybWlzc2lvbnMgbWFuYWdlbWVudC4nLFxuICAgICAgbGV2ZWw6IE5hZ01lc3NhZ2VMZXZlbC5FUlJPUixcbiAgICAgIHJ1bGU6IElBTU5vSW5saW5lUG9saWN5LFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcbiAgICB0aGlzLmFwcGx5UnVsZSh7XG4gICAgICBpbmZvOiAnVGhlIElBTSBwb2xpY3kgZ3JhbnRzIGFkbWluIGFjY2VzcywgbWVhbmluZyB0aGUgcG9saWN5IGFsbG93cyBhIHByaW5jaXBhbCB0byBwZXJmb3JtIGFsbCBhY3Rpb25zIG9uIGFsbCByZXNvdXJjZXMgLSAoQ29udHJvbCBJRHM6IDIuMiwgNy4xLjIsIDcuMS4zLCA3LjIuMSwgNy4yLjIpLicsXG4gICAgICBleHBsYW5hdGlvbjpcbiAgICAgICAgJ0FXUyBJZGVudGl0eSBhbmQgQWNjZXNzIE1hbmFnZW1lbnQgKElBTSkgY2FuIGhlbHAgeW91IGluY29ycG9yYXRlIHRoZSBwcmluY2lwbGVzIG9mIGxlYXN0IHByaXZpbGVnZSBhbmQgc2VwYXJhdGlvbiBvZiBkdXRpZXMgd2l0aCBhY2Nlc3MgcGVybWlzc2lvbnMgYW5kIGF1dGhvcml6YXRpb25zLCBieSBlbnN1cmluZyB0aGF0IElBTSBncm91cHMgaGF2ZSBhdCBsZWFzdCBvbmUgSUFNIHVzZXIuIFBsYWNpbmcgSUFNIHVzZXJzIGluIGdyb3VwcyBiYXNlZCBvbiB0aGVpciBhc3NvY2lhdGVkIHBlcm1pc3Npb25zIG9yIGpvYiBmdW5jdGlvbiBpcyBvbmUgd2F5IHRvIGluY29ycG9yYXRlIGxlYXN0IHByaXZpbGVnZS4nLFxuICAgICAgbGV2ZWw6IE5hZ01lc3NhZ2VMZXZlbC5FUlJPUixcbiAgICAgIHJ1bGU6IElBTVBvbGljeU5vU3RhdGVtZW50c1dpdGhBZG1pbkFjY2VzcyxcbiAgICAgIG5vZGU6IG5vZGUsXG4gICAgfSk7XG4gICAgdGhpcy5hcHBseVJ1bGUoe1xuICAgICAgaW5mbzogJ1RoZSBJQU0gcG9saWN5IGdyYW50cyBmdWxsIGFjY2VzcywgbWVhbmluZyB0aGUgcG9saWN5IGFsbG93cyBhIHByaW5jaXBhbCB0byBwZXJmb3JtIGFsbCBhY3Rpb25zIG9uIGluZGl2aWR1YWwgcmVzb3VyY2VzIC0gKENvbnRyb2wgSURzOiA3LjEuMiwgNy4xLjMsIDcuMi4xLCA3LjIuMikuJyxcbiAgICAgIGV4cGxhbmF0aW9uOlxuICAgICAgICAnRW5zdXJlIElBTSBBY3Rpb25zIGFyZSByZXN0cmljdGVkIHRvIG9ubHkgdGhvc2UgYWN0aW9ucyB0aGF0IGFyZSBuZWVkZWQuIEFsbG93aW5nIHVzZXJzIHRvIGhhdmUgbW9yZSBwcml2aWxlZ2VzIHRoYW4gbmVlZGVkIHRvIGNvbXBsZXRlIGEgdGFzayBtYXkgdmlvbGF0ZSB0aGUgcHJpbmNpcGxlIG9mIGxlYXN0IHByaXZpbGVnZSBhbmQgc2VwYXJhdGlvbiBvZiBkdXRpZXMuJyxcbiAgICAgIGxldmVsOiBOYWdNZXNzYWdlTGV2ZWwuRVJST1IsXG4gICAgICBydWxlOiBJQU1Qb2xpY3lOb1N0YXRlbWVudHNXaXRoRnVsbEFjY2VzcyxcbiAgICAgIG5vZGU6IG5vZGUsXG4gICAgfSk7XG4gICAgdGhpcy5hcHBseVJ1bGUoe1xuICAgICAgaW5mbzogJ1RoZSBJQU0gdXNlciBkb2VzIG5vdCBiZWxvbmcgdG8gYW55IGdyb3VwKHMpIC0gKENvbnRyb2wgSURzOiAyLjIsIDcuMS4yLCA3LjEuMywgNy4yLjEsIDcuMi4yKS4nLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgICdBV1MgSWRlbnRpdHkgYW5kIEFjY2VzcyBNYW5hZ2VtZW50IChJQU0pIGNhbiBoZWxwIHlvdSByZXN0cmljdCBhY2Nlc3MgcGVybWlzc2lvbnMgYW5kIGF1dGhvcml6YXRpb25zIGJ5IGVuc3VyaW5nIElBTSB1c2VycyBhcmUgbWVtYmVycyBvZiBhdCBsZWFzdCBvbmUgZ3JvdXAuIEFsbG93aW5nIHVzZXJzIG1vcmUgcHJpdmlsZWdlcyB0aGFuIG5lZWRlZCB0byBjb21wbGV0ZSBhIHRhc2sgbWF5IHZpb2xhdGUgdGhlIHByaW5jaXBsZSBvZiBsZWFzdCBwcml2aWxlZ2UgYW5kIHNlcGFyYXRpb24gb2YgZHV0aWVzLicsXG4gICAgICBsZXZlbDogTmFnTWVzc2FnZUxldmVsLkVSUk9SLFxuICAgICAgcnVsZTogSUFNVXNlckdyb3VwTWVtYmVyc2hpcCxcbiAgICAgIG5vZGU6IG5vZGUsXG4gICAgfSk7XG4gICAgdGhpcy5hcHBseVJ1bGUoe1xuICAgICAgaW5mbzogJ1RoZSBJQU0gcG9saWN5IGlzIGF0dGFjaGVkIGF0IHRoZSB1c2VyIGxldmVsIC0gKENvbnRyb2wgSURzOiAyLjIsIDcuMS4yLCA3LjEuMywgNy4yLjEsIDcuMi4yKS4nLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgICdBc3NpZ25pbmcgcHJpdmlsZWdlcyBhdCB0aGUgZ3JvdXAgb3IgdGhlIHJvbGUgbGV2ZWwgaGVscHMgdG8gcmVkdWNlIG9wcG9ydHVuaXR5IGZvciBhbiBpZGVudGl0eSB0byByZWNlaXZlIG9yIHJldGFpbiBleGNlc3NpdmUgcHJpdmlsZWdlcy4nLFxuICAgICAgbGV2ZWw6IE5hZ01lc3NhZ2VMZXZlbC5FUlJPUixcbiAgICAgIHJ1bGU6IElBTVVzZXJOb1BvbGljaWVzLFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBLTVMgUmVzb3VyY2VzXG4gICAqIEBwYXJhbSBub2RlIHRoZSBDZm5SZXNvdXJjZSB0byBjaGVja1xuICAgKiBAcGFyYW0gaWdub3JlcyBsaXN0IG9mIGlnbm9yZXMgZm9yIHRoZSByZXNvdXJjZVxuICAgKi9cbiAgcHJpdmF0ZSBjaGVja0tNUyhub2RlOiBDZm5SZXNvdXJjZSk6IHZvaWQge1xuICAgIHRoaXMuYXBwbHlSdWxlKHtcbiAgICAgIGluZm86ICdUaGUgS01TIFN5bW1ldHJpYyBrZXkgZG9lcyBub3QgaGF2ZSBhdXRvbWF0aWMga2V5IHJvdGF0aW9uIGVuYWJsZWQgLSAoQ29udHJvbCBJRHM6IDIuMizCoDMuNSzCoDMuNizCoDMuNi40KS4nLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgICdFbmFibGUga2V5IHJvdGF0aW9uIHRvIGVuc3VyZSB0aGF0IGtleXMgYXJlIHJvdGF0ZWQgb25jZSB0aGV5IGhhdmUgcmVhY2hlZCB0aGUgZW5kIG9mIHRoZWlyIGNyeXB0byBwZXJpb2QuJyxcbiAgICAgIGxldmVsOiBOYWdNZXNzYWdlTGV2ZWwuRVJST1IsXG4gICAgICBydWxlOiBLTVNCYWNraW5nS2V5Um90YXRpb25FbmFibGVkLFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBMYW1iZGEgUmVzb3VyY2VzXG4gICAqIEBwYXJhbSBub2RlIHRoZSBDZm5SZXNvdXJjZSB0byBjaGVja1xuICAgKiBAcGFyYW0gaWdub3JlcyBsaXN0IG9mIGlnbm9yZXMgZm9yIHRoZSByZXNvdXJjZVxuICAgKi9cbiAgcHJpdmF0ZSBjaGVja0xhbWJkYShub2RlOiBDZm5SZXNvdXJjZSkge1xuICAgIHRoaXMuYXBwbHlSdWxlKHtcbiAgICAgIGluZm86ICdUaGUgTGFtYmRhIGZ1bmN0aW9uIHBlcm1pc3Npb24gZ3JhbnRzIHB1YmxpYyBhY2Nlc3MgLSAoQ29udHJvbCBJRHM6IDEuMiwgMS4yLjEsIDEuMywgMS4zLjEsIDEuMy4yLCAxLjMuNCwgMi4yLjIpLicsXG4gICAgICBleHBsYW5hdGlvbjpcbiAgICAgICAgJ1B1YmxpYyBhY2Nlc3MgYWxsb3dzIGFueW9uZSBvbiB0aGUgaW50ZXJuZXQgdG8gcGVyZm9ybSB1bmF1dGhlbnRpY2F0ZWQgYWN0aW9ucyBvbiB5b3VyIGZ1bmN0aW9uIGFuZCBjYW4gcG90ZW50aWFsbHkgbGVhZCB0byBkZWdyYWRlZCBhdmFpbGFiaWxpdHkuJyxcbiAgICAgIGxldmVsOiBOYWdNZXNzYWdlTGV2ZWwuRVJST1IsXG4gICAgICBydWxlOiBMYW1iZGFGdW5jdGlvblB1YmxpY0FjY2Vzc1Byb2hpYml0ZWQsXG4gICAgICBub2RlOiBub2RlLFxuICAgIH0pO1xuICAgIHRoaXMuYXBwbHlSdWxlKHtcbiAgICAgIGluZm86ICdUaGUgTGFtYmRhIGZ1bmN0aW9uIGlzIG5vdCBWUEMgZW5hYmxlZCAtIChDb250cm9sIElEczogMS4yLCAxLjIuMSwgMS4zLCAxLjMuMSwgMS4zLjIsIDEuMy40LCAyLjIuMikuJyxcbiAgICAgIGV4cGxhbmF0aW9uOlxuICAgICAgICAnQmVjYXVzZSBvZiB0aGVpciBsb2dpY2FsIGlzb2xhdGlvbiwgZG9tYWlucyB0aGF0IHJlc2lkZSB3aXRoaW4gYW4gQW1hem9uIFZQQyBoYXZlIGFuIGV4dHJhIGxheWVyIG9mIHNlY3VyaXR5IHdoZW4gY29tcGFyZWQgdG8gZG9tYWlucyB0aGF0IHVzZSBwdWJsaWMgZW5kcG9pbnRzLicsXG4gICAgICBsZXZlbDogTmFnTWVzc2FnZUxldmVsLkVSUk9SLFxuICAgICAgcnVsZTogTGFtYmRhSW5zaWRlVlBDLFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBPcGVuU2VhcmNoIFJlc291cmNlc1xuICAgKiBAcGFyYW0gbm9kZSB0aGUgQ2ZuUmVzb3VyY2UgdG8gY2hlY2tcbiAgICogQHBhcmFtIGlnbm9yZXMgbGlzdCBvZiBpZ25vcmVzIGZvciB0aGUgcmVzb3VyY2VcbiAgICovXG4gIHByaXZhdGUgY2hlY2tPcGVuU2VhcmNoKG5vZGU6IENmblJlc291cmNlKSB7XG4gICAgdGhpcy5hcHBseVJ1bGUoe1xuICAgICAgaW5mbzogJ1RoZSBPcGVuU2VhcmNoIFNlcnZpY2UgZG9tYWluIGRvZXMgbm90IGhhdmUgZW5jcnlwdGlvbiBhdCByZXN0IGVuYWJsZWQgLSAoQ29udHJvbCBJRHM6IDMuNCwgOC4yLjEpLicsXG4gICAgICBleHBsYW5hdGlvbjpcbiAgICAgICAgJ0JlY2F1c2Ugc2Vuc2l0aXZlIGRhdGEgY2FuIGV4aXN0IGFuZCB0byBoZWxwIHByb3RlY3QgZGF0YSBhdCByZXN0LCBlbnN1cmUgZW5jcnlwdGlvbiBpcyBlbmFibGVkIGZvciB5b3VyIEFtYXpvbiBPcGVuU2VhcmNoIFNlcnZpY2UgKE9wZW5TZWFyY2ggU2VydmljZSkgZG9tYWlucy4nLFxuICAgICAgbGV2ZWw6IE5hZ01lc3NhZ2VMZXZlbC5FUlJPUixcbiAgICAgIHJ1bGU6IE9wZW5TZWFyY2hFbmNyeXB0ZWRBdFJlc3QsXG4gICAgICBub2RlOiBub2RlLFxuICAgIH0pO1xuICAgIHRoaXMuYXBwbHlSdWxlKHtcbiAgICAgIGluZm86ICdUaGUgT3BlblNlYXJjaCBTZXJ2aWNlIGRvbWFpbiBpcyBub3QgcnVubmluZyB3aXRoaW4gYSBWUEMgLSAoQ29udHJvbCBJRHM6IDEuMiwgMS4yLjEsIDEuMywgMS4zLjEsIDEuMy4yLCAxLjMuNCwgMS4zLjYsIDIuMi4yKS4nLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgICdWUENzIGhlbHAgc2VjdXJlIHlvdXIgQVdTIHJlc291cmNlcyBhbmQgcHJvdmlkZSBhbiBleHRyYSBsYXllciBvZiBwcm90ZWN0aW9uLicsXG4gICAgICBsZXZlbDogTmFnTWVzc2FnZUxldmVsLkVSUk9SLFxuICAgICAgcnVsZTogT3BlblNlYXJjaEluVlBDT25seSxcbiAgICAgIG5vZGU6IG5vZGUsXG4gICAgfSk7XG4gICAgdGhpcy5hcHBseVJ1bGUoe1xuICAgICAgaW5mbzogJ1RoZSBPcGVuU2VhcmNoIFNlcnZpY2UgZG9tYWluIGRvZXMgbm90IHN0cmVhbSBlcnJvciBsb2dzIChFU19BUFBMSUNBVElPTl9MT0dTKSB0byBDbG91ZFdhdGNoIExvZ3MgLSAoQ29udHJvbCBJRHM6IDEwLjEsIDEwLjIuMSwgMTAuMi4yLCAxMC4yLjMsIDEwLjIuNCwgMTAuMi41LCAxMC4zLjEsIDEwLjMuMiwgMTAuMy4zLCAxMC4zLjQsIDEwLjMuNSwgMTAuMy42KS4nLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgICdFbnN1cmUgQW1hem9uIE9wZW5TZWFyY2ggU2VydmljZSBkb21haW5zIGhhdmUgZXJyb3IgbG9ncyBlbmFibGVkIGFuZCBzdHJlYW1lZCB0byBBbWF6b24gQ2xvdWRXYXRjaCBMb2dzIGZvciByZXRlbnRpb24gYW5kIHJlc3BvbnNlLiBEb21haW4gZXJyb3IgbG9ncyBjYW4gYXNzaXN0IHdpdGggc2VjdXJpdHkgYW5kIGFjY2VzcyBhdWRpdHMsIGFuZCBjYW4gaGVscCB0byBkaWFnbm9zZSBhdmFpbGFiaWxpdHkgaXNzdWVzLicsXG4gICAgICBsZXZlbDogTmFnTWVzc2FnZUxldmVsLkVSUk9SLFxuICAgICAgcnVsZTogT3BlblNlYXJjaEVycm9yTG9nc1RvQ2xvdWRXYXRjaCxcbiAgICAgIG5vZGU6IG5vZGUsXG4gICAgfSk7XG4gICAgdGhpcy5hcHBseVJ1bGUoe1xuICAgICAgaW5mbzogJ1RoZSBPcGVuU2VhcmNoIFNlcnZpY2UgZG9tYWluIGRvZXMgbm90IGhhdmUgbm9kZS10by1ub2RlIGVuY3J5cHRpb24gZW5hYmxlZCAtIChDb250cm9sIElEOiA0LjEpLicsXG4gICAgICBleHBsYW5hdGlvbjpcbiAgICAgICAgJ0JlY2F1c2Ugc2Vuc2l0aXZlIGRhdGEgY2FuIGV4aXN0LCBlbmFibGUgZW5jcnlwdGlvbiBpbiB0cmFuc2l0IHRvIGhlbHAgcHJvdGVjdCB0aGF0IGRhdGEgd2l0aGluIHlvdXIgQW1hem9uIE9wZW5TZWFyY2ggU2VydmljZSAoT3BlblNlYXJjaCBTZXJ2aWNlKSBkb21haW5zLicsXG4gICAgICBsZXZlbDogTmFnTWVzc2FnZUxldmVsLkVSUk9SLFxuICAgICAgcnVsZTogT3BlblNlYXJjaE5vZGVUb05vZGVFbmNyeXB0aW9uLFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBSRFMgUmVzb3VyY2VzXG4gICAqIEBwYXJhbSBub2RlIHRoZSBDZm5SZXNvdXJjZSB0byBjaGVja1xuICAgKiBAcGFyYW0gaWdub3JlcyBsaXN0IG9mIGlnbm9yZXMgZm9yIHRoZSByZXNvdXJjZVxuICAgKi9cbiAgcHJpdmF0ZSBjaGVja1JEUyhub2RlOiBDZm5SZXNvdXJjZSk6IHZvaWQge1xuICAgIHRoaXMuYXBwbHlSdWxlKHtcbiAgICAgIGluZm86IFwiVGhlIHJvdXRlIHRhYmxlIG1heSBjb250YWluIG9uZSBvciBtb3JlIHVucmVzdHJpY3RlZCByb3V0ZShzKSB0byBhbiBJR1cgKCcwLjAuMC4wLzAnIG9yICc6Oi8wJykgLSAoQ29udHJvbCBJRDogNi4yKS5cIixcbiAgICAgIGV4cGxhbmF0aW9uOlxuICAgICAgICAnRW5zdXJlIEFtYXpvbiBFQzIgcm91dGUgdGFibGVzIGRvIG5vdCBoYXZlIHVucmVzdHJpY3RlZCByb3V0ZXMgdG8gYW4gaW50ZXJuZXQgZ2F0ZXdheS4gUmVtb3Zpbmcgb3IgbGltaXRpbmcgdGhlIGFjY2VzcyB0byB0aGUgaW50ZXJuZXQgZm9yIHdvcmtsb2FkcyB3aXRoaW4gQW1hem9uIFZQQ3MgY2FuIHJlZHVjZSB1bmludGVuZGVkIGFjY2VzcyB3aXRoaW4geW91ciBlbnZpcm9ubWVudC4nLFxuICAgICAgbGV2ZWw6IE5hZ01lc3NhZ2VMZXZlbC5FUlJPUixcbiAgICAgIHJ1bGU6IFJEU0F1dG9tYXRpY01pbm9yVmVyc2lvblVwZ3JhZGVFbmFibGVkLFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcbiAgICB0aGlzLmFwcGx5UnVsZSh7XG4gICAgICBpbmZvOiAnVGhlIFJEUyBEQiBJbnN0YW5jZSBhbGxvd3MgcHVibGljIGFjY2VzcyAtIChDb250cm9sIElEczogMS4yLCAxLjIuMSwgMS4zLCAxLjMuMSwgMS4zLjIsIDEuMy40LCAxLjMuNiwgMi4yLjIpLicsXG4gICAgICBleHBsYW5hdGlvbjpcbiAgICAgICAgJ0FtYXpvbiBSRFMgZGF0YWJhc2UgaW5zdGFuY2VzIGNhbiBjb250YWluIHNlbnNpdGl2ZSBpbmZvcm1hdGlvbiwgYW5kIHByaW5jaXBsZXMgYW5kIGFjY2VzcyBjb250cm9sIGlzIHJlcXVpcmVkIGZvciBzdWNoIGFjY291bnRzLicsXG4gICAgICBsZXZlbDogTmFnTWVzc2FnZUxldmVsLkVSUk9SLFxuICAgICAgcnVsZTogUkRTSW5zdGFuY2VQdWJsaWNBY2Nlc3MsXG4gICAgICBub2RlOiBub2RlLFxuICAgIH0pO1xuICAgIHRoaXMuYXBwbHlSdWxlKHtcbiAgICAgIGluZm86ICdUaGUgbm9uLUF1cm9yYSBSRFMgREIgaW5zdGFuY2Ugb3IgQXVyb3JhIGNsdXN0ZXIgZG9lcyBub3QgaGF2ZSBhbGwgQ2xvdWRXYXRjaCBsb2cgdHlwZXMgZXhwb3J0ZWQgLSAoQ29udHJvbCBJRHM6IDEwLjEsIDEwLjIuMSwgMTAuMi4yLCAxMC4yLjMsIDEwLjIuNCwgMTAuMi41LCAxMC4zLjEsIDEwLjMuMiwgMTAuMy4zLCAxMC4zLjQsIDEwLjMuNSwgMTAuMy42KS4nLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgICdUbyBoZWxwIHdpdGggbG9nZ2luZyBhbmQgbW9uaXRvcmluZyB3aXRoaW4geW91ciBlbnZpcm9ubWVudCwgZW5zdXJlIEFtYXpvbiBSZWxhdGlvbmFsIERhdGFiYXNlIFNlcnZpY2UgKEFtYXpvbiBSRFMpIGxvZ2dpbmcgaXMgZW5hYmxlZC4gV2l0aCBBbWF6b24gUkRTIGxvZ2dpbmcsIHlvdSBjYW4gY2FwdHVyZSBldmVudHMgc3VjaCBhcyBjb25uZWN0aW9ucywgZGlzY29ubmVjdGlvbnMsIHF1ZXJpZXMsIG9yIHRhYmxlcyBxdWVyaWVkLicgK1xuICAgICAgICBcIlRoaXMgaXMgYSBncmFudWxhciBydWxlIHRoYXQgcmV0dXJucyBpbmRpdmlkdWFsIGZpbmRpbmdzIHRoYXQgY2FuIGJlIHN1cHByZXNzZWQgd2l0aCAnYXBwbGllc1RvJy4gVGhlIGZpbmRpbmdzIGFyZSBpbiB0aGUgZm9ybWF0ICdMb2dFeHBvcnQ6Ojxsb2c+JyBmb3IgZXhwb3J0ZWQgbG9ncy4gRXhhbXBsZTogYXBwbGllc1RvOiBbJ0xvZ0V4cG9ydDo6YXVkaXQnXS5cIixcbiAgICAgIGxldmVsOiBOYWdNZXNzYWdlTGV2ZWwuRVJST1IsXG4gICAgICBydWxlOiBSRFNMb2dnaW5nRW5hYmxlZCxcbiAgICAgIG5vZGU6IG5vZGUsXG4gICAgfSk7XG4gICAgdGhpcy5hcHBseVJ1bGUoe1xuICAgICAgaW5mbzogJ1RoZSBSRFMgREIgSW5zdGFuY2Ugb3IgQXVyb3JhIENsdXN0ZXIgZG9lcyBub3QgaGF2ZSBzdG9yYWdlIGVuY3J5cHRlZCAtIChDb250cm9sIElEczogMy40LCA4LjIuMSkuJyxcbiAgICAgIGV4cGxhbmF0aW9uOlxuICAgICAgICAnQmVjYXVzZSBzZW5zaXRpdmUgZGF0YSBjYW4gZXhpc3QgYXQgcmVzdCBpbiBBbWF6b24gUkRTIGluc3RhbmNlcywgZW5hYmxlIGVuY3J5cHRpb24gYXQgcmVzdCB0byBoZWxwIHByb3RlY3QgdGhhdCBkYXRhLicsXG4gICAgICBsZXZlbDogTmFnTWVzc2FnZUxldmVsLkVSUk9SLFxuICAgICAgcnVsZTogUkRTU3RvcmFnZUVuY3J5cHRlZCxcbiAgICAgIG5vZGU6IG5vZGUsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgUmVkc2hpZnQgUmVzb3VyY2VzXG4gICAqIEBwYXJhbSBub2RlIHRoZSBDZm5SZXNvdXJjZSB0byBjaGVja1xuICAgKiBAcGFyYW0gaWdub3JlcyBsaXN0IG9mIGlnbm9yZXMgZm9yIHRoZSByZXNvdXJjZVxuICAgKi9cbiAgcHJpdmF0ZSBjaGVja1JlZHNoaWZ0KG5vZGU6IENmblJlc291cmNlKTogdm9pZCB7XG4gICAgdGhpcy5hcHBseVJ1bGUoe1xuICAgICAgaW5mbzogJ1RoZSBSZWRzaGlmdCBjbHVzdGVyIGRvZXMgbm90IGhhdmUgZW5jcnlwdGlvbiBvciBhdWRpdCBsb2dnaW5nIGVuYWJsZWQgLSAoQ29udHJvbCBJRHM6IDMuNCwgOC4yLjEsIDEwLjEsIDEwLjIuMSwgMTAuMi4yLCAxMC4yLjMsIDEwLjIuNCwgMTAuMi41LCAxMC4zLjEsIDEwLjMuMiwgMTAuMy4zLCAxMC4zLjQsIDEwLjMuNSwgMTAuMy42KS4nLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgICdUbyBwcm90ZWN0IGRhdGEgYXQgcmVzdCwgZW5zdXJlIHRoYXQgZW5jcnlwdGlvbiBpcyBlbmFibGVkIGZvciB5b3VyIEFtYXpvbiBSZWRzaGlmdCBjbHVzdGVycy4gWW91IG11c3QgYWxzbyBlbnN1cmUgdGhhdCByZXF1aXJlZCBjb25maWd1cmF0aW9ucyBhcmUgZGVwbG95ZWQgb24gQW1hem9uIFJlZHNoaWZ0IGNsdXN0ZXJzLiBUaGUgYXVkaXQgbG9nZ2luZyBzaG91bGQgYmUgZW5hYmxlZCB0byBwcm92aWRlIGluZm9ybWF0aW9uIGFib3V0IGNvbm5lY3Rpb25zIGFuZCB1c2VyIGFjdGl2aXRpZXMgaW4gdGhlIGRhdGFiYXNlLicsXG4gICAgICBsZXZlbDogTmFnTWVzc2FnZUxldmVsLkVSUk9SLFxuICAgICAgcnVsZTogUmVkc2hpZnRDbHVzdGVyQ29uZmlndXJhdGlvbixcbiAgICAgIG5vZGU6IG5vZGUsXG4gICAgfSk7XG4gICAgdGhpcy5hcHBseVJ1bGUoe1xuICAgICAgaW5mbzogJ1RoZSBSZWRzaGlmdCBjbHVzdGVyIGRvZXMgbm90IGhhdmUgdmVyc2lvbiB1cGdyYWRlcyBlbmFibGVkLCBhdXRvbWF0ZWQgc25hcHNob3QgcmV0ZW50aW9uIHBlcmlvZHMgZW5hYmxlZCwgYW5kIGFuIGV4cGxpY2l0IG1haW50ZW5hbmNlIHdpbmRvdyBjb25maWd1cmVkIC0gKENvbnRyb2wgSUQ6IDYuMikuJyxcbiAgICAgIGV4cGxhbmF0aW9uOlxuICAgICAgICAnRW5zdXJlIHRoYXQgQW1hem9uIFJlZHNoaWZ0IGNsdXN0ZXJzIGhhdmUgdGhlIHByZWZlcnJlZCBzZXR0aW5ncyBmb3IgeW91ciBvcmdhbml6YXRpb24uIFNwZWNpZmljYWxseSwgdGhhdCB0aGV5IGhhdmUgcHJlZmVycmVkIG1haW50ZW5hbmNlIHdpbmRvd3MgYW5kIGF1dG9tYXRlZCBzbmFwc2hvdCByZXRlbnRpb24gcGVyaW9kcyBmb3IgdGhlIGRhdGFiYXNlLiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJyxcbiAgICAgIGxldmVsOiBOYWdNZXNzYWdlTGV2ZWwuRVJST1IsXG4gICAgICBydWxlOiBSZWRzaGlmdENsdXN0ZXJNYWludGVuYW5jZVNldHRpbmdzLFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcbiAgICB0aGlzLmFwcGx5UnVsZSh7XG4gICAgICBpbmZvOiAnVGhlIFJlZHNoaWZ0IGNsdXN0ZXIgYWxsb3dzIHB1YmxpYyBhY2Nlc3MgLSAoQ29udHJvbCBJRHM6IDEuMiwgMS4yLjEsIDEuMywgMS4zLjEsIDEuMy4yLCAxLjMuNCwgMS4zLjYsIDIuMi4yKS4nLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgICdBbWF6b24gUmVkc2hpZnQgY2x1c3RlcnMgY2FuIGNvbnRhaW4gc2Vuc2l0aXZlIGluZm9ybWF0aW9uIGFuZCBwcmluY2lwbGVzIGFuZCBhY2Nlc3MgY29udHJvbCBpcyByZXF1aXJlZCBmb3Igc3VjaCBhY2NvdW50cy4nLFxuICAgICAgbGV2ZWw6IE5hZ01lc3NhZ2VMZXZlbC5FUlJPUixcbiAgICAgIHJ1bGU6IFJlZHNoaWZ0Q2x1c3RlclB1YmxpY0FjY2VzcyxcbiAgICAgIG5vZGU6IG5vZGUsXG4gICAgfSk7XG4gICAgdGhpcy5hcHBseVJ1bGUoe1xuICAgICAgaW5mbzogJ1RoZSBSZWRzaGlmdCBjbHVzdGVyIGRvZXMgbm90IGhhdmUgZW5oYW5jZWQgVlBDIHJvdXRpbmcgZW5hYmxlZCAtIChDb250cm9sIElEczogMS4yLCAxLjMsIDEuMy4xLCAxLjMuMikuJyxcbiAgICAgIGV4cGxhbmF0aW9uOlxuICAgICAgICAnRW5oYW5jZWQgVlBDIHJvdXRpbmcgZm9yY2VzIGFsbCBDT1BZIGFuZCBVTkxPQUQgdHJhZmZpYyBiZXR3ZWVuIHRoZSBjbHVzdGVyIGFuZCBkYXRhIHJlcG9zaXRvcmllcyB0byBnbyB0aHJvdWdoIHlvdXIgQW1hem9uIFZQQy4gWW91IGNhbiB0aGVuIHVzZSBWUEMgZmVhdHVyZXMgc3VjaCBhcyBzZWN1cml0eSBncm91cHMgYW5kIG5ldHdvcmsgYWNjZXNzIGNvbnRyb2wgbGlzdHMgdG8gc2VjdXJlIG5ldHdvcmsgdHJhZmZpYy4gWW91IGNhbiBhbHNvIHVzZSBWUEMgZmxvdyBsb2dzIHRvIG1vbml0b3IgbmV0d29yayB0cmFmZmljLicsXG4gICAgICBsZXZlbDogTmFnTWVzc2FnZUxldmVsLkVSUk9SLFxuICAgICAgcnVsZTogUmVkc2hpZnRFbmhhbmNlZFZQQ1JvdXRpbmdFbmFibGVkLFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcbiAgICB0aGlzLmFwcGx5UnVsZSh7XG4gICAgICBpbmZvOiAnVGhlIFJlZHNoaWZ0IGNsdXN0ZXIgZG9lcyBub3QgcmVxdWlyZSBUTFMvU1NMIGVuY3J5cHRpb24gLSAoQ29udHJvbCBJRHM6IDIuMyzCoDQuMSkuJyxcbiAgICAgIGV4cGxhbmF0aW9uOlxuICAgICAgICAnRW5zdXJlIHRoYXQgeW91ciBBbWF6b24gUmVkc2hpZnQgY2x1c3RlcnMgcmVxdWlyZSBUTFMvU1NMIGVuY3J5cHRpb24gdG8gY29ubmVjdCB0byBTUUwgY2xpZW50cy4gQmVjYXVzZSBzZW5zaXRpdmUgZGF0YSBjYW4gZXhpc3QsIGVuYWJsZSBlbmNyeXB0aW9uIGluIHRyYW5zaXQgdG8gaGVscCBwcm90ZWN0IHRoYXQgZGF0YS4nLFxuICAgICAgbGV2ZWw6IE5hZ01lc3NhZ2VMZXZlbC5FUlJPUixcbiAgICAgIHJ1bGU6IFJlZHNoaWZ0UmVxdWlyZVRsc1NTTCxcbiAgICAgIG5vZGU6IG5vZGUsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgQW1hem9uIFMzIFJlc291cmNlc1xuICAgKiBAcGFyYW0gbm9kZSB0aGUgQ2ZuUmVzb3VyY2UgdG8gY2hlY2tcbiAgICogQHBhcmFtIGlnbm9yZXMgbGlzdCBvZiBpZ25vcmVzIGZvciB0aGUgcmVzb3VyY2VcbiAgICovXG4gIHByaXZhdGUgY2hlY2tTMyhub2RlOiBDZm5SZXNvdXJjZSk6IHZvaWQge1xuICAgIHRoaXMuYXBwbHlSdWxlKHtcbiAgICAgIGluZm86ICdUaGUgUzMgYnVja2V0IGRvZXMgbm90IHByb2hpYml0IHB1YmxpYyBhY2Nlc3MgdGhyb3VnaCBidWNrZXQgbGV2ZWwgc2V0dGluZ3MgLSAoQ29udHJvbCBJRHM6IDEuMiwgMS4yLjEsIDEuMywgMS4zLjEsIDEuMy4yLCAxLjMuNCwgMS4zLjYsIDIuMi4yKS4nLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgICdLZWVwIHNlbnNpdGl2ZSBkYXRhIHNhZmUgZnJvbSB1bmF1dGhvcml6ZWQgcmVtb3RlIHVzZXJzIGJ5IHByZXZlbnRpbmcgcHVibGljIGFjY2VzcyBhdCB0aGUgYnVja2V0IGxldmVsLicsXG4gICAgICBsZXZlbDogTmFnTWVzc2FnZUxldmVsLkVSUk9SLFxuICAgICAgcnVsZTogUzNCdWNrZXRMZXZlbFB1YmxpY0FjY2Vzc1Byb2hpYml0ZWQsXG4gICAgICBub2RlOiBub2RlLFxuICAgIH0pO1xuICAgIHRoaXMuYXBwbHlSdWxlKHtcbiAgICAgIGluZm86ICdUaGUgUzMgQnVja2V0cyBkb2VzIG5vdCBoYXZlIHNlcnZlciBhY2Nlc3MgbG9ncyBlbmFibGVkIC0gKENvbnRyb2wgSURzOiAyLjIsIDEwLjEsIDEwLjIuMSwgMTAuMi4yLCAxMC4yLjMsIDEwLjIuNCwgMTAuMi41LCAxMC4yLjcsIDEwLjMuMSwgMTAuMy4yLCAxMC4zLjMsIDEwLjMuNCwgMTAuMy41LCAxMC4zLjYpLicsXG4gICAgICBleHBsYW5hdGlvbjpcbiAgICAgICAgJ0FtYXpvbiBTaW1wbGUgU3RvcmFnZSBTZXJ2aWNlIChBbWF6b24gUzMpIHNlcnZlciBhY2Nlc3MgbG9nZ2luZyBwcm92aWRlcyBhIG1ldGhvZCB0byBtb25pdG9yIHRoZSBuZXR3b3JrIGZvciBwb3RlbnRpYWwgY3liZXJzZWN1cml0eSBldmVudHMuIFRoZSBldmVudHMgYXJlIG1vbml0b3JlZCBieSBjYXB0dXJpbmcgZGV0YWlsZWQgcmVjb3JkcyBmb3IgdGhlIHJlcXVlc3RzIHRoYXQgYXJlIG1hZGUgdG8gYW4gQW1hem9uIFMzIGJ1Y2tldC4gRWFjaCBhY2Nlc3MgbG9nIHJlY29yZCBwcm92aWRlcyBkZXRhaWxzIGFib3V0IGEgc2luZ2xlIGFjY2VzcyByZXF1ZXN0LiBUaGUgZGV0YWlscyBpbmNsdWRlIHRoZSByZXF1ZXN0ZXIsIGJ1Y2tldCBuYW1lLCByZXF1ZXN0IHRpbWUsIHJlcXVlc3QgYWN0aW9uLCByZXNwb25zZSBzdGF0dXMsIGFuZCBhbiBlcnJvciBjb2RlLCBpZiByZWxldmFudC4nLFxuICAgICAgbGV2ZWw6IE5hZ01lc3NhZ2VMZXZlbC5FUlJPUixcbiAgICAgIHJ1bGU6IFMzQnVja2V0TG9nZ2luZ0VuYWJsZWQsXG4gICAgICBub2RlOiBub2RlLFxuICAgIH0pO1xuICAgIHRoaXMuYXBwbHlSdWxlKHtcbiAgICAgIGluZm86ICdUaGUgUzMgQnVja2V0IGRvZXMgbm90IHByb2hpYml0IHB1YmxpYyByZWFkIGFjY2VzcyB0aHJvdWdoIGl0cyBCbG9jayBQdWJsaWMgQWNjZXNzIGNvbmZpZ3VyYXRpb25zIGFuZCBidWNrZXQgQUNMcyAtIChDb250cm9sIElEczogMS4yLCAxLjIuMSwgMS4zLCAxLjMuMSwgMS4zLjIsIDEuMy40LCAxLjMuNiwgMi4yLCAyLjIuMikuJyxcbiAgICAgIGV4cGxhbmF0aW9uOlxuICAgICAgICAnVGhlIG1hbmFnZW1lbnQgb2YgYWNjZXNzIHNob3VsZCBiZSBjb25zaXN0ZW50IHdpdGggdGhlIGNsYXNzaWZpY2F0aW9uIG9mIHRoZSBkYXRhLicsXG4gICAgICBsZXZlbDogTmFnTWVzc2FnZUxldmVsLkVSUk9SLFxuICAgICAgcnVsZTogUzNCdWNrZXRQdWJsaWNSZWFkUHJvaGliaXRlZCxcbiAgICAgIG5vZGU6IG5vZGUsXG4gICAgfSk7XG4gICAgdGhpcy5hcHBseVJ1bGUoe1xuICAgICAgaW5mbzogJ1RoZSBTMyBCdWNrZXQgZG9lcyBub3QgcHJvaGliaXQgcHVibGljIHdyaXRlIGFjY2VzcyB0aHJvdWdoIGl0cyBCbG9jayBQdWJsaWMgQWNjZXNzIGNvbmZpZ3VyYXRpb25zIGFuZCBidWNrZXQgQUNMcyAtIChDb250cm9sIElEczogMS4yLCAxLjIuMSwgMS4zLCAxLjMuMSwgMS4zLjIsIDEuMy40LCAxLjMuNiwgMi4yLCAyLjIuMikuJyxcbiAgICAgIGV4cGxhbmF0aW9uOlxuICAgICAgICAnVGhlIG1hbmFnZW1lbnQgb2YgYWNjZXNzIHNob3VsZCBiZSBjb25zaXN0ZW50IHdpdGggdGhlIGNsYXNzaWZpY2F0aW9uIG9mIHRoZSBkYXRhLicsXG4gICAgICBsZXZlbDogTmFnTWVzc2FnZUxldmVsLkVSUk9SLFxuICAgICAgcnVsZTogUzNCdWNrZXRQdWJsaWNXcml0ZVByb2hpYml0ZWQsXG4gICAgICBub2RlOiBub2RlLFxuICAgIH0pO1xuICAgIHRoaXMuYXBwbHlSdWxlKHtcbiAgICAgIGluZm86ICdUaGUgUzMgQnVja2V0IGRvZXMgbm90IGhhdmUgcmVwbGljYXRpb24gZW5hYmxlZCAtIChDb250cm9sIElEczogMi4yLCAxMC41LjMpLicsXG4gICAgICBleHBsYW5hdGlvbjpcbiAgICAgICAgJ0FtYXpvbiBTaW1wbGUgU3RvcmFnZSBTZXJ2aWNlIChBbWF6b24gUzMpIENyb3NzLVJlZ2lvbiBSZXBsaWNhdGlvbiAoQ1JSKSBzdXBwb3J0cyBtYWludGFpbmluZyBhZGVxdWF0ZSBjYXBhY2l0eSBhbmQgYXZhaWxhYmlsaXR5LiBDUlIgZW5hYmxlcyBhdXRvbWF0aWMsIGFzeW5jaHJvbm91cyBjb3B5aW5nIG9mIG9iamVjdHMgYWNyb3NzIEFtYXpvbiBTMyBidWNrZXRzIHRvIGhlbHAgZW5zdXJlIHRoYXQgZGF0YSBhdmFpbGFiaWxpdHkgaXMgbWFpbnRhaW5lZC4nLFxuICAgICAgbGV2ZWw6IE5hZ01lc3NhZ2VMZXZlbC5FUlJPUixcbiAgICAgIHJ1bGU6IFMzQnVja2V0UmVwbGljYXRpb25FbmFibGVkLFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcbiAgICB0aGlzLmFwcGx5UnVsZSh7XG4gICAgICBpbmZvOiAnVGhlIFMzIEJ1Y2tldCBvciBidWNrZXQgcG9saWN5IGRvZXMgbm90IHJlcXVpcmUgcmVxdWVzdHMgdG8gdXNlIFNTTCAtIChDb250cm9sIElEczogMi4yLCA0LjEsIDguMi4xKS4nLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgICdUbyBoZWxwIHByb3RlY3QgZGF0YSBpbiB0cmFuc2l0LCBlbnN1cmUgdGhhdCB5b3VyIEFtYXpvbiBTaW1wbGUgU3RvcmFnZSBTZXJ2aWNlIChBbWF6b24gUzMpIGJ1Y2tldHMgcmVxdWlyZSByZXF1ZXN0cyB0byB1c2UgU2VjdXJlIFNvY2tldCBMYXllciAoU1NMKS4gQmVjYXVzZSBzZW5zaXRpdmUgZGF0YSBjYW4gZXhpc3QsIGVuYWJsZSBlbmNyeXB0aW9uIGluIHRyYW5zaXQgdG8gaGVscCBwcm90ZWN0IHRoYXQgZGF0YS4nLFxuICAgICAgbGV2ZWw6IE5hZ01lc3NhZ2VMZXZlbC5FUlJPUixcbiAgICAgIHJ1bGU6IFMzQnVja2V0U1NMUmVxdWVzdHNPbmx5LFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcbiAgICB0aGlzLmFwcGx5UnVsZSh7XG4gICAgICBpbmZvOiAnVGhlIFMzIEJ1Y2tldCBkb2VzIG5vdCBoYXZlIHZlcnNpb25pbmcgZW5hYmxlZCAtIChDb250cm9sIElEOiAxMC41LjMpLicsXG4gICAgICBleHBsYW5hdGlvbjpcbiAgICAgICAgJ1VzZSB2ZXJzaW9uaW5nIHRvIHByZXNlcnZlLCByZXRyaWV2ZSwgYW5kIHJlc3RvcmUgZXZlcnkgdmVyc2lvbiBvZiBldmVyeSBvYmplY3Qgc3RvcmVkIGluIHlvdXIgQW1hem9uIFMzIGJ1Y2tldC4gVmVyc2lvbmluZyBoZWxwcyB5b3UgdG8gZWFzaWx5IHJlY292ZXIgZnJvbSB1bmludGVuZGVkIHVzZXIgYWN0aW9ucyBhbmQgYXBwbGljYXRpb24gZmFpbHVyZXMuJyxcbiAgICAgIGxldmVsOiBOYWdNZXNzYWdlTGV2ZWwuRVJST1IsXG4gICAgICBydWxlOiBTM0J1Y2tldFZlcnNpb25pbmdFbmFibGVkLFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcbiAgICB0aGlzLmFwcGx5UnVsZSh7XG4gICAgICBpbmZvOiAnVGhlIFMzIEJ1Y2tldCBpcyBub3QgZW5jcnlwdGVkIHdpdGggYSBLTVMgS2V5IGJ5IGRlZmF1bHQgLSAoQ29udHJvbCBJRHM6IDMuNCwgOC4yLjEsIDEwLjUpLicsXG4gICAgICBleHBsYW5hdGlvbjpcbiAgICAgICAgJ0Vuc3VyZSB0aGF0IGVuY3J5cHRpb24gaXMgZW5hYmxlZCBmb3IgeW91ciBBbWF6b24gU2ltcGxlIFN0b3JhZ2UgU2VydmljZSAoQW1hem9uIFMzKSBidWNrZXRzLiBCZWNhdXNlIHNlbnNpdGl2ZSBkYXRhIGNhbiBleGlzdCBhdCByZXN0IGluIGFuIEFtYXpvbiBTMyBidWNrZXQsIGVuYWJsZSBlbmNyeXB0aW9uIGF0IHJlc3QgdG8gaGVscCBwcm90ZWN0IHRoYXQgZGF0YS4nLFxuICAgICAgbGV2ZWw6IE5hZ01lc3NhZ2VMZXZlbC5FUlJPUixcbiAgICAgIHJ1bGU6IFMzRGVmYXVsdEVuY3J5cHRpb25LTVMsXG4gICAgICBub2RlOiBub2RlLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIFNhZ2VNYWtlciBSZXNvdXJjZXNcbiAgICogQHBhcmFtIG5vZGUgdGhlIENmblJlc291cmNlIHRvIGNoZWNrXG4gICAqIEBwYXJhbSBpZ25vcmVzIGxpc3Qgb2YgaWdub3JlcyBmb3IgdGhlIHJlc291cmNlXG4gICAqL1xuICBwcml2YXRlIGNoZWNrU2FnZU1ha2VyKG5vZGU6IENmblJlc291cmNlKSB7XG4gICAgdGhpcy5hcHBseVJ1bGUoe1xuICAgICAgaW5mbzogJ1RoZSBTYWdlTWFrZXIgcmVzb3VyY2UgZW5kcG9pbnQgaXMgbm90IGVuY3J5cHRlZCB3aXRoIGEgS01TIGtleSAtIChDb250cm9sIElEczogMy40LCA4LjIuMSkuJyxcbiAgICAgIGV4cGxhbmF0aW9uOlxuICAgICAgICAnQmVjYXVzZSBzZW5zaXRpdmUgZGF0YSBjYW4gZXhpc3QgYXQgcmVzdCBpbiBTYWdlTWFrZXIgZW5kcG9pbnQsIGVuYWJsZSBlbmNyeXB0aW9uIGF0IHJlc3QgdG8gaGVscCBwcm90ZWN0IHRoYXQgZGF0YS4nLFxuICAgICAgbGV2ZWw6IE5hZ01lc3NhZ2VMZXZlbC5FUlJPUixcbiAgICAgIHJ1bGU6IFNhZ2VNYWtlckVuZHBvaW50Q29uZmlndXJhdGlvbktNU0tleUNvbmZpZ3VyZWQsXG4gICAgICBub2RlOiBub2RlLFxuICAgIH0pO1xuICAgIHRoaXMuYXBwbHlSdWxlKHtcbiAgICAgIGluZm86ICdUaGUgU2FnZU1ha2VyIG5vdGVib29rIGlzIG5vdCBlbmNyeXB0ZWQgd2l0aCBhIEtNUyBrZXkgLSAoQ29udHJvbCBJRHM6IDMuNCwgOC4yLjEpLicsXG4gICAgICBleHBsYW5hdGlvbjpcbiAgICAgICAgJ0JlY2F1c2Ugc2Vuc2l0aXZlIGRhdGEgY2FuIGV4aXN0IGF0IHJlc3QgaW4gU2FnZU1ha2VyIG5vdGVib29rLCBlbmFibGUgZW5jcnlwdGlvbiBhdCByZXN0IHRvIGhlbHAgcHJvdGVjdCB0aGF0IGRhdGEuJyxcbiAgICAgIGxldmVsOiBOYWdNZXNzYWdlTGV2ZWwuRVJST1IsXG4gICAgICBydWxlOiBTYWdlTWFrZXJOb3RlYm9va0luc3RhbmNlS01TS2V5Q29uZmlndXJlZCxcbiAgICAgIG5vZGU6IG5vZGUsXG4gICAgfSk7XG4gICAgdGhpcy5hcHBseVJ1bGUoe1xuICAgICAgaW5mbzogJ1RoZSBTYWdlTWFrZXIgbm90ZWJvb2sgZG9lcyBub3QgZGlzYWJsZSBkaXJlY3QgaW50ZXJuZXQgYWNjZXNzIC0gKENvbnRyb2wgSURzOiAxLjIsIDEuMi4xLCAxLjMsIDEuMy4xLCAxLjMuMiwgMS4zLjQsIDEuMy42LCAyLjIuMikuJyxcbiAgICAgIGV4cGxhbmF0aW9uOlxuICAgICAgICAnQnkgcHJldmVudGluZyBkaXJlY3QgaW50ZXJuZXQgYWNjZXNzLCB5b3UgY2FuIGtlZXAgc2Vuc2l0aXZlIGRhdGEgZnJvbSBiZWluZyBhY2Nlc3NlZCBieSB1bmF1dGhvcml6ZWQgdXNlcnMuJyxcbiAgICAgIGxldmVsOiBOYWdNZXNzYWdlTGV2ZWwuRVJST1IsXG4gICAgICBydWxlOiBTYWdlTWFrZXJOb3RlYm9va05vRGlyZWN0SW50ZXJuZXRBY2Nlc3MsXG4gICAgICBub2RlOiBub2RlLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIFNlY3JldHMgTWFuYWdlciBSZXNvdXJjZXNcbiAgICogQHBhcmFtIG5vZGUgdGhlIENmblJlc291cmNlIHRvIGNoZWNrXG4gICAqIEBwYXJhbSBpZ25vcmVzIGxpc3Qgb2YgaWdub3JlcyBmb3IgdGhlIHJlc291cmNlXG4gICAqL1xuICBwcml2YXRlIGNoZWNrU2VjcmV0c01hbmFnZXIobm9kZTogQ2ZuUmVzb3VyY2UpOiB2b2lkIHtcbiAgICB0aGlzLmFwcGx5UnVsZSh7XG4gICAgICBpbmZvOiAnVGhlIHNlY3JldCBpcyBub3QgZW5jcnlwdGVkIHdpdGggYSBLTVMgQ3VzdG9tZXIgbWFuYWdlZCBrZXkgLSAoQ29udHJvbCBJRHM6IDMuNCwgOC4yLjEpLicsXG4gICAgICBleHBsYW5hdGlvbjpcbiAgICAgICAgJ1RvIGhlbHAgcHJvdGVjdCBkYXRhIGF0IHJlc3QsIGVuc3VyZSBlbmNyeXB0aW9uIHdpdGggQVdTIEtleSBNYW5hZ2VtZW50IFNlcnZpY2UgKEFXUyBLTVMpIGlzIGVuYWJsZWQgZm9yIEFXUyBTZWNyZXRzIE1hbmFnZXIgc2VjcmV0cy4gQmVjYXVzZSBzZW5zaXRpdmUgZGF0YSBjYW4gZXhpc3QgYXQgcmVzdCBpbiBTZWNyZXRzIE1hbmFnZXIgc2VjcmV0cywgZW5hYmxlIGVuY3J5cHRpb24gYXQgcmVzdCB0byBoZWxwIHByb3RlY3QgdGhhdCBkYXRhLicsXG4gICAgICBsZXZlbDogTmFnTWVzc2FnZUxldmVsLkVSUk9SLFxuICAgICAgcnVsZTogU2VjcmV0c01hbmFnZXJVc2luZ0tNU0tleSxcbiAgICAgIG5vZGU6IG5vZGUsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgQW1hem9uIFNOUyBSZXNvdXJjZXNcbiAgICogQHBhcmFtIG5vZGUgdGhlIENmblJlc291cmNlIHRvIGNoZWNrXG4gICAqIEBwYXJhbSBpZ25vcmVzIGxpc3Qgb2YgaWdub3JlcyBmb3IgdGhlIHJlc291cmNlXG4gICAqL1xuICBwcml2YXRlIGNoZWNrU05TKG5vZGU6IENmblJlc291cmNlKTogdm9pZCB7XG4gICAgdGhpcy5hcHBseVJ1bGUoe1xuICAgICAgaW5mbzogJ1RoZSBTTlMgdG9waWMgZG9lcyBub3QgaGF2ZSBLTVMgZW5jcnlwdGlvbiBlbmFibGVkIC0gKENvbnRyb2wgSUQ6IDguMi4xKS4nLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgICdUbyBoZWxwIHByb3RlY3QgZGF0YSBhdCByZXN0LCBlbnN1cmUgdGhhdCB5b3VyIEFtYXpvbiBTaW1wbGUgTm90aWZpY2F0aW9uIFNlcnZpY2UgKEFtYXpvbiBTTlMpIHRvcGljcyByZXF1aXJlIGVuY3J5cHRpb24gdXNpbmcgQVdTIEtleSBNYW5hZ2VtZW50IFNlcnZpY2UgKEFXUyBLTVMpIEJlY2F1c2Ugc2Vuc2l0aXZlIGRhdGEgY2FuIGV4aXN0IGF0IHJlc3QgaW4gcHVibGlzaGVkIG1lc3NhZ2VzLCBlbmFibGUgZW5jcnlwdGlvbiBhdCByZXN0IHRvIGhlbHAgcHJvdGVjdCB0aGF0IGRhdGEuJyxcbiAgICAgIGxldmVsOiBOYWdNZXNzYWdlTGV2ZWwuRVJST1IsXG4gICAgICBydWxlOiBTTlNFbmNyeXB0ZWRLTVMsXG4gICAgICBub2RlOiBub2RlLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIFZQQyBSZXNvdXJjZXNcbiAgICogQHBhcmFtIG5vZGUgdGhlIENmblJlc291cmNlIHRvIGNoZWNrXG4gICAqIEBwYXJhbSBpZ25vcmVzIGxpc3Qgb2YgaWdub3JlcyBmb3IgdGhlIHJlc291cmNlXG4gICAqL1xuICBwcml2YXRlIGNoZWNrVlBDKG5vZGU6IENmblJlc291cmNlKTogdm9pZCB7XG4gICAgdGhpcy5hcHBseVJ1bGUoe1xuICAgICAgaW5mbzogXCJUaGUgVlBDJ3MgZGVmYXVsdCBzZWN1cml0eSBncm91cCBhbGxvd3MgaW5ib3VuZCBvciBvdXRib3VuZCB0cmFmZmljIC0gKENvbnRyb2wgSURzOiAxLjIsIDEuMi4xLCAxLjMsIDEuMy4xLCAxLjMuMiwgMi4xLCAyLjIsIDIuMi4yKS5cIixcbiAgICAgIGV4cGxhbmF0aW9uOlxuICAgICAgICAnQW1hem9uIEVsYXN0aWMgQ29tcHV0ZSBDbG91ZCAoQW1hem9uIEVDMikgc2VjdXJpdHkgZ3JvdXBzIGNhbiBoZWxwIGluIHRoZSBtYW5hZ2VtZW50IG9mIG5ldHdvcmsgYWNjZXNzIGJ5IHByb3ZpZGluZyBzdGF0ZWZ1bCBmaWx0ZXJpbmcgb2YgaW5ncmVzcyBhbmQgZWdyZXNzIG5ldHdvcmsgdHJhZmZpYyB0byBBV1MgcmVzb3VyY2VzLiBSZXN0cmljdGluZyBhbGwgdGhlIHRyYWZmaWMgb24gdGhlIGRlZmF1bHQgc2VjdXJpdHkgZ3JvdXAgaGVscHMgaW4gcmVzdHJpY3RpbmcgcmVtb3RlIGFjY2VzcyB0byB5b3VyIEFXUyByZXNvdXJjZXMuJyxcbiAgICAgIGxldmVsOiBOYWdNZXNzYWdlTGV2ZWwuV0FSTixcbiAgICAgIHJ1bGU6IFZQQ0RlZmF1bHRTZWN1cml0eUdyb3VwQ2xvc2VkLFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcbiAgICB0aGlzLmFwcGx5UnVsZSh7XG4gICAgICBpbmZvOiAnVGhlIFZQQyBkb2VzIG5vdCBoYXZlIGFuIGFzc29jaWF0ZWQgRmxvdyBMb2cgLSAoQ29udHJvbCBJRHM6IDIuMiwgMTAuMSwgMTAuMy4yLCAxMC4zLjMsIDEwLjMuNCwgMTAuMy41LCAxMC4zLjYpLicsXG4gICAgICBleHBsYW5hdGlvbjpcbiAgICAgICAgJ1RoZSBWUEMgZmxvdyBsb2dzIHByb3ZpZGUgZGV0YWlsZWQgcmVjb3JkcyBmb3IgaW5mb3JtYXRpb24gYWJvdXQgdGhlIElQIHRyYWZmaWMgZ29pbmcgdG8gYW5kIGZyb20gbmV0d29yayBpbnRlcmZhY2VzIGluIHlvdXIgQW1hem9uIFZpcnR1YWwgUHJpdmF0ZSBDbG91ZCAoQW1hem9uIFZQQykuIEJ5IGRlZmF1bHQsIHRoZSBmbG93IGxvZyByZWNvcmQgaW5jbHVkZXMgdmFsdWVzIGZvciB0aGUgZGlmZmVyZW50IGNvbXBvbmVudHMgb2YgdGhlIElQIGZsb3csIGluY2x1ZGluZyB0aGUgc291cmNlLCBkZXN0aW5hdGlvbiwgYW5kIHByb3RvY29sLicsXG4gICAgICBsZXZlbDogTmFnTWVzc2FnZUxldmVsLkVSUk9SLFxuICAgICAgcnVsZTogVlBDRmxvd0xvZ3NFbmFibGVkLFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcbiAgICB0aGlzLmFwcGx5UnVsZSh7XG4gICAgICBpbmZvOiBcIlRoZSByb3V0ZSB0YWJsZSBtYXkgY29udGFpbiBvbmUgb3IgbW9yZSB1bnJlc3RyaWN0ZWQgcm91dGUocykgdG8gYW4gSUdXICgnMC4wLjAuMC8wJyBvciAnOjovMCcpIC0gKENvbnRyb2wgSURzOiAxLjIsIDEuMi4xLCAxLjMsIDEuMy4xLCAxLjMuMiwgMi4yLjIpLlwiLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgICdFbnN1cmUgQW1hem9uIEVDMiByb3V0ZSB0YWJsZXMgZG8gbm90IGhhdmUgdW5yZXN0cmljdGVkIHJvdXRlcyB0byBhbiBpbnRlcm5ldCBnYXRld2F5LiBSZW1vdmluZyBvciBsaW1pdGluZyB0aGUgYWNjZXNzIHRvIHRoZSBpbnRlcm5ldCBmb3Igd29ya2xvYWRzIHdpdGhpbiBBbWF6b24gVlBDcyBjYW4gcmVkdWNlIHVuaW50ZW5kZWQgYWNjZXNzIHdpdGhpbiB5b3VyIGVudmlyb25tZW50LicsXG4gICAgICBsZXZlbDogTmFnTWVzc2FnZUxldmVsLkVSUk9SLFxuICAgICAgcnVsZTogVlBDTm9VbnJlc3RyaWN0ZWRSb3V0ZVRvSUdXLFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcbiAgICB0aGlzLmFwcGx5UnVsZSh7XG4gICAgICBpbmZvOiAnVGhlIHN1Ym5ldCBhdXRvLWFzc2lnbnMgcHVibGljIElQIGFkZHJlc3NlcyAtIChDb250cm9sIElEczogMS4yLCAxLjIuMSwgMS4zLCAxLjMuMSwgMS4zLjIsIDEuMy40LCAxLjMuNiwgMi4yLjIpLicsXG4gICAgICBleHBsYW5hdGlvbjpcbiAgICAgICAgJ01hbmFnZSBhY2Nlc3MgdG8gdGhlIEFXUyBDbG91ZCBieSBlbnN1cmluZyBBbWF6b24gVmlydHVhbCBQcml2YXRlIENsb3VkIChWUEMpIHN1Ym5ldHMgYXJlIG5vdCBhdXRvbWF0aWNhbGx5IGFzc2lnbmVkIGEgcHVibGljIElQIGFkZHJlc3MuIEFtYXpvbiBFbGFzdGljIENvbXB1dGUgQ2xvdWQgKEVDMikgaW5zdGFuY2VzIHRoYXQgYXJlIGxhdW5jaGVkIGludG8gc3VibmV0cyB0aGF0IGhhdmUgdGhpcyBhdHRyaWJ1dGUgZW5hYmxlZCBoYXZlIGEgcHVibGljIElQIGFkZHJlc3MgYXNzaWduZWQgdG8gdGhlaXIgcHJpbWFyeSBuZXR3b3JrIGludGVyZmFjZS4nLFxuICAgICAgbGV2ZWw6IE5hZ01lc3NhZ2VMZXZlbC5FUlJPUixcbiAgICAgIHJ1bGU6IFZQQ1N1Ym5ldEF1dG9Bc3NpZ25QdWJsaWNJcERpc2FibGVkLFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBXQUYgUmVzb3VyY2VzXG4gICAqIEBwYXJhbSBub2RlIHRoZSBDZm5SZXNvdXJjZSB0byBjaGVja1xuICAgKiBAcGFyYW0gaWdub3JlcyBsaXN0IG9mIGlnbm9yZXMgZm9yIHRoZSByZXNvdXJjZVxuICAgKi9cbiAgcHJpdmF0ZSBjaGVja1dBRihub2RlOiBDZm5SZXNvdXJjZSk6IHZvaWQge1xuICAgIHRoaXMuYXBwbHlSdWxlKHtcbiAgICAgIGluZm86ICdUaGUgV0FGdjIgd2ViIEFDTCBkb2VzIG5vdCBoYXZlIGxvZ2dpbmcgZW5hYmxlZCAtIChDb250cm9sIElEczogMTAuMSzCoDEwLjMuMSzCoDEwLjMuMizCoDEwLjMuMyzCoDEwLjMuNCzCoDEwLjMuNSzCoDEwLjMuNizCoDEwLjUuNCkuJyxcbiAgICAgIGV4cGxhbmF0aW9uOlxuICAgICAgICAnQVdTIFdBRiBsb2dnaW5nIHByb3ZpZGVzIGRldGFpbGVkIGluZm9ybWF0aW9uIGFib3V0IHRoZSB0cmFmZmljIHRoYXQgaXMgYW5hbHl6ZWQgYnkgeW91ciB3ZWIgQUNMLiBUaGUgbG9ncyByZWNvcmQgdGhlIHRpbWUgdGhhdCBBV1MgV0FGIHJlY2VpdmVkIHRoZSByZXF1ZXN0IGZyb20geW91ciBBV1MgcmVzb3VyY2UsIGluZm9ybWF0aW9uIGFib3V0IHRoZSByZXF1ZXN0LCBhbmQgYW4gYWN0aW9uIGZvciB0aGUgcnVsZSB0aGF0IGVhY2ggcmVxdWVzdCBtYXRjaGVkLicsXG4gICAgICBsZXZlbDogTmFnTWVzc2FnZUxldmVsLkVSUk9SLFxuICAgICAgcnVsZTogV0FGdjJMb2dnaW5nRW5hYmxlZCxcbiAgICAgIG5vZGU6IG5vZGUsXG4gICAgfSk7XG4gIH1cbn1cbiJdfQ==
@@ -61,7 +61,7 @@
61
61
  "jsii-pacmak": "^1.106.0",
62
62
  "jsii-rosetta": "~5.6.0",
63
63
  "prettier": "^2.8.8",
64
- "projen": "^0.91.7",
64
+ "projen": "^0.91.8",
65
65
  "ts-jest": "^27",
66
66
  "typescript": "^4.9.5"
67
67
  },
@@ -77,7 +77,7 @@
77
77
  "publishConfig": {
78
78
  "access": "public"
79
79
  },
80
- "version": "2.35.8",
80
+ "version": "2.35.13",
81
81
  "jest": {
82
82
  "coverageProvider": "v8",
83
83
  "testMatch": [
package/package.json CHANGED
@@ -19,31 +19,30 @@
19
19
  "package-all": "npx projen package-all",
20
20
  "package:js": "npx projen package:js",
21
21
  "post-compile": "npx projen post-compile",
22
- "post-upgrade": "npx projen post-upgrade",
23
22
  "pre-compile": "npx projen pre-compile",
24
23
  "release": "npx projen release",
25
24
  "test": "npx projen test",
26
25
  "test:watch": "npx projen test:watch",
27
26
  "unbump": "npx projen unbump",
28
- "upgrade": "npx projen upgrade",
29
27
  "watch": "npx projen watch",
30
28
  "projen": "npx projen",
29
+ "prepare": "husky install",
30
+ "awslint": "awslint",
31
+ "integ-test": "integ-runner --directory ./integ-tests --parallel-regions eu-west-2 --parallel-regions eu-west-1 --update-on-failed",
31
32
  "synth": "npx cdk synth -q",
32
33
  "publish-assets": "npx ts-node -P tsconfig.json --prefer-ts-exts src/scripts/publish-assets.ts",
33
- "prepare": "husky install",
34
- "prepare-integ-test": "rm -rf cdk.out && npx cdk synth -q",
35
- "integ-test": "integ-runner --directory ./integ-tests --parallel-regions eu-west-2 --parallel-regions eu-west-1 --update-on-failed"
34
+ "prepare-integ-test": "rm -rf cdk.out && npx cdk synth -q"
36
35
  },
37
36
  "author": {
38
37
  "name": "Manuel Vogel",
39
- "email": "mavogel@posteo.de",
40
- "organization": false
38
+ "email": "8409778+mavogel@users.noreply.github.com",
39
+ "organization": true
41
40
  },
42
41
  "devDependencies": {
43
- "@aws-cdk/integ-runner": "^2.90.0-alpha.0",
44
- "@aws-cdk/integ-tests-alpha": "^2.90.0-alpha.0",
45
- "@commitlint/cli": "^17.8.1",
46
- "@commitlint/config-conventional": "^17.8.1",
42
+ "@aws-cdk/integ-runner": "^2.177.0-alpha.0",
43
+ "@aws-cdk/integ-tests-alpha": "^2.177.0-alpha.0",
44
+ "@commitlint/cli": "^19.6.1",
45
+ "@commitlint/config-conventional": "^19.6.0",
47
46
  "@stylistic/eslint-plugin": "^2",
48
47
  "@types/async-retry": "^1.4.9",
49
48
  "@types/aws-lambda": "^8.10.147",
@@ -51,25 +50,25 @@
51
50
  "@types/jest": "^29.5.14",
52
51
  "@types/jsonfile": "^6.1.4",
53
52
  "@types/mailparser": "^3.4.5",
54
- "@types/node": "^18",
53
+ "@types/node": "^20",
55
54
  "@types/uuid": "^9.0.8",
56
55
  "@typescript-eslint/eslint-plugin": "^8",
57
56
  "@typescript-eslint/parser": "^8",
58
- "aws-cdk-lib": "2.90.0",
59
- "cdk-assets": "^2.155.104",
57
+ "aws-cdk-lib": "2.177.0",
58
+ "awslint": "^2.72.1",
59
+ "cdk-assets": "^2.155.105",
60
60
  "commit-and-tag-version": "^12",
61
- "constructs": "10.0.5",
62
61
  "eslint": "^9",
63
62
  "eslint-import-resolver-typescript": "^3.7.0",
64
63
  "eslint-plugin-import": "^2.31.0",
65
- "husky": "^8.0.3",
64
+ "husky": "^9.1.7",
66
65
  "jest": "^29.7.0",
67
66
  "jest-junit": "^16",
68
- "jsii": "~5.5.0",
67
+ "jsii": "~5.7.0",
69
68
  "jsii-diff": "^1.106.0",
70
69
  "jsii-docgen": "^10.5.0",
71
70
  "jsii-pacmak": "^1.106.0",
72
- "jsii-rosetta": "~5.5.0",
71
+ "jsii-rosetta": "~5.7.0",
73
72
  "jsonfile": "^6.1.0",
74
73
  "projen": "^0.91.7",
75
74
  "ts-jest": "^29.2.5",
@@ -77,18 +76,20 @@
77
76
  "typescript": "^5.7.3"
78
77
  },
79
78
  "peerDependencies": {
80
- "aws-cdk-lib": "^2.90.0",
79
+ "aws-cdk-lib": "^2.177.0",
81
80
  "constructs": "^10.0.5"
82
81
  },
83
82
  "dependencies": {
84
- "@aws-sdk/client-cloudwatch-logs": "^3.738.0",
85
- "@aws-sdk/client-route-53": "^3.738.0",
86
- "@aws-sdk/client-s3": "^3.740.0",
87
- "@aws-sdk/client-ses": "^3.738.0",
88
- "@aws-sdk/client-ssm": "^3.738.0",
83
+ "@aws-sdk/client-cloudwatch-logs": "^3.741.0",
84
+ "@aws-sdk/client-route-53": "^3.741.0",
85
+ "@aws-sdk/client-s3": "^3.741.0",
86
+ "@aws-sdk/client-ses": "^3.741.0",
87
+ "@aws-sdk/client-ssm": "^3.741.0",
88
+ "@mavogel/mvc-projen": "^0.0.2",
89
89
  "async-retry": "^1.3.3",
90
90
  "axios": "^1.7.9",
91
- "cdk-nag": "^2.35.8",
91
+ "cdk-nag": "^2.35.0",
92
+ "constructs": "^10.4.2",
92
93
  "mailparser": "^3.7.2",
93
94
  "uuid": "^9.0.1"
94
95
  },
@@ -111,12 +112,15 @@
111
112
  "rootmail",
112
113
  "ses"
113
114
  ],
115
+ "engines": {
116
+ "node": ">= 20.x"
117
+ },
114
118
  "main": "lib/index.js",
115
119
  "license": "Apache-2.0",
116
120
  "publishConfig": {
117
121
  "access": "public"
118
122
  },
119
- "version": "0.0.289",
123
+ "version": "0.0.291",
120
124
  "jest": {
121
125
  "coverageProvider": "v8",
122
126
  "testMatch": [
@@ -163,7 +167,7 @@
163
167
  }
164
168
  },
165
169
  "types": "lib/index.d.ts",
166
- "stability": "stable",
170
+ "stability": "experimental",
167
171
  "jsii": {
168
172
  "outdir": "dist",
169
173
  "targets": {},
@@ -1,14 +0,0 @@
1
- interface LogRetentionEvent extends Omit<AWSLambda.CloudFormationCustomResourceEvent, 'ResourceProperties'> {
2
- ResourceProperties: {
3
- ServiceToken: string;
4
- LogGroupName: string;
5
- LogGroupRegion?: string;
6
- RetentionInDays?: string;
7
- SdkRetry?: {
8
- maxRetries?: string;
9
- };
10
- RemovalPolicy?: string;
11
- };
12
- }
13
- export declare function handler(event: LogRetentionEvent, context: AWSLambda.Context): Promise<void>;
14
- export {};
@@ -1 +0,0 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.handler=void 0;const Logs=require("@aws-sdk/client-cloudwatch-logs");async function createLogGroupSafe(logGroupName,client,withDelay){await withDelay(async()=>{try{const params={logGroupName},command=new Logs.CreateLogGroupCommand(params);await client.send(command)}catch(error){if(error instanceof Logs.ResourceAlreadyExistsException||error.name==="ResourceAlreadyExistsException")return;throw error}})}async function deleteLogGroup(logGroupName,client,withDelay){await withDelay(async()=>{try{const params={logGroupName},command=new Logs.DeleteLogGroupCommand(params);await client.send(command)}catch(error){if(error instanceof Logs.ResourceNotFoundException||error.name==="ResourceNotFoundException")return;throw error}})}async function setRetentionPolicy(logGroupName,client,withDelay,retentionInDays){await withDelay(async()=>{if(retentionInDays){const params={logGroupName,retentionInDays},putCommand=new Logs.PutRetentionPolicyCommand(params);await client.send(putCommand)}else{const params={logGroupName},deleteCommand=new Logs.DeleteRetentionPolicyCommand(params);await client.send(deleteCommand)}})}async function handler(event,context){try{console.log(JSON.stringify({...event,ResponseURL:"..."}));const logGroupName=event.ResourceProperties.LogGroupName,logGroupRegion=event.ResourceProperties.LogGroupRegion,withDelay=makeWithDelay(parseIntOptional(event.ResourceProperties.SdkRetry?.maxRetries)),sdkConfig={logger:console,region:logGroupRegion},client=new Logs.CloudWatchLogsClient(sdkConfig);if((event.RequestType==="Create"||event.RequestType==="Update")&&(await createLogGroupSafe(logGroupName,client,withDelay),await setRetentionPolicy(logGroupName,client,withDelay,parseIntOptional(event.ResourceProperties.RetentionInDays)),event.RequestType==="Create")){const clientForCustomResourceFunction=new Logs.CloudWatchLogsClient({logger:console,region:process.env.AWS_REGION});await createLogGroupSafe(`/aws/lambda/${context.functionName}`,clientForCustomResourceFunction,withDelay),await setRetentionPolicy(`/aws/lambda/${context.functionName}`,clientForCustomResourceFunction,withDelay,1)}event.RequestType==="Delete"&&event.ResourceProperties.RemovalPolicy==="destroy"&&await deleteLogGroup(logGroupName,client,withDelay),await respond("SUCCESS","OK",logGroupName)}catch(e){console.log(e),await respond("FAILED",e.message,event.ResourceProperties.LogGroupName)}function respond(responseStatus,reason,physicalResourceId){const responseBody=JSON.stringify({Status:responseStatus,Reason:reason,PhysicalResourceId:physicalResourceId,StackId:event.StackId,RequestId:event.RequestId,LogicalResourceId:event.LogicalResourceId,Data:{LogGroupName:event.ResourceProperties.LogGroupName}});console.log("Responding",responseBody);const parsedUrl=require("url").parse(event.ResponseURL),requestOptions={hostname:parsedUrl.hostname,path:parsedUrl.path,method:"PUT",headers:{"content-type":"","content-length":Buffer.byteLength(responseBody,"utf8")}};return new Promise((resolve,reject)=>{try{const request=require("https").request(requestOptions,resolve);request.on("error",reject),request.write(responseBody),request.end()}catch(e){reject(e)}})}}exports.handler=handler;function parseIntOptional(value,base=10){if(value!==void 0)return parseInt(value,base)}function makeWithDelay(maxRetries=5,delayBase=100,delayCap=10*1e3){return async block=>{let attempts=0;do try{return await block()}catch(error){if(error instanceof Logs.OperationAbortedException||error.name==="OperationAbortedException")if(attempts<maxRetries){attempts++,await new Promise(resolve=>setTimeout(resolve,calculateDelay(attempts,delayBase,delayCap)));continue}else throw new Error("Out of attempts to change log group");throw error}while(!0)}}function calculateDelay(attempt,base,cap){return Math.round(Math.random()*Math.min(cap,base*2**attempt))}
@@ -1 +0,0 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.Retry=exports.safeHandler=exports.includeStackTraces=exports.submitResponse=exports.MISSING_PHYSICAL_ID_MARKER=exports.CREATE_FAILED_PHYSICAL_ID_MARKER=void 0;const url=require("url"),outbound_1=require("./outbound"),util_1=require("./util");exports.CREATE_FAILED_PHYSICAL_ID_MARKER="AWSCDK::CustomResourceProviderFramework::CREATE_FAILED",exports.MISSING_PHYSICAL_ID_MARKER="AWSCDK::CustomResourceProviderFramework::MISSING_PHYSICAL_ID";async function submitResponse(status,event,options={}){const json={Status:status,Reason:options.reason||status,StackId:event.StackId,RequestId:event.RequestId,PhysicalResourceId:event.PhysicalResourceId||exports.MISSING_PHYSICAL_ID_MARKER,LogicalResourceId:event.LogicalResourceId,NoEcho:options.noEcho,Data:event.Data};(0,util_1.log)("submit response to cloudformation",json);const responseBody=JSON.stringify(json),parsedUrl=url.parse(event.ResponseURL),retryOptions={attempts:5,sleep:1e3};await(0,util_1.withRetries)(retryOptions,outbound_1.httpRequest)({hostname:parsedUrl.hostname,path:parsedUrl.path,method:"PUT",headers:{"content-type":"","content-length":Buffer.byteLength(responseBody,"utf8")}},responseBody)}exports.submitResponse=submitResponse,exports.includeStackTraces=!0;function safeHandler(block){return async event=>{if(event.RequestType==="Delete"&&event.PhysicalResourceId===exports.CREATE_FAILED_PHYSICAL_ID_MARKER){(0,util_1.log)("ignoring DELETE event caused by a failed CREATE event"),await submitResponse("SUCCESS",event);return}try{await block(event)}catch(e){if(e instanceof Retry)throw(0,util_1.log)("retry requested by handler"),e;event.PhysicalResourceId||(event.RequestType==="Create"?((0,util_1.log)("CREATE failed, responding with a marker physical resource id so that the subsequent DELETE will be ignored"),event.PhysicalResourceId=exports.CREATE_FAILED_PHYSICAL_ID_MARKER):(0,util_1.log)(`ERROR: Malformed event. "PhysicalResourceId" is required: ${JSON.stringify({...event,ResponseURL:"..."})}`)),await submitResponse("FAILED",event,{reason:exports.includeStackTraces?e.stack:e.message})}}}exports.safeHandler=safeHandler;class Retry extends Error{}exports.Retry=Retry;
@@ -1,3 +0,0 @@
1
- "use strict";const cfnResponse=require("./cfn-response"),consts=require("./consts"),outbound_1=require("./outbound"),util_1=require("./util");async function onEvent(cfnRequest){const sanitizedRequest={...cfnRequest,ResponseURL:"..."};(0,util_1.log)("onEventHandler",sanitizedRequest),cfnRequest.ResourceProperties=cfnRequest.ResourceProperties||{};const onEventResult=await invokeUserFunction(consts.USER_ON_EVENT_FUNCTION_ARN_ENV,sanitizedRequest,cfnRequest.ResponseURL);(0,util_1.log)("onEvent returned:",onEventResult);const resourceEvent=createResponseEvent(cfnRequest,onEventResult);if((0,util_1.log)("event:",onEventResult),!process.env[consts.USER_IS_COMPLETE_FUNCTION_ARN_ENV])return cfnResponse.submitResponse("SUCCESS",resourceEvent,{noEcho:resourceEvent.NoEcho});const waiter={stateMachineArn:(0,util_1.getEnv)(consts.WAITER_STATE_MACHINE_ARN_ENV),name:resourceEvent.RequestId,input:JSON.stringify(resourceEvent)};(0,util_1.log)("starting waiter",waiter),await(0,outbound_1.startExecution)(waiter)}async function isComplete(event){const sanitizedRequest={...event,ResponseURL:"..."};(0,util_1.log)("isComplete",sanitizedRequest);const isCompleteResult=await invokeUserFunction(consts.USER_IS_COMPLETE_FUNCTION_ARN_ENV,sanitizedRequest,event.ResponseURL);if((0,util_1.log)("user isComplete returned:",isCompleteResult),!isCompleteResult.IsComplete)throw isCompleteResult.Data&&Object.keys(isCompleteResult.Data).length>0?new Error('"Data" is not allowed if "IsComplete" is "False"'):new cfnResponse.Retry(JSON.stringify(event));const response={...event,...isCompleteResult,Data:{...event.Data,...isCompleteResult.Data}};await cfnResponse.submitResponse("SUCCESS",response,{noEcho:event.NoEcho})}async function onTimeout(timeoutEvent){(0,util_1.log)("timeoutHandler",timeoutEvent);const isCompleteRequest=JSON.parse(JSON.parse(timeoutEvent.Cause).errorMessage);await cfnResponse.submitResponse("FAILED",isCompleteRequest,{reason:"Operation timed out"})}async function invokeUserFunction(functionArnEnv,sanitizedPayload,responseUrl){const functionArn=(0,util_1.getEnv)(functionArnEnv);(0,util_1.log)(`executing user function ${functionArn} with payload`,sanitizedPayload);const resp=await(0,outbound_1.invokeFunction)({FunctionName:functionArn,Payload:JSON.stringify({...sanitizedPayload,ResponseURL:responseUrl})});(0,util_1.log)("user function response:",resp,typeof resp);const jsonPayload=parseJsonPayload(resp.Payload);if(resp.FunctionError){(0,util_1.log)("user function threw an error:",resp.FunctionError);const errorMessage=jsonPayload.errorMessage||"error",arn=functionArn.split(":"),functionName=arn[arn.length-1],message=[errorMessage,"",`Logs: /aws/lambda/${functionName}`,""].join(`
2
- `),e=new Error(message);throw jsonPayload.trace&&(e.stack=[message,...jsonPayload.trace.slice(1)].join(`
3
- `)),e}return jsonPayload}function parseJsonPayload(payload){if(!payload)return{};let text=new TextDecoder().decode(Buffer.from(payload));try{return JSON.parse(text)}catch{throw new Error(`return values from user-handlers must be JSON objects. got: "${text}"`)}}function createResponseEvent(cfnRequest,onEventResult){onEventResult=onEventResult||{};const physicalResourceId=onEventResult.PhysicalResourceId||defaultPhysicalResourceId(cfnRequest);if(cfnRequest.RequestType==="Delete"&&physicalResourceId!==cfnRequest.PhysicalResourceId)throw new Error(`DELETE: cannot change the physical resource ID from "${cfnRequest.PhysicalResourceId}" to "${onEventResult.PhysicalResourceId}" during deletion`);return cfnRequest.RequestType==="Update"&&physicalResourceId!==cfnRequest.PhysicalResourceId&&(0,util_1.log)(`UPDATE: changing physical resource ID from "${cfnRequest.PhysicalResourceId}" to "${onEventResult.PhysicalResourceId}"`),{...cfnRequest,...onEventResult,PhysicalResourceId:physicalResourceId}}function defaultPhysicalResourceId(req){switch(req.RequestType){case"Create":return req.RequestId;case"Update":case"Delete":return req.PhysicalResourceId;default:throw new Error(`Invalid "RequestType" in request "${JSON.stringify(req)}"`)}}module.exports={[consts.FRAMEWORK_ON_EVENT_HANDLER_NAME]:cfnResponse.safeHandler(onEvent),[consts.FRAMEWORK_IS_COMPLETE_HANDLER_NAME]:cfnResponse.safeHandler(isComplete),[consts.FRAMEWORK_ON_TIMEOUT_HANDLER_NAME]:onTimeout};
@@ -1 +0,0 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.httpRequest=exports.invokeFunction=exports.startExecution=void 0;const https=require("https"),client_lambda_1=require("@aws-sdk/client-lambda"),client_sfn_1=require("@aws-sdk/client-sfn"),FRAMEWORK_HANDLER_TIMEOUT=9e5,awsSdkConfig={httpOptions:{timeout:FRAMEWORK_HANDLER_TIMEOUT}};async function defaultHttpRequest(options,responseBody){return new Promise((resolve,reject)=>{try{const request=https.request(options,resolve);request.on("error",reject),request.write(responseBody),request.end()}catch(e){reject(e)}})}let sfn,lambda;async function defaultStartExecution(req){return sfn||(sfn=new client_sfn_1.SFN(awsSdkConfig)),sfn.startExecution(req)}async function defaultInvokeFunction(req){lambda||(lambda=new client_lambda_1.Lambda(awsSdkConfig));try{return await lambda.invoke(req)}catch{return await(0,client_lambda_1.waitUntilFunctionActive)({client:lambda,maxWaitTime:60},{FunctionName:req.FunctionName}),await lambda.invoke(req)}}exports.startExecution=defaultStartExecution,exports.invokeFunction=defaultInvokeFunction,exports.httpRequest=defaultHttpRequest;
@@ -1 +0,0 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.withRetries=exports.log=exports.getEnv=void 0;function getEnv(name){const value=process.env[name];if(!value)throw new Error(`The environment variable "${name}" is not defined`);return value}exports.getEnv=getEnv;function log(title,...args){console.log("[provider-framework]",title,...args.map(x=>typeof x=="object"?JSON.stringify(x,void 0,2):x))}exports.log=log;function withRetries(options,fn){return async(...xs)=>{let attempts=options.attempts,ms=options.sleep;for(;;)try{return await fn(...xs)}catch(e){if(attempts--<=0)throw e;await sleep(Math.floor(Math.random()*ms)),ms*=2}}}exports.withRetries=withRetries;async function sleep(ms){return new Promise(ok=>setTimeout(ok,ms))}
@@ -1,14 +0,0 @@
1
- interface LogRetentionEvent extends Omit<AWSLambda.CloudFormationCustomResourceEvent, 'ResourceProperties'> {
2
- ResourceProperties: {
3
- ServiceToken: string;
4
- LogGroupName: string;
5
- LogGroupRegion?: string;
6
- RetentionInDays?: string;
7
- SdkRetry?: {
8
- maxRetries?: string;
9
- };
10
- RemovalPolicy?: string;
11
- };
12
- }
13
- export declare function handler(event: LogRetentionEvent, context: AWSLambda.Context): Promise<void>;
14
- export {};
@@ -1 +0,0 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.handler=void 0;const Logs=require("@aws-sdk/client-cloudwatch-logs");async function createLogGroupSafe(logGroupName,client,withDelay){await withDelay(async()=>{try{const params={logGroupName},command=new Logs.CreateLogGroupCommand(params);await client.send(command)}catch(error){if(error instanceof Logs.ResourceAlreadyExistsException||error.name==="ResourceAlreadyExistsException")return;throw error}})}async function deleteLogGroup(logGroupName,client,withDelay){await withDelay(async()=>{try{const params={logGroupName},command=new Logs.DeleteLogGroupCommand(params);await client.send(command)}catch(error){if(error instanceof Logs.ResourceNotFoundException||error.name==="ResourceNotFoundException")return;throw error}})}async function setRetentionPolicy(logGroupName,client,withDelay,retentionInDays){await withDelay(async()=>{if(retentionInDays){const params={logGroupName,retentionInDays},putCommand=new Logs.PutRetentionPolicyCommand(params);await client.send(putCommand)}else{const params={logGroupName},deleteCommand=new Logs.DeleteRetentionPolicyCommand(params);await client.send(deleteCommand)}})}async function handler(event,context){try{console.log(JSON.stringify({...event,ResponseURL:"..."}));const logGroupName=event.ResourceProperties.LogGroupName,logGroupRegion=event.ResourceProperties.LogGroupRegion,withDelay=makeWithDelay(parseIntOptional(event.ResourceProperties.SdkRetry?.maxRetries)),sdkConfig={logger:console,region:logGroupRegion},client=new Logs.CloudWatchLogsClient(sdkConfig);if((event.RequestType==="Create"||event.RequestType==="Update")&&(await createLogGroupSafe(logGroupName,client,withDelay),await setRetentionPolicy(logGroupName,client,withDelay,parseIntOptional(event.ResourceProperties.RetentionInDays)),event.RequestType==="Create")){const clientForCustomResourceFunction=new Logs.CloudWatchLogsClient({logger:console,region:process.env.AWS_REGION});await createLogGroupSafe(`/aws/lambda/${context.functionName}`,clientForCustomResourceFunction,withDelay),await setRetentionPolicy(`/aws/lambda/${context.functionName}`,clientForCustomResourceFunction,withDelay,1)}event.RequestType==="Delete"&&event.ResourceProperties.RemovalPolicy==="destroy"&&await deleteLogGroup(logGroupName,client,withDelay),await respond("SUCCESS","OK",logGroupName)}catch(e){console.log(e),await respond("FAILED",e.message,event.ResourceProperties.LogGroupName)}function respond(responseStatus,reason,physicalResourceId){const responseBody=JSON.stringify({Status:responseStatus,Reason:reason,PhysicalResourceId:physicalResourceId,StackId:event.StackId,RequestId:event.RequestId,LogicalResourceId:event.LogicalResourceId,Data:{LogGroupName:event.ResourceProperties.LogGroupName}});console.log("Responding",responseBody);const parsedUrl=require("url").parse(event.ResponseURL),requestOptions={hostname:parsedUrl.hostname,path:parsedUrl.path,method:"PUT",headers:{"content-type":"","content-length":Buffer.byteLength(responseBody,"utf8")}};return new Promise((resolve,reject)=>{try{const request=require("https").request(requestOptions,resolve);request.on("error",reject),request.write(responseBody),request.end()}catch(e){reject(e)}})}}exports.handler=handler;function parseIntOptional(value,base=10){if(value!==void 0)return parseInt(value,base)}function makeWithDelay(maxRetries=5,delayBase=100,delayCap=10*1e3){return async block=>{let attempts=0;do try{return await block()}catch(error){if(error instanceof Logs.OperationAbortedException||error.name==="OperationAbortedException")if(attempts<maxRetries){attempts++,await new Promise(resolve=>setTimeout(resolve,calculateDelay(attempts,delayBase,delayCap)));continue}else throw new Error("Out of attempts to change log group");throw error}while(!0)}}function calculateDelay(attempt,base,cap){return Math.round(Math.random()*Math.min(cap,base*2**attempt))}
@@ -1 +0,0 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.Retry=exports.safeHandler=exports.includeStackTraces=exports.submitResponse=exports.MISSING_PHYSICAL_ID_MARKER=exports.CREATE_FAILED_PHYSICAL_ID_MARKER=void 0;const url=require("url"),outbound_1=require("./outbound"),util_1=require("./util");exports.CREATE_FAILED_PHYSICAL_ID_MARKER="AWSCDK::CustomResourceProviderFramework::CREATE_FAILED",exports.MISSING_PHYSICAL_ID_MARKER="AWSCDK::CustomResourceProviderFramework::MISSING_PHYSICAL_ID";async function submitResponse(status,event,options={}){const json={Status:status,Reason:options.reason||status,StackId:event.StackId,RequestId:event.RequestId,PhysicalResourceId:event.PhysicalResourceId||exports.MISSING_PHYSICAL_ID_MARKER,LogicalResourceId:event.LogicalResourceId,NoEcho:options.noEcho,Data:event.Data};(0,util_1.log)("submit response to cloudformation",json);const responseBody=JSON.stringify(json),parsedUrl=url.parse(event.ResponseURL),retryOptions={attempts:5,sleep:1e3};await(0,util_1.withRetries)(retryOptions,outbound_1.httpRequest)({hostname:parsedUrl.hostname,path:parsedUrl.path,method:"PUT",headers:{"content-type":"","content-length":Buffer.byteLength(responseBody,"utf8")}},responseBody)}exports.submitResponse=submitResponse,exports.includeStackTraces=!0;function safeHandler(block){return async event=>{if(event.RequestType==="Delete"&&event.PhysicalResourceId===exports.CREATE_FAILED_PHYSICAL_ID_MARKER){(0,util_1.log)("ignoring DELETE event caused by a failed CREATE event"),await submitResponse("SUCCESS",event);return}try{await block(event)}catch(e){if(e instanceof Retry)throw(0,util_1.log)("retry requested by handler"),e;event.PhysicalResourceId||(event.RequestType==="Create"?((0,util_1.log)("CREATE failed, responding with a marker physical resource id so that the subsequent DELETE will be ignored"),event.PhysicalResourceId=exports.CREATE_FAILED_PHYSICAL_ID_MARKER):(0,util_1.log)(`ERROR: Malformed event. "PhysicalResourceId" is required: ${JSON.stringify({...event,ResponseURL:"..."})}`)),await submitResponse("FAILED",event,{reason:exports.includeStackTraces?e.stack:e.message})}}}exports.safeHandler=safeHandler;class Retry extends Error{}exports.Retry=Retry;
@@ -1,3 +0,0 @@
1
- "use strict";const cfnResponse=require("./cfn-response"),consts=require("./consts"),outbound_1=require("./outbound"),util_1=require("./util");async function onEvent(cfnRequest){const sanitizedRequest={...cfnRequest,ResponseURL:"..."};(0,util_1.log)("onEventHandler",sanitizedRequest),cfnRequest.ResourceProperties=cfnRequest.ResourceProperties||{};const onEventResult=await invokeUserFunction(consts.USER_ON_EVENT_FUNCTION_ARN_ENV,sanitizedRequest,cfnRequest.ResponseURL);(0,util_1.log)("onEvent returned:",onEventResult);const resourceEvent=createResponseEvent(cfnRequest,onEventResult);if((0,util_1.log)("event:",onEventResult),!process.env[consts.USER_IS_COMPLETE_FUNCTION_ARN_ENV])return cfnResponse.submitResponse("SUCCESS",resourceEvent,{noEcho:resourceEvent.NoEcho});const waiter={stateMachineArn:(0,util_1.getEnv)(consts.WAITER_STATE_MACHINE_ARN_ENV),name:resourceEvent.RequestId,input:JSON.stringify(resourceEvent)};(0,util_1.log)("starting waiter",waiter),await(0,outbound_1.startExecution)(waiter)}async function isComplete(event){const sanitizedRequest={...event,ResponseURL:"..."};(0,util_1.log)("isComplete",sanitizedRequest);const isCompleteResult=await invokeUserFunction(consts.USER_IS_COMPLETE_FUNCTION_ARN_ENV,sanitizedRequest,event.ResponseURL);if((0,util_1.log)("user isComplete returned:",isCompleteResult),!isCompleteResult.IsComplete)throw isCompleteResult.Data&&Object.keys(isCompleteResult.Data).length>0?new Error('"Data" is not allowed if "IsComplete" is "False"'):new cfnResponse.Retry(JSON.stringify(event));const response={...event,...isCompleteResult,Data:{...event.Data,...isCompleteResult.Data}};await cfnResponse.submitResponse("SUCCESS",response,{noEcho:event.NoEcho})}async function onTimeout(timeoutEvent){(0,util_1.log)("timeoutHandler",timeoutEvent);const isCompleteRequest=JSON.parse(JSON.parse(timeoutEvent.Cause).errorMessage);await cfnResponse.submitResponse("FAILED",isCompleteRequest,{reason:"Operation timed out"})}async function invokeUserFunction(functionArnEnv,sanitizedPayload,responseUrl){const functionArn=(0,util_1.getEnv)(functionArnEnv);(0,util_1.log)(`executing user function ${functionArn} with payload`,sanitizedPayload);const resp=await(0,outbound_1.invokeFunction)({FunctionName:functionArn,Payload:JSON.stringify({...sanitizedPayload,ResponseURL:responseUrl})});(0,util_1.log)("user function response:",resp,typeof resp);const jsonPayload=parseJsonPayload(resp.Payload);if(resp.FunctionError){(0,util_1.log)("user function threw an error:",resp.FunctionError);const errorMessage=jsonPayload.errorMessage||"error",arn=functionArn.split(":"),functionName=arn[arn.length-1],message=[errorMessage,"",`Logs: /aws/lambda/${functionName}`,""].join(`
2
- `),e=new Error(message);throw jsonPayload.trace&&(e.stack=[message,...jsonPayload.trace.slice(1)].join(`
3
- `)),e}return jsonPayload}function parseJsonPayload(payload){if(!payload)return{};let text=new TextDecoder().decode(Buffer.from(payload));try{return JSON.parse(text)}catch{throw new Error(`return values from user-handlers must be JSON objects. got: "${text}"`)}}function createResponseEvent(cfnRequest,onEventResult){onEventResult=onEventResult||{};const physicalResourceId=onEventResult.PhysicalResourceId||defaultPhysicalResourceId(cfnRequest);if(cfnRequest.RequestType==="Delete"&&physicalResourceId!==cfnRequest.PhysicalResourceId)throw new Error(`DELETE: cannot change the physical resource ID from "${cfnRequest.PhysicalResourceId}" to "${onEventResult.PhysicalResourceId}" during deletion`);return cfnRequest.RequestType==="Update"&&physicalResourceId!==cfnRequest.PhysicalResourceId&&(0,util_1.log)(`UPDATE: changing physical resource ID from "${cfnRequest.PhysicalResourceId}" to "${onEventResult.PhysicalResourceId}"`),{...cfnRequest,...onEventResult,PhysicalResourceId:physicalResourceId}}function defaultPhysicalResourceId(req){switch(req.RequestType){case"Create":return req.RequestId;case"Update":case"Delete":return req.PhysicalResourceId;default:throw new Error(`Invalid "RequestType" in request "${JSON.stringify(req)}"`)}}module.exports={[consts.FRAMEWORK_ON_EVENT_HANDLER_NAME]:cfnResponse.safeHandler(onEvent),[consts.FRAMEWORK_IS_COMPLETE_HANDLER_NAME]:cfnResponse.safeHandler(isComplete),[consts.FRAMEWORK_ON_TIMEOUT_HANDLER_NAME]:onTimeout};
@@ -1 +0,0 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.httpRequest=exports.invokeFunction=exports.startExecution=void 0;const https=require("https"),client_lambda_1=require("@aws-sdk/client-lambda"),client_sfn_1=require("@aws-sdk/client-sfn"),FRAMEWORK_HANDLER_TIMEOUT=9e5,awsSdkConfig={httpOptions:{timeout:FRAMEWORK_HANDLER_TIMEOUT}};async function defaultHttpRequest(options,responseBody){return new Promise((resolve,reject)=>{try{const request=https.request(options,resolve);request.on("error",reject),request.write(responseBody),request.end()}catch(e){reject(e)}})}let sfn,lambda;async function defaultStartExecution(req){return sfn||(sfn=new client_sfn_1.SFN(awsSdkConfig)),sfn.startExecution(req)}async function defaultInvokeFunction(req){lambda||(lambda=new client_lambda_1.Lambda(awsSdkConfig));try{return await lambda.invoke(req)}catch{return await(0,client_lambda_1.waitUntilFunctionActive)({client:lambda,maxWaitTime:60},{FunctionName:req.FunctionName}),await lambda.invoke(req)}}exports.startExecution=defaultStartExecution,exports.invokeFunction=defaultInvokeFunction,exports.httpRequest=defaultHttpRequest;
@@ -1 +0,0 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.withRetries=exports.log=exports.getEnv=void 0;function getEnv(name){const value=process.env[name];if(!value)throw new Error(`The environment variable "${name}" is not defined`);return value}exports.getEnv=getEnv;function log(title,...args){console.log("[provider-framework]",title,...args.map(x=>typeof x=="object"?JSON.stringify(x,void 0,2):x))}exports.log=log;function withRetries(options,fn){return async(...xs)=>{let attempts=options.attempts,ms=options.sleep;for(;;)try{return await fn(...xs)}catch(e){if(attempts--<=0)throw e;await sleep(Math.floor(Math.random()*ms)),ms*=2}}}exports.withRetries=withRetries;async function sleep(ms){return new Promise(ok=>setTimeout(ok,ms))}
@@ -1,14 +0,0 @@
1
- interface LogRetentionEvent extends Omit<AWSLambda.CloudFormationCustomResourceEvent, 'ResourceProperties'> {
2
- ResourceProperties: {
3
- ServiceToken: string;
4
- LogGroupName: string;
5
- LogGroupRegion?: string;
6
- RetentionInDays?: string;
7
- SdkRetry?: {
8
- maxRetries?: string;
9
- };
10
- RemovalPolicy?: string;
11
- };
12
- }
13
- export declare function handler(event: LogRetentionEvent, context: AWSLambda.Context): Promise<void>;
14
- export {};
@@ -1 +0,0 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.handler=void 0;const Logs=require("@aws-sdk/client-cloudwatch-logs");async function createLogGroupSafe(logGroupName,client,withDelay){await withDelay(async()=>{try{const params={logGroupName},command=new Logs.CreateLogGroupCommand(params);await client.send(command)}catch(error){if(error instanceof Logs.ResourceAlreadyExistsException||error.name==="ResourceAlreadyExistsException")return;throw error}})}async function deleteLogGroup(logGroupName,client,withDelay){await withDelay(async()=>{try{const params={logGroupName},command=new Logs.DeleteLogGroupCommand(params);await client.send(command)}catch(error){if(error instanceof Logs.ResourceNotFoundException||error.name==="ResourceNotFoundException")return;throw error}})}async function setRetentionPolicy(logGroupName,client,withDelay,retentionInDays){await withDelay(async()=>{if(retentionInDays){const params={logGroupName,retentionInDays},putCommand=new Logs.PutRetentionPolicyCommand(params);await client.send(putCommand)}else{const params={logGroupName},deleteCommand=new Logs.DeleteRetentionPolicyCommand(params);await client.send(deleteCommand)}})}async function handler(event,context){try{console.log(JSON.stringify({...event,ResponseURL:"..."}));const logGroupName=event.ResourceProperties.LogGroupName,logGroupRegion=event.ResourceProperties.LogGroupRegion,withDelay=makeWithDelay(parseIntOptional(event.ResourceProperties.SdkRetry?.maxRetries)),sdkConfig={logger:console,region:logGroupRegion},client=new Logs.CloudWatchLogsClient(sdkConfig);if((event.RequestType==="Create"||event.RequestType==="Update")&&(await createLogGroupSafe(logGroupName,client,withDelay),await setRetentionPolicy(logGroupName,client,withDelay,parseIntOptional(event.ResourceProperties.RetentionInDays)),event.RequestType==="Create")){const clientForCustomResourceFunction=new Logs.CloudWatchLogsClient({logger:console,region:process.env.AWS_REGION});await createLogGroupSafe(`/aws/lambda/${context.functionName}`,clientForCustomResourceFunction,withDelay),await setRetentionPolicy(`/aws/lambda/${context.functionName}`,clientForCustomResourceFunction,withDelay,1)}event.RequestType==="Delete"&&event.ResourceProperties.RemovalPolicy==="destroy"&&await deleteLogGroup(logGroupName,client,withDelay),await respond("SUCCESS","OK",logGroupName)}catch(e){console.log(e),await respond("FAILED",e.message,event.ResourceProperties.LogGroupName)}function respond(responseStatus,reason,physicalResourceId){const responseBody=JSON.stringify({Status:responseStatus,Reason:reason,PhysicalResourceId:physicalResourceId,StackId:event.StackId,RequestId:event.RequestId,LogicalResourceId:event.LogicalResourceId,Data:{LogGroupName:event.ResourceProperties.LogGroupName}});console.log("Responding",responseBody);const parsedUrl=require("url").parse(event.ResponseURL),requestOptions={hostname:parsedUrl.hostname,path:parsedUrl.path,method:"PUT",headers:{"content-type":"","content-length":Buffer.byteLength(responseBody,"utf8")}};return new Promise((resolve,reject)=>{try{const request=require("https").request(requestOptions,resolve);request.on("error",reject),request.write(responseBody),request.end()}catch(e){reject(e)}})}}exports.handler=handler;function parseIntOptional(value,base=10){if(value!==void 0)return parseInt(value,base)}function makeWithDelay(maxRetries=5,delayBase=100,delayCap=10*1e3){return async block=>{let attempts=0;do try{return await block()}catch(error){if(error instanceof Logs.OperationAbortedException||error.name==="OperationAbortedException")if(attempts<maxRetries){attempts++,await new Promise(resolve=>setTimeout(resolve,calculateDelay(attempts,delayBase,delayCap)));continue}else throw new Error("Out of attempts to change log group");throw error}while(!0)}}function calculateDelay(attempt,base,cap){return Math.round(Math.random()*Math.min(cap,base*2**attempt))}
@@ -1 +0,0 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.Retry=exports.safeHandler=exports.includeStackTraces=exports.submitResponse=exports.MISSING_PHYSICAL_ID_MARKER=exports.CREATE_FAILED_PHYSICAL_ID_MARKER=void 0;const url=require("url"),outbound_1=require("./outbound"),util_1=require("./util");exports.CREATE_FAILED_PHYSICAL_ID_MARKER="AWSCDK::CustomResourceProviderFramework::CREATE_FAILED",exports.MISSING_PHYSICAL_ID_MARKER="AWSCDK::CustomResourceProviderFramework::MISSING_PHYSICAL_ID";async function submitResponse(status,event,options={}){const json={Status:status,Reason:options.reason||status,StackId:event.StackId,RequestId:event.RequestId,PhysicalResourceId:event.PhysicalResourceId||exports.MISSING_PHYSICAL_ID_MARKER,LogicalResourceId:event.LogicalResourceId,NoEcho:options.noEcho,Data:event.Data};(0,util_1.log)("submit response to cloudformation",json);const responseBody=JSON.stringify(json),parsedUrl=url.parse(event.ResponseURL),retryOptions={attempts:5,sleep:1e3};await(0,util_1.withRetries)(retryOptions,outbound_1.httpRequest)({hostname:parsedUrl.hostname,path:parsedUrl.path,method:"PUT",headers:{"content-type":"","content-length":Buffer.byteLength(responseBody,"utf8")}},responseBody)}exports.submitResponse=submitResponse,exports.includeStackTraces=!0;function safeHandler(block){return async event=>{if(event.RequestType==="Delete"&&event.PhysicalResourceId===exports.CREATE_FAILED_PHYSICAL_ID_MARKER){(0,util_1.log)("ignoring DELETE event caused by a failed CREATE event"),await submitResponse("SUCCESS",event);return}try{await block(event)}catch(e){if(e instanceof Retry)throw(0,util_1.log)("retry requested by handler"),e;event.PhysicalResourceId||(event.RequestType==="Create"?((0,util_1.log)("CREATE failed, responding with a marker physical resource id so that the subsequent DELETE will be ignored"),event.PhysicalResourceId=exports.CREATE_FAILED_PHYSICAL_ID_MARKER):(0,util_1.log)(`ERROR: Malformed event. "PhysicalResourceId" is required: ${JSON.stringify({...event,ResponseURL:"..."})}`)),await submitResponse("FAILED",event,{reason:exports.includeStackTraces?e.stack:e.message})}}}exports.safeHandler=safeHandler;class Retry extends Error{}exports.Retry=Retry;
@@ -1,3 +0,0 @@
1
- "use strict";const cfnResponse=require("./cfn-response"),consts=require("./consts"),outbound_1=require("./outbound"),util_1=require("./util");async function onEvent(cfnRequest){const sanitizedRequest={...cfnRequest,ResponseURL:"..."};(0,util_1.log)("onEventHandler",sanitizedRequest),cfnRequest.ResourceProperties=cfnRequest.ResourceProperties||{};const onEventResult=await invokeUserFunction(consts.USER_ON_EVENT_FUNCTION_ARN_ENV,sanitizedRequest,cfnRequest.ResponseURL);(0,util_1.log)("onEvent returned:",onEventResult);const resourceEvent=createResponseEvent(cfnRequest,onEventResult);if((0,util_1.log)("event:",onEventResult),!process.env[consts.USER_IS_COMPLETE_FUNCTION_ARN_ENV])return cfnResponse.submitResponse("SUCCESS",resourceEvent,{noEcho:resourceEvent.NoEcho});const waiter={stateMachineArn:(0,util_1.getEnv)(consts.WAITER_STATE_MACHINE_ARN_ENV),name:resourceEvent.RequestId,input:JSON.stringify(resourceEvent)};(0,util_1.log)("starting waiter",waiter),await(0,outbound_1.startExecution)(waiter)}async function isComplete(event){const sanitizedRequest={...event,ResponseURL:"..."};(0,util_1.log)("isComplete",sanitizedRequest);const isCompleteResult=await invokeUserFunction(consts.USER_IS_COMPLETE_FUNCTION_ARN_ENV,sanitizedRequest,event.ResponseURL);if((0,util_1.log)("user isComplete returned:",isCompleteResult),!isCompleteResult.IsComplete)throw isCompleteResult.Data&&Object.keys(isCompleteResult.Data).length>0?new Error('"Data" is not allowed if "IsComplete" is "False"'):new cfnResponse.Retry(JSON.stringify(event));const response={...event,...isCompleteResult,Data:{...event.Data,...isCompleteResult.Data}};await cfnResponse.submitResponse("SUCCESS",response,{noEcho:event.NoEcho})}async function onTimeout(timeoutEvent){(0,util_1.log)("timeoutHandler",timeoutEvent);const isCompleteRequest=JSON.parse(JSON.parse(timeoutEvent.Cause).errorMessage);await cfnResponse.submitResponse("FAILED",isCompleteRequest,{reason:"Operation timed out"})}async function invokeUserFunction(functionArnEnv,sanitizedPayload,responseUrl){const functionArn=(0,util_1.getEnv)(functionArnEnv);(0,util_1.log)(`executing user function ${functionArn} with payload`,sanitizedPayload);const resp=await(0,outbound_1.invokeFunction)({FunctionName:functionArn,Payload:JSON.stringify({...sanitizedPayload,ResponseURL:responseUrl})});(0,util_1.log)("user function response:",resp,typeof resp);const jsonPayload=parseJsonPayload(resp.Payload);if(resp.FunctionError){(0,util_1.log)("user function threw an error:",resp.FunctionError);const errorMessage=jsonPayload.errorMessage||"error",arn=functionArn.split(":"),functionName=arn[arn.length-1],message=[errorMessage,"",`Logs: /aws/lambda/${functionName}`,""].join(`
2
- `),e=new Error(message);throw jsonPayload.trace&&(e.stack=[message,...jsonPayload.trace.slice(1)].join(`
3
- `)),e}return jsonPayload}function parseJsonPayload(payload){if(!payload)return{};let text=new TextDecoder().decode(Buffer.from(payload));try{return JSON.parse(text)}catch{throw new Error(`return values from user-handlers must be JSON objects. got: "${text}"`)}}function createResponseEvent(cfnRequest,onEventResult){onEventResult=onEventResult||{};const physicalResourceId=onEventResult.PhysicalResourceId||defaultPhysicalResourceId(cfnRequest);if(cfnRequest.RequestType==="Delete"&&physicalResourceId!==cfnRequest.PhysicalResourceId)throw new Error(`DELETE: cannot change the physical resource ID from "${cfnRequest.PhysicalResourceId}" to "${onEventResult.PhysicalResourceId}" during deletion`);return cfnRequest.RequestType==="Update"&&physicalResourceId!==cfnRequest.PhysicalResourceId&&(0,util_1.log)(`UPDATE: changing physical resource ID from "${cfnRequest.PhysicalResourceId}" to "${onEventResult.PhysicalResourceId}"`),{...cfnRequest,...onEventResult,PhysicalResourceId:physicalResourceId}}function defaultPhysicalResourceId(req){switch(req.RequestType){case"Create":return req.RequestId;case"Update":case"Delete":return req.PhysicalResourceId;default:throw new Error(`Invalid "RequestType" in request "${JSON.stringify(req)}"`)}}module.exports={[consts.FRAMEWORK_ON_EVENT_HANDLER_NAME]:cfnResponse.safeHandler(onEvent),[consts.FRAMEWORK_IS_COMPLETE_HANDLER_NAME]:cfnResponse.safeHandler(isComplete),[consts.FRAMEWORK_ON_TIMEOUT_HANDLER_NAME]:onTimeout};
@@ -1 +0,0 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.httpRequest=exports.invokeFunction=exports.startExecution=void 0;const https=require("https"),client_lambda_1=require("@aws-sdk/client-lambda"),client_sfn_1=require("@aws-sdk/client-sfn"),FRAMEWORK_HANDLER_TIMEOUT=9e5,awsSdkConfig={httpOptions:{timeout:FRAMEWORK_HANDLER_TIMEOUT}};async function defaultHttpRequest(options,responseBody){return new Promise((resolve,reject)=>{try{const request=https.request(options,resolve);request.on("error",reject),request.write(responseBody),request.end()}catch(e){reject(e)}})}let sfn,lambda;async function defaultStartExecution(req){return sfn||(sfn=new client_sfn_1.SFN(awsSdkConfig)),sfn.startExecution(req)}async function defaultInvokeFunction(req){lambda||(lambda=new client_lambda_1.Lambda(awsSdkConfig));try{return await lambda.invoke(req)}catch{return await(0,client_lambda_1.waitUntilFunctionActive)({client:lambda,maxWaitTime:60},{FunctionName:req.FunctionName}),await lambda.invoke(req)}}exports.startExecution=defaultStartExecution,exports.invokeFunction=defaultInvokeFunction,exports.httpRequest=defaultHttpRequest;
@@ -1 +0,0 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.withRetries=exports.log=exports.getEnv=void 0;function getEnv(name){const value=process.env[name];if(!value)throw new Error(`The environment variable "${name}" is not defined`);return value}exports.getEnv=getEnv;function log(title,...args){console.log("[provider-framework]",title,...args.map(x=>typeof x=="object"?JSON.stringify(x,void 0,2):x))}exports.log=log;function withRetries(options,fn){return async(...xs)=>{let attempts=options.attempts,ms=options.sleep;for(;;)try{return await fn(...xs)}catch(e){if(attempts--<=0)throw e;await sleep(Math.floor(Math.random()*ms)),ms*=2}}}exports.withRetries=withRetries;async function sleep(ms){return new Promise(ok=>setTimeout(ok,ms))}