@fjall/components-infrastructure 2.29.0 → 2.30.3

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 (93) hide show
  1. package/dist/lib/__tests__/setup.d.ts +48 -0
  2. package/dist/lib/__tests__/setup.js +1 -0
  3. package/dist/lib/app.d.ts +8 -4
  4. package/dist/lib/app.js +24 -6
  5. package/dist/lib/config/aws/accountId.d.ts +6 -0
  6. package/dist/lib/config/aws/accountId.js +33 -0
  7. package/dist/lib/config/aws/backupGlobalSettings.d.ts +29 -0
  8. package/dist/lib/config/aws/backupGlobalSettings.js +51 -0
  9. package/dist/lib/config/aws/costAllocationTags.d.ts +12 -0
  10. package/dist/lib/config/aws/costAllocationTags.js +48 -0
  11. package/dist/lib/config/aws/eventBus.d.ts +7 -0
  12. package/dist/lib/config/aws/eventBus.js +24 -0
  13. package/dist/lib/config/aws/identityCenterGroupMembership.d.ts +10 -0
  14. package/dist/lib/config/aws/identityCenterGroupMembership.js +115 -0
  15. package/dist/lib/config/aws/ipamDelegateAdmin.d.ts +8 -0
  16. package/dist/lib/config/aws/ipamDelegateAdmin.js +58 -0
  17. package/dist/lib/config/aws/ipamPoolId.d.ts +10 -0
  18. package/dist/lib/config/aws/ipamPoolId.js +39 -0
  19. package/dist/lib/config/aws/organisation.d.ts +30 -0
  20. package/dist/lib/config/aws/organisation.js +95 -0
  21. package/dist/lib/config/aws/organisationId.d.ts +7 -0
  22. package/dist/lib/config/aws/organisationId.js +46 -0
  23. package/dist/lib/config/aws/organisationsAccess.d.ts +10 -0
  24. package/dist/lib/config/aws/organisationsAccess.js +50 -0
  25. package/dist/lib/config/aws/ramSharing.d.ts +4 -0
  26. package/dist/lib/config/aws/ramSharing.js +35 -0
  27. package/dist/lib/config/monitoring.d.ts +18 -0
  28. package/dist/lib/config/monitoring.js +22 -0
  29. package/dist/lib/lambda-assets/static-site-forms/asset/index.js +175 -0
  30. package/dist/lib/lambda-assets/static-site-forms/asset/package.json +4 -0
  31. package/dist/lib/patterns/aws/cdn.d.ts +19 -2
  32. package/dist/lib/patterns/aws/cdn.js +13 -2
  33. package/dist/lib/patterns/aws/cicdRole.d.ts +67 -0
  34. package/dist/lib/patterns/aws/cicdRole.js +68 -0
  35. package/dist/lib/patterns/aws/compute.js +9 -0
  36. package/dist/lib/patterns/aws/computeLambda.d.ts +38 -3
  37. package/dist/lib/patterns/aws/computeLambda.js +29 -2
  38. package/dist/lib/patterns/aws/hostedZone.d.ts +28 -0
  39. package/dist/lib/patterns/aws/hostedZone.js +150 -0
  40. package/dist/lib/patterns/aws/interfaces/pattern.d.ts +134 -5
  41. package/dist/lib/patterns/aws/interfaces/pattern.js +6 -0
  42. package/dist/lib/patterns/aws/managedAccount.d.ts +9 -0
  43. package/dist/lib/patterns/aws/managedAccount.js +55 -0
  44. package/dist/lib/patterns/aws/managedIdentityCenter.d.ts +4 -0
  45. package/dist/lib/patterns/aws/managedIdentityCenter.js +24 -0
  46. package/dist/lib/patterns/aws/managedOrganisation.d.ts +36 -0
  47. package/dist/lib/patterns/aws/managedOrganisation.js +97 -0
  48. package/dist/lib/patterns/aws/managedPlatform.d.ts +12 -0
  49. package/dist/lib/patterns/aws/managedPlatform.js +29 -0
  50. package/dist/lib/patterns/aws/pattern.d.ts +20 -5
  51. package/dist/lib/patterns/aws/pattern.js +12 -6
  52. package/dist/lib/patterns/aws/staticSite.d.ts +59 -0
  53. package/dist/lib/patterns/aws/staticSite.js +307 -0
  54. package/dist/lib/patterns/aws/subdomainHostedZone.d.ts +9 -0
  55. package/dist/lib/patterns/aws/subdomainHostedZone.js +39 -0
  56. package/dist/lib/resources/aws/cdn/cloudFront.d.ts +35 -2
  57. package/dist/lib/resources/aws/cdn/cloudFront.js +63 -25
  58. package/dist/lib/resources/aws/cdn/index.d.ts +1 -0
  59. package/dist/lib/resources/aws/cdn/index.js +1 -0
  60. package/dist/lib/resources/aws/cdn/responseHeadersPolicy.d.ts +56 -0
  61. package/dist/lib/resources/aws/cdn/responseHeadersPolicy.js +92 -0
  62. package/dist/lib/resources/aws/cicd/cicdRole.d.ts +65 -0
  63. package/dist/lib/resources/aws/cicd/cicdRole.js +191 -0
  64. package/dist/lib/resources/aws/compute/ecsFreeTier.d.ts +75 -0
  65. package/dist/lib/resources/aws/compute/ecsFreeTier.js +1 -0
  66. package/dist/lib/resources/aws/compute/ecsImages.js +3 -25
  67. package/dist/lib/resources/aws/compute/ecsSpot.d.ts +75 -0
  68. package/dist/lib/resources/aws/compute/ecsSpot.js +1 -0
  69. package/dist/lib/resources/aws/compute/imageTagParameter.d.ts +12 -0
  70. package/dist/lib/resources/aws/compute/imageTagParameter.js +32 -0
  71. package/dist/lib/resources/aws/compute/lambda.d.ts +7 -0
  72. package/dist/lib/resources/aws/compute/utilities/capacityProviderDrainWaiter.d.ts +20 -0
  73. package/dist/lib/resources/aws/compute/utilities/capacityProviderDrainWaiter.js +1 -0
  74. package/dist/lib/resources/aws/database/database.d.ts +14 -0
  75. package/dist/lib/resources/aws/database/database.js +28 -0
  76. package/dist/lib/resources/aws/database/databaseInstance.d.ts +15 -0
  77. package/dist/lib/resources/aws/database/databaseInstance.js +30 -0
  78. package/dist/lib/resources/aws/iam/identityCenter/attachManagedPolicy.d.ts +13 -0
  79. package/dist/lib/resources/aws/iam/identityCenter/attachManagedPolicy.js +52 -0
  80. package/dist/lib/resources/aws/iam/securityGroup.d.ts +5 -0
  81. package/dist/lib/resources/aws/iam/securityGroup.js +14 -0
  82. package/dist/lib/resources/aws/monitoring/monitoringRole.d.ts +28 -0
  83. package/dist/lib/resources/aws/monitoring/monitoringRole.js +125 -0
  84. package/dist/lib/resources/aws/networking/domainCertificate.d.ts +7 -0
  85. package/dist/lib/resources/aws/networking/domainCertificate.js +9 -7
  86. package/dist/lib/resources/aws/utilities/cfnOutput.d.ts +5 -0
  87. package/dist/lib/resources/aws/utilities/cfnOutput.js +1 -0
  88. package/dist/lib/utils/addSuffixToEmail.js +5 -1
  89. package/dist/lib/utils/capitalizeString.d.ts +1 -0
  90. package/dist/lib/utils/capitalizeString.js +7 -0
  91. package/package.json +7 -5
  92. package/dist/lib/config/aws/identityCenterMembership.d.ts +0 -11
  93. package/dist/lib/config/aws/identityCenterMembership.js +0 -61
@@ -0,0 +1,92 @@
1
+ import { Duration } from "aws-cdk-lib";
2
+ import { ResponseHeadersPolicy as CdkResponseHeadersPolicy, HeadersFrameOption, HeadersReferrerPolicy } from "aws-cdk-lib/aws-cloudfront";
3
+ const REFERRER_POLICY_MAP = {
4
+ "no-referrer": HeadersReferrerPolicy.NO_REFERRER,
5
+ "no-referrer-when-downgrade": HeadersReferrerPolicy.NO_REFERRER_WHEN_DOWNGRADE,
6
+ origin: HeadersReferrerPolicy.ORIGIN,
7
+ "origin-when-cross-origin": HeadersReferrerPolicy.ORIGIN_WHEN_CROSS_ORIGIN,
8
+ "same-origin": HeadersReferrerPolicy.SAME_ORIGIN,
9
+ "strict-origin": HeadersReferrerPolicy.STRICT_ORIGIN,
10
+ "strict-origin-when-cross-origin": HeadersReferrerPolicy.STRICT_ORIGIN_WHEN_CROSS_ORIGIN,
11
+ "unsafe-url": HeadersReferrerPolicy.UNSAFE_URL
12
+ };
13
+ const DEFAULT_HSTS_MAX_AGE_DAYS = 730;
14
+ const DEFAULT_COMMENT = "Fjall security headers policy";
15
+ /**
16
+ * Fjall wrapper for `aws-cdk-lib/aws-cloudfront.ResponseHeadersPolicy`.
17
+ *
18
+ * Wrapped on the description + SOC2-defaults trigger (NOT taggability — the
19
+ * resource is not taggable): it owns Fjall's uniform security-header defaults
20
+ * so every consumer inherits the same posture in one edit. Per
21
+ * `.claude/rules/generator-standards.md § Wrapper Routing Discipline`,
22
+ * `lib/{config,patterns}/` instantiate this class, never the raw L2.
23
+ *
24
+ * Defaults (all `override:true`): HSTS 730d+includeSubdomains+preload,
25
+ * X-Content-Type-Options: nosniff, X-Frame-Options: DENY,
26
+ * Referrer-Policy: strict-origin-when-cross-origin. CSP is opt-in only (§5.5).
27
+ */
28
+ export class SecurityHeadersPolicy extends CdkResponseHeadersPolicy {
29
+ constructor(scope, id, props) {
30
+ const securityHeadersBehavior = SecurityHeadersPolicy.buildSecurityHeaders(props);
31
+ const customHeaders = SecurityHeadersPolicy.buildCustomHeaders(props.customHeaders);
32
+ super(scope, id, {
33
+ responseHeadersPolicyName: props.policyName,
34
+ comment: props.comment ?? DEFAULT_COMMENT,
35
+ securityHeadersBehavior,
36
+ ...(customHeaders.length > 0 && {
37
+ customHeadersBehavior: { customHeaders }
38
+ })
39
+ });
40
+ }
41
+ static buildSecurityHeaders(props) {
42
+ const behaviour = {};
43
+ if (props.hsts !== false) {
44
+ const hsts = props.hsts ?? {};
45
+ behaviour.strictTransportSecurity = {
46
+ accessControlMaxAge: Duration.days(hsts.maxAgeDays ?? DEFAULT_HSTS_MAX_AGE_DAYS),
47
+ includeSubdomains: hsts.includeSubdomains ?? true,
48
+ preload: hsts.preload ?? true,
49
+ override: true
50
+ };
51
+ }
52
+ if (props.contentTypeOptions !== false) {
53
+ behaviour.contentTypeOptions = { override: true };
54
+ }
55
+ if (props.frameOptions !== false) {
56
+ behaviour.frameOptions = {
57
+ frameOption: props.frameOptions === "SAMEORIGIN"
58
+ ? HeadersFrameOption.SAMEORIGIN
59
+ : HeadersFrameOption.DENY,
60
+ override: true
61
+ };
62
+ }
63
+ if (props.referrerPolicy !== false) {
64
+ behaviour.referrerPolicy = {
65
+ referrerPolicy: REFERRER_POLICY_MAP[props.referrerPolicy ?? "strict-origin-when-cross-origin"],
66
+ override: true
67
+ };
68
+ }
69
+ // CSP is opt-in — only emitted when a policy string is supplied (§5.5).
70
+ if (props.contentSecurityPolicy !== undefined) {
71
+ behaviour.contentSecurityPolicy = {
72
+ contentSecurityPolicy: props.contentSecurityPolicy,
73
+ override: true
74
+ };
75
+ }
76
+ return behaviour;
77
+ }
78
+ static buildCustomHeaders(customHeaders) {
79
+ if (customHeaders === undefined) {
80
+ return [];
81
+ }
82
+ return Object.entries(customHeaders).map(([header, value]) => ({
83
+ header,
84
+ value,
85
+ override: true
86
+ }));
87
+ }
88
+ /** The underlying policy, for wiring into a distribution behaviour. */
89
+ getPolicy() {
90
+ return this;
91
+ }
92
+ }
@@ -0,0 +1,65 @@
1
+ import { Role, PolicyStatement } from "aws-cdk-lib/aws-iam";
2
+ import { type Construct } from "constructs";
3
+ /**
4
+ * Supported CI/CD providers
5
+ */
6
+ export type CICDProvider = "github-actions" | "buildkite" | "gitlab-ci";
7
+ /**
8
+ * Configuration for creating a CI/CD deploy role
9
+ */
10
+ export interface CICDRoleConfig {
11
+ /**
12
+ * The CI/CD provider (github-actions, buildkite, gitlab-ci)
13
+ */
14
+ provider: CICDProvider;
15
+ /**
16
+ * The application name to scope the role's permissions to
17
+ */
18
+ appName: string;
19
+ /**
20
+ * For GitHub Actions: repository (org/repo)
21
+ * For Buildkite: organization slug
22
+ * For GitLab CI: project path (group/project)
23
+ */
24
+ repositoryOrOrg: string;
25
+ /**
26
+ * Optional role name. Defaults to "FjallDeploy-{provider}-{appName}"
27
+ */
28
+ roleName?: string;
29
+ /**
30
+ * Optional IAM path for the role. Defaults to "/"
31
+ */
32
+ rolePath?: string;
33
+ /**
34
+ * Optional custom permissions. If not provided, default deployment permissions will be used.
35
+ */
36
+ customPermissions?: PolicyStatement[];
37
+ /**
38
+ * Whether to use existing OIDC provider or create a new one
39
+ * If true, will look for existing provider by URL
40
+ */
41
+ useExistingProvider?: boolean;
42
+ /**
43
+ * Optional ARN of existing OIDC provider (skips creation)
44
+ */
45
+ existingProviderArn?: string;
46
+ }
47
+ /**
48
+ * Factory to build a CI/CD deploy IAM role with OIDC authentication.
49
+ * Creates both the OIDC provider (if needed) and the deploy role with appropriate permissions.
50
+ */
51
+ export declare class CICDRoleFactory {
52
+ /**
53
+ * Build a CI/CD deploy role with OIDC authentication
54
+ */
55
+ static build(id: string, config: CICDRoleConfig): (app: Construct, scope: Construct) => Role;
56
+ /**
57
+ * Build trust policy conditions based on CI/CD provider
58
+ */
59
+ private static buildTrustConditions;
60
+ /**
61
+ * Add default deployment permissions to the role
62
+ */
63
+ private static addDefaultDeployPermissions;
64
+ }
65
+ export default CICDRoleFactory;
@@ -0,0 +1,191 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CICDRoleFactory = void 0;
4
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
5
+ const aws_iam_1 = require("aws-cdk-lib/aws-iam");
6
+ /**
7
+ * OIDC provider configurations for different CI/CD systems
8
+ */
9
+ const OIDC_CONFIGS = {
10
+ "github-actions": {
11
+ url: "https://token.actions.githubusercontent.com",
12
+ clientIds: ["sts.amazonaws.com"],
13
+ thumbprints: [
14
+ "6938fd4d98bab03faadb97b34396831e3780aea1",
15
+ "1c58a3a8518e8759bf075b76b750d4f2df264fcd"
16
+ ]
17
+ },
18
+ buildkite: {
19
+ url: "https://agent.buildkite.com",
20
+ clientIds: ["sts.amazonaws.com"],
21
+ thumbprints: ["9e99a48a9960b14926bb7f3b02e22da2b0ab7280"]
22
+ },
23
+ "gitlab-ci": {
24
+ url: "https://gitlab.com",
25
+ clientIds: ["https://gitlab.com"],
26
+ thumbprints: ["b3dd7606d2b5a8b4a13771dbecc9ee1cecafa38a"]
27
+ }
28
+ };
29
+ /**
30
+ * Factory to build a CI/CD deploy IAM role with OIDC authentication.
31
+ * Creates both the OIDC provider (if needed) and the deploy role with appropriate permissions.
32
+ */
33
+ class CICDRoleFactory {
34
+ /**
35
+ * Build a CI/CD deploy role with OIDC authentication
36
+ */
37
+ static build(id, config) {
38
+ return (_app, scope) => {
39
+ const providerConfig = OIDC_CONFIGS[config.provider];
40
+ const roleName = config.roleName || `FjallDeploy-${config.provider}-${config.appName}`;
41
+ // Create or reference OIDC provider
42
+ let oidcProvider;
43
+ if (config.existingProviderArn) {
44
+ // Use existing provider by ARN
45
+ oidcProvider = aws_iam_1.OpenIdConnectProvider.fromOpenIdConnectProviderArn(scope, `${id}OidcProvider`, config.existingProviderArn);
46
+ }
47
+ else {
48
+ // Create new OIDC provider
49
+ oidcProvider = new aws_iam_1.OpenIdConnectProvider(scope, `${id}OidcProvider`, {
50
+ url: providerConfig.url,
51
+ clientIds: providerConfig.clientIds,
52
+ thumbprints: providerConfig.thumbprints
53
+ });
54
+ }
55
+ // Build trust policy conditions based on provider
56
+ const conditions = this.buildTrustConditions(config.provider, config.repositoryOrOrg, oidcProvider.openIdConnectProviderIssuer);
57
+ // Create the role with OIDC web identity principal
58
+ const role = new aws_iam_1.Role(scope, id, {
59
+ roleName: roleName,
60
+ path: config.rolePath || "/",
61
+ assumedBy: new aws_iam_1.WebIdentityPrincipal(oidcProvider.openIdConnectProviderArn, conditions),
62
+ description: `CI/CD deploy role for ${config.provider} - ${config.appName}`
63
+ });
64
+ // Add permissions
65
+ if (config.customPermissions) {
66
+ config.customPermissions.forEach((statement) => {
67
+ role.addToPolicy(statement);
68
+ });
69
+ }
70
+ else {
71
+ this.addDefaultDeployPermissions(role);
72
+ }
73
+ // Export the role ARN
74
+ new aws_cdk_lib_1.CfnOutput(scope, `${id}Arn`, {
75
+ value: role.roleArn,
76
+ description: `ARN of the CI/CD deploy role for ${config.appName}`,
77
+ exportName: `${config.appName}-CICDRoleArn`
78
+ });
79
+ // Export the OIDC provider ARN
80
+ new aws_cdk_lib_1.CfnOutput(scope, `${id}ProviderArn`, {
81
+ value: oidcProvider.openIdConnectProviderArn,
82
+ description: `ARN of the OIDC provider for ${config.provider}`,
83
+ exportName: `${config.appName}-CICDProviderArn`
84
+ });
85
+ return role;
86
+ };
87
+ }
88
+ /**
89
+ * Build trust policy conditions based on CI/CD provider
90
+ */
91
+ static buildTrustConditions(provider, repositoryOrOrg, issuer) {
92
+ const conditions = {
93
+ StringEquals: {
94
+ [`${issuer}:aud`]: OIDC_CONFIGS[provider].clientIds[0]
95
+ }
96
+ };
97
+ // Add provider-specific subject claim conditions
98
+ switch (provider) {
99
+ case "github-actions":
100
+ conditions.StringLike = {
101
+ [`${issuer}:sub`]: `repo:${repositoryOrOrg}:*`
102
+ };
103
+ break;
104
+ case "buildkite":
105
+ conditions.StringLike = {
106
+ [`${issuer}:sub`]: `organization:${repositoryOrOrg}:*`
107
+ };
108
+ break;
109
+ case "gitlab-ci":
110
+ conditions.StringLike = {
111
+ [`${issuer}:sub`]: `project_path:${repositoryOrOrg}:*`
112
+ };
113
+ break;
114
+ }
115
+ return conditions;
116
+ }
117
+ /**
118
+ * Add default deployment permissions to the role
119
+ */
120
+ static addDefaultDeployPermissions(role) {
121
+ // CloudFormation permissions for CDK deployments
122
+ role.addToPolicy(new aws_iam_1.PolicyStatement({
123
+ effect: aws_iam_1.Effect.ALLOW,
124
+ actions: ["cloudformation:*"],
125
+ resources: ["*"]
126
+ }));
127
+ // S3 permissions for CDK assets
128
+ role.addToPolicy(new aws_iam_1.PolicyStatement({
129
+ effect: aws_iam_1.Effect.ALLOW,
130
+ actions: ["s3:*"],
131
+ resources: ["*"]
132
+ }));
133
+ // ECR permissions for container images
134
+ role.addToPolicy(new aws_iam_1.PolicyStatement({
135
+ effect: aws_iam_1.Effect.ALLOW,
136
+ actions: ["ecr:*"],
137
+ resources: ["*"]
138
+ }));
139
+ // ECS permissions for service deployments
140
+ role.addToPolicy(new aws_iam_1.PolicyStatement({
141
+ effect: aws_iam_1.Effect.ALLOW,
142
+ actions: ["ecs:*"],
143
+ resources: ["*"]
144
+ }));
145
+ // CloudWatch Logs permissions
146
+ role.addToPolicy(new aws_iam_1.PolicyStatement({
147
+ effect: aws_iam_1.Effect.ALLOW,
148
+ actions: ["logs:*"],
149
+ resources: ["*"]
150
+ }));
151
+ // IAM permissions for role management
152
+ role.addToPolicy(new aws_iam_1.PolicyStatement({
153
+ effect: aws_iam_1.Effect.ALLOW,
154
+ actions: [
155
+ "iam:PassRole",
156
+ "iam:GetRole",
157
+ "iam:CreateRole",
158
+ "iam:DeleteRole",
159
+ "iam:AttachRolePolicy",
160
+ "iam:DetachRolePolicy",
161
+ "iam:PutRolePolicy",
162
+ "iam:DeleteRolePolicy"
163
+ ],
164
+ resources: ["*"]
165
+ }));
166
+ // SSM and Secrets Manager for runtime configuration
167
+ role.addToPolicy(new aws_iam_1.PolicyStatement({
168
+ effect: aws_iam_1.Effect.ALLOW,
169
+ actions: [
170
+ "ssm:GetParameter",
171
+ "ssm:GetParameters",
172
+ "secretsmanager:GetSecretValue"
173
+ ],
174
+ resources: ["*"]
175
+ }));
176
+ // EC2 permissions for VPC/networking queries
177
+ role.addToPolicy(new aws_iam_1.PolicyStatement({
178
+ effect: aws_iam_1.Effect.ALLOW,
179
+ actions: [
180
+ "ec2:DescribeAvailabilityZones",
181
+ "ec2:DescribeVpcs",
182
+ "ec2:DescribeSubnets",
183
+ "ec2:DescribeSecurityGroups"
184
+ ],
185
+ resources: ["*"]
186
+ }));
187
+ }
188
+ }
189
+ exports.CICDRoleFactory = CICDRoleFactory;
190
+ exports.default = CICDRoleFactory;
191
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2ljZFJvbGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9saWIvcmVzb3VyY2VzL2F3cy9jaWNkL2NpY2RSb2xlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDZDQUF3QztBQUN4QyxpREFNNkI7QUFpRTdCOztHQUVHO0FBQ0gsTUFBTSxZQUFZLEdBQTZDO0lBQzdELGdCQUFnQixFQUFFO1FBQ2hCLEdBQUcsRUFBRSw2Q0FBNkM7UUFDbEQsU0FBUyxFQUFFLENBQUMsbUJBQW1CLENBQUM7UUFDaEMsV0FBVyxFQUFFO1lBQ1gsMENBQTBDO1lBQzFDLDBDQUEwQztTQUMzQztLQUNGO0lBQ0QsU0FBUyxFQUFFO1FBQ1QsR0FBRyxFQUFFLDZCQUE2QjtRQUNsQyxTQUFTLEVBQUUsQ0FBQyxtQkFBbUIsQ0FBQztRQUNoQyxXQUFXLEVBQUUsQ0FBQywwQ0FBMEMsQ0FBQztLQUMxRDtJQUNELFdBQVcsRUFBRTtRQUNYLEdBQUcsRUFBRSxvQkFBb0I7UUFDekIsU0FBUyxFQUFFLENBQUMsb0JBQW9CLENBQUM7UUFDakMsV0FBVyxFQUFFLENBQUMsMENBQTBDLENBQUM7S0FDMUQ7Q0FDRixDQUFDO0FBRUY7OztHQUdHO0FBQ0gsTUFBYSxlQUFlO0lBQzFCOztPQUVHO0lBQ0ksTUFBTSxDQUFDLEtBQUssQ0FDakIsRUFBVSxFQUNWLE1BQXNCO1FBRXRCLE9BQU8sQ0FBQyxJQUFlLEVBQUUsS0FBZ0IsRUFBRSxFQUFFO1lBQzNDLE1BQU0sY0FBYyxHQUFHLFlBQVksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDckQsTUFBTSxRQUFRLEdBQ1osTUFBTSxDQUFDLFFBQVEsSUFBSSxlQUFlLE1BQU0sQ0FBQyxRQUFRLElBQUksTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBRXhFLG9DQUFvQztZQUNwQyxJQUFJLFlBQW1DLENBQUM7WUFFeEMsSUFBSSxNQUFNLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztnQkFD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QUFDLEdBQUcsQ0FBQztTQUNqQixDQUFDLENBQ0gsQ0FBQztJQUNKLENBQUM7Q0FDRjtBQWpORCwwQ0FpTkM7QUFFRCxrQkFBZSxlQUFlLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDZm5PdXRwdXQgfSBmcm9tIFwiYXdzLWNkay1saWJcIjtcbmltcG9ydCB7XG4gIFJvbGUsXG4gIFdlYklkZW50aXR5UHJpbmNpcGFsLFxuICBPcGVuSWRDb25uZWN0UHJvdmlkZXIsXG4gIFBvbGljeVN0YXRlbWVudCxcbiAgRWZmZWN0XG59IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtaWFtXCI7XG5pbXBvcnQgeyB0eXBlIENvbnN0cnVjdCB9IGZyb20gXCJjb25zdHJ1Y3RzXCI7XG5cbi8qKlxuICogU3VwcG9ydGVkIENJL0NEIHByb3ZpZGVyc1xuICovXG5leHBvcnQgdHlwZSBDSUNEUHJvdmlkZXIgPSBcImdpdGh1Yi1hY3Rpb25zXCIgfCBcImJ1aWxka2l0ZVwiIHwgXCJnaXRsYWItY2lcIjtcblxuLyoqXG4gKiBPSURDIHByb3ZpZGVyIGNvbmZpZ3VyYXRpb25cbiAqL1xuaW50ZXJmYWNlIE9JRENQcm92aWRlckNvbmZpZyB7XG4gIHVybDogc3RyaW5nO1xuICBjbGllbnRJZHM6IHN0cmluZ1tdO1xuICB0aHVtYnByaW50czogc3RyaW5nW107XG59XG5cbi8qKlxuICogQ29uZmlndXJhdGlvbiBmb3IgY3JlYXRpbmcgYSBDSS9DRCBkZXBsb3kgcm9sZVxuICovXG5leHBvcnQgaW50ZXJmYWNlIENJQ0RSb2xlQ29uZmlnIHtcbiAgLyoqXG4gICAqIFRoZSBDSS9DRCBwcm92aWRlciAoZ2l0aHViLWFjdGlvbnMsIGJ1aWxka2l0ZSwgZ2l0bGFiLWNpKVxuICAgKi9cbiAgcHJvdmlkZXI6IENJQ0RQcm92aWRlcjtcblxuICAvKipcbiAgICogVGhlIGFwcGxpY2F0aW9uIG5hbWUgdG8gc2NvcGUgdGhlIHJvbGUncyBwZXJtaXNzaW9ucyB0b1xuICAgKi9cbiAgYXBwTmFtZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBGb3IgR2l0SHViIEFjdGlvbnM6IHJlcG9zaXRvcnkgKG9yZy9yZXBvKVxuICAgKiBGb3IgQnVpbGRraXRlOiBvcmdhbml6YXRpb24gc2x1Z1xuICAgKiBGb3IgR2l0TGFiIENJOiBwcm9qZWN0IHBhdGggKGdyb3VwL3Byb2plY3QpXG4gICAqL1xuICByZXBvc2l0b3J5T3JPcmc6IHN0cmluZztcblxuICAvKipcbiAgICogT3B0aW9uYWwgcm9sZSBuYW1lLiBEZWZhdWx0cyB0byBcIkZqYWxsRGVwbG95LXtwcm92aWRlcn0te2FwcE5hbWV9XCJcbiAgICovXG4gIHJvbGVOYW1lPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBPcHRpb25hbCBJQU0gcGF0aCBmb3IgdGhlIHJvbGUuIERlZmF1bHRzIHRvIFwiL1wiXG4gICAqL1xuICByb2xlUGF0aD86IHN0cmluZztcblxuICAvKipcbiAgICogT3B0aW9uYWwgY3VzdG9tIHBlcm1pc3Npb25zLiBJZiBub3QgcHJvdmlkZWQsIGRlZmF1bHQgZGVwbG95bWVudCBwZXJtaXNzaW9ucyB3aWxsIGJlIHVzZWQuXG4gICAqL1xuICBjdXN0b21QZXJtaXNzaW9ucz86IFBvbGljeVN0YXRlbWVudFtdO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIHVzZSBleGlzdGluZyBPSURDIHByb3ZpZGVyIG9yIGNyZWF0ZSBhIG5ldyBvbmVcbiAgICogSWYgdHJ1ZSwgd2lsbCBsb29rIGZvciBleGlzdGluZyBwcm92aWRlciBieSBVUkxcbiAgICovXG4gIHVzZUV4aXN0aW5nUHJvdmlkZXI/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBPcHRpb25hbCBBUk4gb2YgZXhpc3RpbmcgT0lEQyBwcm92aWRlciAoc2tpcHMgY3JlYXRpb24pXG4gICAqL1xuICBleGlzdGluZ1Byb3ZpZGVyQXJuPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIE9JREMgcHJvdmlkZXIgY29uZmlndXJhdGlvbnMgZm9yIGRpZmZlcmVudCBDSS9DRCBzeXN0ZW1zXG4gKi9cbmNvbnN0IE9JRENfQ09ORklHUzogUmVjb3JkPENJQ0RQcm92aWRlciwgT0lEQ1Byb3ZpZGVyQ29uZmlnPiA9IHtcbiAgXCJnaXRodWItYWN0aW9uc1wiOiB7XG4gICAgdXJsOiBcImh0dHBzOi8vdG9rZW4uYWN0aW9ucy5naXRodWJ1c2VyY29udGVudC5jb21cIixcbiAgICBjbGllbnRJZHM6IFtcInN0cy5hbWF6b25hd3MuY29tXCJdLFxuICAgIHRodW1icHJpbnRzOiBbXG4gICAgICBcIjY5MzhmZDRkOThiYWIwM2ZhYWRiOTdiMzQzOTY4MzFlMzc4MGFlYTFcIixcbiAgICAgIFwiMWM1OGEzYTg1MThlODc1OWJmMDc1Yjc2Yjc1MGQ0ZjJkZjI2NGZjZFwiXG4gICAgXVxuICB9LFxuICBidWlsZGtpdGU6IHtcbiAgICB1cmw6IFwiaHR0cHM6Ly9hZ2VudC5idWlsZGtpdGUuY29tXCIsXG4gICAgY2xpZW50SWRzOiBbXCJzdHMuYW1hem9uYXdzLmNvbVwiXSxcbiAgICB0aHVtYnByaW50czogW1wiOWU5OWE0OGE5OTYwYjE0OTI2YmI3ZjNiMDJlMjJkYTJiMGFiNzI4MFwiXVxuICB9LFxuICBcImdpdGxhYi1jaVwiOiB7XG4gICAgdXJsOiBcImh0dHBzOi8vZ2l0bGFiLmNvbVwiLFxuICAgIGNsaWVudElkczogW1wiaHR0cHM6Ly9naXRsYWIuY29tXCJdLFxuICAgIHRodW1icHJpbnRzOiBbXCJiM2RkNzYwNmQyYjVhOGI0YTEzNzcxZGJlY2M5ZWUxY2VjYWZhMzhhXCJdXG4gIH1cbn07XG5cbi8qKlxuICogRmFjdG9yeSB0byBidWlsZCBhIENJL0NEIGRlcGxveSBJQU0gcm9sZSB3aXRoIE9JREMgYXV0aGVudGljYXRpb24uXG4gKiBDcmVhdGVzIGJvdGggdGhlIE9JREMgcHJvdmlkZXIgKGlmIG5lZWRlZCkgYW5kIHRoZSBkZXBsb3kgcm9sZSB3aXRoIGFwcHJvcHJpYXRlIHBlcm1pc3Npb25zLlxuICovXG5leHBvcnQgY2xhc3MgQ0lDRFJvbGVGYWN0b3J5IHtcbiAgLyoqXG4gICAqIEJ1aWxkIGEgQ0kvQ0QgZGVwbG95IHJvbGUgd2l0aCBPSURDIGF1dGhlbnRpY2F0aW9uXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGJ1aWxkKFxuICAgIGlkOiBzdHJpbmcsXG4gICAgY29uZmlnOiBDSUNEUm9sZUNvbmZpZ1xuICApOiAoYXBwOiBDb25zdHJ1Y3QsIHNjb3BlOiBDb25zdHJ1Y3QpID0+IFJvbGUge1xuICAgIHJldHVybiAoX2FwcDogQ29uc3RydWN0LCBzY29wZTogQ29uc3RydWN0KSA9PiB7XG4gICAgICBjb25zdCBwcm92aWRlckNvbmZpZyA9IE9JRENfQ09ORklHU1tjb25maWcucHJvdmlkZXJdO1xuICAgICAgY29uc3Qgcm9sZU5hbWUgPVxuICAgICAgICBjb25maWcucm9sZU5hbWUgfHwgYEZqYWxsRGVwbG95LSR7Y29uZmlnLnByb3ZpZGVyfS0ke2NvbmZpZy5hcHBOYW1lfWA7XG5cbiAgICAgIC8vIENyZWF0ZSBvciByZWZlcmVuY2UgT0lEQyBwcm92aWRlclxuICAgICAgbGV0IG9pZGNQcm92aWRlcjogT3BlbklkQ29ubmVjdFByb3ZpZGVyO1xuXG4gICAgICBpZiAoY29uZmlnLmV4aXN0aW5nUHJvdmlkZXJBcm4pIHtcbiAgICAgICAgLy8gVXNlIGV4aXN0aW5nIHByb3ZpZGVyIGJ5IEFSTlxuICAgICAgICBvaWRjUHJvdmlkZXIgPSBPcGVuSWRDb25uZWN0UHJvdmlkZXIuZnJvbU9wZW5JZENvbm5lY3RQcm92aWRlckFybihcbiAgICAgICAgICBzY29wZSxcbiAgICAgICAgICBgJHtpZH1PaWRjUHJvdmlkZXJgLFxuICAgICAgICAgIGNvbmZpZy5leGlzdGluZ1Byb3ZpZGVyQXJuXG4gICAgICAgICk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBDcmVhdGUgbmV3IE9JREMgcHJvdmlkZXJcbiAgICAgICAgb2lkY1Byb3ZpZGVyID0gbmV3IE9wZW5JZENvbm5lY3RQcm92aWRlcihzY29wZSwgYCR7aWR9T2lkY1Byb3ZpZGVyYCwge1xuICAgICAgICAgIHVybDogcHJvdmlkZXJDb25maWcudXJsLFxuICAgICAgICAgIGNsaWVudElkczogcHJvdmlkZXJDb25maWcuY2xpZW50SWRzLFxuICAgICAgICAgIHRodW1icHJpbnRzOiBwcm92aWRlckNvbmZpZy50aHVtYnByaW50c1xuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgLy8gQnVpbGQgdHJ1c3QgcG9saWN5IGNvbmRpdGlvbnMgYmFzZWQgb24gcHJvdmlkZXJcbiAgICAgIGNvbnN0IGNvbmRpdGlvbnMgPSB0aGlzLmJ1aWxkVHJ1c3RDb25kaXRpb25zKFxuICAgICAgICBjb25maWcucHJvdmlkZXIsXG4gICAgICAgIGNvbmZpZy5yZXBvc2l0b3J5T3JPcmcsXG4gICAgICAgIG9pZGNQcm92aWRlci5vcGVuSWRDb25uZWN0UHJvdmlkZXJJc3N1ZXJcbiAgICAgICk7XG5cbiAgICAgIC8vIENyZWF0ZSB0aGUgcm9sZSB3aXRoIE9JREMgd2ViIGlkZW50aXR5IHByaW5jaXBhbFxuICAgICAgY29uc3Qgcm9sZSA9IG5ldyBSb2xlKHNjb3BlLCBpZCwge1xuICAgICAgICByb2xlTmFtZTogcm9sZU5hbWUsXG4gICAgICAgIHBhdGg6IGNvbmZpZy5yb2xlUGF0aCB8fCBcIi9cIixcbiAgICAgICAgYXNzdW1lZEJ5OiBuZXcgV2ViSWRlbnRpdHlQcmluY2lwYWwoXG4gICAgICAgICAgb2lkY1Byb3ZpZGVyLm9wZW5JZENvbm5lY3RQcm92aWRlckFybixcbiAgICAgICAgICBjb25kaXRpb25zXG4gICAgICAgICksXG4gICAgICAgIGRlc2NyaXB0aW9uOiBgQ0kvQ0QgZGVwbG95IHJvbGUgZm9yICR7Y29uZmlnLnByb3ZpZGVyfSAtICR7Y29uZmlnLmFwcE5hbWV9YFxuICAgICAgfSk7XG5cbiAgICAgIC8vIEFkZCBwZXJtaXNzaW9uc1xuICAgICAgaWYgKGNvbmZpZy5jdXN0b21QZXJtaXNzaW9ucykge1xuICAgICAgICBjb25maWcuY3VzdG9tUGVybWlzc2lvbnMuZm9yRWFjaCgoc3RhdGVtZW50KSA9PiB7XG4gICAgICAgICAgcm9sZS5hZGRUb1BvbGljeShzdGF0ZW1lbnQpO1xuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuYWRkRGVmYXVsdERlcGxveVBlcm1pc3Npb25zKHJvbGUpO1xuICAgICAgfVxuXG4gICAgICAvLyBFeHBvcnQgdGhlIHJvbGUgQVJOXG4gICAgICBuZXcgQ2ZuT3V0cHV0KHNjb3BlLCBgJHtpZH1Bcm5gLCB7XG4gICAgICAgIHZhbHVlOiByb2xlLnJvbGVBcm4sXG4gICAgICAgIGRlc2NyaXB0aW9uOiBgQVJOIG9mIHRoZSBDSS9DRCBkZXBsb3kgcm9sZSBmb3IgJHtjb25maWcuYXBwTmFtZX1gLFxuICAgICAgICBleHBvcnROYW1lOiBgJHtjb25maWcuYXBwTmFtZX0tQ0lDRFJvbGVBcm5gXG4gICAgICB9KTtcblxuICAgICAgLy8gRXhwb3J0IHRoZSBPSURDIHByb3ZpZGVyIEFSTlxuICAgICAgbmV3IENmbk91dHB1dChzY29wZSwgYCR7aWR9UHJvdmlkZXJBcm5gLCB7XG4gICAgICAgIHZhbHVlOiBvaWRjUHJvdmlkZXIub3BlbklkQ29ubmVjdFByb3ZpZGVyQXJuLFxuICAgICAgICBkZXNjcmlwdGlvbjogYEFSTiBvZiB0aGUgT0lEQyBwcm92aWRlciBmb3IgJHtjb25maWcucHJvdmlkZXJ9YCxcbiAgICAgICAgZXhwb3J0TmFtZTogYCR7Y29uZmlnLmFwcE5hbWV9LUNJQ0RQcm92aWRlckFybmBcbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4gcm9sZTtcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkIHRydXN0IHBvbGljeSBjb25kaXRpb25zIGJhc2VkIG9uIENJL0NEIHByb3ZpZGVyXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyBidWlsZFRydXN0Q29uZGl0aW9ucyhcbiAgICBwcm92aWRlcjogQ0lDRFByb3ZpZGVyLFxuICAgIHJlcG9zaXRvcnlPck9yZzogc3RyaW5nLFxuICAgIGlzc3Vlcjogc3RyaW5nXG4gICk6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHtcbiAgICBjb25zdCBjb25kaXRpb25zOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHtcbiAgICAgIFN0cmluZ0VxdWFsczoge1xuICAgICAgICBbYCR7aXNzdWVyfTphdWRgXTogT0lEQ19DT05GSUdTW3Byb3ZpZGVyXS5jbGllbnRJZHNbMF1cbiAgICAgIH1cbiAgICB9O1xuXG4gICAgLy8gQWRkIHByb3ZpZGVyLXNwZWNpZmljIHN1YmplY3QgY2xhaW0gY29uZGl0aW9uc1xuICAgIHN3aXRjaCAocHJvdmlkZXIpIHtcbiAgICAgIGNhc2UgXCJnaXRodWItYWN0aW9uc1wiOlxuICAgICAgICBjb25kaXRpb25zLlN0cmluZ0xpa2UgPSB7XG4gICAgICAgICAgW2Ake2lzc3Vlcn06c3ViYF06IGByZXBvOiR7cmVwb3NpdG9yeU9yT3JnfToqYFxuICAgICAgICB9O1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSBcImJ1aWxka2l0ZVwiOlxuICAgICAgICBjb25kaXRpb25zLlN0cmluZ0xpa2UgPSB7XG4gICAgICAgICAgW2Ake2lzc3Vlcn06c3ViYF06IGBvcmdhbml6YXRpb246JHtyZXBvc2l0b3J5T3JPcmd9OipgXG4gICAgICAgIH07XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIFwiZ2l0bGFiLWNpXCI6XG4gICAgICAgIGNvbmRpdGlvbnMuU3RyaW5nTGlrZSA9IHtcbiAgICAgICAgICBbYCR7aXNzdWVyfTpzdWJgXTogYHByb2plY3RfcGF0aDoke3JlcG9zaXRvcnlPck9yZ306KmBcbiAgICAgICAgfTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbmRpdGlvbnM7XG4gIH1cblxuICAvKipcbiAgICogQWRkIGRlZmF1bHQgZGVwbG95bWVudCBwZXJtaXNzaW9ucyB0byB0aGUgcm9sZVxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgYWRkRGVmYXVsdERlcGxveVBlcm1pc3Npb25zKHJvbGU6IFJvbGUpOiB2b2lkIHtcbiAgICAvLyBDbG91ZEZvcm1hdGlvbiBwZXJtaXNzaW9ucyBmb3IgQ0RLIGRlcGxveW1lbnRzXG4gICAgcm9sZS5hZGRUb1BvbGljeShcbiAgICAgIG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICBlZmZlY3Q6IEVmZmVjdC5BTExPVyxcbiAgICAgICAgYWN0aW9uczogW1wiY2xvdWRmb3JtYXRpb246KlwiXSxcbiAgICAgICAgcmVzb3VyY2VzOiBbXCIqXCJdXG4gICAgICB9KVxuICAgICk7XG5cbiAgICAvLyBTMyBwZXJtaXNzaW9ucyBmb3IgQ0RLIGFzc2V0c1xuICAgIHJvbGUuYWRkVG9Qb2xpY3koXG4gICAgICBuZXcgUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgZWZmZWN0OiBFZmZlY3QuQUxMT1csXG4gICAgICAgIGFjdGlvbnM6IFtcInMzOipcIl0sXG4gICAgICAgIHJlc291cmNlczogW1wiKlwiXVxuICAgICAgfSlcbiAgICApO1xuXG4gICAgLy8gRUNSIHBlcm1pc3Npb25zIGZvciBjb250YWluZXIgaW1hZ2VzXG4gICAgcm9sZS5hZGRUb1BvbGljeShcbiAgICAgIG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICBlZmZlY3Q6IEVmZmVjdC5BTExPVyxcbiAgICAgICAgYWN0aW9uczogW1wiZWNyOipcIl0sXG4gICAgICAgIHJlc291cmNlczogW1wiKlwiXVxuICAgICAgfSlcbiAgICApO1xuXG4gICAgLy8gRUNTIHBlcm1pc3Npb25zIGZvciBzZXJ2aWNlIGRlcGxveW1lbnRzXG4gICAgcm9sZS5hZGRUb1BvbGljeShcbiAgICAgIG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICBlZmZlY3Q6IEVmZmVjdC5BTExPVyxcbiAgICAgICAgYWN0aW9uczogW1wiZWNzOipcIl0sXG4gICAgICAgIHJlc291cmNlczogW1wiKlwiXVxuICAgICAgfSlcbiAgICApO1xuXG4gICAgLy8gQ2xvdWRXYXRjaCBMb2dzIHBlcm1pc3Npb25zXG4gICAgcm9sZS5hZGRUb1BvbGljeShcbiAgICAgIG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICBlZmZlY3Q6IEVmZmVjdC5BTExPVyxcbiAgICAgICAgYWN0aW9uczogW1wibG9nczoqXCJdLFxuICAgICAgICByZXNvdXJjZXM6IFtcIipcIl1cbiAgICAgIH0pXG4gICAgKTtcblxuICAgIC8vIElBTSBwZXJtaXNzaW9ucyBmb3Igcm9sZSBtYW5hZ2VtZW50XG4gICAgcm9sZS5hZGRUb1BvbGljeShcbiAgICAgIG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICBlZmZlY3Q6IEVmZmVjdC5BTExPVyxcbiAgICAgICAgYWN0aW9uczogW1xuICAgICAgICAgIFwiaWFtOlBhc3NSb2xlXCIsXG4gICAgICAgICAgXCJpYW06R2V0Um9sZVwiLFxuICAgICAgICAgIFwiaWFtOkNyZWF0ZVJvbGVcIixcbiAgICAgICAgICBcImlhbTpEZWxldGVSb2xlXCIsXG4gICAgICAgICAgXCJpYW06QXR0YWNoUm9sZVBvbGljeVwiLFxuICAgICAgICAgIFwiaWFtOkRldGFjaFJvbGVQb2xpY3lcIixcbiAgICAgICAgICBcImlhbTpQdXRSb2xlUG9saWN5XCIsXG4gICAgICAgICAgXCJpYW06RGVsZXRlUm9sZVBvbGljeVwiXG4gICAgICAgIF0sXG4gICAgICAgIHJlc291cmNlczogW1wiKlwiXVxuICAgICAgfSlcbiAgICApO1xuXG4gICAgLy8gU1NNIGFuZCBTZWNyZXRzIE1hbmFnZXIgZm9yIHJ1bnRpbWUgY29uZmlndXJhdGlvblxuICAgIHJvbGUuYWRkVG9Qb2xpY3koXG4gICAgICBuZXcgUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgZWZmZWN0OiBFZmZlY3QuQUxMT1csXG4gICAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAgICBcInNzbTpHZXRQYXJhbWV0ZXJcIixcbiAgICAgICAgICBcInNzbTpHZXRQYXJhbWV0ZXJzXCIsXG4gICAgICAgICAgXCJzZWNyZXRzbWFuYWdlcjpHZXRTZWNyZXRWYWx1ZVwiXG4gICAgICAgIF0sXG4gICAgICAgIHJlc291cmNlczogW1wiKlwiXVxuICAgICAgfSlcbiAgICApO1xuXG4gICAgLy8gRUMyIHBlcm1pc3Npb25zIGZvciBWUEMvbmV0d29ya2luZyBxdWVyaWVzXG4gICAgcm9sZS5hZGRUb1BvbGljeShcbiAgICAgIG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICBlZmZlY3Q6IEVmZmVjdC5BTExPVyxcbiAgICAgICAgYWN0aW9uczogW1xuICAgICAgICAgIFwiZWMyOkRlc2NyaWJlQXZhaWxhYmlsaXR5Wm9uZXNcIixcbiAgICAgICAgICBcImVjMjpEZXNjcmliZVZwY3NcIixcbiAgICAgICAgICBcImVjMjpEZXNjcmliZVN1Ym5ldHNcIixcbiAgICAgICAgICBcImVjMjpEZXNjcmliZVNlY3VyaXR5R3JvdXBzXCJcbiAgICAgICAgXSxcbiAgICAgICAgcmVzb3VyY2VzOiBbXCIqXCJdXG4gICAgICB9KVxuICAgICk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgQ0lDRFJvbGVGYWN0b3J5O1xuIl19
@@ -0,0 +1,75 @@
1
+ import { ContainerImage, type RepositoryImage } from "aws-cdk-lib/aws-ecs";
2
+ import { Connections, type IConnectable, type IVpc } from "aws-cdk-lib/aws-ec2";
3
+ import { Construct } from "constructs";
4
+ import { type StackBuilder } from "../base/awsStack";
5
+ import { type SecretValue } from "aws-cdk-lib";
6
+ import { type IManagedPolicy, PolicyDocument, Role } from "aws-cdk-lib/aws-iam";
7
+ import { Repository } from "aws-cdk-lib/aws-ecr";
8
+ import { type KeyValue } from "../../../types";
9
+ export declare enum ScalingType {
10
+ CPU = "ECSServiceAverageCPUUtilization",
11
+ MEMORY = "ECSServiceAverageMemoryUtilization"
12
+ }
13
+ export interface ContainerSecret {
14
+ [key: string]: SecretValue;
15
+ }
16
+ type Ec2ClusterProps = {
17
+ ecrRepository: Repository | RepositoryImage | string;
18
+ clusterName: string;
19
+ containerEntryPoint?: string[];
20
+ containerCommand?: string[];
21
+ containerEnvironment?: KeyValue;
22
+ containerSecrets?: ContainerSecret;
23
+ containerPort?: number;
24
+ cpu?: number;
25
+ parentDomain?: string;
26
+ desiredCount?: number;
27
+ healthCheckPath?: string;
28
+ listenerPort?: number;
29
+ memoryLimitMiB?: number;
30
+ publicLoadBalancer?: boolean;
31
+ scalingType?: ScalingType;
32
+ serviceName: string;
33
+ taskRoleInlinePolicies?: {
34
+ [name: string]: PolicyDocument;
35
+ };
36
+ taskRoleManagedPolicies?: IManagedPolicy[];
37
+ vpc?: IVpc;
38
+ };
39
+ export default class Ec2Cluster extends Construct implements IConnectable {
40
+ connections: Connections;
41
+ private cluster;
42
+ private autoScalingGroup;
43
+ private asgSecurityGroup;
44
+ private asgCapacityProvider;
45
+ private loadBalancer;
46
+ private loadBalancerSecurityGroup;
47
+ private loadBalancerListener;
48
+ private executionRole;
49
+ private taskDefinition;
50
+ private containerDefinition;
51
+ private ec2Service;
52
+ private scalingPolicy;
53
+ private hostedZone;
54
+ private certificate;
55
+ private aRecord;
56
+ private secrets;
57
+ constructor(scope: Construct, id: string, props: Ec2ClusterProps);
58
+ addCluster(props: Ec2ClusterProps): void;
59
+ addAutoScalingGroup(props: Ec2ClusterProps): void;
60
+ addSecrets(props: Ec2ClusterProps): void;
61
+ addExecutionRole(props: Ec2ClusterProps): void;
62
+ addTaskDefinition(props: Ec2ClusterProps): void;
63
+ addContainerDefinition(props: Ec2ClusterProps): void;
64
+ addEc2Service(props: Ec2ClusterProps): void;
65
+ addScalingPolicy(props: Ec2ClusterProps): void;
66
+ addLoadBalancer(props: Ec2ClusterProps): void;
67
+ removeAutoScalingGroup(): void;
68
+ addLoadBalancerListener(props: Ec2ClusterProps): void;
69
+ addHostedZone(props: Ec2ClusterProps): void;
70
+ registerLoadBalancerTargets(props: Ec2ClusterProps): void;
71
+ getImage(props: Ec2ClusterProps): ContainerImage;
72
+ getTaskRole(): Role | undefined;
73
+ static build(id: string, props: Ec2ClusterProps): (sb: StackBuilder) => Construct;
74
+ }
75
+ export {};