diff --git a/packages/@aws-cdk/aws-eks/lib/kubectl-handler/helm/__init__.py b/packages/@aws-cdk/aws-eks/lib/kubectl-handler/helm/__init__.py index c9120c1926e03..286976ced219a 100644 --- a/packages/@aws-cdk/aws-eks/lib/kubectl-handler/helm/__init__.py +++ b/packages/@aws-cdk/aws-eks/lib/kubectl-handler/helm/__init__.py @@ -111,7 +111,7 @@ def get_oci_cmd(repository, version): region = os.environ.get('AWS_REGION', 'us-east-1') cmnd = [ - f"aws ecr-public get-login-password --region {region} | " \ + f"aws ecr-public get-login-password --region us-east-1 | " \ f"helm registry login --username AWS --password-stdin {public_registry['registry']}; helm pull {repository} --version {version} --untar" ] else: diff --git a/packages/@aws-cdk/aws-eks/lib/kubectl-provider.ts b/packages/@aws-cdk/aws-eks/lib/kubectl-provider.ts index 93978ff1c1f1c..1c6236615dcd5 100644 --- a/packages/@aws-cdk/aws-eks/lib/kubectl-provider.ts +++ b/packages/@aws-cdk/aws-eks/lib/kubectl-provider.ts @@ -165,6 +165,11 @@ export class KubectlProvider extends NestedStack implements IKubectlProvider { iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonEC2ContainerRegistryReadOnly'), ); + // For OCI helm chart public ECR authorization. + this.handlerRole.addManagedPolicy( + iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonElasticContainerRegistryPublicReadOnly'), + ); + // allow this handler to assume the kubectl role cluster.kubectlRole.grant(this.handlerRole, 'sts:AssumeRole'); diff --git a/packages/@aws-cdk/aws-eks/test/cluster.test.ts b/packages/@aws-cdk/aws-eks/test/cluster.test.ts index 6dc7ebac05d97..92e010a8ac378 100644 --- a/packages/@aws-cdk/aws-eks/test/cluster.test.ts +++ b/packages/@aws-cdk/aws-eks/test/cluster.test.ts @@ -2103,6 +2103,13 @@ describe('cluster', () => { ':iam::aws:policy/AmazonEC2ContainerRegistryReadOnly', ]], }, + { + 'Fn::Join': ['', [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly', + ]], + }, ], }); }); @@ -2297,6 +2304,13 @@ describe('cluster', () => { ':iam::aws:policy/AmazonEC2ContainerRegistryReadOnly', ]], }, + { + 'Fn::Join': ['', [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly', + ]], + }, ], }); }); diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.d.ts b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js similarity index 71% rename from packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js index a4c5ba868774f..c9dc1b8d2c19a 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js +++ b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js @@ -256,8 +256,8 @@ function analyzeUpdate(oldProps, newProps) { const oldEnc = oldProps.encryptionConfig || {}; return { replaceName: newProps.name !== oldProps.name, - replaceVpc: JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), + replaceVpc: JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), @@ -270,4 +270,4 @@ function analyzeUpdate(oldProps, newProps) { function setsEqual(first, second) { return first.size === second.size && [...first].every((e) => second.has(e)); } -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0lBQ2hHLENBQUM7SUFoQkQsSUFBVyxXQUFXO1FBQ3BCLElBQUksQ0FBQyxJQUFJLENBQUMsa0JBQWtCLEVBQUU7WUFDNUIsTUFBTSxJQUFJLEtBQUssQ0FBQyw0REFBNEQsQ0FBQyxDQUFDO1NBQy9FO1FBRUQsT0FBTyxJQUFJLENBQUMsa0JBQWtCLENBQUM7SUFDakMsQ0FBQztJQVlELFNBQVM7SUFDVCxTQUFTO0lBQ1QsU0FBUztJQUVDLEtBQUssQ0FBQyxRQUFRO1FBQ3RCLE9BQU8sQ0FBQyxHQUFHLENBQUMsMENBQTBDLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3JHLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRTtZQUMxQixNQUFNLElBQUksS0FBSyxDQUFDLHVCQUF1QixDQUFDLENBQUM7U0FDMUM7UUFFRCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFD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LENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztRQUNuRSxhQUFhLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBa0IsRUFBRSxNQUFtQjtJQUN4RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgRWtzQ2xpZW50LCBSZXNvdXJjZUV2ZW50LCBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX05BTUVfTEVOID0gMTAwO1xuXG5leHBvcnQgY2xhc3MgQ2x1c3RlclJlc291cmNlSGFuZGxlciBleHRlbmRzIFJlc291cmNlSGFuZGxlciB7XG4gIHB1YmxpYyBnZXQgY2x1c3Rlck5hbWUoKSB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZGV0ZXJtaW5lIGNsdXN0ZXIgbmFtZSB3aXRob3V0IHBoeXNpY2FsIHJlc291cmNlIElEJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PjtcblxuICBjb25zdHJ1Y3Rvcihla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICBzdXBlcihla3MsIGV2ZW50KTtcblxuICAgIHRoaXMubmV3UHJvcHMgPSBwYXJzZVByb3BzKHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLm9sZFByb3BzID0gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnID8gcGFyc2VQcm9wcyhldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMpIDoge307XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gQ1JFQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCdvbkNyZWF0ZTogY3JlYXRpbmcgY2x1c3RlciB3aXRoIG9wdGlvbnM6JywgSlNPTi5zdHJpbmdpZnkodGhpcy5uZXdQcm9wcywgdW5kZWZpbmVkLCAyKSk7XG4gICAgaWYgKCF0aGlzLm5ld1Byb3BzLnJvbGVBcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJyb2xlQXJuXCIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyTmFtZSA9IHRoaXMubmV3UHJvcHMubmFtZSB8fCB0aGlzLmdlbmVyYXRlQ2x1c3Rlck5hbWUoKTtcblxuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmVrcy5jcmVhdGVDbHVzdGVyKHtcbiAgICAgIC4uLnRoaXMubmV3UHJvcHMsXG4gICAgICBuYW1lOiBjbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcC5jbHVzdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBjbHVzdGVyICR7Y2x1c3Rlck5hbWV9OiBDcmVhdGVDbHVzdGVyIHJldHVybmVkIHdpdGhvdXQgY2x1c3RlciBpbmZvcm1hdGlvbmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHJlc3AuY2x1c3Rlci5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIERFTEVURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25EZWxldGUoKTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgb25EZWxldGU6IGRlbGV0aW5nIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfWApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVrcy5kZWxldGVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyICR7dGhpcy5jbHVzdGVyTmFtZX0gbm90IGZvdW5kLCBpZGVtcG90ZW50bHkgc3VjY2VlZGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coYGlzRGVsZXRlQ29tcGxldGU6IHdhaXRpbmcgZm9yIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSB0byBiZSBkZWxldGVkYCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJldHVybmVkOicsIEpTT04uc3RyaW5naWZ5KHJlc3AsIHVuZGVmaW5lZCwgMikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICBjb25zb2xlLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgY2x1c3RlciBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0cnVlIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgZXJyb3I6JywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIFVQREFURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IGFuYWx5emVVcGRhdGUodGhpcy5vbGRQcm9wcywgdGhpcy5uZXdQcm9wcyk7XG4gICAgY29uc29sZS5sb2coJ29uVXBkYXRlOicsIEpTT04uc3RyaW5naWZ5KHsgdXBkYXRlcyB9LCB1bmRlZmluZWQsIDIpKTtcblxuICAgIC8vIHVwZGF0ZXMgdG8gZW5jcnlwdGlvbiBjb25maWcgaXMgbm90IHN1cHBvcnRlZFxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUVuY3J5cHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHVwZGF0ZSBjbHVzdGVyIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZXJlIGlzIGFuIHVwZGF0ZSB0aGF0IHJlcXVpcmVzIHJlcGxhY2VtZW50LCBnbyBhaGVhZCBhbmQganVzdCBjcmVhdGVcbiAgICAvLyBhIG5ldyBjbHVzdGVyIHdpdGggdGhlIG5ldyBjb25maWcuIFRoZSBvbGQgY2x1c3RlciB3aWxsIGF1dG9tYXRpY2FsbHkgYmVcbiAgICAvLyBkZWxldGVkIGJ5IGNsb3VkZm9ybWF0aW9uIHVwb24gc3VjY2Vzcy5cbiAgICBpZiAodXBkYXRlcy5yZXBsYWNlTmFtZSB8fCB1cGRhdGVzLnJlcGxhY2VSb2xlIHx8IHVwZGF0ZXMucmVwbGFjZVZwYykge1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgcmVwbGFjaW5nIHRoaXMgY2x1c3RlciBhbmQgdGhlIGNsdXN0ZXIgaGFzIGFuIGV4cGxpY2l0XG4gICAgICAvLyBwaHlzaWNhbCBuYW1lLCB0aGUgY3JlYXRpb24gb2YgdGhlIG5ldyBjbHVzdGVyIHdpbGwgZmFpbCB3aXRoIFwidGhlcmUgaXNcbiAgICAgIC8vIGFscmVhZHkgYSBjbHVzdGVyIHdpdGggdGhhdCBuYW1lXCIuIHRoaXMgaXMgYSBjb21tb24gYmVoYXZpb3IgZm9yXG4gICAgICAvLyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZXMgdGhhdCBzdXBwb3J0IHNwZWNpZnlpbmcgYSBwaHlzaWNhbCBuYW1lLlxuICAgICAgaWYgKHRoaXMub2xkUHJvcHMubmFtZSA9PT0gdGhpcy5uZXdQcm9wcy5uYW1lICYmIHRoaXMub2xkUHJvcHMubmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXBsYWNlIGNsdXN0ZXIgXCIke3RoaXMub2xkUHJvcHMubmFtZX1cIiBzaW5jZSBpdCBoYXMgYW4gZXhwbGljaXQgcGh5c2ljYWwgbmFtZS4gRWl0aGVyIHJlbmFtZSB0aGUgY2x1c3RlciBvciByZW1vdmUgdGhlIFwibmFtZVwiIGNvbmZpZ3VyYXRpb25gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub25DcmVhdGUoKTtcbiAgICB9XG5cbiAgICAvLyBpZiBhIHZlcnNpb24gdXBkYXRlIGlzIHJlcXVpcmVkLCBpc3N1ZSB0aGUgdmVyc2lvbiB1cGRhdGVcbiAgICBpZiAodXBkYXRlcy51cGRhdGVWZXJzaW9uKSB7XG4gICAgICBpZiAoIXRoaXMubmV3UHJvcHMudmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZW1vdmUgY2x1c3RlciB2ZXJzaW9uIGNvbmZpZ3VyYXRpb24uIEN1cnJlbnQgdmVyc2lvbiBpcyAke3RoaXMub2xkUHJvcHMudmVyc2lvbn1gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlQ2x1c3RlclZlcnNpb24odGhpcy5uZXdQcm9wcy52ZXJzaW9uKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nICYmIHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1cGRhdGUgbG9nZ2luZyBhbmQgYWNjZXNzIGF0IHRoZSBzYW1lIHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nIHx8IHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICBjb25zdCBjb25maWc6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QgPSB7XG4gICAgICAgIG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgICB9O1xuICAgICAgaWYgKHVwZGF0ZXMudXBkYXRlTG9nZ2luZykge1xuICAgICAgICBjb25maWcubG9nZ2luZyA9IHRoaXMubmV3UHJvcHMubG9nZ2luZztcbiAgICAgIH07XG4gICAgICBpZiAodXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIGNsdXN0ZXIgd2l0aCBzZWN1cml0eUdyb3VwSWRzIGFuZCBzdWJuZXRJZHMgKGFzIHNwZWNpZmllZCBpbiB0aGUgd2FybmluZyBoZXJlOlxuICAgICAgICAvLyBodHRwczovL2F3c2NsaS5hbWF6b25hd3MuY29tL3YyL2RvY3VtZW50YXRpb24vYXBpL2xhdGVzdC9yZWZlcmVuY2UvZWtzL3VwZGF0ZS1jbHVzdGVyLWNvbmZpZy5odG1sKVxuICAgICAgICAvLyB3aWxsIGZhaWwsIHRoZXJlZm9yZSB3ZSB0YWtlIG9ubHkgdGhlIGFjY2VzcyBmaWVsZHMgZXhwbGljaXRseVxuICAgICAgICBjb25maWcucmVzb3VyY2VzVnBjQ29uZmlnID0ge1xuICAgICAgICAgIGVuZHBvaW50UHJpdmF0ZUFjY2VzczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzLFxuICAgICAgICAgIGVuZHBvaW50UHVibGljQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyxcbiAgICAgICAgICBwdWJsaWNBY2Nlc3NDaWRyczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcucHVibGljQWNjZXNzQ2lkcnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgICB9XG5cbiAgICAvLyBubyB1cGRhdGVzXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc29sZS5sb2coJ2lzVXBkYXRlQ29tcGxldGUnKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYW4gRUtTIHVwZGF0ZSwgd2Ugd2lsbCBtb25pdG9yIHRoZSB1cGRhdGUgZXZlbnQgaXRzZWxmXG4gICAgaWYgKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gYXdhaXQgdGhpcy5pc0Vrc1VwZGF0ZUNvbXBsZXRlKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpO1xuICAgICAgaWYgKCFjb21wbGV0ZSkge1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiBmYWxzZSB9O1xuICAgICAgfVxuXG4gICAgICAvLyBmYWxsIHRocm91Z2g6IGlmIHRoZSB1cGRhdGUgaXMgZG9uZSwgd2Ugc2ltcGx5IGRlbGVnYXRlIHRvIGlzQWN0aXZlKClcbiAgICAgIC8vIGluIG9yZGVyIHRvIGV4dHJhY3QgYXR0cmlidXRlcyBhbmQgc3RhdGUgZnJvbSB0aGUgY2x1c3RlciBpdHNlbGYsIHdoaWNoXG4gICAgICAvLyBpcyBzdXBwb3NlZCB0byBiZSBpbiBhbiBBQ1RJVkUgc3RhdGUgYWZ0ZXIgdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbHVzdGVyVmVyc2lvbihuZXdWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgdXBkYXRpbmcgY2x1c3RlciB2ZXJzaW9uIHRvICR7bmV3VmVyc2lvbn1gKTtcblxuICAgIC8vIHVwZGF0ZS1jbHVzdGVyLXZlcnNpb24gd2lsbCBmYWlsIGlmIHdlIHRyeSB0byB1cGRhdGUgdG8gdGhlIHNhbWUgdmVyc2lvbixcbiAgICAvLyBzbyBza2lwIGluIHRoaXMgY2FzZS5cbiAgICBjb25zdCBjbHVzdGVyID0gKGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSkpLmNsdXN0ZXI7XG4gICAgaWYgKGNsdXN0ZXI/LnZlcnNpb24gPT09IG5ld1ZlcnNpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyIGFscmVhZHkgYXQgdmVyc2lvbiAke2NsdXN0ZXIudmVyc2lvbn0sIHNraXBwaW5nIHZlcnNpb24gdXBkYXRlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy51cGRhdGVDbHVzdGVyVmVyc2lvbih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsIHZlcnNpb246IG5ld1ZlcnNpb24gfSk7XG4gICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNBY3RpdmUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZygnd2FpdGluZyBmb3IgY2x1c3RlciB0byBiZWNvbWUgQUNUSVZFJyk7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciByZXN1bHQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgY29uc3QgY2x1c3RlciA9IHJlc3AuY2x1c3RlcjtcblxuICAgIC8vIGlmIGNsdXN0ZXIgaXMgdW5kZWZpbmVkIChzaG91bGRudCBoYXBwZW4pIG9yIHN0YXR1cyBpcyBub3QgQUNUSVZFLCB3ZSBhcmVcbiAgICAvLyBub3QgY29tcGxldGUuIG5vdGUgdGhhdCB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZyYW1ld29yayBmb3JiaWRzXG4gICAgLy8gcmV0dXJuaW5nIGF0dHJpYnV0ZXMgKERhdGEpIGlmIGlzQ29tcGxldGUgaXMgZmFsc2UuXG4gICAgaWYgKGNsdXN0ZXI/LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgIC8vIG5vdCB2ZXJ5IGluZm9ybWF0aXZlLCB1bmZvcnR1bmF0ZWx5IHRoZSByZXNwb25zZSBkb2Vzbid0IGNvbnRhaW4gYW55IGVycm9yXG4gICAgICAvLyBpbmZvcm1hdGlvbiA6XFxcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2x1c3RlciBpcyBpbiBhIEZBSUxFRCBzdGF0dXMnKTtcbiAgICB9IGVsc2UgaWYgKGNsdXN0ZXI/LnN0YXR1cyAhPT0gJ0FDVElWRScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIE5hbWU6IGNsdXN0ZXIubmFtZSxcbiAgICAgICAgICBFbmRwb2ludDogY2x1c3Rlci5lbmRwb2ludCxcbiAgICAgICAgICBBcm46IGNsdXN0ZXIuYXJuLFxuXG4gICAgICAgICAgLy8gSU1QT1JUQU5UOiBDRk4gZXhwZWN0cyB0aGF0IGF0dHJpYnV0ZXMgd2lsbCAqYWx3YXlzKiBoYXZlIHZhbHVlcyxcbiAgICAgICAgICAvLyBzbyByZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGluIGNhc2UgdGhlIHZhbHVlIGlzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQ0ZOIHdpbGwgdGhyb3cgd2l0aCBgVmVuZG9yIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpblxuICAgICAgICAgIC8vIFhYWFgga2V5YC5cblxuICAgICAgICAgIENlcnRpZmljYXRlQXV0aG9yaXR5RGF0YTogY2x1c3Rlci5jZXJ0aWZpY2F0ZUF1dGhvcml0eT8uZGF0YSA/PyAnJyxcbiAgICAgICAgICBDbHVzdGVyU2VjdXJpdHlHcm91cElkOiBjbHVzdGVyLnJlc291cmNlc1ZwY0NvbmZpZz8uY2x1c3RlclNlY3VyaXR5R3JvdXBJZCA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyVXJsOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXIgPz8gJycsXG4gICAgICAgICAgT3BlbklkQ29ubmVjdElzc3VlcjogY2x1c3Rlci5pZGVudGl0eT8ub2lkYz8uaXNzdWVyPy5zdWJzdHJpbmcoOCkgPz8gJycsIC8vIFN0cmlwcyBvZmYgaHR0cHM6Ly8gZnJvbSB0aGUgaXNzdWVyIHVybFxuXG4gICAgICAgICAgLy8gV2UgY2FuIHNhZmVseSByZXR1cm4gdGhlIGZpcnN0IGl0ZW0gZnJvbSBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gYXJyYXksIGJlY2F1c2UgaXQgaGFzIGEgbGltaXQgb2YgMSBpdGVtXG4gICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vrcy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDbHVzdGVyLmh0bWwjQW1hem9uRUtTLUNyZWF0ZUNsdXN0ZXItcmVxdWVzdC1lbmNyeXB0aW9uQ29uZmlnXG4gICAgICAgICAgRW5jcnlwdGlvbkNvbmZpZ0tleUFybjogY2x1c3Rlci5lbmNyeXB0aW9uQ29uZmlnPy5zaGlmdCgpPy5wcm92aWRlcj8ua2V5QXJuID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzRWtzVXBkYXRlQ29tcGxldGUoZWtzVXBkYXRlSWQ6IHN0cmluZykge1xuICAgIHRoaXMubG9nKHsgaXNFa3NVcGRhdGVDb21wbGV0ZTogZWtzVXBkYXRlSWQgfSk7XG5cbiAgICBjb25zdCBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVVcGRhdGUoe1xuICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgIHVwZGF0ZUlkOiBla3NVcGRhdGVJZCxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nKHsgZGVzY3JpYmVVcGRhdGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5hYmxlIHRvIGRlc2NyaWJlIHVwZGF0ZSB3aXRoIGlkIFwiJHtla3NVcGRhdGVJZH1cImApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzKSB7XG4gICAgICBjYXNlICdJblByb2dyZXNzJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgY2FzZSAnU3VjY2Vzc2Z1bCc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnRmFpbGVkJzpcbiAgICAgIGNhc2UgJ0NhbmNlbGxlZCc6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2x1c3RlciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiIGZhaWxlZCB3aXRoIGVycm9yczogJHtKU09OLnN0cmluZ2lmeShkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5lcnJvcnMpfWApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIHN0YXR1cyBcIiR7ZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzfVwiIGZvciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNsdXN0ZXJOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9DTFVTVEVSX05BTUVfTEVOIC0gc3VmZml4Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5sb2dpY2FsUmVzb3VyY2VJZC5zbGljZSgwLCBvZmZzZXQgPiAwID8gb2Zmc2V0IDogMCk7XG4gICAgcmV0dXJuIGAke3ByZWZpeH0tJHtzdWZmaXh9YDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3BzKHByb3BzOiBhbnkpOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0IHtcblxuICBjb25zdCBwYXJzZWQgPSBwcm9wcz8uQ29uZmlnID8/IHt9O1xuXG4gIC8vIHRoaXMgaXMgd2VpcmQgYnV0IHRoZXNlIGJvb2xlYW4gcHJvcGVydGllcyBhcmUgcGFzc2VkIGJ5IENGTiBhcyBhIHN0cmluZywgYW5kIHdlIG5lZWQgdGhlbSB0byBiZSBib29sZWFuaWMgZm9yIHRoZSBTREsuXG4gIC8vIE90aGVyd2lzZSBpdCBmYWlscyB3aXRoICdVbmV4cGVjdGVkIFBhcmFtZXRlcjogcGFyYW1zLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgaXMgZXhwZWN0ZWQgdG8gYmUgYSBib29sZWFuJ1xuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWc/LmVuZHBvaW50UHJpdmF0ZUFjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9PT0gJ3RydWUnO1xuICB9XG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQdWJsaWNBY2Nlc3MpID09PSAnc3RyaW5nJykge1xuICAgIHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQubG9nZ2luZz8uY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCkgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9IHBhcnNlZC5sb2dnaW5nLmNsdXN0ZXJMb2dnaW5nWzBdLmVuYWJsZWQgPT09ICd0cnVlJztcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQ7XG5cbn1cblxuaW50ZXJmYWNlIFVwZGF0ZU1hcCB7XG4gIHJlcGxhY2VOYW1lOiBib29sZWFuOyAvLyBuYW1lXG4gIHJlcGxhY2VWcGM6IGJvb2xlYW47IC8vIHJlc291cmNlc1ZwY0NvbmZpZy5zdWJuZXRJZHMgYW5kIHNlY3VyaXR5R3JvdXBJZHNcbiAgcmVwbGFjZVJvbGU6IGJvb2xlYW47IC8vIHJvbGVBcm5cblxuICB1cGRhdGVWZXJzaW9uOiBib29sZWFuOyAvLyB2ZXJzaW9uXG4gIHVwZGF0ZUxvZ2dpbmc6IGJvb2xlYW47IC8vIGxvZ2dpbmdcbiAgdXBkYXRlRW5jcnlwdGlvbjogYm9vbGVhbjsgLy8gZW5jcnlwdGlvbiAoY2Fubm90IGJlIHVwZGF0ZWQpXG4gIHVwZGF0ZUFjY2VzczogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBhbmQgZW5kcG9pbnRQdWJsaWNBY2Nlc3Ncbn1cblxuZnVuY3Rpb24gYW5hbHl6ZVVwZGF0ZShvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PiwgbmV3UHJvcHM6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBVcGRhdGVNYXAge1xuICBjb25zb2xlLmxvZygnb2xkIHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShvbGRQcm9wcykpO1xuICBjb25zb2xlLmxvZygnbmV3IHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShuZXdQcm9wcykpO1xuXG4gIGNvbnN0IG5ld1ZwY1Byb3BzID0gbmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRWcGNQcm9wcyA9IG9sZFByb3BzLnJlc291cmNlc1ZwY0NvbmZpZyB8fCB7fTtcblxuICBjb25zdCBvbGRQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQob2xkVnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQobmV3VnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdFbmMgPSBuZXdQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRFbmMgPSBvbGRQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgcmVwbGFjZU5hbWU6IG5ld1Byb3BzLm5hbWUgIT09IG9sZFByb3BzLm5hbWUsXG4gICAgcmVwbGFjZVZwYzpcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnN1Ym5ldElkcykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFZwY1Byb3BzLnN1Ym5ldElkcykgfHxcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnNlY3VyaXR5R3JvdXBJZHMpICE9PSBKU09OLnN0cmluZ2lmeShvbGRWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzKSxcbiAgICB1cGRhdGVBY2Nlc3M6XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgIT09IG9sZFZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyB8fFxuICAgICAgbmV3VnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgIT09IG9sZFZwY1Byb3BzLmVuZHBvaW50UHVibGljQWNjZXNzIHx8XG4gICAgICAhc2V0c0VxdWFsKG5ld1B1YmxpY0FjY2Vzc0NpZHJzLCBvbGRQdWJsaWNBY2Nlc3NDaWRycyksXG4gICAgcmVwbGFjZVJvbGU6IG5ld1Byb3BzLnJvbGVBcm4gIT09IG9sZFByb3BzLnJvbGVBcm4sXG4gICAgdXBkYXRlVmVyc2lvbjogbmV3UHJvcHMudmVyc2lvbiAhPT0gb2xkUHJvcHMudmVyc2lvbixcbiAgICB1cGRhdGVFbmNyeXB0aW9uOiBKU09OLnN0cmluZ2lmeShuZXdFbmMpICE9PSBKU09OLnN0cmluZ2lmeShvbGRFbmMpLFxuICAgIHVwZGF0ZUxvZ2dpbmc6IEpTT04uc3RyaW5naWZ5KG5ld1Byb3BzLmxvZ2dpbmcpICE9PSBKU09OLnN0cmluZ2lmeShvbGRQcm9wcy5sb2dnaW5nKSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gc2V0c0VxdWFsKGZpcnN0OiBTZXQ8c3RyaW5nPiwgc2Vjb25kOiBTZXQ8c3RyaW5nPikge1xuICByZXR1cm4gZmlyc3Quc2l6ZSA9PT0gc2Vjb25kLnNpemUgJiYgWy4uLmZpcnN0XS5ldmVyeSgoZTogc3RyaW5nKSA9PiBzZWNvbmQuaGFzKGUpKTtcbn1cbiJdfQ== \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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LENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztRQUNuRSxhQUFhLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBa0IsRUFBRSxNQUFtQjtJQUN4RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgRWtzQ2xpZW50LCBSZXNvdXJjZUV2ZW50LCBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX05BTUVfTEVOID0gMTAwO1xuXG5leHBvcnQgY2xhc3MgQ2x1c3RlclJlc291cmNlSGFuZGxlciBleHRlbmRzIFJlc291cmNlSGFuZGxlciB7XG4gIHB1YmxpYyBnZXQgY2x1c3Rlck5hbWUoKSB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZGV0ZXJtaW5lIGNsdXN0ZXIgbmFtZSB3aXRob3V0IHBoeXNpY2FsIHJlc291cmNlIElEJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PjtcblxuICBjb25zdHJ1Y3Rvcihla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICBzdXBlcihla3MsIGV2ZW50KTtcblxuICAgIHRoaXMubmV3UHJvcHMgPSBwYXJzZVByb3BzKHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLm9sZFByb3BzID0gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnID8gcGFyc2VQcm9wcyhldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMpIDoge307XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gQ1JFQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCdvbkNyZWF0ZTogY3JlYXRpbmcgY2x1c3RlciB3aXRoIG9wdGlvbnM6JywgSlNPTi5zdHJpbmdpZnkodGhpcy5uZXdQcm9wcywgdW5kZWZpbmVkLCAyKSk7XG4gICAgaWYgKCF0aGlzLm5ld1Byb3BzLnJvbGVBcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJyb2xlQXJuXCIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyTmFtZSA9IHRoaXMubmV3UHJvcHMubmFtZSB8fCB0aGlzLmdlbmVyYXRlQ2x1c3Rlck5hbWUoKTtcblxuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmVrcy5jcmVhdGVDbHVzdGVyKHtcbiAgICAgIC4uLnRoaXMubmV3UHJvcHMsXG4gICAgICBuYW1lOiBjbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcC5jbHVzdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBjbHVzdGVyICR7Y2x1c3Rlck5hbWV9OiBDcmVhdGVDbHVzdGVyIHJldHVybmVkIHdpdGhvdXQgY2x1c3RlciBpbmZvcm1hdGlvbmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHJlc3AuY2x1c3Rlci5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIERFTEVURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25EZWxldGUoKTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgb25EZWxldGU6IGRlbGV0aW5nIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfWApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVrcy5kZWxldGVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyICR7dGhpcy5jbHVzdGVyTmFtZX0gbm90IGZvdW5kLCBpZGVtcG90ZW50bHkgc3VjY2VlZGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coYGlzRGVsZXRlQ29tcGxldGU6IHdhaXRpbmcgZm9yIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSB0byBiZSBkZWxldGVkYCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJldHVybmVkOicsIEpTT04uc3RyaW5naWZ5KHJlc3AsIHVuZGVmaW5lZCwgMikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICBjb25zb2xlLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgY2x1c3RlciBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0cnVlIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgZXJyb3I6JywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIFVQREFURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IGFuYWx5emVVcGRhdGUodGhpcy5vbGRQcm9wcywgdGhpcy5uZXdQcm9wcyk7XG4gICAgY29uc29sZS5sb2coJ29uVXBkYXRlOicsIEpTT04uc3RyaW5naWZ5KHsgdXBkYXRlcyB9LCB1bmRlZmluZWQsIDIpKTtcblxuICAgIC8vIHVwZGF0ZXMgdG8gZW5jcnlwdGlvbiBjb25maWcgaXMgbm90IHN1cHBvcnRlZFxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUVuY3J5cHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHVwZGF0ZSBjbHVzdGVyIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZXJlIGlzIGFuIHVwZGF0ZSB0aGF0IHJlcXVpcmVzIHJlcGxhY2VtZW50LCBnbyBhaGVhZCBhbmQganVzdCBjcmVhdGVcbiAgICAvLyBhIG5ldyBjbHVzdGVyIHdpdGggdGhlIG5ldyBjb25maWcuIFRoZSBvbGQgY2x1c3RlciB3aWxsIGF1dG9tYXRpY2FsbHkgYmVcbiAgICAvLyBkZWxldGVkIGJ5IGNsb3VkZm9ybWF0aW9uIHVwb24gc3VjY2Vzcy5cbiAgICBpZiAodXBkYXRlcy5yZXBsYWNlTmFtZSB8fCB1cGRhdGVzLnJlcGxhY2VSb2xlIHx8IHVwZGF0ZXMucmVwbGFjZVZwYykge1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgcmVwbGFjaW5nIHRoaXMgY2x1c3RlciBhbmQgdGhlIGNsdXN0ZXIgaGFzIGFuIGV4cGxpY2l0XG4gICAgICAvLyBwaHlzaWNhbCBuYW1lLCB0aGUgY3JlYXRpb24gb2YgdGhlIG5ldyBjbHVzdGVyIHdpbGwgZmFpbCB3aXRoIFwidGhlcmUgaXNcbiAgICAgIC8vIGFscmVhZHkgYSBjbHVzdGVyIHdpdGggdGhhdCBuYW1lXCIuIHRoaXMgaXMgYSBjb21tb24gYmVoYXZpb3IgZm9yXG4gICAgICAvLyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZXMgdGhhdCBzdXBwb3J0IHNwZWNpZnlpbmcgYSBwaHlzaWNhbCBuYW1lLlxuICAgICAgaWYgKHRoaXMub2xkUHJvcHMubmFtZSA9PT0gdGhpcy5uZXdQcm9wcy5uYW1lICYmIHRoaXMub2xkUHJvcHMubmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXBsYWNlIGNsdXN0ZXIgXCIke3RoaXMub2xkUHJvcHMubmFtZX1cIiBzaW5jZSBpdCBoYXMgYW4gZXhwbGljaXQgcGh5c2ljYWwgbmFtZS4gRWl0aGVyIHJlbmFtZSB0aGUgY2x1c3RlciBvciByZW1vdmUgdGhlIFwibmFtZVwiIGNvbmZpZ3VyYXRpb25gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub25DcmVhdGUoKTtcbiAgICB9XG5cbiAgICAvLyBpZiBhIHZlcnNpb24gdXBkYXRlIGlzIHJlcXVpcmVkLCBpc3N1ZSB0aGUgdmVyc2lvbiB1cGRhdGVcbiAgICBpZiAodXBkYXRlcy51cGRhdGVWZXJzaW9uKSB7XG4gICAgICBpZiAoIXRoaXMubmV3UHJvcHMudmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZW1vdmUgY2x1c3RlciB2ZXJzaW9uIGNvbmZpZ3VyYXRpb24uIEN1cnJlbnQgdmVyc2lvbiBpcyAke3RoaXMub2xkUHJvcHMudmVyc2lvbn1gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlQ2x1c3RlclZlcnNpb24odGhpcy5uZXdQcm9wcy52ZXJzaW9uKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nICYmIHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1cGRhdGUgbG9nZ2luZyBhbmQgYWNjZXNzIGF0IHRoZSBzYW1lIHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nIHx8IHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICBjb25zdCBjb25maWc6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QgPSB7XG4gICAgICAgIG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgICB9O1xuICAgICAgaWYgKHVwZGF0ZXMudXBkYXRlTG9nZ2luZykge1xuICAgICAgICBjb25maWcubG9nZ2luZyA9IHRoaXMubmV3UHJvcHMubG9nZ2luZztcbiAgICAgIH07XG4gICAgICBpZiAodXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIGNsdXN0ZXIgd2l0aCBzZWN1cml0eUdyb3VwSWRzIGFuZCBzdWJuZXRJZHMgKGFzIHNwZWNpZmllZCBpbiB0aGUgd2FybmluZyBoZXJlOlxuICAgICAgICAvLyBodHRwczovL2F3c2NsaS5hbWF6b25hd3MuY29tL3YyL2RvY3VtZW50YXRpb24vYXBpL2xhdGVzdC9yZWZlcmVuY2UvZWtzL3VwZGF0ZS1jbHVzdGVyLWNvbmZpZy5odG1sKVxuICAgICAgICAvLyB3aWxsIGZhaWwsIHRoZXJlZm9yZSB3ZSB0YWtlIG9ubHkgdGhlIGFjY2VzcyBmaWVsZHMgZXhwbGljaXRseVxuICAgICAgICBjb25maWcucmVzb3VyY2VzVnBjQ29uZmlnID0ge1xuICAgICAgICAgIGVuZHBvaW50UHJpdmF0ZUFjY2VzczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzLFxuICAgICAgICAgIGVuZHBvaW50UHVibGljQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyxcbiAgICAgICAgICBwdWJsaWNBY2Nlc3NDaWRyczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcucHVibGljQWNjZXNzQ2lkcnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgICB9XG5cbiAgICAvLyBubyB1cGRhdGVzXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc29sZS5sb2coJ2lzVXBkYXRlQ29tcGxldGUnKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYW4gRUtTIHVwZGF0ZSwgd2Ugd2lsbCBtb25pdG9yIHRoZSB1cGRhdGUgZXZlbnQgaXRzZWxmXG4gICAgaWYgKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gYXdhaXQgdGhpcy5pc0Vrc1VwZGF0ZUNvbXBsZXRlKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpO1xuICAgICAgaWYgKCFjb21wbGV0ZSkge1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiBmYWxzZSB9O1xuICAgICAgfVxuXG4gICAgICAvLyBmYWxsIHRocm91Z2g6IGlmIHRoZSB1cGRhdGUgaXMgZG9uZSwgd2Ugc2ltcGx5IGRlbGVnYXRlIHRvIGlzQWN0aXZlKClcbiAgICAgIC8vIGluIG9yZGVyIHRvIGV4dHJhY3QgYXR0cmlidXRlcyBhbmQgc3RhdGUgZnJvbSB0aGUgY2x1c3RlciBpdHNlbGYsIHdoaWNoXG4gICAgICAvLyBpcyBzdXBwb3NlZCB0byBiZSBpbiBhbiBBQ1RJVkUgc3RhdGUgYWZ0ZXIgdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbHVzdGVyVmVyc2lvbihuZXdWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgdXBkYXRpbmcgY2x1c3RlciB2ZXJzaW9uIHRvICR7bmV3VmVyc2lvbn1gKTtcblxuICAgIC8vIHVwZGF0ZS1jbHVzdGVyLXZlcnNpb24gd2lsbCBmYWlsIGlmIHdlIHRyeSB0byB1cGRhdGUgdG8gdGhlIHNhbWUgdmVyc2lvbixcbiAgICAvLyBzbyBza2lwIGluIHRoaXMgY2FzZS5cbiAgICBjb25zdCBjbHVzdGVyID0gKGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSkpLmNsdXN0ZXI7XG4gICAgaWYgKGNsdXN0ZXI/LnZlcnNpb24gPT09IG5ld1ZlcnNpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyIGFscmVhZHkgYXQgdmVyc2lvbiAke2NsdXN0ZXIudmVyc2lvbn0sIHNraXBwaW5nIHZlcnNpb24gdXBkYXRlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy51cGRhdGVDbHVzdGVyVmVyc2lvbih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsIHZlcnNpb246IG5ld1ZlcnNpb24gfSk7XG4gICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNBY3RpdmUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZygnd2FpdGluZyBmb3IgY2x1c3RlciB0byBiZWNvbWUgQUNUSVZFJyk7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciByZXN1bHQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgY29uc3QgY2x1c3RlciA9IHJlc3AuY2x1c3RlcjtcblxuICAgIC8vIGlmIGNsdXN0ZXIgaXMgdW5kZWZpbmVkIChzaG91bGRudCBoYXBwZW4pIG9yIHN0YXR1cyBpcyBub3QgQUNUSVZFLCB3ZSBhcmVcbiAgICAvLyBub3QgY29tcGxldGUuIG5vdGUgdGhhdCB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZyYW1ld29yayBmb3JiaWRzXG4gICAgLy8gcmV0dXJuaW5nIGF0dHJpYnV0ZXMgKERhdGEpIGlmIGlzQ29tcGxldGUgaXMgZmFsc2UuXG4gICAgaWYgKGNsdXN0ZXI/LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgIC8vIG5vdCB2ZXJ5IGluZm9ybWF0aXZlLCB1bmZvcnR1bmF0ZWx5IHRoZSByZXNwb25zZSBkb2Vzbid0IGNvbnRhaW4gYW55IGVycm9yXG4gICAgICAvLyBpbmZvcm1hdGlvbiA6XFxcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2x1c3RlciBpcyBpbiBhIEZBSUxFRCBzdGF0dXMnKTtcbiAgICB9IGVsc2UgaWYgKGNsdXN0ZXI/LnN0YXR1cyAhPT0gJ0FDVElWRScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIE5hbWU6IGNsdXN0ZXIubmFtZSxcbiAgICAgICAgICBFbmRwb2ludDogY2x1c3Rlci5lbmRwb2ludCxcbiAgICAgICAgICBBcm46IGNsdXN0ZXIuYXJuLFxuXG4gICAgICAgICAgLy8gSU1QT1JUQU5UOiBDRk4gZXhwZWN0cyB0aGF0IGF0dHJpYnV0ZXMgd2lsbCAqYWx3YXlzKiBoYXZlIHZhbHVlcyxcbiAgICAgICAgICAvLyBzbyByZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGluIGNhc2UgdGhlIHZhbHVlIGlzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQ0ZOIHdpbGwgdGhyb3cgd2l0aCBgVmVuZG9yIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpblxuICAgICAgICAgIC8vIFhYWFgga2V5YC5cblxuICAgICAgICAgIENlcnRpZmljYXRlQXV0aG9yaXR5RGF0YTogY2x1c3Rlci5jZXJ0aWZpY2F0ZUF1dGhvcml0eT8uZGF0YSA/PyAnJyxcbiAgICAgICAgICBDbHVzdGVyU2VjdXJpdHlHcm91cElkOiBjbHVzdGVyLnJlc291cmNlc1ZwY0NvbmZpZz8uY2x1c3RlclNlY3VyaXR5R3JvdXBJZCA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyVXJsOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXIgPz8gJycsXG4gICAgICAgICAgT3BlbklkQ29ubmVjdElzc3VlcjogY2x1c3Rlci5pZGVudGl0eT8ub2lkYz8uaXNzdWVyPy5zdWJzdHJpbmcoOCkgPz8gJycsIC8vIFN0cmlwcyBvZmYgaHR0cHM6Ly8gZnJvbSB0aGUgaXNzdWVyIHVybFxuXG4gICAgICAgICAgLy8gV2UgY2FuIHNhZmVseSByZXR1cm4gdGhlIGZpcnN0IGl0ZW0gZnJvbSBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gYXJyYXksIGJlY2F1c2UgaXQgaGFzIGEgbGltaXQgb2YgMSBpdGVtXG4gICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vrcy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDbHVzdGVyLmh0bWwjQW1hem9uRUtTLUNyZWF0ZUNsdXN0ZXItcmVxdWVzdC1lbmNyeXB0aW9uQ29uZmlnXG4gICAgICAgICAgRW5jcnlwdGlvbkNvbmZpZ0tleUFybjogY2x1c3Rlci5lbmNyeXB0aW9uQ29uZmlnPy5zaGlmdCgpPy5wcm92aWRlcj8ua2V5QXJuID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzRWtzVXBkYXRlQ29tcGxldGUoZWtzVXBkYXRlSWQ6IHN0cmluZykge1xuICAgIHRoaXMubG9nKHsgaXNFa3NVcGRhdGVDb21wbGV0ZTogZWtzVXBkYXRlSWQgfSk7XG5cbiAgICBjb25zdCBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVVcGRhdGUoe1xuICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgIHVwZGF0ZUlkOiBla3NVcGRhdGVJZCxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nKHsgZGVzY3JpYmVVcGRhdGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5hYmxlIHRvIGRlc2NyaWJlIHVwZGF0ZSB3aXRoIGlkIFwiJHtla3NVcGRhdGVJZH1cImApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzKSB7XG4gICAgICBjYXNlICdJblByb2dyZXNzJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgY2FzZSAnU3VjY2Vzc2Z1bCc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnRmFpbGVkJzpcbiAgICAgIGNhc2UgJ0NhbmNlbGxlZCc6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2x1c3RlciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiIGZhaWxlZCB3aXRoIGVycm9yczogJHtKU09OLnN0cmluZ2lmeShkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5lcnJvcnMpfWApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIHN0YXR1cyBcIiR7ZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzfVwiIGZvciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNsdXN0ZXJOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9DTFVTVEVSX05BTUVfTEVOIC0gc3VmZml4Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5sb2dpY2FsUmVzb3VyY2VJZC5zbGljZSgwLCBvZmZzZXQgPiAwID8gb2Zmc2V0IDogMCk7XG4gICAgcmV0dXJuIGAke3ByZWZpeH0tJHtzdWZmaXh9YDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3BzKHByb3BzOiBhbnkpOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0IHtcblxuICBjb25zdCBwYXJzZWQgPSBwcm9wcz8uQ29uZmlnID8/IHt9O1xuXG4gIC8vIHRoaXMgaXMgd2VpcmQgYnV0IHRoZXNlIGJvb2xlYW4gcHJvcGVydGllcyBhcmUgcGFzc2VkIGJ5IENGTiBhcyBhIHN0cmluZywgYW5kIHdlIG5lZWQgdGhlbSB0byBiZSBib29sZWFuaWMgZm9yIHRoZSBTREsuXG4gIC8vIE90aGVyd2lzZSBpdCBmYWlscyB3aXRoICdVbmV4cGVjdGVkIFBhcmFtZXRlcjogcGFyYW1zLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgaXMgZXhwZWN0ZWQgdG8gYmUgYSBib29sZWFuJ1xuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWc/LmVuZHBvaW50UHJpdmF0ZUFjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9PT0gJ3RydWUnO1xuICB9XG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQdWJsaWNBY2Nlc3MpID09PSAnc3RyaW5nJykge1xuICAgIHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQubG9nZ2luZz8uY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCkgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9IHBhcnNlZC5sb2dnaW5nLmNsdXN0ZXJMb2dnaW5nWzBdLmVuYWJsZWQgPT09ICd0cnVlJztcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQ7XG5cbn1cblxuaW50ZXJmYWNlIFVwZGF0ZU1hcCB7XG4gIHJlcGxhY2VOYW1lOiBib29sZWFuOyAvLyBuYW1lXG4gIHJlcGxhY2VWcGM6IGJvb2xlYW47IC8vIHJlc291cmNlc1ZwY0NvbmZpZy5zdWJuZXRJZHMgYW5kIHNlY3VyaXR5R3JvdXBJZHNcbiAgcmVwbGFjZVJvbGU6IGJvb2xlYW47IC8vIHJvbGVBcm5cblxuICB1cGRhdGVWZXJzaW9uOiBib29sZWFuOyAvLyB2ZXJzaW9uXG4gIHVwZGF0ZUxvZ2dpbmc6IGJvb2xlYW47IC8vIGxvZ2dpbmdcbiAgdXBkYXRlRW5jcnlwdGlvbjogYm9vbGVhbjsgLy8gZW5jcnlwdGlvbiAoY2Fubm90IGJlIHVwZGF0ZWQpXG4gIHVwZGF0ZUFjY2VzczogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBhbmQgZW5kcG9pbnRQdWJsaWNBY2Nlc3Ncbn1cblxuZnVuY3Rpb24gYW5hbHl6ZVVwZGF0ZShvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PiwgbmV3UHJvcHM6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBVcGRhdGVNYXAge1xuICBjb25zb2xlLmxvZygnb2xkIHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShvbGRQcm9wcykpO1xuICBjb25zb2xlLmxvZygnbmV3IHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShuZXdQcm9wcykpO1xuXG4gIGNvbnN0IG5ld1ZwY1Byb3BzID0gbmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRWcGNQcm9wcyA9IG9sZFByb3BzLnJlc291cmNlc1ZwY0NvbmZpZyB8fCB7fTtcblxuICBjb25zdCBvbGRQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQob2xkVnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQobmV3VnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdFbmMgPSBuZXdQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRFbmMgPSBvbGRQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgcmVwbGFjZU5hbWU6IG5ld1Byb3BzLm5hbWUgIT09IG9sZFByb3BzLm5hbWUsXG4gICAgcmVwbGFjZVZwYzpcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnN1Ym5ldElkcz8uc29ydCgpKSAhPT0gSlNPTi5zdHJpbmdpZnkob2xkVnBjUHJvcHMuc3VibmV0SWRzPy5zb3J0KCkpIHx8XG4gICAgICBKU09OLnN0cmluZ2lmeShuZXdWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpICE9PSBKU09OLnN0cmluZ2lmeShvbGRWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpLFxuICAgIHVwZGF0ZUFjY2VzczpcbiAgICAgIG5ld1ZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQcml2YXRlQWNjZXNzIHx8XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFB1YmxpY0FjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgfHxcbiAgICAgICFzZXRzRXF1YWwobmV3UHVibGljQWNjZXNzQ2lkcnMsIG9sZFB1YmxpY0FjY2Vzc0NpZHJzKSxcbiAgICByZXBsYWNlUm9sZTogbmV3UHJvcHMucm9sZUFybiAhPT0gb2xkUHJvcHMucm9sZUFybixcbiAgICB1cGRhdGVWZXJzaW9uOiBuZXdQcm9wcy52ZXJzaW9uICE9PSBvbGRQcm9wcy52ZXJzaW9uLFxuICAgIHVwZGF0ZUVuY3J5cHRpb246IEpTT04uc3RyaW5naWZ5KG5ld0VuYykgIT09IEpTT04uc3RyaW5naWZ5KG9sZEVuYyksXG4gICAgdXBkYXRlTG9nZ2luZzogSlNPTi5zdHJpbmdpZnkobmV3UHJvcHMubG9nZ2luZykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFByb3BzLmxvZ2dpbmcpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzZXRzRXF1YWwoZmlyc3Q6IFNldDxzdHJpbmc+LCBzZWNvbmQ6IFNldDxzdHJpbmc+KSB7XG4gIHJldHVybiBmaXJzdC5zaXplID09PSBzZWNvbmQuc2l6ZSAmJiBbLi4uZmlyc3RdLmV2ZXJ5KChlOiBzdHJpbmcpID0+IHNlY29uZC5oYXMoZSkpO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.ts b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts similarity index 98% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.ts rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts index e6930b7844d32..4b7fdda6d1dd1 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.ts +++ b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts @@ -326,8 +326,8 @@ function analyzeUpdate(oldProps: Partial, newProps return { replaceName: newProps.name !== oldProps.name, replaceVpc: - JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), + JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.d.ts b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.js b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.js rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.ts b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.ts rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.d.ts b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.js b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.js rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.ts b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.ts rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.d.ts b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.js b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.js rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.ts b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.ts rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.d.ts b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.js b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.js rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.ts b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.ts rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.js b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.js deleted file mode 100644 index a5480014d5fc4..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.js +++ /dev/null @@ -1,43 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.ResourceHandler = void 0; -class ResourceHandler { - constructor(eks, event) { - this.eks = eks; - this.requestType = event.RequestType; - this.requestId = event.RequestId; - this.logicalResourceId = event.LogicalResourceId; - this.physicalResourceId = event.PhysicalResourceId; - this.event = event; - const roleToAssume = event.ResourceProperties.AssumeRoleArn; - if (!roleToAssume) { - throw new Error('AssumeRoleArn must be provided'); - } - eks.configureAssumeRole({ - RoleArn: roleToAssume, - RoleSessionName: `AWSCDK.EKSCluster.${this.requestType}.${this.requestId}`, - }); - } - onEvent() { - switch (this.requestType) { - case 'Create': return this.onCreate(); - case 'Update': return this.onUpdate(); - case 'Delete': return this.onDelete(); - } - throw new Error(`Invalid request type ${this.requestType}`); - } - isComplete() { - switch (this.requestType) { - case 'Create': return this.isCreateComplete(); - case 'Update': return this.isUpdateComplete(); - case 'Delete': return this.isDeleteComplete(); - } - throw new Error(`Invalid request type ${this.requestType}`); - } - log(x) { - // eslint-disable-next-line no-console - console.log(JSON.stringify(x, undefined, 2)); - } -} -exports.ResourceHandler = ResourceHandler; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tbW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiY29tbW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQWlCQSxNQUFzQixlQUFlO0lBT25DLFlBQStCLEdBQWMsRUFBRSxLQUFvQjtRQUFwQyxRQUFHLEdBQUgsR0FBRyxDQUFXO1FBQzNDLElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSyxDQUFDLFdBQVcsQ0FBQztRQUNyQyxJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQyxTQUFTLENBQUM7UUFDakMsSUFBSSxDQUFDLGlCQUFpQixHQUFHLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQztRQUNqRCxJQUFJLENBQUMsa0JBQWtCLEdBQUksS0FBYSxDQUFDLGtCQUFrQixDQUFDO1FBQzVELElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO1FBRW5CLE1BQU0sWUFBWSxHQUFHLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxhQUFhLENBQUM7UUFDNUQsSUFBSSxDQUFDLFlBQVksRUFBRTtZQUNqQixNQUFNLElBQUksS0FBSyxDQUFDLGdDQUFnQyxDQUFDLENBQUM7U0FDbkQ7UUFFRCxHQUFHLENBQUMsbUJBQW1CLENBQUM7WUFDdEIsT0FBTyxFQUFFLFlBQVk7WUFDckIsZUFBZSxFQUFFLHFCQUFxQixJQUFJLENBQUMsV0FBVyxJQUFJLElBQUksQ0FBQyxTQUFTLEVBQUU7U0FDM0UsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVNLE9BQU87UUFDWixRQUFRLElBQUksQ0FBQyxXQUFXLEVBQUU7WUFDeEIsS0FBSyxRQUFRLENBQUMsQ0FBQyxPQUFPLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUN0QyxLQUFLLFFBQVEsQ0FBQyxDQUFDLE9BQU8sSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ3RDLEtBQUssUUFBUSxDQUFDLENBQUMsT0FBTyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7U0FDdkM7UUFFRCxNQUFNLElBQUksS0FBSyxDQUFDLHdCQUF3QixJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztJQUM5RCxDQUFDO0lBRU0sVUFBVTtRQUNmLFFBQVEsSUFBSSxDQUFDLFdBQVcsRUFBRTtZQUN4QixLQUFLLFFBQVEsQ0FBQyxDQUFDLE9BQU8sSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7WUFDOUMsS0FBSyxRQUFRLENBQUMsQ0FBQyxPQUFPLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1lBQzlDLEtBQUssUUFBUSxDQUFDLENBQUMsT0FBTyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztTQUMvQztRQUVELE1BQU0sSUFBSSxLQUFLLENBQUMsd0JBQXdCLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO0lBQzlELENBQUM7SUFFUyxHQUFHLENBQUMsQ0FBTTtRQUNsQixzQ0FBc0M7UUFDdEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMvQyxDQUFDO0NBUUY7QUF4REQsMENBd0RDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzXG5pbXBvcnQgKiBhcyBhd3MgZnJvbSAnYXdzLXNkayc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRWtzVXBkYXRlSWQge1xuICAvKipcbiAgICogSWYgdGhpcyBmaWVsZCBpcyBpbmNsdWRlZCBpbiBhbiBldmVudCBwYXNzZWQgdG8gXCJJc0NvbXBsZXRlXCIsIGl0IG1lYW5zIHdlXG4gICAqIGluaXRpYXRlZCBhbiBFS1MgdXBkYXRlIHRoYXQgc2hvdWxkIGJlIG1vbml0b3JlZCB1c2luZyBla3M6RGVzY3JpYmVVcGRhdGVcbiAgICogaW5zdGVhZCBvZiBqdXN0IGxvb2tpbmcgYXQgdGhlIGNsdXN0ZXIgc3RhdHVzLlxuICAgKi9cbiAgRWtzVXBkYXRlSWQ/OiBzdHJpbmdcbn1cblxuZXhwb3J0IHR5cGUgUmVzb3VyY2VFdmVudCA9IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlRXZlbnQgJiBFa3NVcGRhdGVJZDtcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIFJlc291cmNlSGFuZGxlciB7XG4gIHByb3RlY3RlZCByZWFkb25seSByZXF1ZXN0SWQ6IHN0cmluZztcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGxvZ2ljYWxSZXNvdXJjZUlkOiBzdHJpbmc7XG4gIHByb3RlY3RlZCByZWFkb25seSByZXF1ZXN0VHlwZTogJ0NyZWF0ZScgfCAnVXBkYXRlJyB8ICdEZWxldGUnO1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgcGh5c2ljYWxSZXNvdXJjZUlkPzogc3RyaW5nO1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgZXZlbnQ6IFJlc291cmNlRXZlbnQ7XG5cbiAgY29uc3RydWN0b3IocHJvdGVjdGVkIHJlYWRvbmx5IGVrczogRWtzQ2xpZW50LCBldmVudDogUmVzb3VyY2VFdmVudCkge1xuICAgIHRoaXMucmVxdWVzdFR5cGUgPSBldmVudC5SZXF1ZXN0VHlwZTtcbiAgICB0aGlzLnJlcXVlc3RJZCA9IGV2ZW50LlJlcXVlc3RJZDtcbiAgICB0aGlzLmxvZ2ljYWxSZXNvdXJjZUlkID0gZXZlbnQuTG9naWNhbFJlc291cmNlSWQ7XG4gICAgdGhpcy5waHlzaWNhbFJlc291cmNlSWQgPSAoZXZlbnQgYXMgYW55KS5QaHlzaWNhbFJlc291cmNlSWQ7XG4gICAgdGhpcy5ldmVudCA9IGV2ZW50O1xuXG4gICAgY29uc3Qgcm9sZVRvQXNzdW1lID0gZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLkFzc3VtZVJvbGVBcm47XG4gICAgaWYgKCFyb2xlVG9Bc3N1bWUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQXNzdW1lUm9sZUFybiBtdXN0IGJlIHByb3ZpZGVkJyk7XG4gICAgfVxuXG4gICAgZWtzLmNvbmZpZ3VyZUFzc3VtZVJvbGUoe1xuICAgICAgUm9sZUFybjogcm9sZVRvQXNzdW1lLFxuICAgICAgUm9sZVNlc3Npb25OYW1lOiBgQVdTQ0RLLkVLU0NsdXN0ZXIuJHt0aGlzLnJlcXVlc3RUeXBlfS4ke3RoaXMucmVxdWVzdElkfWAsXG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgb25FdmVudCgpIHtcbiAgICBzd2l0Y2ggKHRoaXMucmVxdWVzdFR5cGUpIHtcbiAgICAgIGNhc2UgJ0NyZWF0ZSc6IHJldHVybiB0aGlzLm9uQ3JlYXRlKCk7XG4gICAgICBjYXNlICdVcGRhdGUnOiByZXR1cm4gdGhpcy5vblVwZGF0ZSgpO1xuICAgICAgY2FzZSAnRGVsZXRlJzogcmV0dXJuIHRoaXMub25EZWxldGUoKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgcmVxdWVzdCB0eXBlICR7dGhpcy5yZXF1ZXN0VHlwZX1gKTtcbiAgfVxuXG4gIHB1YmxpYyBpc0NvbXBsZXRlKCkge1xuICAgIHN3aXRjaCAodGhpcy5yZXF1ZXN0VHlwZSkge1xuICAgICAgY2FzZSAnQ3JlYXRlJzogcmV0dXJuIHRoaXMuaXNDcmVhdGVDb21wbGV0ZSgpO1xuICAgICAgY2FzZSAnVXBkYXRlJzogcmV0dXJuIHRoaXMuaXNVcGRhdGVDb21wbGV0ZSgpO1xuICAgICAgY2FzZSAnRGVsZXRlJzogcmV0dXJuIHRoaXMuaXNEZWxldGVDb21wbGV0ZSgpO1xuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCByZXF1ZXN0IHR5cGUgJHt0aGlzLnJlcXVlc3RUeXBlfWApO1xuICB9XG5cbiAgcHJvdGVjdGVkIGxvZyh4OiBhbnkpIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgIGNvbnNvbGUubG9nKEpTT04uc3RyaW5naWZ5KHgsIHVuZGVmaW5lZCwgMikpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFic3RyYWN0IGFzeW5jIG9uQ3JlYXRlKCk6IFByb21pc2U8T25FdmVudFJlc3BvbnNlPjtcbiAgcHJvdGVjdGVkIGFic3RyYWN0IGFzeW5jIG9uRGVsZXRlKCk6IFByb21pc2U8T25FdmVudFJlc3BvbnNlIHwgdm9pZD47XG4gIHByb3RlY3RlZCBhYnN0cmFjdCBhc3luYyBvblVwZGF0ZSgpOiBQcm9taXNlPChPbkV2ZW50UmVzcG9uc2UgJiBFa3NVcGRhdGVJZCkgfCB2b2lkPjtcbiAgcHJvdGVjdGVkIGFic3RyYWN0IGFzeW5jIGlzQ3JlYXRlQ29tcGxldGUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+O1xuICBwcm90ZWN0ZWQgYWJzdHJhY3QgYXN5bmMgaXNEZWxldGVDb21wbGV0ZSgpOiBQcm9taXNlPElzQ29tcGxldGVSZXNwb25zZT47XG4gIHByb3RlY3RlZCBhYnN0cmFjdCBhc3luYyBpc1VwZGF0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBFa3NDbGllbnQge1xuICBjb25maWd1cmVBc3N1bWVSb2xlKHJlcXVlc3Q6IGF3cy5TVFMuQXNzdW1lUm9sZVJlcXVlc3QpOiB2b2lkO1xuICBjcmVhdGVDbHVzdGVyKHJlcXVlc3Q6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBQcm9taXNlPGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlc3BvbnNlPjtcbiAgZGVsZXRlQ2x1c3RlcihyZXF1ZXN0OiBhd3MuRUtTLkRlbGV0ZUNsdXN0ZXJSZXF1ZXN0KTogUHJvbWlzZTxhd3MuRUtTLkRlbGV0ZUNsdXN0ZXJSZXNwb25zZT47XG4gIGRlc2NyaWJlQ2x1c3RlcihyZXF1ZXN0OiBhd3MuRUtTLkRlc2NyaWJlQ2x1c3RlclJlcXVlc3QpOiBQcm9taXNlPGF3cy5FS1MuRGVzY3JpYmVDbHVzdGVyUmVzcG9uc2U+O1xuICB1cGRhdGVDbHVzdGVyQ29uZmlnKHJlcXVlc3Q6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QpOiBQcm9taXNlPGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1Jlc3BvbnNlPjtcbiAgdXBkYXRlQ2x1c3RlclZlcnNpb24ocmVxdWVzdDogYXdzLkVLUy5VcGRhdGVDbHVzdGVyVmVyc2lvblJlcXVlc3QpOiBQcm9taXNlPGF3cy5FS1MuVXBkYXRlQ2x1c3RlclZlcnNpb25SZXNwb25zZT47XG4gIGRlc2NyaWJlVXBkYXRlKHJlcTogYXdzLkVLUy5EZXNjcmliZVVwZGF0ZVJlcXVlc3QpOiBQcm9taXNlPGF3cy5FS1MuRGVzY3JpYmVVcGRhdGVSZXNwb25zZT47XG4gIGNyZWF0ZUZhcmdhdGVQcm9maWxlKHJlcXVlc3Q6IGF3cy5FS1MuQ3JlYXRlRmFyZ2F0ZVByb2ZpbGVSZXF1ZXN0KTogUHJvbWlzZTxhd3MuRUtTLkNyZWF0ZUZhcmdhdGVQcm9maWxlUmVzcG9uc2U+O1xuICBkZXNjcmliZUZhcmdhdGVQcm9maWxlKHJlcXVlc3Q6IGF3cy5FS1MuRGVzY3JpYmVGYXJnYXRlUHJvZmlsZVJlcXVlc3QpOiBQcm9taXNlPGF3cy5FS1MuRGVzY3JpYmVGYXJnYXRlUHJvZmlsZVJlc3BvbnNlPjtcbiAgZGVsZXRlRmFyZ2F0ZVByb2ZpbGUocmVxdWVzdDogYXdzLkVLUy5EZWxldGVGYXJnYXRlUHJvZmlsZVJlcXVlc3QpOiBQcm9taXNlPGF3cy5FS1MuRGVsZXRlRmFyZ2F0ZVByb2ZpbGVSZXNwb25zZT47XG59XG4iXX0= \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.js b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.js deleted file mode 100644 index 91815a754a525..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.js +++ /dev/null @@ -1,102 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.FargateProfileResourceHandler = void 0; -const common_1 = require("./common"); -const MAX_NAME_LEN = 63; -class FargateProfileResourceHandler extends common_1.ResourceHandler { - async onCreate() { - const fargateProfileName = this.event.ResourceProperties.Config.fargateProfileName ?? this.generateProfileName(); - const createFargateProfile = { - fargateProfileName, - ...this.event.ResourceProperties.Config, - }; - this.log({ createFargateProfile }); - const createFargateProfileResponse = await this.eks.createFargateProfile(createFargateProfile); - this.log({ createFargateProfileResponse }); - if (!createFargateProfileResponse.fargateProfile) { - throw new Error('invalid CreateFargateProfile response'); - } - return { - PhysicalResourceId: createFargateProfileResponse.fargateProfile.fargateProfileName, - Data: { - fargateProfileArn: createFargateProfileResponse.fargateProfile.fargateProfileArn, - }, - }; - } - async onDelete() { - if (!this.physicalResourceId) { - throw new Error('Cannot delete a profile without a physical id'); - } - const deleteFargateProfile = { - clusterName: this.event.ResourceProperties.Config.clusterName, - fargateProfileName: this.physicalResourceId, - }; - this.log({ deleteFargateProfile }); - const deleteFargateProfileResponse = await this.eks.deleteFargateProfile(deleteFargateProfile); - this.log({ deleteFargateProfileResponse }); - return; - } - async onUpdate() { - // all updates require a replacement. as long as name is generated, we are - // good. if name is explicit, update will fail, which is common when trying - // to replace cfn resources with explicit physical names - return this.onCreate(); - } - async isCreateComplete() { - return this.isUpdateComplete(); - } - async isUpdateComplete() { - const status = await this.queryStatus(); - return { - IsComplete: status === 'ACTIVE', - }; - } - async isDeleteComplete() { - const status = await this.queryStatus(); - return { - IsComplete: status === 'NOT_FOUND', - }; - } - /** - * Generates a fargate profile name. - */ - generateProfileName() { - const suffix = this.requestId.replace(/-/g, ''); // 32 chars - const offset = MAX_NAME_LEN - suffix.length - 1; - const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); - return `${prefix}-${suffix}`; - } - /** - * Queries the Fargate profile's current status and returns the status or - * NOT_FOUND if the profile doesn't exist (i.e. it has been deleted). - */ - async queryStatus() { - if (!this.physicalResourceId) { - throw new Error('Unable to determine status for fargate profile without a resource name'); - } - const describeFargateProfile = { - clusterName: this.event.ResourceProperties.Config.clusterName, - fargateProfileName: this.physicalResourceId, - }; - try { - this.log({ describeFargateProfile }); - const describeFargateProfileResponse = await this.eks.describeFargateProfile(describeFargateProfile); - this.log({ describeFargateProfileResponse }); - const status = describeFargateProfileResponse.fargateProfile?.status; - if (status === 'CREATE_FAILED' || status === 'DELETE_FAILED') { - throw new Error(status); - } - return status; - } - catch (describeFargateProfileError) { - if (describeFargateProfileError.code === 'ResourceNotFoundException') { - this.log('received ResourceNotFoundException, this means the profile has been deleted (or never existed)'); - return 'NOT_FOUND'; - } - this.log({ describeFargateProfileError }); - throw describeFargateProfileError; - } - } -} -exports.FargateProfileResourceHandler = FargateProfileResourceHandler; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFyZ2F0ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImZhcmdhdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQ0EscUNBQTJDO0FBRTNDLE1BQU0sWUFBWSxHQUFHLEVBQUUsQ0FBQztBQUV4QixNQUFhLDZCQUE4QixTQUFRLHdCQUFlO0lBQ3RELEtBQUssQ0FBQyxRQUFRO1FBQ3RCLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsa0JBQWtCLElBQUksSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUM7UUFFakgsTUFBTSxvQkFBb0IsR0FBd0M7WUFDaEUsa0JBQWtCO1lBQ2xCLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNO1NBQ3hDLENBQUM7UUFFRixJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsb0JBQW9CLEVBQUUsQ0FBQyxDQUFDO1FBQ25DLE1BQU0sNEJBQTRCLEdBQUcsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLG9CQUFvQixDQUFDLG9CQUFvQixDQUFDLENBQUM7UUFDL0YsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLDRCQUE0QixFQUFFLENBQUMsQ0FBQztRQUUzQyxJQUFJLENBQUMsNEJBQTRCLENBQUMsY0FBYyxFQUFFO1lBQ2hELE1BQU0sSUFBSSxLQUFLLENBQUMsdUNBQXVDLENBQUMsQ0FBQztTQUMxRDtRQUVELE9BQU87WUFDTCxrQkFBa0IsRUFBRSw0QkFBNEIsQ0FBQyxjQUFjLENBQUMsa0JBQWtCO1lBQ2xGLElBQUksRUFBRTtnQkFDSixpQkFBaUIsRUFBRSw0QkFBNEIsQ0FBQyxjQUFjLENBQUMsaUJBQWlCO2FBQ2pGO1NBQ0YsQ0FBQztJQUNKLENBQUM7SUFFUyxLQUFLLENBQUMsUUFBUTtRQUN0QixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsK0NBQStDLENB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QkFBMkIsQ0FBQyxJQUFJLEtBQUssMkJBQTJCLEVBQUU7Z0JBQ3BFLElBQUksQ0FBQyxHQUFHLENBQUMsZ0dBQWdHLENBQUMsQ0FBQztnQkFDM0csT0FBTyxXQUFXLENBQUM7YUFDcEI7WUFFRCxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsMkJBQTJCLEVBQUUsQ0FBQyxDQUFDO1lBQzFDLE1BQU0sMkJBQTJCLENBQUM7U0FDbkM7SUFDSCxDQUFDO0NBQ0Y7QUFqSEQsc0VBaUhDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgUmVzb3VyY2VIYW5kbGVyIH0gZnJvbSAnLi9jb21tb24nO1xuXG5jb25zdCBNQVhfTkFNRV9MRU4gPSA2MztcblxuZXhwb3J0IGNsYXNzIEZhcmdhdGVQcm9maWxlUmVzb3VyY2VIYW5kbGVyIGV4dGVuZHMgUmVzb3VyY2VIYW5kbGVyIHtcbiAgcHJvdGVjdGVkIGFzeW5jIG9uQ3JlYXRlKCkge1xuICAgIGNvbnN0IGZhcmdhdGVQcm9maWxlTmFtZSA9IHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLkNvbmZpZy5mYXJnYXRlUHJvZmlsZU5hbWUgPz8gdGhpcy5nZW5lcmF0ZVByb2ZpbGVOYW1lKCk7XG5cbiAgICBjb25zdCBjcmVhdGVGYXJnYXRlUHJvZmlsZTogYXdzLkVLUy5DcmVhdGVGYXJnYXRlUHJvZmlsZVJlcXVlc3QgPSB7XG4gICAgICBmYXJnYXRlUHJvZmlsZU5hbWUsXG4gICAgICAuLi50aGlzLmV2ZW50LlJlc291cmNlUHJvcGVydGllcy5Db25maWcsXG4gICAgfTtcblxuICAgIHRoaXMubG9nKHsgY3JlYXRlRmFyZ2F0ZVByb2ZpbGUgfSk7XG4gICAgY29uc3QgY3JlYXRlRmFyZ2F0ZVByb2ZpbGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLmNyZWF0ZUZhcmdhdGVQcm9maWxlKGNyZWF0ZUZhcmdhdGVQcm9maWxlKTtcbiAgICB0aGlzLmxvZyh7IGNyZWF0ZUZhcmdhdGVQcm9maWxlUmVzcG9uc2UgfSk7XG5cbiAgICBpZiAoIWNyZWF0ZUZhcmdhdGVQcm9maWxlUmVzcG9uc2UuZmFyZ2F0ZVByb2ZpbGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBDcmVhdGVGYXJnYXRlUHJvZmlsZSByZXNwb25zZScpO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IGNyZWF0ZUZhcmdhdGVQcm9maWxlUmVzcG9uc2UuZmFyZ2F0ZVByb2ZpbGUuZmFyZ2F0ZVByb2ZpbGVOYW1lLFxuICAgICAgRGF0YToge1xuICAgICAgICBmYXJnYXRlUHJvZmlsZUFybjogY3JlYXRlRmFyZ2F0ZVByb2ZpbGVSZXNwb25zZS5mYXJnYXRlUHJvZmlsZS5mYXJnYXRlUHJvZmlsZUFybixcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkRlbGV0ZSgpIHtcbiAgICBpZiAoIXRoaXMucGh5c2ljYWxSZXNvdXJjZUlkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBkZWxldGUgYSBwcm9maWxlIHdpdGhvdXQgYSBwaHlzaWNhbCBpZCcpO1xuICAgIH1cblxuICAgIGNvbnN0IGRlbGV0ZUZhcmdhdGVQcm9maWxlOiBhd3MuRUtTLkRlbGV0ZUZhcmdhdGVQcm9maWxlUmVxdWVzdCA9IHtcbiAgICAgIGNsdXN0ZXJOYW1lOiB0aGlzLmV2ZW50LlJlc291cmNlUHJvcGVydGllcy5Db25maWcuY2x1c3Rlck5hbWUsXG4gICAgICBmYXJnYXRlUHJvZmlsZU5hbWU6IHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkLFxuICAgIH07XG5cbiAgICB0aGlzLmxvZyh7IGRlbGV0ZUZhcmdhdGVQcm9maWxlIH0pO1xuICAgIGNvbnN0IGRlbGV0ZUZhcmdhdGVQcm9maWxlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy5kZWxldGVGYXJnYXRlUHJvZmlsZShkZWxldGVGYXJnYXRlUHJvZmlsZSk7XG4gICAgdGhpcy5sb2coeyBkZWxldGVGYXJnYXRlUHJvZmlsZVJlc3BvbnNlIH0pO1xuXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIG9uVXBkYXRlKCkge1xuICAgIC8vIGFsbCB1cGRhdGVzIHJlcXVpcmUgYSByZXBsYWNlbWVudC4gYXMgbG9uZyBhcyBuYW1lIGlzIGdlbmVyYXRlZCwgd2UgYXJlXG4gICAgLy8gZ29vZC4gaWYgbmFtZSBpcyBleHBsaWNpdCwgdXBkYXRlIHdpbGwgZmFpbCwgd2hpY2ggaXMgY29tbW9uIHdoZW4gdHJ5aW5nXG4gICAgLy8gdG8gcmVwbGFjZSBjZm4gcmVzb3VyY2VzIHdpdGggZXhwbGljaXQgcGh5c2ljYWwgbmFtZXNcbiAgICByZXR1cm4gdGhpcy5vbkNyZWF0ZSgpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzQ3JlYXRlQ29tcGxldGUoKSB7XG4gICAgcmV0dXJuIHRoaXMuaXNVcGRhdGVDb21wbGV0ZSgpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc3Qgc3RhdHVzID0gYXdhaXQgdGhpcy5xdWVyeVN0YXR1cygpO1xuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBzdGF0dXMgPT09ICdBQ1RJVkUnLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNEZWxldGVDb21wbGV0ZSgpIHtcbiAgICBjb25zdCBzdGF0dXMgPSBhd2FpdCB0aGlzLnF1ZXJ5U3RhdHVzKCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIElzQ29tcGxldGU6IHN0YXR1cyA9PT0gJ05PVF9GT1VORCcsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZW5lcmF0ZXMgYSBmYXJnYXRlIHByb2ZpbGUgbmFtZS5cbiAgICovXG4gIHByaXZhdGUgZ2VuZXJhdGVQcm9maWxlTmFtZSgpIHtcbiAgICBjb25zdCBzdWZmaXggPSB0aGlzLnJlcXVlc3RJZC5yZXBsYWNlKC8tL2csICcnKTsgLy8gMzIgY2hhcnNcbiAgICBjb25zdCBvZmZzZXQgPSBNQVhfTkFNRV9MRU4gLSBzdWZmaXgubGVuZ3RoIC0gMTtcbiAgICBjb25zdCBwcmVmaXggPSB0aGlzLmxvZ2ljYWxSZXNvdXJjZUlkLnNsaWNlKDAsIG9mZnNldCA+IDAgPyBvZmZzZXQgOiAwKTtcbiAgICByZXR1cm4gYCR7cHJlZml4fS0ke3N1ZmZpeH1gO1xuICB9XG5cbiAgLyoqXG4gICAqIFF1ZXJpZXMgdGhlIEZhcmdhdGUgcHJvZmlsZSdzIGN1cnJlbnQgc3RhdHVzIGFuZCByZXR1cm5zIHRoZSBzdGF0dXMgb3JcbiAgICogTk9UX0ZPVU5EIGlmIHRoZSBwcm9maWxlIGRvZXNuJ3QgZXhpc3QgKGkuZS4gaXQgaGFzIGJlZW4gZGVsZXRlZCkuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHF1ZXJ5U3RhdHVzKCk6IFByb21pc2U8YXdzLkVLUy5GYXJnYXRlUHJvZmlsZVN0YXR1cyB8ICdOT1RfRk9VTkQnIHwgdW5kZWZpbmVkPiB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbmFibGUgdG8gZGV0ZXJtaW5lIHN0YXR1cyBmb3IgZmFyZ2F0ZSBwcm9maWxlIHdpdGhvdXQgYSByZXNvdXJjZSBuYW1lJyk7XG4gICAgfVxuXG4gICAgY29uc3QgZGVzY3JpYmVGYXJnYXRlUHJvZmlsZTogYXdzLkVLUy5EZXNjcmliZUZhcmdhdGVQcm9maWxlUmVxdWVzdCA9IHtcbiAgICAgIGNsdXN0ZXJOYW1lOiB0aGlzLmV2ZW50LlJlc291cmNlUHJvcGVydGllcy5Db25maWcuY2x1c3Rlck5hbWUsXG4gICAgICBmYXJnYXRlUHJvZmlsZU5hbWU6IHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkLFxuICAgIH07XG5cbiAgICB0cnkge1xuXG4gICAgICB0aGlzLmxvZyh7IGRlc2NyaWJlRmFyZ2F0ZVByb2ZpbGUgfSk7XG4gICAgICBjb25zdCBkZXNjcmliZUZhcmdhdGVQcm9maWxlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy5kZXNjcmliZUZhcmdhdGVQcm9maWxlKGRlc2NyaWJlRmFyZ2F0ZVByb2ZpbGUpO1xuICAgICAgdGhpcy5sb2coeyBkZXNjcmliZUZhcmdhdGVQcm9maWxlUmVzcG9uc2UgfSk7XG4gICAgICBjb25zdCBzdGF0dXMgPSBkZXNjcmliZUZhcmdhdGVQcm9maWxlUmVzcG9uc2UuZmFyZ2F0ZVByb2ZpbGU/LnN0YXR1cztcblxuICAgICAgaWYgKHN0YXR1cyA9PT0gJ0NSRUFURV9GQUlMRUQnIHx8IHN0YXR1cyA9PT0gJ0RFTEVURV9GQUlMRUQnKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihzdGF0dXMpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gc3RhdHVzO1xuICAgIH0gY2F0Y2ggKGRlc2NyaWJlRmFyZ2F0ZVByb2ZpbGVFcnJvcikge1xuICAgICAgaWYgKGRlc2NyaWJlRmFyZ2F0ZVByb2ZpbGVFcnJvci5jb2RlID09PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhpcy5sb2coJ3JlY2VpdmVkIFJlc291cmNlTm90Rm91bmRFeGNlcHRpb24sIHRoaXMgbWVhbnMgdGhlIHByb2ZpbGUgaGFzIGJlZW4gZGVsZXRlZCAob3IgbmV2ZXIgZXhpc3RlZCknKTtcbiAgICAgICAgcmV0dXJuICdOT1RfRk9VTkQnO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmxvZyh7IGRlc2NyaWJlRmFyZ2F0ZVByb2ZpbGVFcnJvciB9KTtcbiAgICAgIHRocm93IGRlc2NyaWJlRmFyZ2F0ZVByb2ZpbGVFcnJvcjtcbiAgICB9XG4gIH1cbn1cbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/apply/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/apply/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/get/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/get/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/helm/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py similarity index 99% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/helm/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py index c9120c1926e03..286976ced219a 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/helm/__init__.py +++ b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py @@ -111,7 +111,7 @@ def get_oci_cmd(repository, version): region = os.environ.get('AWS_REGION', 'us-east-1') cmnd = [ - f"aws ecr-public get-login-password --region {region} | " \ + f"aws ecr-public get-login-password --region us-east-1 | " \ f"helm registry login --username AWS --password-stdin {public_registry['registry']}; helm pull {repository} --version {version} --untar" ] else: diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/index.py b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/index.py rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/patch/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/patch/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/aws-cdk-eks-cluster-alb-controller-test.assets.json b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/aws-cdk-eks-cluster-alb-controller-test.assets.json index 7ab4fbe9c8163..74a70481a208c 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/aws-cdk-eks-cluster-alb-controller-test.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/aws-cdk-eks-cluster-alb-controller-test.assets.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "files": { "c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064": { "source": { @@ -27,15 +27,15 @@ } } }, - "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5": { + "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee": { "source": { - "path": "asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5", + "path": "asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip", + "objectKey": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -53,15 +53,15 @@ } } }, - "e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9": { + "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8": { "source": { - "path": "asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9", + "path": "asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9.zip", + "objectKey": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -118,7 +118,7 @@ } } }, - "6df565359d56c0de1e282f3c7873eb1a3f559e7c211404cd093371d2353fafaa": { + "e4ab354e4ce56910344523e060e9ee973ebdfc30595080f5c68466ef4864e7cd": { "source": { "path": "awscdkeksclusteralbcontrollertestawscdkawseksClusterResourceProvider5DBBAFBB.nested.template.json", "packaging": "file" @@ -126,12 +126,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "6df565359d56c0de1e282f3c7873eb1a3f559e7c211404cd093371d2353fafaa.json", + "objectKey": "e4ab354e4ce56910344523e060e9ee973ebdfc30595080f5c68466ef4864e7cd.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "e3798b4ae5b4db51a5a5aefe3810d3e8a7d38f80580164d4e420662c13779fbe": { + "b36b8f77c87ea19316f26c348678df34ab1ae50aafc1fe31ed45171c2c04ab05": { "source": { "path": "awscdkeksclusteralbcontrollertestawscdkawseksKubectlProviderA1AC28D1.nested.template.json", "packaging": "file" @@ -139,12 +139,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "e3798b4ae5b4db51a5a5aefe3810d3e8a7d38f80580164d4e420662c13779fbe.json", + "objectKey": "b36b8f77c87ea19316f26c348678df34ab1ae50aafc1fe31ed45171c2c04ab05.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "238b406e7ada5a7a0848309eef25cca04f52ecca98b545b9c67196669131e8c8": { + "d9fceb38127eccde41bf131a9109819a47a96e69777046c86417c8f4d36f8b2f": { "source": { "path": "aws-cdk-eks-cluster-alb-controller-test.template.json", "packaging": "file" @@ -152,7 +152,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "238b406e7ada5a7a0848309eef25cca04f52ecca98b545b9c67196669131e8c8.json", + "objectKey": "d9fceb38127eccde41bf131a9109819a47a96e69777046c86417c8f4d36f8b2f.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/aws-cdk-eks-cluster-alb-controller-test.template.json b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/aws-cdk-eks-cluster-alb-controller-test.template.json index eec2a808fa721..8076bfb7d4689 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/aws-cdk-eks-cluster-alb-controller-test.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/aws-cdk-eks-cluster-alb-controller-test.template.json @@ -983,7 +983,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/6df565359d56c0de1e282f3c7873eb1a3f559e7c211404cd093371d2353fafaa.json" + "/e4ab354e4ce56910344523e060e9ee973ebdfc30595080f5c68466ef4864e7cd.json" ] ] }, @@ -1018,7 +1018,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/e3798b4ae5b4db51a5a5aefe3810d3e8a7d38f80580164d4e420662c13779fbe.json" + "/b36b8f77c87ea19316f26c348678df34ab1ae50aafc1fe31ed45171c2c04ab05.json" ] ] }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/awscdkclusteralbcontrollerDefaultTestDeployAssert78AE94CA.assets.json b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/awscdkclusteralbcontrollerDefaultTestDeployAssert78AE94CA.assets.json index 49d2f81af953f..534e2cac21573 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/awscdkclusteralbcontrollerDefaultTestDeployAssert78AE94CA.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/awscdkclusteralbcontrollerDefaultTestDeployAssert78AE94CA.assets.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/awscdkeksclusteralbcontrollertestawscdkawseksClusterResourceProvider5DBBAFBB.nested.template.json b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/awscdkeksclusteralbcontrollertestawscdkawseksClusterResourceProvider5DBBAFBB.nested.template.json index 97c528c79331d..b22efad346b63 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/awscdkeksclusteralbcontrollertestawscdkawseksClusterResourceProvider5DBBAFBB.nested.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/awscdkeksclusteralbcontrollertestawscdkawseksClusterResourceProvider5DBBAFBB.nested.template.json @@ -73,7 +73,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ @@ -162,7 +162,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/awscdkeksclusteralbcontrollertestawscdkawseksKubectlProviderA1AC28D1.nested.template.json b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/awscdkeksclusteralbcontrollertestawscdkawseksKubectlProviderA1AC28D1.nested.template.json index e6d825f2a3324..70d390d2737c9 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/awscdkeksclusteralbcontrollertestawscdkawseksKubectlProviderA1AC28D1.nested.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/awscdkeksclusteralbcontrollertestawscdkawseksKubectlProviderA1AC28D1.nested.template.json @@ -51,6 +51,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -92,7 +104,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9.zip" + "S3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/cdk.out b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/cdk.out index ae4b03c54e770..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"30.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/integ.json b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/integ.json index 77a12a9e47232..e4e3b445b834c 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "testCases": { "aws-cdk-cluster-alb-controller/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/manifest.json b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/manifest.json index 905c34e872fc0..44b356cc9a4e8 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "artifacts": { "aws-cdk-eks-cluster-alb-controller-test.assets": { "type": "cdk:asset-manifest", @@ -17,7 +17,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/238b406e7ada5a7a0848309eef25cca04f52ecca98b545b9c67196669131e8c8.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/d9fceb38127eccde41bf131a9109819a47a96e69777046c86417c8f4d36f8b2f.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/tree.json b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/tree.json index 7dd81a6f1f937..d49f7060509a5 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/tree.json @@ -1511,7 +1511,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -1684,7 +1684,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -2582,7 +2582,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/6df565359d56c0de1e282f3c7873eb1a3f559e7c211404cd093371d2353fafaa.json" + "/e4ab354e4ce56910344523e060e9ee973ebdfc30595080f5c68466ef4864e7cd.json" ] ] }, @@ -2681,6 +2681,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -2780,7 +2792,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9.zip" + "s3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "role": { "Fn::GetAtt": [ @@ -3202,7 +3214,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/e3798b4ae5b4db51a5a5aefe3810d3e8a7d38f80580164d4e420662c13779fbe.json" + "/b36b8f77c87ea19316f26c348678df34ab1ae50aafc1fe31ed45171c2c04ab05.json" ] ] }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/helm/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/helm/__init__.py deleted file mode 100644 index b9a741c8972c4..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/helm/__init__.py +++ /dev/null @@ -1,187 +0,0 @@ -import json -import logging -import os -import re -import subprocess -import shutil -import tempfile -import zipfile -from urllib.parse import urlparse, unquote - -logger = logging.getLogger() -logger.setLevel(logging.INFO) - -# these are coming from the kubectl layer -os.environ['PATH'] = '/opt/helm:/opt/awscli:' + os.environ['PATH'] - -outdir = os.environ.get('TEST_OUTDIR', '/tmp') -kubeconfig = os.path.join(outdir, 'kubeconfig') - -def get_chart_asset_from_url(chart_asset_url): - chart_zip = os.path.join(outdir, 'chart.zip') - shutil.rmtree(chart_zip, ignore_errors=True) - subprocess.check_call(['aws', 's3', 'cp', chart_asset_url, chart_zip]) - chart_dir = os.path.join(outdir, 'chart') - shutil.rmtree(chart_dir, ignore_errors=True) - os.mkdir(chart_dir) - with zipfile.ZipFile(chart_zip, 'r') as zip_ref: - zip_ref.extractall(chart_dir) - return chart_dir - -def helm_handler(event, context): - logger.info(json.dumps(dict(event, ResponseURL='...'))) - - request_type = event['RequestType'] - props = event['ResourceProperties'] - - # resource properties - cluster_name = props['ClusterName'] - role_arn = props['RoleArn'] - release = props['Release'] - chart = props.get('Chart', None) - chart_asset_url = props.get('ChartAssetURL', None) - version = props.get('Version', None) - wait = props.get('Wait', False) - timeout = props.get('Timeout', None) - namespace = props.get('Namespace', None) - create_namespace = props.get('CreateNamespace', None) - repository = props.get('Repository', None) - values_text = props.get('Values', None) - - # "log in" to the cluster - subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig', - '--role-arn', role_arn, - '--name', cluster_name, - '--kubeconfig', kubeconfig - ]) - - if os.path.isfile(kubeconfig): - os.chmod(kubeconfig, 0o600) - - # Write out the values to a file and include them with the install and upgrade - values_file = None - if not request_type == "Delete" and not values_text is None: - values = json.loads(values_text) - values_file = os.path.join(outdir, 'values.yaml') - with open(values_file, "w") as f: - f.write(json.dumps(values, indent=2)) - - if request_type == 'Create' or request_type == 'Update': - # Ensure chart or chart_asset_url are set - if chart == None and chart_asset_url == None: - raise RuntimeError(f'chart or chartAsset must be specified') - - if chart_asset_url != None: - assert(chart==None) - assert(repository==None) - assert(version==None) - if not chart_asset_url.startswith('s3://'): - raise RuntimeError(f'ChartAssetURL must point to as s3 location but is {chart_asset_url}') - # future work: support versions from s3 assets - chart = get_chart_asset_from_url(chart_asset_url) - - if repository is not None and repository.startswith('oci://'): - tmpdir = tempfile.TemporaryDirectory() - chart_dir = get_chart_from_oci(tmpdir.name, release, repository, version) - chart = chart_dir - - helm('upgrade', release, chart, repository, values_file, namespace, version, wait, timeout, create_namespace) - elif request_type == "Delete": - try: - helm('uninstall', release, namespace=namespace, timeout=timeout) - except Exception as e: - logger.info("delete error: %s" % e) - - -def get_oci_cmd(repository, version): - # Generates OCI command based on pattern. Public ECR vs Private ECR are treated differently. - cmnd = [] - private_ecr_pattern = '\d+.dkr.ecr.[a-z]+-[a-z]+-\d.amazonaws.com' - public_ecr = 'public.ecr.aws' - - registry = repository.rsplit('/', 1)[0].replace('oci://', '') - - if re.fullmatch(private_ecr_pattern, registry) is not None: - logger.info("Found AWS private repository") - region = registry.replace('.amazonaws.com', '').split('.')[-1] - cmnd = [ - f"aws ecr get-login-password --region {region} | " \ - f"helm registry login --username AWS --password-stdin {registry}; helm pull {repository} --version {version} --untar" - ] - elif registry.startswith(public_ecr): - logger.info("Found AWS public repository, will use default region as deployment") - region = os.environ.get('AWS_REGION', 'us-east-1') - - cmnd = [ - f"aws ecr-public get-login-password --region {region} | " \ - f"helm registry login --username AWS --password-stdin {public_ecr}; helm pull {repository} --version {version} --untar" - ] - else: - logger.error("OCI repository format not recognized, falling back to helm pull") - cmnd = ['helm', 'pull', repository, '--version', version, '--untar'] - - return cmnd - - -def get_chart_from_oci(tmpdir, release, repository = None, version = None): - - cmnd = get_oci_cmd(repository, version) - - maxAttempts = 3 - retry = maxAttempts - while retry > 0: - try: - logger.info(cmnd) - output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=tmpdir, shell=True) - logger.info(output) - - return os.path.join(tmpdir, release) - except subprocess.CalledProcessError as exc: - output = exc.output - if b'Broken pipe' in output: - retry = retry - 1 - logger.info("Broken pipe, retries left: %s" % retry) - else: - raise Exception(output) - raise Exception(f'Operation failed after {maxAttempts} attempts: {output}') - - -def helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None): - import subprocess - - cmnd = ['helm', verb, release] - if not chart is None: - cmnd.append(chart) - if verb == 'upgrade': - cmnd.append('--install') - if create_namespace: - cmnd.append('--create-namespace') - if not repo is None: - cmnd.extend(['--repo', repo]) - if not file is None: - cmnd.extend(['--values', file]) - if not version is None: - cmnd.extend(['--version', version]) - if not namespace is None: - cmnd.extend(['--namespace', namespace]) - if wait: - cmnd.append('--wait') - if not timeout is None: - cmnd.extend(['--timeout', timeout]) - cmnd.extend(['--kubeconfig', kubeconfig]) - - maxAttempts = 3 - retry = maxAttempts - while retry > 0: - try: - output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir) - logger.info(output) - return - except subprocess.CalledProcessError as exc: - output = exc.output - if b'Broken pipe' in output: - retry = retry - 1 - logger.info("Broken pipe, retries left: %s" % retry) - else: - raise Exception(output) - raise Exception(f'Operation failed after {maxAttempts} attempts: {output}') diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js similarity index 55% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js index 1d08e9d7b865b..c9dc1b8d2c19a 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js @@ -256,8 +256,8 @@ function analyzeUpdate(oldProps, newProps) { const oldEnc = oldProps.encryptionConfig || {}; return { replaceName: newProps.name !== oldProps.name, - replaceVpc: JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), + replaceVpc: JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), @@ -270,4 +270,4 @@ function analyzeUpdate(oldProps, newProps) { function setsEqual(first, second) { return first.size === second.size && [...first].every((e) => second.has(e)); } -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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SSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBa0IsRUFBRSxNQUFtQjtJQUN4RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgRWtzQ2xpZW50LCBSZXNvdXJjZUV2ZW50LCBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX05BTUVfTEVOID0gMTAwO1xuXG5leHBvcnQgY2xhc3MgQ2x1c3RlclJlc291cmNlSGFuZGxlciBleHRlbmRzIFJlc291cmNlSGFuZGxlciB7XG4gIHB1YmxpYyBnZXQgY2x1c3Rlck5hbWUoKSB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZGV0ZXJtaW5lIGNsdXN0ZXIgbmFtZSB3aXRob3V0IHBoeXNpY2FsIHJlc291cmNlIElEJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PjtcblxuICBjb25zdHJ1Y3Rvcihla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICBzdXBlcihla3MsIGV2ZW50KTtcblxuICAgIHRoaXMubmV3UHJvcHMgPSBwYXJzZVByb3BzKHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLm9sZFByb3BzID0gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnID8gcGFyc2VQcm9wcyhldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMpIDoge307XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gQ1JFQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCdvbkNyZWF0ZTogY3JlYXRpbmcgY2x1c3RlciB3aXRoIG9wdGlvbnM6JywgSlNPTi5zdHJpbmdpZnkodGhpcy5uZXdQcm9wcywgdW5kZWZpbmVkLCAyKSk7XG4gICAgaWYgKCF0aGlzLm5ld1Byb3BzLnJvbGVBcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJyb2xlQXJuXCIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyTmFtZSA9IHRoaXMubmV3UHJvcHMubmFtZSB8fCB0aGlzLmdlbmVyYXRlQ2x1c3Rlck5hbWUoKTtcblxuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmVrcy5jcmVhdGVDbHVzdGVyKHtcbiAgICAgIC4uLnRoaXMubmV3UHJvcHMsXG4gICAgICBuYW1lOiBjbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcC5jbHVzdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBjbHVzdGVyICR7Y2x1c3Rlck5hbWV9OiBDcmVhdGVDbHVzdGVyIHJldHVybmVkIHdpdGhvdXQgY2x1c3RlciBpbmZvcm1hdGlvbmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHJlc3AuY2x1c3Rlci5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIERFTEVURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25EZWxldGUoKTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgb25EZWxldGU6IGRlbGV0aW5nIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfWApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVrcy5kZWxldGVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyICR7dGhpcy5jbHVzdGVyTmFtZX0gbm90IGZvdW5kLCBpZGVtcG90ZW50bHkgc3VjY2VlZGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coYGlzRGVsZXRlQ29tcGxldGU6IHdhaXRpbmcgZm9yIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSB0byBiZSBkZWxldGVkYCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJldHVybmVkOicsIEpTT04uc3RyaW5naWZ5KHJlc3AsIHVuZGVmaW5lZCwgMikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICBjb25zb2xlLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgY2x1c3RlciBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0cnVlIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgZXJyb3I6JywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIFVQREFURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IGFuYWx5emVVcGRhdGUodGhpcy5vbGRQcm9wcywgdGhpcy5uZXdQcm9wcyk7XG4gICAgY29uc29sZS5sb2coJ29uVXBkYXRlOicsIEpTT04uc3RyaW5naWZ5KHsgdXBkYXRlcyB9LCB1bmRlZmluZWQsIDIpKTtcblxuICAgIC8vIHVwZGF0ZXMgdG8gZW5jcnlwdGlvbiBjb25maWcgaXMgbm90IHN1cHBvcnRlZFxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUVuY3J5cHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHVwZGF0ZSBjbHVzdGVyIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZXJlIGlzIGFuIHVwZGF0ZSB0aGF0IHJlcXVpcmVzIHJlcGxhY2VtZW50LCBnbyBhaGVhZCBhbmQganVzdCBjcmVhdGVcbiAgICAvLyBhIG5ldyBjbHVzdGVyIHdpdGggdGhlIG5ldyBjb25maWcuIFRoZSBvbGQgY2x1c3RlciB3aWxsIGF1dG9tYXRpY2FsbHkgYmVcbiAgICAvLyBkZWxldGVkIGJ5IGNsb3VkZm9ybWF0aW9uIHVwb24gc3VjY2Vzcy5cbiAgICBpZiAodXBkYXRlcy5yZXBsYWNlTmFtZSB8fCB1cGRhdGVzLnJlcGxhY2VSb2xlIHx8IHVwZGF0ZXMucmVwbGFjZVZwYykge1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgcmVwbGFjaW5nIHRoaXMgY2x1c3RlciBhbmQgdGhlIGNsdXN0ZXIgaGFzIGFuIGV4cGxpY2l0XG4gICAgICAvLyBwaHlzaWNhbCBuYW1lLCB0aGUgY3JlYXRpb24gb2YgdGhlIG5ldyBjbHVzdGVyIHdpbGwgZmFpbCB3aXRoIFwidGhlcmUgaXNcbiAgICAgIC8vIGFscmVhZHkgYSBjbHVzdGVyIHdpdGggdGhhdCBuYW1lXCIuIHRoaXMgaXMgYSBjb21tb24gYmVoYXZpb3IgZm9yXG4gICAgICAvLyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZXMgdGhhdCBzdXBwb3J0IHNwZWNpZnlpbmcgYSBwaHlzaWNhbCBuYW1lLlxuICAgICAgaWYgKHRoaXMub2xkUHJvcHMubmFtZSA9PT0gdGhpcy5uZXdQcm9wcy5uYW1lICYmIHRoaXMub2xkUHJvcHMubmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXBsYWNlIGNsdXN0ZXIgXCIke3RoaXMub2xkUHJvcHMubmFtZX1cIiBzaW5jZSBpdCBoYXMgYW4gZXhwbGljaXQgcGh5c2ljYWwgbmFtZS4gRWl0aGVyIHJlbmFtZSB0aGUgY2x1c3RlciBvciByZW1vdmUgdGhlIFwibmFtZVwiIGNvbmZpZ3VyYXRpb25gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub25DcmVhdGUoKTtcbiAgICB9XG5cbiAgICAvLyBpZiBhIHZlcnNpb24gdXBkYXRlIGlzIHJlcXVpcmVkLCBpc3N1ZSB0aGUgdmVyc2lvbiB1cGRhdGVcbiAgICBpZiAodXBkYXRlcy51cGRhdGVWZXJzaW9uKSB7XG4gICAgICBpZiAoIXRoaXMubmV3UHJvcHMudmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZW1vdmUgY2x1c3RlciB2ZXJzaW9uIGNvbmZpZ3VyYXRpb24uIEN1cnJlbnQgdmVyc2lvbiBpcyAke3RoaXMub2xkUHJvcHMudmVyc2lvbn1gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlQ2x1c3RlclZlcnNpb24odGhpcy5uZXdQcm9wcy52ZXJzaW9uKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nICYmIHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1cGRhdGUgbG9nZ2luZyBhbmQgYWNjZXNzIGF0IHRoZSBzYW1lIHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nIHx8IHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICBjb25zdCBjb25maWc6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QgPSB7XG4gICAgICAgIG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgICB9O1xuICAgICAgaWYgKHVwZGF0ZXMudXBkYXRlTG9nZ2luZykge1xuICAgICAgICBjb25maWcubG9nZ2luZyA9IHRoaXMubmV3UHJvcHMubG9nZ2luZztcbiAgICAgIH07XG4gICAgICBpZiAodXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIGNsdXN0ZXIgd2l0aCBzZWN1cml0eUdyb3VwSWRzIGFuZCBzdWJuZXRJZHMgKGFzIHNwZWNpZmllZCBpbiB0aGUgd2FybmluZyBoZXJlOlxuICAgICAgICAvLyBodHRwczovL2F3c2NsaS5hbWF6b25hd3MuY29tL3YyL2RvY3VtZW50YXRpb24vYXBpL2xhdGVzdC9yZWZlcmVuY2UvZWtzL3VwZGF0ZS1jbHVzdGVyLWNvbmZpZy5odG1sKVxuICAgICAgICAvLyB3aWxsIGZhaWwsIHRoZXJlZm9yZSB3ZSB0YWtlIG9ubHkgdGhlIGFjY2VzcyBmaWVsZHMgZXhwbGljaXRseVxuICAgICAgICBjb25maWcucmVzb3VyY2VzVnBjQ29uZmlnID0ge1xuICAgICAgICAgIGVuZHBvaW50UHJpdmF0ZUFjY2VzczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzLFxuICAgICAgICAgIGVuZHBvaW50UHVibGljQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyxcbiAgICAgICAgICBwdWJsaWNBY2Nlc3NDaWRyczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcucHVibGljQWNjZXNzQ2lkcnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgICB9XG5cbiAgICAvLyBubyB1cGRhdGVzXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc29sZS5sb2coJ2lzVXBkYXRlQ29tcGxldGUnKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYW4gRUtTIHVwZGF0ZSwgd2Ugd2lsbCBtb25pdG9yIHRoZSB1cGRhdGUgZXZlbnQgaXRzZWxmXG4gICAgaWYgKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gYXdhaXQgdGhpcy5pc0Vrc1VwZGF0ZUNvbXBsZXRlKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpO1xuICAgICAgaWYgKCFjb21wbGV0ZSkge1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiBmYWxzZSB9O1xuICAgICAgfVxuXG4gICAgICAvLyBmYWxsIHRocm91Z2g6IGlmIHRoZSB1cGRhdGUgaXMgZG9uZSwgd2Ugc2ltcGx5IGRlbGVnYXRlIHRvIGlzQWN0aXZlKClcbiAgICAgIC8vIGluIG9yZGVyIHRvIGV4dHJhY3QgYXR0cmlidXRlcyBhbmQgc3RhdGUgZnJvbSB0aGUgY2x1c3RlciBpdHNlbGYsIHdoaWNoXG4gICAgICAvLyBpcyBzdXBwb3NlZCB0byBiZSBpbiBhbiBBQ1RJVkUgc3RhdGUgYWZ0ZXIgdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbHVzdGVyVmVyc2lvbihuZXdWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgdXBkYXRpbmcgY2x1c3RlciB2ZXJzaW9uIHRvICR7bmV3VmVyc2lvbn1gKTtcblxuICAgIC8vIHVwZGF0ZS1jbHVzdGVyLXZlcnNpb24gd2lsbCBmYWlsIGlmIHdlIHRyeSB0byB1cGRhdGUgdG8gdGhlIHNhbWUgdmVyc2lvbixcbiAgICAvLyBzbyBza2lwIGluIHRoaXMgY2FzZS5cbiAgICBjb25zdCBjbHVzdGVyID0gKGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSkpLmNsdXN0ZXI7XG4gICAgaWYgKGNsdXN0ZXI/LnZlcnNpb24gPT09IG5ld1ZlcnNpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyIGFscmVhZHkgYXQgdmVyc2lvbiAke2NsdXN0ZXIudmVyc2lvbn0sIHNraXBwaW5nIHZlcnNpb24gdXBkYXRlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy51cGRhdGVDbHVzdGVyVmVyc2lvbih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsIHZlcnNpb246IG5ld1ZlcnNpb24gfSk7XG4gICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNBY3RpdmUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZygnd2FpdGluZyBmb3IgY2x1c3RlciB0byBiZWNvbWUgQUNUSVZFJyk7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciByZXN1bHQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgY29uc3QgY2x1c3RlciA9IHJlc3AuY2x1c3RlcjtcblxuICAgIC8vIGlmIGNsdXN0ZXIgaXMgdW5kZWZpbmVkIChzaG91bGRudCBoYXBwZW4pIG9yIHN0YXR1cyBpcyBub3QgQUNUSVZFLCB3ZSBhcmVcbiAgICAvLyBub3QgY29tcGxldGUuIG5vdGUgdGhhdCB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZyYW1ld29yayBmb3JiaWRzXG4gICAgLy8gcmV0dXJuaW5nIGF0dHJpYnV0ZXMgKERhdGEpIGlmIGlzQ29tcGxldGUgaXMgZmFsc2UuXG4gICAgaWYgKGNsdXN0ZXI/LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgIC8vIG5vdCB2ZXJ5IGluZm9ybWF0aXZlLCB1bmZvcnR1bmF0ZWx5IHRoZSByZXNwb25zZSBkb2Vzbid0IGNvbnRhaW4gYW55IGVycm9yXG4gICAgICAvLyBpbmZvcm1hdGlvbiA6XFxcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2x1c3RlciBpcyBpbiBhIEZBSUxFRCBzdGF0dXMnKTtcbiAgICB9IGVsc2UgaWYgKGNsdXN0ZXI/LnN0YXR1cyAhPT0gJ0FDVElWRScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIE5hbWU6IGNsdXN0ZXIubmFtZSxcbiAgICAgICAgICBFbmRwb2ludDogY2x1c3Rlci5lbmRwb2ludCxcbiAgICAgICAgICBBcm46IGNsdXN0ZXIuYXJuLFxuXG4gICAgICAgICAgLy8gSU1QT1JUQU5UOiBDRk4gZXhwZWN0cyB0aGF0IGF0dHJpYnV0ZXMgd2lsbCAqYWx3YXlzKiBoYXZlIHZhbHVlcyxcbiAgICAgICAgICAvLyBzbyByZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGluIGNhc2UgdGhlIHZhbHVlIGlzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQ0ZOIHdpbGwgdGhyb3cgd2l0aCBgVmVuZG9yIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpblxuICAgICAgICAgIC8vIFhYWFgga2V5YC5cblxuICAgICAgICAgIENlcnRpZmljYXRlQXV0aG9yaXR5RGF0YTogY2x1c3Rlci5jZXJ0aWZpY2F0ZUF1dGhvcml0eT8uZGF0YSA/PyAnJyxcbiAgICAgICAgICBDbHVzdGVyU2VjdXJpdHlHcm91cElkOiBjbHVzdGVyLnJlc291cmNlc1ZwY0NvbmZpZz8uY2x1c3RlclNlY3VyaXR5R3JvdXBJZCA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyVXJsOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXIgPz8gJycsXG4gICAgICAgICAgT3BlbklkQ29ubmVjdElzc3VlcjogY2x1c3Rlci5pZGVudGl0eT8ub2lkYz8uaXNzdWVyPy5zdWJzdHJpbmcoOCkgPz8gJycsIC8vIFN0cmlwcyBvZmYgaHR0cHM6Ly8gZnJvbSB0aGUgaXNzdWVyIHVybFxuXG4gICAgICAgICAgLy8gV2UgY2FuIHNhZmVseSByZXR1cm4gdGhlIGZpcnN0IGl0ZW0gZnJvbSBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gYXJyYXksIGJlY2F1c2UgaXQgaGFzIGEgbGltaXQgb2YgMSBpdGVtXG4gICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vrcy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDbHVzdGVyLmh0bWwjQW1hem9uRUtTLUNyZWF0ZUNsdXN0ZXItcmVxdWVzdC1lbmNyeXB0aW9uQ29uZmlnXG4gICAgICAgICAgRW5jcnlwdGlvbkNvbmZpZ0tleUFybjogY2x1c3Rlci5lbmNyeXB0aW9uQ29uZmlnPy5zaGlmdCgpPy5wcm92aWRlcj8ua2V5QXJuID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzRWtzVXBkYXRlQ29tcGxldGUoZWtzVXBkYXRlSWQ6IHN0cmluZykge1xuICAgIHRoaXMubG9nKHsgaXNFa3NVcGRhdGVDb21wbGV0ZTogZWtzVXBkYXRlSWQgfSk7XG5cbiAgICBjb25zdCBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVVcGRhdGUoe1xuICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgIHVwZGF0ZUlkOiBla3NVcGRhdGVJZCxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nKHsgZGVzY3JpYmVVcGRhdGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5hYmxlIHRvIGRlc2NyaWJlIHVwZGF0ZSB3aXRoIGlkIFwiJHtla3NVcGRhdGVJZH1cImApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzKSB7XG4gICAgICBjYXNlICdJblByb2dyZXNzJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgY2FzZSAnU3VjY2Vzc2Z1bCc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnRmFpbGVkJzpcbiAgICAgIGNhc2UgJ0NhbmNlbGxlZCc6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2x1c3RlciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiIGZhaWxlZCB3aXRoIGVycm9yczogJHtKU09OLnN0cmluZ2lmeShkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5lcnJvcnMpfWApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIHN0YXR1cyBcIiR7ZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzfVwiIGZvciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNsdXN0ZXJOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9DTFVTVEVSX05BTUVfTEVOIC0gc3VmZml4Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5sb2dpY2FsUmVzb3VyY2VJZC5zbGljZSgwLCBvZmZzZXQgPiAwID8gb2Zmc2V0IDogMCk7XG4gICAgcmV0dXJuIGAke3ByZWZpeH0tJHtzdWZmaXh9YDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3BzKHByb3BzOiBhbnkpOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0IHtcblxuICBjb25zdCBwYXJzZWQgPSBwcm9wcz8uQ29uZmlnID8/IHt9O1xuXG4gIC8vIHRoaXMgaXMgd2VpcmQgYnV0IHRoZXNlIGJvb2xlYW4gcHJvcGVydGllcyBhcmUgcGFzc2VkIGJ5IENGTiBhcyBhIHN0cmluZywgYW5kIHdlIG5lZWQgdGhlbSB0byBiZSBib29sZWFuaWMgZm9yIHRoZSBTREsuXG4gIC8vIE90aGVyd2lzZSBpdCBmYWlscyB3aXRoICdVbmV4cGVjdGVkIFBhcmFtZXRlcjogcGFyYW1zLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgaXMgZXhwZWN0ZWQgdG8gYmUgYSBib29sZWFuJ1xuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWc/LmVuZHBvaW50UHJpdmF0ZUFjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9PT0gJ3RydWUnO1xuICB9XG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQdWJsaWNBY2Nlc3MpID09PSAnc3RyaW5nJykge1xuICAgIHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQubG9nZ2luZz8uY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCkgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9IHBhcnNlZC5sb2dnaW5nLmNsdXN0ZXJMb2dnaW5nWzBdLmVuYWJsZWQgPT09ICd0cnVlJztcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQ7XG5cbn1cblxuaW50ZXJmYWNlIFVwZGF0ZU1hcCB7XG4gIHJlcGxhY2VOYW1lOiBib29sZWFuOyAvLyBuYW1lXG4gIHJlcGxhY2VWcGM6IGJvb2xlYW47IC8vIHJlc291cmNlc1ZwY0NvbmZpZy5zdWJuZXRJZHMgYW5kIHNlY3VyaXR5R3JvdXBJZHNcbiAgcmVwbGFjZVJvbGU6IGJvb2xlYW47IC8vIHJvbGVBcm5cblxuICB1cGRhdGVWZXJzaW9uOiBib29sZWFuOyAvLyB2ZXJzaW9uXG4gIHVwZGF0ZUxvZ2dpbmc6IGJvb2xlYW47IC8vIGxvZ2dpbmdcbiAgdXBkYXRlRW5jcnlwdGlvbjogYm9vbGVhbjsgLy8gZW5jcnlwdGlvbiAoY2Fubm90IGJlIHVwZGF0ZWQpXG4gIHVwZGF0ZUFjY2VzczogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBhbmQgZW5kcG9pbnRQdWJsaWNBY2Nlc3Ncbn1cblxuZnVuY3Rpb24gYW5hbHl6ZVVwZGF0ZShvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PiwgbmV3UHJvcHM6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBVcGRhdGVNYXAge1xuICBjb25zb2xlLmxvZygnb2xkIHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShvbGRQcm9wcykpO1xuICBjb25zb2xlLmxvZygnbmV3IHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShuZXdQcm9wcykpO1xuXG4gIGNvbnN0IG5ld1ZwY1Byb3BzID0gbmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRWcGNQcm9wcyA9IG9sZFByb3BzLnJlc291cmNlc1ZwY0NvbmZpZyB8fCB7fTtcblxuICBjb25zdCBvbGRQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQob2xkVnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQobmV3VnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdFbmMgPSBuZXdQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRFbmMgPSBvbGRQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgcmVwbGFjZU5hbWU6IG5ld1Byb3BzLm5hbWUgIT09IG9sZFByb3BzLm5hbWUsXG4gICAgcmVwbGFjZVZwYzpcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnN1Ym5ldElkcykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFZwY1Byb3BzLnN1Ym5ldElkcykgfHxcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnNlY3VyaXR5R3JvdXBJZHMpICE9PSBKU09OLnN0cmluZ2lmeShvbGRWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzKSxcbiAgICB1cGRhdGVBY2Nlc3M6XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgIT09IG9sZFZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyB8fFxuICAgICAgbmV3VnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgIT09IG9sZFZwY1Byb3BzLmVuZHBvaW50UHVibGljQWNjZXNzIHx8XG4gICAgICAhc2V0c0VxdWFsKG5ld1B1YmxpY0FjY2Vzc0NpZHJzLCBvbGRQdWJsaWNBY2Nlc3NDaWRycyksXG4gICAgcmVwbGFjZVJvbGU6IG5ld1Byb3BzLnJvbGVBcm4gIT09IG9sZFByb3BzLnJvbGVBcm4sXG4gICAgdXBkYXRlVmVyc2lvbjogbmV3UHJvcHMudmVyc2lvbiAhPT0gb2xkUHJvcHMudmVyc2lvbixcbiAgICB1cGRhdGVFbmNyeXB0aW9uOiBKU09OLnN0cmluZ2lmeShuZXdFbmMpICE9PSBKU09OLnN0cmluZ2lmeShvbGRFbmMpLFxuICAgIHVwZGF0ZUxvZ2dpbmc6IEpTT04uc3RyaW5naWZ5KG5ld1Byb3BzLmxvZ2dpbmcpICE9PSBKU09OLnN0cmluZ2lmeShvbGRQcm9wcy5sb2dnaW5nKSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gc2V0c0VxdWFsKGZpcnN0OiBTZXQ8c3RyaW5nPiwgc2Vjb25kOiBTZXQ8c3RyaW5nPikge1xuICByZXR1cm4gZmlyc3Quc2l6ZSA9PT0gc2Vjb25kLnNpemUgJiYgWy4uLmZpcnN0XS5ldmVyeSgoZTogc3RyaW5nKSA9PiBzZWNvbmQuaGFzKGUpKTtcbn1cbiJdfQ== \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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LENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztRQUNuRSxhQUFhLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBa0IsRUFBRSxNQUFtQjtJQUN4RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgRWtzQ2xpZW50LCBSZXNvdXJjZUV2ZW50LCBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX05BTUVfTEVOID0gMTAwO1xuXG5leHBvcnQgY2xhc3MgQ2x1c3RlclJlc291cmNlSGFuZGxlciBleHRlbmRzIFJlc291cmNlSGFuZGxlciB7XG4gIHB1YmxpYyBnZXQgY2x1c3Rlck5hbWUoKSB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZGV0ZXJtaW5lIGNsdXN0ZXIgbmFtZSB3aXRob3V0IHBoeXNpY2FsIHJlc291cmNlIElEJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PjtcblxuICBjb25zdHJ1Y3Rvcihla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICBzdXBlcihla3MsIGV2ZW50KTtcblxuICAgIHRoaXMubmV3UHJvcHMgPSBwYXJzZVByb3BzKHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLm9sZFByb3BzID0gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnID8gcGFyc2VQcm9wcyhldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMpIDoge307XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gQ1JFQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCdvbkNyZWF0ZTogY3JlYXRpbmcgY2x1c3RlciB3aXRoIG9wdGlvbnM6JywgSlNPTi5zdHJpbmdpZnkodGhpcy5uZXdQcm9wcywgdW5kZWZpbmVkLCAyKSk7XG4gICAgaWYgKCF0aGlzLm5ld1Byb3BzLnJvbGVBcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJyb2xlQXJuXCIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyTmFtZSA9IHRoaXMubmV3UHJvcHMubmFtZSB8fCB0aGlzLmdlbmVyYXRlQ2x1c3Rlck5hbWUoKTtcblxuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmVrcy5jcmVhdGVDbHVzdGVyKHtcbiAgICAgIC4uLnRoaXMubmV3UHJvcHMsXG4gICAgICBuYW1lOiBjbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcC5jbHVzdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBjbHVzdGVyICR7Y2x1c3Rlck5hbWV9OiBDcmVhdGVDbHVzdGVyIHJldHVybmVkIHdpdGhvdXQgY2x1c3RlciBpbmZvcm1hdGlvbmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHJlc3AuY2x1c3Rlci5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIERFTEVURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25EZWxldGUoKTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgb25EZWxldGU6IGRlbGV0aW5nIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfWApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVrcy5kZWxldGVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyICR7dGhpcy5jbHVzdGVyTmFtZX0gbm90IGZvdW5kLCBpZGVtcG90ZW50bHkgc3VjY2VlZGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coYGlzRGVsZXRlQ29tcGxldGU6IHdhaXRpbmcgZm9yIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSB0byBiZSBkZWxldGVkYCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJldHVybmVkOicsIEpTT04uc3RyaW5naWZ5KHJlc3AsIHVuZGVmaW5lZCwgMikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICBjb25zb2xlLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgY2x1c3RlciBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0cnVlIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgZXJyb3I6JywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIFVQREFURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IGFuYWx5emVVcGRhdGUodGhpcy5vbGRQcm9wcywgdGhpcy5uZXdQcm9wcyk7XG4gICAgY29uc29sZS5sb2coJ29uVXBkYXRlOicsIEpTT04uc3RyaW5naWZ5KHsgdXBkYXRlcyB9LCB1bmRlZmluZWQsIDIpKTtcblxuICAgIC8vIHVwZGF0ZXMgdG8gZW5jcnlwdGlvbiBjb25maWcgaXMgbm90IHN1cHBvcnRlZFxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUVuY3J5cHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHVwZGF0ZSBjbHVzdGVyIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZXJlIGlzIGFuIHVwZGF0ZSB0aGF0IHJlcXVpcmVzIHJlcGxhY2VtZW50LCBnbyBhaGVhZCBhbmQganVzdCBjcmVhdGVcbiAgICAvLyBhIG5ldyBjbHVzdGVyIHdpdGggdGhlIG5ldyBjb25maWcuIFRoZSBvbGQgY2x1c3RlciB3aWxsIGF1dG9tYXRpY2FsbHkgYmVcbiAgICAvLyBkZWxldGVkIGJ5IGNsb3VkZm9ybWF0aW9uIHVwb24gc3VjY2Vzcy5cbiAgICBpZiAodXBkYXRlcy5yZXBsYWNlTmFtZSB8fCB1cGRhdGVzLnJlcGxhY2VSb2xlIHx8IHVwZGF0ZXMucmVwbGFjZVZwYykge1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgcmVwbGFjaW5nIHRoaXMgY2x1c3RlciBhbmQgdGhlIGNsdXN0ZXIgaGFzIGFuIGV4cGxpY2l0XG4gICAgICAvLyBwaHlzaWNhbCBuYW1lLCB0aGUgY3JlYXRpb24gb2YgdGhlIG5ldyBjbHVzdGVyIHdpbGwgZmFpbCB3aXRoIFwidGhlcmUgaXNcbiAgICAgIC8vIGFscmVhZHkgYSBjbHVzdGVyIHdpdGggdGhhdCBuYW1lXCIuIHRoaXMgaXMgYSBjb21tb24gYmVoYXZpb3IgZm9yXG4gICAgICAvLyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZXMgdGhhdCBzdXBwb3J0IHNwZWNpZnlpbmcgYSBwaHlzaWNhbCBuYW1lLlxuICAgICAgaWYgKHRoaXMub2xkUHJvcHMubmFtZSA9PT0gdGhpcy5uZXdQcm9wcy5uYW1lICYmIHRoaXMub2xkUHJvcHMubmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXBsYWNlIGNsdXN0ZXIgXCIke3RoaXMub2xkUHJvcHMubmFtZX1cIiBzaW5jZSBpdCBoYXMgYW4gZXhwbGljaXQgcGh5c2ljYWwgbmFtZS4gRWl0aGVyIHJlbmFtZSB0aGUgY2x1c3RlciBvciByZW1vdmUgdGhlIFwibmFtZVwiIGNvbmZpZ3VyYXRpb25gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub25DcmVhdGUoKTtcbiAgICB9XG5cbiAgICAvLyBpZiBhIHZlcnNpb24gdXBkYXRlIGlzIHJlcXVpcmVkLCBpc3N1ZSB0aGUgdmVyc2lvbiB1cGRhdGVcbiAgICBpZiAodXBkYXRlcy51cGRhdGVWZXJzaW9uKSB7XG4gICAgICBpZiAoIXRoaXMubmV3UHJvcHMudmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZW1vdmUgY2x1c3RlciB2ZXJzaW9uIGNvbmZpZ3VyYXRpb24uIEN1cnJlbnQgdmVyc2lvbiBpcyAke3RoaXMub2xkUHJvcHMudmVyc2lvbn1gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlQ2x1c3RlclZlcnNpb24odGhpcy5uZXdQcm9wcy52ZXJzaW9uKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nICYmIHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1cGRhdGUgbG9nZ2luZyBhbmQgYWNjZXNzIGF0IHRoZSBzYW1lIHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nIHx8IHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICBjb25zdCBjb25maWc6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QgPSB7XG4gICAgICAgIG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgICB9O1xuICAgICAgaWYgKHVwZGF0ZXMudXBkYXRlTG9nZ2luZykge1xuICAgICAgICBjb25maWcubG9nZ2luZyA9IHRoaXMubmV3UHJvcHMubG9nZ2luZztcbiAgICAgIH07XG4gICAgICBpZiAodXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIGNsdXN0ZXIgd2l0aCBzZWN1cml0eUdyb3VwSWRzIGFuZCBzdWJuZXRJZHMgKGFzIHNwZWNpZmllZCBpbiB0aGUgd2FybmluZyBoZXJlOlxuICAgICAgICAvLyBodHRwczovL2F3c2NsaS5hbWF6b25hd3MuY29tL3YyL2RvY3VtZW50YXRpb24vYXBpL2xhdGVzdC9yZWZlcmVuY2UvZWtzL3VwZGF0ZS1jbHVzdGVyLWNvbmZpZy5odG1sKVxuICAgICAgICAvLyB3aWxsIGZhaWwsIHRoZXJlZm9yZSB3ZSB0YWtlIG9ubHkgdGhlIGFjY2VzcyBmaWVsZHMgZXhwbGljaXRseVxuICAgICAgICBjb25maWcucmVzb3VyY2VzVnBjQ29uZmlnID0ge1xuICAgICAgICAgIGVuZHBvaW50UHJpdmF0ZUFjY2VzczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzLFxuICAgICAgICAgIGVuZHBvaW50UHVibGljQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyxcbiAgICAgICAgICBwdWJsaWNBY2Nlc3NDaWRyczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcucHVibGljQWNjZXNzQ2lkcnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgICB9XG5cbiAgICAvLyBubyB1cGRhdGVzXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc29sZS5sb2coJ2lzVXBkYXRlQ29tcGxldGUnKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYW4gRUtTIHVwZGF0ZSwgd2Ugd2lsbCBtb25pdG9yIHRoZSB1cGRhdGUgZXZlbnQgaXRzZWxmXG4gICAgaWYgKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gYXdhaXQgdGhpcy5pc0Vrc1VwZGF0ZUNvbXBsZXRlKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpO1xuICAgICAgaWYgKCFjb21wbGV0ZSkge1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiBmYWxzZSB9O1xuICAgICAgfVxuXG4gICAgICAvLyBmYWxsIHRocm91Z2g6IGlmIHRoZSB1cGRhdGUgaXMgZG9uZSwgd2Ugc2ltcGx5IGRlbGVnYXRlIHRvIGlzQWN0aXZlKClcbiAgICAgIC8vIGluIG9yZGVyIHRvIGV4dHJhY3QgYXR0cmlidXRlcyBhbmQgc3RhdGUgZnJvbSB0aGUgY2x1c3RlciBpdHNlbGYsIHdoaWNoXG4gICAgICAvLyBpcyBzdXBwb3NlZCB0byBiZSBpbiBhbiBBQ1RJVkUgc3RhdGUgYWZ0ZXIgdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbHVzdGVyVmVyc2lvbihuZXdWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgdXBkYXRpbmcgY2x1c3RlciB2ZXJzaW9uIHRvICR7bmV3VmVyc2lvbn1gKTtcblxuICAgIC8vIHVwZGF0ZS1jbHVzdGVyLXZlcnNpb24gd2lsbCBmYWlsIGlmIHdlIHRyeSB0byB1cGRhdGUgdG8gdGhlIHNhbWUgdmVyc2lvbixcbiAgICAvLyBzbyBza2lwIGluIHRoaXMgY2FzZS5cbiAgICBjb25zdCBjbHVzdGVyID0gKGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSkpLmNsdXN0ZXI7XG4gICAgaWYgKGNsdXN0ZXI/LnZlcnNpb24gPT09IG5ld1ZlcnNpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyIGFscmVhZHkgYXQgdmVyc2lvbiAke2NsdXN0ZXIudmVyc2lvbn0sIHNraXBwaW5nIHZlcnNpb24gdXBkYXRlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy51cGRhdGVDbHVzdGVyVmVyc2lvbih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsIHZlcnNpb246IG5ld1ZlcnNpb24gfSk7XG4gICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNBY3RpdmUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZygnd2FpdGluZyBmb3IgY2x1c3RlciB0byBiZWNvbWUgQUNUSVZFJyk7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciByZXN1bHQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgY29uc3QgY2x1c3RlciA9IHJlc3AuY2x1c3RlcjtcblxuICAgIC8vIGlmIGNsdXN0ZXIgaXMgdW5kZWZpbmVkIChzaG91bGRudCBoYXBwZW4pIG9yIHN0YXR1cyBpcyBub3QgQUNUSVZFLCB3ZSBhcmVcbiAgICAvLyBub3QgY29tcGxldGUuIG5vdGUgdGhhdCB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZyYW1ld29yayBmb3JiaWRzXG4gICAgLy8gcmV0dXJuaW5nIGF0dHJpYnV0ZXMgKERhdGEpIGlmIGlzQ29tcGxldGUgaXMgZmFsc2UuXG4gICAgaWYgKGNsdXN0ZXI/LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgIC8vIG5vdCB2ZXJ5IGluZm9ybWF0aXZlLCB1bmZvcnR1bmF0ZWx5IHRoZSByZXNwb25zZSBkb2Vzbid0IGNvbnRhaW4gYW55IGVycm9yXG4gICAgICAvLyBpbmZvcm1hdGlvbiA6XFxcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2x1c3RlciBpcyBpbiBhIEZBSUxFRCBzdGF0dXMnKTtcbiAgICB9IGVsc2UgaWYgKGNsdXN0ZXI/LnN0YXR1cyAhPT0gJ0FDVElWRScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIE5hbWU6IGNsdXN0ZXIubmFtZSxcbiAgICAgICAgICBFbmRwb2ludDogY2x1c3Rlci5lbmRwb2ludCxcbiAgICAgICAgICBBcm46IGNsdXN0ZXIuYXJuLFxuXG4gICAgICAgICAgLy8gSU1QT1JUQU5UOiBDRk4gZXhwZWN0cyB0aGF0IGF0dHJpYnV0ZXMgd2lsbCAqYWx3YXlzKiBoYXZlIHZhbHVlcyxcbiAgICAgICAgICAvLyBzbyByZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGluIGNhc2UgdGhlIHZhbHVlIGlzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQ0ZOIHdpbGwgdGhyb3cgd2l0aCBgVmVuZG9yIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpblxuICAgICAgICAgIC8vIFhYWFgga2V5YC5cblxuICAgICAgICAgIENlcnRpZmljYXRlQXV0aG9yaXR5RGF0YTogY2x1c3Rlci5jZXJ0aWZpY2F0ZUF1dGhvcml0eT8uZGF0YSA/PyAnJyxcbiAgICAgICAgICBDbHVzdGVyU2VjdXJpdHlHcm91cElkOiBjbHVzdGVyLnJlc291cmNlc1ZwY0NvbmZpZz8uY2x1c3RlclNlY3VyaXR5R3JvdXBJZCA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyVXJsOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXIgPz8gJycsXG4gICAgICAgICAgT3BlbklkQ29ubmVjdElzc3VlcjogY2x1c3Rlci5pZGVudGl0eT8ub2lkYz8uaXNzdWVyPy5zdWJzdHJpbmcoOCkgPz8gJycsIC8vIFN0cmlwcyBvZmYgaHR0cHM6Ly8gZnJvbSB0aGUgaXNzdWVyIHVybFxuXG4gICAgICAgICAgLy8gV2UgY2FuIHNhZmVseSByZXR1cm4gdGhlIGZpcnN0IGl0ZW0gZnJvbSBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gYXJyYXksIGJlY2F1c2UgaXQgaGFzIGEgbGltaXQgb2YgMSBpdGVtXG4gICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vrcy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDbHVzdGVyLmh0bWwjQW1hem9uRUtTLUNyZWF0ZUNsdXN0ZXItcmVxdWVzdC1lbmNyeXB0aW9uQ29uZmlnXG4gICAgICAgICAgRW5jcnlwdGlvbkNvbmZpZ0tleUFybjogY2x1c3Rlci5lbmNyeXB0aW9uQ29uZmlnPy5zaGlmdCgpPy5wcm92aWRlcj8ua2V5QXJuID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzRWtzVXBkYXRlQ29tcGxldGUoZWtzVXBkYXRlSWQ6IHN0cmluZykge1xuICAgIHRoaXMubG9nKHsgaXNFa3NVcGRhdGVDb21wbGV0ZTogZWtzVXBkYXRlSWQgfSk7XG5cbiAgICBjb25zdCBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVVcGRhdGUoe1xuICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgIHVwZGF0ZUlkOiBla3NVcGRhdGVJZCxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nKHsgZGVzY3JpYmVVcGRhdGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5hYmxlIHRvIGRlc2NyaWJlIHVwZGF0ZSB3aXRoIGlkIFwiJHtla3NVcGRhdGVJZH1cImApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzKSB7XG4gICAgICBjYXNlICdJblByb2dyZXNzJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgY2FzZSAnU3VjY2Vzc2Z1bCc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnRmFpbGVkJzpcbiAgICAgIGNhc2UgJ0NhbmNlbGxlZCc6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2x1c3RlciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiIGZhaWxlZCB3aXRoIGVycm9yczogJHtKU09OLnN0cmluZ2lmeShkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5lcnJvcnMpfWApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIHN0YXR1cyBcIiR7ZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzfVwiIGZvciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNsdXN0ZXJOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9DTFVTVEVSX05BTUVfTEVOIC0gc3VmZml4Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5sb2dpY2FsUmVzb3VyY2VJZC5zbGljZSgwLCBvZmZzZXQgPiAwID8gb2Zmc2V0IDogMCk7XG4gICAgcmV0dXJuIGAke3ByZWZpeH0tJHtzdWZmaXh9YDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3BzKHByb3BzOiBhbnkpOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0IHtcblxuICBjb25zdCBwYXJzZWQgPSBwcm9wcz8uQ29uZmlnID8/IHt9O1xuXG4gIC8vIHRoaXMgaXMgd2VpcmQgYnV0IHRoZXNlIGJvb2xlYW4gcHJvcGVydGllcyBhcmUgcGFzc2VkIGJ5IENGTiBhcyBhIHN0cmluZywgYW5kIHdlIG5lZWQgdGhlbSB0byBiZSBib29sZWFuaWMgZm9yIHRoZSBTREsuXG4gIC8vIE90aGVyd2lzZSBpdCBmYWlscyB3aXRoICdVbmV4cGVjdGVkIFBhcmFtZXRlcjogcGFyYW1zLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgaXMgZXhwZWN0ZWQgdG8gYmUgYSBib29sZWFuJ1xuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWc/LmVuZHBvaW50UHJpdmF0ZUFjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9PT0gJ3RydWUnO1xuICB9XG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQdWJsaWNBY2Nlc3MpID09PSAnc3RyaW5nJykge1xuICAgIHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQubG9nZ2luZz8uY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCkgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9IHBhcnNlZC5sb2dnaW5nLmNsdXN0ZXJMb2dnaW5nWzBdLmVuYWJsZWQgPT09ICd0cnVlJztcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQ7XG5cbn1cblxuaW50ZXJmYWNlIFVwZGF0ZU1hcCB7XG4gIHJlcGxhY2VOYW1lOiBib29sZWFuOyAvLyBuYW1lXG4gIHJlcGxhY2VWcGM6IGJvb2xlYW47IC8vIHJlc291cmNlc1ZwY0NvbmZpZy5zdWJuZXRJZHMgYW5kIHNlY3VyaXR5R3JvdXBJZHNcbiAgcmVwbGFjZVJvbGU6IGJvb2xlYW47IC8vIHJvbGVBcm5cblxuICB1cGRhdGVWZXJzaW9uOiBib29sZWFuOyAvLyB2ZXJzaW9uXG4gIHVwZGF0ZUxvZ2dpbmc6IGJvb2xlYW47IC8vIGxvZ2dpbmdcbiAgdXBkYXRlRW5jcnlwdGlvbjogYm9vbGVhbjsgLy8gZW5jcnlwdGlvbiAoY2Fubm90IGJlIHVwZGF0ZWQpXG4gIHVwZGF0ZUFjY2VzczogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBhbmQgZW5kcG9pbnRQdWJsaWNBY2Nlc3Ncbn1cblxuZnVuY3Rpb24gYW5hbHl6ZVVwZGF0ZShvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PiwgbmV3UHJvcHM6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBVcGRhdGVNYXAge1xuICBjb25zb2xlLmxvZygnb2xkIHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShvbGRQcm9wcykpO1xuICBjb25zb2xlLmxvZygnbmV3IHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShuZXdQcm9wcykpO1xuXG4gIGNvbnN0IG5ld1ZwY1Byb3BzID0gbmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRWcGNQcm9wcyA9IG9sZFByb3BzLnJlc291cmNlc1ZwY0NvbmZpZyB8fCB7fTtcblxuICBjb25zdCBvbGRQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQob2xkVnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQobmV3VnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdFbmMgPSBuZXdQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRFbmMgPSBvbGRQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgcmVwbGFjZU5hbWU6IG5ld1Byb3BzLm5hbWUgIT09IG9sZFByb3BzLm5hbWUsXG4gICAgcmVwbGFjZVZwYzpcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnN1Ym5ldElkcz8uc29ydCgpKSAhPT0gSlNPTi5zdHJpbmdpZnkob2xkVnBjUHJvcHMuc3VibmV0SWRzPy5zb3J0KCkpIHx8XG4gICAgICBKU09OLnN0cmluZ2lmeShuZXdWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpICE9PSBKU09OLnN0cmluZ2lmeShvbGRWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpLFxuICAgIHVwZGF0ZUFjY2VzczpcbiAgICAgIG5ld1ZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQcml2YXRlQWNjZXNzIHx8XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFB1YmxpY0FjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgfHxcbiAgICAgICFzZXRzRXF1YWwobmV3UHVibGljQWNjZXNzQ2lkcnMsIG9sZFB1YmxpY0FjY2Vzc0NpZHJzKSxcbiAgICByZXBsYWNlUm9sZTogbmV3UHJvcHMucm9sZUFybiAhPT0gb2xkUHJvcHMucm9sZUFybixcbiAgICB1cGRhdGVWZXJzaW9uOiBuZXdQcm9wcy52ZXJzaW9uICE9PSBvbGRQcm9wcy52ZXJzaW9uLFxuICAgIHVwZGF0ZUVuY3J5cHRpb246IEpTT04uc3RyaW5naWZ5KG5ld0VuYykgIT09IEpTT04uc3RyaW5naWZ5KG9sZEVuYyksXG4gICAgdXBkYXRlTG9nZ2luZzogSlNPTi5zdHJpbmdpZnkobmV3UHJvcHMubG9nZ2luZykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFByb3BzLmxvZ2dpbmcpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzZXRzRXF1YWwoZmlyc3Q6IFNldDxzdHJpbmc+LCBzZWNvbmQ6IFNldDxzdHJpbmc+KSB7XG4gIHJldHVybiBmaXJzdC5zaXplID09PSBzZWNvbmQuc2l6ZSAmJiBbLi4uZmlyc3RdLmV2ZXJ5KChlOiBzdHJpbmcpID0+IHNlY29uZC5oYXMoZSkpO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts similarity index 98% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts index e6930b7844d32..4b7fdda6d1dd1 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.ts +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts @@ -326,8 +326,8 @@ function analyzeUpdate(oldProps: Partial, newProps return { replaceName: newProps.name !== oldProps.name, replaceVpc: - JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), + JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.js b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.js b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.js b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.js b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip index 593043af0139a..f62fe1e5a06d6 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js deleted file mode 100644 index 70203dcc42f3f..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js +++ /dev/null @@ -1,45 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.httpRequest = exports.invokeFunction = exports.startExecution = void 0; -/* istanbul ignore file */ -const https = require("https"); -// eslint-disable-next-line import/no-extraneous-dependencies -const AWS = require("aws-sdk"); -const FRAMEWORK_HANDLER_TIMEOUT = 900000; // 15 minutes -// In order to honor the overall maximum timeout set for the target process, -// the default 2 minutes from AWS SDK has to be overriden: -// https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html#httpOptions-property -const 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; -let lambda; -async function defaultStartExecution(req) { - if (!sfn) { - sfn = new AWS.StepFunctions(awsSdkConfig); - } - return sfn.startExecution(req).promise(); -} -async function defaultInvokeFunction(req) { - if (!lambda) { - lambda = new AWS.Lambda(awsSdkConfig); - } - return lambda.invoke(req).promise(); -} -exports.startExecution = defaultStartExecution; -exports.invokeFunction = defaultInvokeFunction; -exports.httpRequest = defaultHttpRequest; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3V0Ym91bmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJvdXRib3VuZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwwQkFBMEI7QUFDMUIsK0JBQStCO0FBQy9CLDZEQUE2RDtBQUM3RCwrQkFBK0I7QUFJL0IsTUFBTSx5QkFBeUIsR0FBRyxNQUFNLENBQUMsQ0FBQyxhQUFhO0FBRXZELDRFQUE0RTtBQUM1RSwwREFBMEQ7QUFDMUQsMkZBQTJGO0FBQzNGLE1BQU0sWUFBWSxHQUF5QjtJQUN6QyxXQUFXLEVBQUUsRUFBRSxPQUFPLEVBQUUseUJBQXlCLEVBQUU7Q0FDcEQsQ0FBQztBQUVGLEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxPQUE2QixFQUFFLFlBQW9CO0lBQ25GLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDckMsSUFBSTtZQUNGLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ2hELE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDNUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1NBQ2Y7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNYO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsSUFBSSxHQUFzQixDQUFDO0FBQzNCLElBQUksTUFBa0IsQ0FBQztBQUV2QixLQUFLLFVBQVUscUJBQXFCLENBQUMsR0FBMEM7SUFDN0UsSUFBSSxDQUFDLEdBQUcsRUFBRTtRQUNSLEdBQUcsR0FBRyxJQUFJLEdBQUcsQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUM7S0FDM0M7SUFFRCxPQUFPLEdBQUcsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7QUFDM0MsQ0FBQztBQUVELEtBQUssVUFBVSxxQkFBcUIsQ0FBQyxHQUFpQztJQUNwRSxJQUFJLENBQUMsTUFBTSxFQUFFO1FBQ1gsTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztLQUN2QztJQUVELE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztBQUN0QyxDQUFDO0FBRVUsUUFBQSxjQUFjLEdBQUcscUJBQXFCLENBQUM7QUFDdkMsUUFBQSxjQUFjLEdBQUcscUJBQXFCLENBQUM7QUFDdkMsUUFBQSxXQUFXLEdBQUcsa0JBQWtCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBpc3RhbmJ1bCBpZ25vcmUgZmlsZSAqL1xuaW1wb3J0ICogYXMgaHR0cHMgZnJvbSAnaHR0cHMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgQVdTIGZyb20gJ2F3cy1zZGsnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHR5cGUgeyBDb25maWd1cmF0aW9uT3B0aW9ucyB9IGZyb20gJ2F3cy1zZGsvbGliL2NvbmZpZy1iYXNlJztcblxuY29uc3QgRlJBTUVXT1JLX0hBTkRMRVJfVElNRU9VVCA9IDkwMDAwMDsgLy8gMTUgbWludXRlc1xuXG4vLyBJbiBvcmRlciB0byBob25vciB0aGUgb3ZlcmFsbCBtYXhpbXVtIHRpbWVvdXQgc2V0IGZvciB0aGUgdGFyZ2V0IHByb2Nlc3MsXG4vLyB0aGUgZGVmYXVsdCAyIG1pbnV0ZXMgZnJvbSBBV1MgU0RLIGhhcyB0byBiZSBvdmVycmlkZW46XG4vLyBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTSmF2YVNjcmlwdFNESy9sYXRlc3QvQVdTL0NvbmZpZy5odG1sI2h0dHBPcHRpb25zLXByb3BlcnR5XG5jb25zdCBhd3NTZGtDb25maWc6IENvbmZpZ3VyYXRpb25PcHRpb25zID0ge1xuICBodHRwT3B0aW9uczogeyB0aW1lb3V0OiBGUkFNRVdPUktfSEFORExFUl9USU1FT1VUIH0sXG59O1xuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0SHR0cFJlcXVlc3Qob3B0aW9uczogaHR0cHMuUmVxdWVzdE9wdGlvbnMsIHJlc3BvbnNlQm9keTogc3RyaW5nKSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlcXVlc3QgPSBodHRwcy5yZXF1ZXN0KG9wdGlvbnMsIHJlc29sdmUpO1xuICAgICAgcmVxdWVzdC5vbignZXJyb3InLCByZWplY3QpO1xuICAgICAgcmVxdWVzdC53cml0ZShyZXNwb25zZUJvZHkpO1xuICAgICAgcmVxdWVzdC5lbmQoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZWplY3QoZSk7XG4gICAgfVxuICB9KTtcbn1cblxubGV0IHNmbjogQVdTLlN0ZXBGdW5jdGlvbnM7XG5sZXQgbGFtYmRhOiBBV1MuTGFtYmRhO1xuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0U3RhcnRFeGVjdXRpb24ocmVxOiBBV1MuU3RlcEZ1bmN0aW9ucy5TdGFydEV4ZWN1dGlvbklucHV0KTogUHJvbWlzZTxBV1MuU3RlcEZ1bmN0aW9ucy5TdGFydEV4ZWN1dGlvbk91dHB1dD4ge1xuICBpZiAoIXNmbikge1xuICAgIHNmbiA9IG5ldyBBV1MuU3RlcEZ1bmN0aW9ucyhhd3NTZGtDb25maWcpO1xuICB9XG5cbiAgcmV0dXJuIHNmbi5zdGFydEV4ZWN1dGlvbihyZXEpLnByb21pc2UoKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdEludm9rZUZ1bmN0aW9uKHJlcTogQVdTLkxhbWJkYS5JbnZvY2F0aW9uUmVxdWVzdCk6IFByb21pc2U8QVdTLkxhbWJkYS5JbnZvY2F0aW9uUmVzcG9uc2U+IHtcbiAgaWYgKCFsYW1iZGEpIHtcbiAgICBsYW1iZGEgPSBuZXcgQVdTLkxhbWJkYShhd3NTZGtDb25maWcpO1xuICB9XG5cbiAgcmV0dXJuIGxhbWJkYS5pbnZva2UocmVxKS5wcm9taXNlKCk7XG59XG5cbmV4cG9ydCBsZXQgc3RhcnRFeGVjdXRpb24gPSBkZWZhdWx0U3RhcnRFeGVjdXRpb247XG5leHBvcnQgbGV0IGludm9rZUZ1bmN0aW9uID0gZGVmYXVsdEludm9rZUZ1bmN0aW9uO1xuZXhwb3J0IGxldCBodHRwUmVxdWVzdCA9IGRlZmF1bHRIdHRwUmVxdWVzdDtcbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.js b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.js deleted file mode 100644 index 6efe7fd22e321..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.js +++ /dev/null @@ -1,267 +0,0 @@ -"use strict"; -/* eslint-disable no-console */ -Object.defineProperty(exports, "__esModule", { value: true }); -exports.ClusterResourceHandler = void 0; -const common_1 = require("./common"); -const MAX_CLUSTER_NAME_LEN = 100; -class ClusterResourceHandler extends common_1.ResourceHandler { - constructor(eks, event) { - super(eks, event); - this.newProps = parseProps(this.event.ResourceProperties); - this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; - } - get clusterName() { - if (!this.physicalResourceId) { - throw new Error('Cannot determine cluster name without physical resource ID'); - } - return this.physicalResourceId; - } - // ------ - // CREATE - // ------ - async onCreate() { - console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); - if (!this.newProps.roleArn) { - throw new Error('"roleArn" is required'); - } - const clusterName = this.newProps.name || this.generateClusterName(); - const resp = await this.eks.createCluster({ - ...this.newProps, - name: clusterName, - }); - if (!resp.cluster) { - throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); - } - return { - PhysicalResourceId: resp.cluster.name, - }; - } - async isCreateComplete() { - return this.isActive(); - } - // ------ - // DELETE - // ------ - async onDelete() { - console.log(`onDelete: deleting cluster ${this.clusterName}`); - try { - await this.eks.deleteCluster({ name: this.clusterName }); - } - catch (e) { - if (e.code !== 'ResourceNotFoundException') { - throw e; - } - else { - console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); - } - } - return { - PhysicalResourceId: this.clusterName, - }; - } - async isDeleteComplete() { - console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); - try { - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); - } - catch (e) { - if (e.code === 'ResourceNotFoundException') { - console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); - return { IsComplete: true }; - } - console.log('describeCluster error:', e); - throw e; - } - return { - IsComplete: false, - }; - } - // ------ - // UPDATE - // ------ - async onUpdate() { - const updates = analyzeUpdate(this.oldProps, this.newProps); - console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); - // updates to encryption config is not supported - if (updates.updateEncryption) { - throw new Error('Cannot update cluster encryption configuration'); - } - // if there is an update that requires replacement, go ahead and just create - // a new cluster with the new config. The old cluster will automatically be - // deleted by cloudformation upon success. - if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { - // if we are replacing this cluster and the cluster has an explicit - // physical name, the creation of the new cluster will fail with "there is - // already a cluster with that name". this is a common behavior for - // CloudFormation resources that support specifying a physical name. - if (this.oldProps.name === this.newProps.name && this.oldProps.name) { - throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); - } - return this.onCreate(); - } - // if a version update is required, issue the version update - if (updates.updateVersion) { - if (!this.newProps.version) { - throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); - } - return this.updateClusterVersion(this.newProps.version); - } - if (updates.updateLogging || updates.updateAccess) { - const config = { - name: this.clusterName, - logging: this.newProps.logging, - }; - if (updates.updateAccess) { - // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: - // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) - // will fail, therefore we take only the access fields explicitly - config.resourcesVpcConfig = { - endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, - endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, - publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, - }; - } - const updateResponse = await this.eks.updateClusterConfig(config); - return { EksUpdateId: updateResponse.update?.id }; - } - // no updates - return; - } - async isUpdateComplete() { - console.log('isUpdateComplete'); - // if this is an EKS update, we will monitor the update event itself - if (this.event.EksUpdateId) { - const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); - if (!complete) { - return { IsComplete: false }; - } - // fall through: if the update is done, we simply delegate to isActive() - // in order to extract attributes and state from the cluster itself, which - // is supposed to be in an ACTIVE state after the update is complete. - } - return this.isActive(); - } - async updateClusterVersion(newVersion) { - console.log(`updating cluster version to ${newVersion}`); - // update-cluster-version will fail if we try to update to the same version, - // so skip in this case. - const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; - if (cluster?.version === newVersion) { - console.log(`cluster already at version ${cluster.version}, skipping version update`); - return; - } - const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); - return { EksUpdateId: updateResponse.update?.id }; - } - async isActive() { - console.log('waiting for cluster to become ACTIVE'); - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); - const cluster = resp.cluster; - // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are - // not complete. note that the custom resource provider framework forbids - // returning attributes (Data) if isComplete is false. - if (cluster?.status === 'FAILED') { - // not very informative, unfortunately the response doesn't contain any error - // information :\ - throw new Error('Cluster is in a FAILED status'); - } - else if (cluster?.status !== 'ACTIVE') { - return { - IsComplete: false, - }; - } - else { - return { - IsComplete: true, - Data: { - Name: cluster.name, - Endpoint: cluster.endpoint, - Arn: cluster.arn, - // IMPORTANT: CFN expects that attributes will *always* have values, - // so return an empty string in case the value is not defined. - // Otherwise, CFN will throw with `Vendor response doesn't contain - // XXXX key`. - CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', - ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', - OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', - OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', - // We can safely return the first item from encryption configuration array, because it has a limit of 1 item - // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig - EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', - }, - }; - } - } - async isEksUpdateComplete(eksUpdateId) { - this.log({ isEksUpdateComplete: eksUpdateId }); - const describeUpdateResponse = await this.eks.describeUpdate({ - name: this.clusterName, - updateId: eksUpdateId, - }); - this.log({ describeUpdateResponse }); - if (!describeUpdateResponse.update) { - throw new Error(`unable to describe update with id "${eksUpdateId}"`); - } - switch (describeUpdateResponse.update.status) { - case 'InProgress': - return false; - case 'Successful': - return true; - case 'Failed': - case 'Cancelled': - throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); - default: - throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); - } - } - generateClusterName() { - const suffix = this.requestId.replace(/-/g, ''); // 32 chars - const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; - const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); - return `${prefix}-${suffix}`; - } -} -exports.ClusterResourceHandler = ClusterResourceHandler; -function parseProps(props) { - const parsed = props?.Config ?? {}; - // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. - // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' - if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; - } - if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; - } - if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { - parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; - } - return parsed; -} -function analyzeUpdate(oldProps, newProps) { - console.log('old props: ', JSON.stringify(oldProps)); - console.log('new props: ', JSON.stringify(newProps)); - const newVpcProps = newProps.resourcesVpcConfig || {}; - const oldVpcProps = oldProps.resourcesVpcConfig || {}; - const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); - const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); - const newEnc = newProps.encryptionConfig || {}; - const oldEnc = oldProps.encryptionConfig || {}; - return { - replaceName: newProps.name !== oldProps.name, - replaceVpc: JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), - updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || - newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || - !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), - replaceRole: newProps.roleArn !== oldProps.roleArn, - updateVersion: newProps.version !== oldProps.version, - updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), - updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), - }; -} -function setsEqual(first, second) { - return first.size === second.size || [...first].every((e) => second.has(e)); -} -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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LElBQUksS0FBSyxNQUFNLENBQUMsSUFBSSxJQUFJLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFTLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUN0RixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgbm8tY29uc29sZSAqL1xuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzXG5pbXBvcnQgeyBJc0NvbXBsZXRlUmVzcG9uc2UsIE9uRXZlbnRSZXNwb25zZSB9IGZyb20gJ0Bhd3MtY2RrL2N1c3RvbS1yZXNvdXJjZXMvbGliL3Byb3ZpZGVyLWZyYW1ld29yay90eXBlcyc7XG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzXG5pbXBvcnQgKiBhcyBhd3MgZnJvbSAnYXdzLXNkayc7XG5pbXBvcnQgeyBFa3NDbGllbnQsIFJlc291cmNlRXZlbnQsIFJlc291cmNlSGFuZGxlciB9IGZyb20gJy4vY29tbW9uJztcblxuY29uc3QgTUFYX0NMVVNURVJfTkFNRV9MRU4gPSAxMDA7XG5cbmV4cG9ydCBjbGFzcyBDbHVzdGVyUmVzb3VyY2VIYW5kbGVyIGV4dGVuZHMgUmVzb3VyY2VIYW5kbGVyIHtcbiAgcHVibGljIGdldCBjbHVzdGVyTmFtZSgpIHtcbiAgICBpZiAoIXRoaXMucGh5c2ljYWxSZXNvdXJjZUlkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBkZXRlcm1pbmUgY2x1c3RlciBuYW1lIHdpdGhvdXQgcGh5c2ljYWwgcmVzb3VyY2UgSUQnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5waHlzaWNhbFJlc291cmNlSWQ7XG4gIH1cblxuICBwcml2YXRlIHJlYWRvbmx5IG5ld1Byb3BzOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0O1xuICBwcml2YXRlIHJlYWRvbmx5IG9sZFByb3BzOiBQYXJ0aWFsPGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3Q+O1xuXG4gIGNvbnN0cnVjdG9yKGVrczogRWtzQ2xpZW50LCBldmVudDogUmVzb3VyY2VFdmVudCkge1xuICAgIHN1cGVyKGVrcywgZXZlbnQpO1xuXG4gICAgdGhpcy5uZXdQcm9wcyA9IHBhcnNlUHJvcHModGhpcy5ldmVudC5SZXNvdXJjZVByb3BlcnRpZXMpO1xuICAgIHRoaXMub2xkUHJvcHMgPSBldmVudC5SZXF1ZXN0VHlwZSA9PT0gJ1VwZGF0ZScgPyBwYXJzZVByb3BzKGV2ZW50Lk9sZFJlc291cmNlUHJvcGVydGllcykgOiB7fTtcbiAgfVxuXG4gIC8vIC0tLS0tLVxuICAvLyBDUkVBVEVcbiAgLy8gLS0tLS0tXG5cbiAgcHJvdGVjdGVkIGFzeW5jIG9uQ3JlYXRlKCk6IFByb21pc2U8T25FdmVudFJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coJ29uQ3JlYXRlOiBjcmVhdGluZyBjbHVzdGVyIHdpdGggb3B0aW9uczonLCBKU09OLnN0cmluZ2lmeSh0aGlzLm5ld1Byb3BzLCB1bmRlZmluZWQsIDIpKTtcbiAgICBpZiAoIXRoaXMubmV3UHJvcHMucm9sZUFybikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdcInJvbGVBcm5cIiBpcyByZXF1aXJlZCcpO1xuICAgIH1cblxuICAgIGNvbnN0IGNsdXN0ZXJOYW1lID0gdGhpcy5uZXdQcm9wcy5uYW1lIHx8IHRoaXMuZ2VuZXJhdGVDbHVzdGVyTmFtZSgpO1xuXG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmNyZWF0ZUNsdXN0ZXIoe1xuICAgICAgLi4udGhpcy5uZXdQcm9wcyxcbiAgICAgIG5hbWU6IGNsdXN0ZXJOYW1lLFxuICAgIH0pO1xuXG4gICAgaWYgKCFyZXNwLmNsdXN0ZXIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3Igd2hlbiB0cnlpbmcgdG8gY3JlYXRlIGNsdXN0ZXIgJHtjbHVzdGVyTmFtZX06IENyZWF0ZUNsdXN0ZXIgcmV0dXJuZWQgd2l0aG91dCBjbHVzdGVyIGluZm9ybWF0aW9uYCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogcmVzcC5jbHVzdGVyLm5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0NyZWF0ZUNvbXBsZXRlKCkge1xuICAgIHJldHVybiB0aGlzLmlzQWN0aXZlKCk7XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gREVMRVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkRlbGV0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKGBvbkRlbGV0ZTogZGVsZXRpbmcgY2x1c3RlciAke3RoaXMuY2x1c3Rlck5hbWV9YCk7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuZWtzLmRlbGV0ZUNsdXN0ZXIoeyBuYW1lOiB0aGlzLmNsdXN0ZXJOYW1lIH0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgIT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc29sZS5sb2coYGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSBub3QgZm91bmQsIGlkZW1wb3RlbnRseSBzdWNjZWVkZWRgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICB9O1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzRGVsZXRlQ29tcGxldGUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgaXNEZWxldGVDb21wbGV0ZTogd2FpdGluZyBmb3IgY2x1c3RlciAke3RoaXMuY2x1c3Rlck5hbWV9IHRvIGJlIGRlbGV0ZWRgKTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXNwID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgcmV0dXJuZWQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKGUuY29kZSA9PT0gJ1Jlc291cmNlTm90Rm91bmRFeGNlcHRpb24nKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdyZWNlaXZlZCBSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uLCB0aGlzIG1lYW5zIHRoZSBjbHVzdGVyIGhhcyBiZWVuIGRlbGV0ZWQgKG9yIG5ldmVyIGV4aXN0ZWQpJyk7XG4gICAgICAgIHJldHVybiB7IElzQ29tcGxldGU6IHRydWUgfTtcbiAgICAgIH1cblxuICAgICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciBlcnJvcjonLCBlKTtcbiAgICAgIHRocm93IGU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgIH07XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gVVBEQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvblVwZGF0ZSgpIHtcbiAgICBjb25zdCB1cGRhdGVzID0gYW5hbHl6ZVVwZGF0ZSh0aGlzLm9sZFByb3BzLCB0aGlzLm5ld1Byb3BzKTtcbiAgICBjb25zb2xlLmxvZygnb25VcGRhdGU6JywgSlNPTi5zdHJpbmdpZnkoeyB1cGRhdGVzIH0sIHVuZGVmaW5lZCwgMikpO1xuXG4gICAgLy8gdXBkYXRlcyB0byBlbmNyeXB0aW9uIGNvbmZpZyBpcyBub3Qgc3VwcG9ydGVkXG4gICAgaWYgKHVwZGF0ZXMudXBkYXRlRW5jcnlwdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgdXBkYXRlIGNsdXN0ZXIgZW5jcnlwdGlvbiBjb25maWd1cmF0aW9uJyk7XG4gICAgfVxuXG4gICAgLy8gaWYgdGhlcmUgaXMgYW4gdXBkYXRlIHRoYXQgcmVxdWlyZXMgcmVwbGFjZW1lbnQsIGdvIGFoZWFkIGFuZCBqdXN0IGNyZWF0ZVxuICAgIC8vIGEgbmV3IGNsdXN0ZXIgd2l0aCB0aGUgbmV3IGNvbmZpZy4gVGhlIG9sZCBjbHVzdGVyIHdpbGwgYXV0b21hdGljYWxseSBiZVxuICAgIC8vIGRlbGV0ZWQgYnkgY2xvdWRmb3JtYXRpb24gdXBvbiBzdWNjZXNzLlxuICAgIGlmICh1cGRhdGVzLnJlcGxhY2VOYW1lIHx8IHVwZGF0ZXMucmVwbGFjZVJvbGUgfHwgdXBkYXRlcy5yZXBsYWNlVnBjKSB7XG5cbiAgICAgIC8vIGlmIHdlIGFyZSByZXBsYWNpbmcgdGhpcyBjbHVzdGVyIGFuZCB0aGUgY2x1c3RlciBoYXMgYW4gZXhwbGljaXRcbiAgICAgIC8vIHBoeXNpY2FsIG5hbWUsIHRoZSBjcmVhdGlvbiBvZiB0aGUgbmV3IGNsdXN0ZXIgd2lsbCBmYWlsIHdpdGggXCJ0aGVyZSBpc1xuICAgICAgLy8gYWxyZWFkeSBhIGNsdXN0ZXIgd2l0aCB0aGF0IG5hbWVcIi4gdGhpcyBpcyBhIGNvbW1vbiBiZWhhdmlvciBmb3JcbiAgICAgIC8vIENsb3VkRm9ybWF0aW9uIHJlc291cmNlcyB0aGF0IHN1cHBvcnQgc3BlY2lmeWluZyBhIHBoeXNpY2FsIG5hbWUuXG4gICAgICBpZiAodGhpcy5vbGRQcm9wcy5uYW1lID09PSB0aGlzLm5ld1Byb3BzLm5hbWUgJiYgdGhpcy5vbGRQcm9wcy5uYW1lKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IHJlcGxhY2UgY2x1c3RlciBcIiR7dGhpcy5vbGRQcm9wcy5uYW1lfVwiIHNpbmNlIGl0IGhhcyBhbiBleHBsaWNpdCBwaHlzaWNhbCBuYW1lLiBFaXRoZXIgcmVuYW1lIHRoZSBjbHVzdGVyIG9yIHJlbW92ZSB0aGUgXCJuYW1lXCIgY29uZmlndXJhdGlvbmApO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy5vbkNyZWF0ZSgpO1xuICAgIH1cblxuICAgIC8vIGlmIGEgdmVyc2lvbiB1cGRhdGUgaXMgcmVxdWlyZWQsIGlzc3VlIHRoZSB2ZXJzaW9uIHVwZGF0ZVxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZVZlcnNpb24pIHtcbiAgICAgIGlmICghdGhpcy5uZXdQcm9wcy52ZXJzaW9uKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IHJlbW92ZSBjbHVzdGVyIHZlcnNpb24gY29uZmlndXJhdGlvbi4gQ3VycmVudCB2ZXJzaW9uIGlzICR7dGhpcy5vbGRQcm9wcy52ZXJzaW9ufWApO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy51cGRhdGVDbHVzdGVyVmVyc2lvbih0aGlzLm5ld1Byb3BzLnZlcnNpb24pO1xuICAgIH1cblxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUxvZ2dpbmcgfHwgdXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgIGNvbnN0IGNvbmZpZzogYXdzLkVLUy5VcGRhdGVDbHVzdGVyQ29uZmlnUmVxdWVzdCA9IHtcbiAgICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgICAgbG9nZ2luZzogdGhpcy5uZXdQcm9wcy5sb2dnaW5nLFxuICAgICAgfTtcbiAgICAgIGlmICh1cGRhdGVzLnVwZGF0ZUFjY2Vzcykge1xuICAgICAgICAvLyBVcGRhdGluZyB0aGUgY2x1c3RlciB3aXRoIHNlY3VyaXR5R3JvdXBJZHMgYW5kIHN1Ym5ldElkcyAoYXMgc3BlY2lmaWVkIGluIHRoZSB3YXJuaW5nIGhlcmU6XG4gICAgICAgIC8vIGh0dHBzOi8vYXdzY2xpLmFtYXpvbmF3cy5jb20vdjIvZG9jdW1lbnRhdGlvbi9hcGkvbGF0ZXN0L3JlZmVyZW5jZS9la3MvdXBkYXRlLWNsdXN0ZXItY29uZmlnLmh0bWwpXG4gICAgICAgIC8vIHdpbGwgZmFpbCwgdGhlcmVmb3JlIHdlIHRha2Ugb25seSB0aGUgYWNjZXNzIGZpZWxkcyBleHBsaWNpdGx5XG4gICAgICAgIGNvbmZpZy5yZXNvdXJjZXNWcGNDb25maWcgPSB7XG4gICAgICAgICAgZW5kcG9pbnRQcml2YXRlQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MsXG4gICAgICAgICAgZW5kcG9pbnRQdWJsaWNBY2Nlc3M6IHRoaXMubmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzLFxuICAgICAgICAgIHB1YmxpY0FjY2Vzc0NpZHJzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5wdWJsaWNBY2Nlc3NDaWRycyxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MudXBkYXRlQ2x1c3RlckNvbmZpZyhjb25maWcpO1xuXG4gICAgICByZXR1cm4geyBFa3NVcGRhdGVJZDogdXBkYXRlUmVzcG9uc2UudXBkYXRlPy5pZCB9O1xuICAgIH1cblxuICAgIC8vIG5vIHVwZGF0ZXNcbiAgICByZXR1cm47XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNVcGRhdGVDb21wbGV0ZSgpIHtcbiAgICBjb25zb2xlLmxvZygnaXNVcGRhdGVDb21wbGV0ZScpO1xuXG4gICAgLy8gaWYgdGhpcyBpcyBhbiBFS1MgdXBkYXRlLCB3ZSB3aWxsIG1vbml0b3IgdGhlIHVwZGF0ZSBldmVudCBpdHNlbGZcbiAgICBpZiAodGhpcy5ldmVudC5Fa3NVcGRhdGVJZCkge1xuICAgICAgY29uc3QgY29tcGxldGUgPSBhd2FpdCB0aGlzLmlzRWtzVXBkYXRlQ29tcGxldGUodGhpcy5ldmVudC5Fa3NVcGRhdGVJZCk7XG4gICAgICBpZiAoIWNvbXBsZXRlKSB7XG4gICAgICAgIHJldHVybiB7IElzQ29tcGxldGU6IGZhbHNlIH07XG4gICAgICB9XG5cbiAgICAgIC8vIGZhbGwgdGhyb3VnaDogaWYgdGhlIHVwZGF0ZSBpcyBkb25lLCB3ZSBzaW1wbHkgZGVsZWdhdGUgdG8gaXNBY3RpdmUoKVxuICAgICAgLy8gaW4gb3JkZXIgdG8gZXh0cmFjdCBhdHRyaWJ1dGVzIGFuZCBzdGF0ZSBmcm9tIHRoZSBjbHVzdGVyIGl0c2VsZiwgd2hpY2hcbiAgICAgIC8vIGlzIHN1cHBvc2VkIHRvIGJlIGluIGFuIEFDVElWRSBzdGF0ZSBhZnRlciB0aGUgdXBkYXRlIGlzIGNvbXBsZXRlLlxuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmlzQWN0aXZlKCk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHVwZGF0ZUNsdXN0ZXJWZXJzaW9uKG5ld1ZlcnNpb246IHN0cmluZykge1xuICAgIGNvbnNvbGUubG9nKGB1cGRhdGluZyBjbHVzdGVyIHZlcnNpb24gdG8gJHtuZXdWZXJzaW9ufWApO1xuXG4gICAgLy8gdXBkYXRlLWNsdXN0ZXItdmVyc2lvbiB3aWxsIGZhaWwgaWYgd2UgdHJ5IHRvIHVwZGF0ZSB0byB0aGUgc2FtZSB2ZXJzaW9uLFxuICAgIC8vIHNvIHNraXAgaW4gdGhpcyBjYXNlLlxuICAgIGNvbnN0IGNsdXN0ZXIgPSAoYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KSkuY2x1c3RlcjtcbiAgICBpZiAoY2x1c3Rlcj8udmVyc2lvbiA9PT0gbmV3VmVyc2lvbikge1xuICAgICAgY29uc29sZS5sb2coYGNsdXN0ZXIgYWxyZWFkeSBhdCB2ZXJzaW9uICR7Y2x1c3Rlci52ZXJzaW9ufSwgc2tpcHBpbmcgdmVyc2lvbiB1cGRhdGVgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJWZXJzaW9uKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSwgdmVyc2lvbjogbmV3VmVyc2lvbiB9KTtcbiAgICByZXR1cm4geyBFa3NVcGRhdGVJZDogdXBkYXRlUmVzcG9uc2UudXBkYXRlPy5pZCB9O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBpc0FjdGl2ZSgpOiBQcm9taXNlPElzQ29tcGxldGVSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCd3YWl0aW5nIGZvciBjbHVzdGVyIHRvIGJlY29tZSBBQ1RJVkUnKTtcbiAgICBjb25zdCByZXNwID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJlc3VsdDonLCBKU09OLnN0cmluZ2lmeShyZXNwLCB1bmRlZmluZWQsIDIpKTtcbiAgICBjb25zdCBjbHVzdGVyID0gcmVzcC5jbHVzdGVyO1xuXG4gICAgLy8gaWYgY2x1c3RlciBpcyB1bmRlZmluZWQgKHNob3VsZG50IGhhcHBlbikgb3Igc3RhdHVzIGlzIG5vdCBBQ1RJVkUsIHdlIGFyZVxuICAgIC8vIG5vdCBjb21wbGV0ZS4gbm90ZSB0aGF0IHRoZSBjdXN0b20gcmVzb3VyY2UgcHJvdmlkZXIgZnJhbWV3b3JrIGZvcmJpZHNcbiAgICAvLyByZXR1cm5pbmcgYXR0cmlidXRlcyAoRGF0YSkgaWYgaXNDb21wbGV0ZSBpcyBmYWxzZS5cbiAgICBpZiAoY2x1c3Rlcj8uc3RhdHVzID09PSAnRkFJTEVEJykge1xuICAgICAgLy8gbm90IHZlcnkgaW5mb3JtYXRpdmUsIHVuZm9ydHVuYXRlbHkgdGhlIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpbiBhbnkgZXJyb3JcbiAgICAgIC8vIGluZm9ybWF0aW9uIDpcXFxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDbHVzdGVyIGlzIGluIGEgRkFJTEVEIHN0YXR1cycpO1xuICAgIH0gZWxzZSBpZiAoY2x1c3Rlcj8uc3RhdHVzICE9PSAnQUNUSVZFJykge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogZmFsc2UsXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBJc0NvbXBsZXRlOiB0cnVlLFxuICAgICAgICBEYXRhOiB7XG4gICAgICAgICAgTmFtZTogY2x1c3Rlci5uYW1lLFxuICAgICAgICAgIEVuZHBvaW50OiBjbHVzdGVyLmVuZHBvaW50LFxuICAgICAgICAgIEFybjogY2x1c3Rlci5hcm4sXG5cbiAgICAgICAgICAvLyBJTVBPUlRBTlQ6IENGTiBleHBlY3RzIHRoYXQgYXR0cmlidXRlcyB3aWxsICphbHdheXMqIGhhdmUgdmFsdWVzLFxuICAgICAgICAgIC8vIHNvIHJldHVybiBhbiBlbXB0eSBzdHJpbmcgaW4gY2FzZSB0aGUgdmFsdWUgaXMgbm90IGRlZmluZWQuXG4gICAgICAgICAgLy8gT3RoZXJ3aXNlLCBDRk4gd2lsbCB0aHJvdyB3aXRoIGBWZW5kb3IgcmVzcG9uc2UgZG9lc24ndCBjb250YWluXG4gICAgICAgICAgLy8gWFhYWCBrZXlgLlxuXG4gICAgICAgICAgQ2VydGlmaWNhdGVBdXRob3JpdHlEYXRhOiBjbHVzdGVyLmNlcnRpZmljYXRlQXV0aG9yaXR5Py5kYXRhID8/ICcnLFxuICAgICAgICAgIENsdXN0ZXJTZWN1cml0eUdyb3VwSWQ6IGNsdXN0ZXIucmVzb3VyY2VzVnBjQ29uZmlnPy5jbHVzdGVyU2VjdXJpdHlHcm91cElkID8/ICcnLFxuICAgICAgICAgIE9wZW5JZENvbm5lY3RJc3N1ZXJVcmw6IGNsdXN0ZXIuaWRlbnRpdHk/Lm9pZGM/Lmlzc3VlciA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXI/LnN1YnN0cmluZyg4KSA/PyAnJywgLy8gU3RyaXBzIG9mZiBodHRwczovLyBmcm9tIHRoZSBpc3N1ZXIgdXJsXG5cbiAgICAgICAgICAvLyBXZSBjYW4gc2FmZWx5IHJldHVybiB0aGUgZmlyc3QgaXRlbSBmcm9tIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbiBhcnJheSwgYmVjYXVzZSBpdCBoYXMgYSBsaW1pdCBvZiAxIGl0ZW1cbiAgICAgICAgICAvLyBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vZWtzL2xhdGVzdC9BUElSZWZlcmVuY2UvQVBJX0NyZWF0ZUNsdXN0ZXIuaHRtbCNBbWF6b25FS1MtQ3JlYXRlQ2x1c3Rlci1yZXF1ZXN0LWVuY3J5cHRpb25Db25maWdcbiAgICAgICAgICBFbmNyeXB0aW9uQ29uZmlnS2V5QXJuOiBjbHVzdGVyLmVuY3J5cHRpb25Db25maWc/LnNoaWZ0KCk/LnByb3ZpZGVyPy5rZXlBcm4gPz8gJycsXG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNFa3NVcGRhdGVDb21wbGV0ZShla3NVcGRhdGVJZDogc3RyaW5nKSB7XG4gICAgdGhpcy5sb2coeyBpc0Vrc1VwZGF0ZUNvbXBsZXRlOiBla3NVcGRhdGVJZCB9KTtcblxuICAgIGNvbnN0IGRlc2NyaWJlVXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy5kZXNjcmliZVVwZGF0ZSh7XG4gICAgICBuYW1lOiB0aGlzLmNsdXN0ZXJOYW1lLFxuICAgICAgdXBkYXRlSWQ6IGVrc1VwZGF0ZUlkLFxuICAgIH0pO1xuXG4gICAgdGhpcy5sb2coeyBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlIH0pO1xuXG4gICAgaWYgKCFkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmFibGUgdG8gZGVzY3JpYmUgdXBkYXRlIHdpdGggaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuXG4gICAgc3dpdGNoIChkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5zdGF0dXMpIHtcbiAgICAgIGNhc2UgJ0luUHJvZ3Jlc3MnOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBjYXNlICdTdWNjZXNzZnVsJzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlICdGYWlsZWQnOlxuICAgICAgY2FzZSAnQ2FuY2VsbGVkJzpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBjbHVzdGVyIHVwZGF0ZSBpZCBcIiR7ZWtzVXBkYXRlSWR9XCIgZmFpbGVkIHdpdGggZXJyb3JzOiAke0pTT04uc3RyaW5naWZ5KGRlc2NyaWJlVXBkYXRlUmVzcG9uc2UudXBkYXRlLmVycm9ycyl9YCk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHVua25vd24gc3RhdHVzIFwiJHtkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5zdGF0dXN9XCIgZm9yIHVwZGF0ZSBpZCBcIiR7ZWtzVXBkYXRlSWR9XCJgKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGdlbmVyYXRlQ2x1c3Rlck5hbWUoKSB7XG4gICAgY29uc3Qgc3VmZml4ID0gdGhpcy5yZXF1ZXN0SWQucmVwbGFjZSgvLS9nLCAnJyk7IC8vIDMyIGNoYXJzXG4gICAgY29uc3Qgb2Zmc2V0ID0gTUFYX0NMVVNURVJfTkFNRV9MRU4gLSBzdWZmaXgubGVuZ3RoIC0gMTtcbiAgICBjb25zdCBwcmVmaXggPSB0aGlzLmxvZ2ljYWxSZXNvdXJjZUlkLnNsaWNlKDAsIG9mZnNldCA+IDAgPyBvZmZzZXQgOiAwKTtcbiAgICByZXR1cm4gYCR7cHJlZml4fS0ke3N1ZmZpeH1gO1xuICB9XG59XG5cbmZ1bmN0aW9uIHBhcnNlUHJvcHMocHJvcHM6IGFueSk6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3Qge1xuXG4gIGNvbnN0IHBhcnNlZCA9IHByb3BzPy5Db25maWcgPz8ge307XG5cbiAgLy8gdGhpcyBpcyB3ZWlyZCBidXQgdGhlc2UgYm9vbGVhbiBwcm9wZXJ0aWVzIGFyZSBwYXNzZWQgYnkgQ0ZOIGFzIGEgc3RyaW5nLCBhbmQgd2UgbmVlZCB0aGVtIHRvIGJlIGJvb2xlYW5pYyBmb3IgdGhlIFNESy5cbiAgLy8gT3RoZXJ3aXNlIGl0IGZhaWxzIHdpdGggJ1VuZXhwZWN0ZWQgUGFyYW1ldGVyOiBwYXJhbXMucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBpcyBleHBlY3RlZCB0byBiZSBhIGJvb2xlYW4nXG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQcml2YXRlQWNjZXNzKSA9PT0gJ3N0cmluZycpIHtcbiAgICBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9IHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnPy5lbmRwb2ludFB1YmxpY0FjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyA9IHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPT09ICd0cnVlJztcbiAgfVxuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5sb2dnaW5nPy5jbHVzdGVyTG9nZ2luZ1swXS5lbmFibGVkKSA9PT0gJ3N0cmluZycpIHtcbiAgICBwYXJzZWQubG9nZ2luZy5jbHVzdGVyTG9nZ2luZ1swXS5lbmFibGVkID0gcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9PT0gJ3RydWUnO1xuICB9XG5cbiAgcmV0dXJuIHBhcnNlZDtcblxufVxuXG5pbnRlcmZhY2UgVXBkYXRlTWFwIHtcbiAgcmVwbGFjZU5hbWU6IGJvb2xlYW47IC8vIG5hbWVcbiAgcmVwbGFjZVZwYzogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLnN1Ym5ldElkcyBhbmQgc2VjdXJpdHlHcm91cElkc1xuICByZXBsYWNlUm9sZTogYm9vbGVhbjsgLy8gcm9sZUFyblxuXG4gIHVwZGF0ZVZlcnNpb246IGJvb2xlYW47IC8vIHZlcnNpb25cbiAgdXBkYXRlTG9nZ2luZzogYm9vbGVhbjsgLy8gbG9nZ2luZ1xuICB1cGRhdGVFbmNyeXB0aW9uOiBib29sZWFuOyAvLyBlbmNyeXB0aW9uIChjYW5ub3QgYmUgdXBkYXRlZClcbiAgdXBkYXRlQWNjZXNzOiBib29sZWFuOyAvLyByZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzIGFuZCBlbmRwb2ludFB1YmxpY0FjY2Vzc1xufVxuXG5mdW5jdGlvbiBhbmFseXplVXBkYXRlKG9sZFByb3BzOiBQYXJ0aWFsPGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3Q+LCBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdCk6IFVwZGF0ZU1hcCB7XG4gIGNvbnNvbGUubG9nKCdvbGQgcHJvcHM6ICcsIEpTT04uc3RyaW5naWZ5KG9sZFByb3BzKSk7XG4gIGNvbnNvbGUubG9nKCduZXcgcHJvcHM6ICcsIEpTT04uc3RyaW5naWZ5KG5ld1Byb3BzKSk7XG5cbiAgY29uc3QgbmV3VnBjUHJvcHMgPSBuZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcgfHwge307XG4gIGNvbnN0IG9sZFZwY1Byb3BzID0gb2xkUHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuXG4gIGNvbnN0IG9sZFB1YmxpY0FjY2Vzc0NpZHJzID0gbmV3IFNldChvbGRWcGNQcm9wcy5wdWJsaWNBY2Nlc3NDaWRycyA/PyBbXSk7XG4gIGNvbnN0IG5ld1B1YmxpY0FjY2Vzc0NpZHJzID0gbmV3IFNldChuZXdWcGNQcm9wcy5wdWJsaWNBY2Nlc3NDaWRycyA/PyBbXSk7XG4gIGNvbnN0IG5ld0VuYyA9IG5ld1Byb3BzLmVuY3J5cHRpb25Db25maWcgfHwge307XG4gIGNvbnN0IG9sZEVuYyA9IG9sZFByb3BzLmVuY3J5cHRpb25Db25maWcgfHwge307XG5cbiAgcmV0dXJuIHtcbiAgICByZXBsYWNlTmFtZTogbmV3UHJvcHMubmFtZSAhPT0gb2xkUHJvcHMubmFtZSxcbiAgICByZXBsYWNlVnBjOlxuICAgICAgSlNPTi5zdHJpbmdpZnkobmV3VnBjUHJvcHMuc3VibmV0SWRzKSAhPT0gSlNPTi5zdHJpbmdpZnkob2xkVnBjUHJvcHMuc3VibmV0SWRzKSB8fFxuICAgICAgSlNPTi5zdHJpbmdpZnkobmV3VnBjUHJvcHMuc2VjdXJpdHlHcm91cElkcykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFZwY1Byb3BzLnNlY3VyaXR5R3JvdXBJZHMpLFxuICAgIHVwZGF0ZUFjY2VzczpcbiAgICAgIG5ld1ZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQcml2YXRlQWNjZXNzIHx8XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFB1YmxpY0FjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgfHxcbiAgICAgICFzZXRzRXF1YWwobmV3UHVibGljQWNjZXNzQ2lkcnMsIG9sZFB1YmxpY0FjY2Vzc0NpZHJzKSxcbiAgICByZXBsYWNlUm9sZTogbmV3UHJvcHMucm9sZUFybiAhPT0gb2xkUHJvcHMucm9sZUFybixcbiAgICB1cGRhdGVWZXJzaW9uOiBuZXdQcm9wcy52ZXJzaW9uICE9PSBvbGRQcm9wcy52ZXJzaW9uLFxuICAgIHVwZGF0ZUVuY3J5cHRpb246IEpTT04uc3RyaW5naWZ5KG5ld0VuYykgIT09IEpTT04uc3RyaW5naWZ5KG9sZEVuYyksXG4gICAgdXBkYXRlTG9nZ2luZzogSlNPTi5zdHJpbmdpZnkobmV3UHJvcHMubG9nZ2luZykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFByb3BzLmxvZ2dpbmcpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzZXRzRXF1YWwoZmlyc3Q6IFNldDxzdHJpbmc+LCBzZWNvbmQ6IFNldDxzdHJpbmc+KSB7XG4gIHJldHVybiBmaXJzdC5zaXplID09PSBzZWNvbmQuc2l6ZSB8fCBbLi4uZmlyc3RdLmV2ZXJ5KChlOiBzdHJpbmcpID0+IHNlY29uZC5oYXMoZSkpO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.ts deleted file mode 100644 index 0177a7e21b695..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.ts +++ /dev/null @@ -1,338 +0,0 @@ -/* eslint-disable no-console */ - -// eslint-disable-next-line import/no-extraneous-dependencies -import { IsCompleteResponse, OnEventResponse } from '@aws-cdk/custom-resources/lib/provider-framework/types'; -// eslint-disable-next-line import/no-extraneous-dependencies -import * as aws from 'aws-sdk'; -import { EksClient, ResourceEvent, ResourceHandler } from './common'; - -const MAX_CLUSTER_NAME_LEN = 100; - -export class ClusterResourceHandler extends ResourceHandler { - public get clusterName() { - if (!this.physicalResourceId) { - throw new Error('Cannot determine cluster name without physical resource ID'); - } - - return this.physicalResourceId; - } - - private readonly newProps: aws.EKS.CreateClusterRequest; - private readonly oldProps: Partial; - - constructor(eks: EksClient, event: ResourceEvent) { - super(eks, event); - - this.newProps = parseProps(this.event.ResourceProperties); - this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; - } - - // ------ - // CREATE - // ------ - - protected async onCreate(): Promise { - console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); - if (!this.newProps.roleArn) { - throw new Error('"roleArn" is required'); - } - - const clusterName = this.newProps.name || this.generateClusterName(); - - const resp = await this.eks.createCluster({ - ...this.newProps, - name: clusterName, - }); - - if (!resp.cluster) { - throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); - } - - return { - PhysicalResourceId: resp.cluster.name, - }; - } - - protected async isCreateComplete() { - return this.isActive(); - } - - // ------ - // DELETE - // ------ - - protected async onDelete(): Promise { - console.log(`onDelete: deleting cluster ${this.clusterName}`); - try { - await this.eks.deleteCluster({ name: this.clusterName }); - } catch (e) { - if (e.code !== 'ResourceNotFoundException') { - throw e; - } else { - console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); - } - } - return { - PhysicalResourceId: this.clusterName, - }; - } - - protected async isDeleteComplete(): Promise { - console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); - - try { - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); - } catch (e) { - if (e.code === 'ResourceNotFoundException') { - console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); - return { IsComplete: true }; - } - - console.log('describeCluster error:', e); - throw e; - } - - return { - IsComplete: false, - }; - } - - // ------ - // UPDATE - // ------ - - protected async onUpdate() { - const updates = analyzeUpdate(this.oldProps, this.newProps); - console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); - - // updates to encryption config is not supported - if (updates.updateEncryption) { - throw new Error('Cannot update cluster encryption configuration'); - } - - // if there is an update that requires replacement, go ahead and just create - // a new cluster with the new config. The old cluster will automatically be - // deleted by cloudformation upon success. - if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { - - // if we are replacing this cluster and the cluster has an explicit - // physical name, the creation of the new cluster will fail with "there is - // already a cluster with that name". this is a common behavior for - // CloudFormation resources that support specifying a physical name. - if (this.oldProps.name === this.newProps.name && this.oldProps.name) { - throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); - } - - return this.onCreate(); - } - - // if a version update is required, issue the version update - if (updates.updateVersion) { - if (!this.newProps.version) { - throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); - } - - return this.updateClusterVersion(this.newProps.version); - } - - if (updates.updateLogging || updates.updateAccess) { - const config: aws.EKS.UpdateClusterConfigRequest = { - name: this.clusterName, - logging: this.newProps.logging, - }; - if (updates.updateAccess) { - // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: - // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) - // will fail, therefore we take only the access fields explicitly - config.resourcesVpcConfig = { - endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, - endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, - publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, - }; - } - const updateResponse = await this.eks.updateClusterConfig(config); - - return { EksUpdateId: updateResponse.update?.id }; - } - - // no updates - return; - } - - protected async isUpdateComplete() { - console.log('isUpdateComplete'); - - // if this is an EKS update, we will monitor the update event itself - if (this.event.EksUpdateId) { - const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); - if (!complete) { - return { IsComplete: false }; - } - - // fall through: if the update is done, we simply delegate to isActive() - // in order to extract attributes and state from the cluster itself, which - // is supposed to be in an ACTIVE state after the update is complete. - } - - return this.isActive(); - } - - private async updateClusterVersion(newVersion: string) { - console.log(`updating cluster version to ${newVersion}`); - - // update-cluster-version will fail if we try to update to the same version, - // so skip in this case. - const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; - if (cluster?.version === newVersion) { - console.log(`cluster already at version ${cluster.version}, skipping version update`); - return; - } - - const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); - return { EksUpdateId: updateResponse.update?.id }; - } - - private async isActive(): Promise { - console.log('waiting for cluster to become ACTIVE'); - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); - const cluster = resp.cluster; - - // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are - // not complete. note that the custom resource provider framework forbids - // returning attributes (Data) if isComplete is false. - if (cluster?.status === 'FAILED') { - // not very informative, unfortunately the response doesn't contain any error - // information :\ - throw new Error('Cluster is in a FAILED status'); - } else if (cluster?.status !== 'ACTIVE') { - return { - IsComplete: false, - }; - } else { - return { - IsComplete: true, - Data: { - Name: cluster.name, - Endpoint: cluster.endpoint, - Arn: cluster.arn, - - // IMPORTANT: CFN expects that attributes will *always* have values, - // so return an empty string in case the value is not defined. - // Otherwise, CFN will throw with `Vendor response doesn't contain - // XXXX key`. - - CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', - ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', - OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', - OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', // Strips off https:// from the issuer url - - // We can safely return the first item from encryption configuration array, because it has a limit of 1 item - // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig - EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', - }, - }; - } - } - - private async isEksUpdateComplete(eksUpdateId: string) { - this.log({ isEksUpdateComplete: eksUpdateId }); - - const describeUpdateResponse = await this.eks.describeUpdate({ - name: this.clusterName, - updateId: eksUpdateId, - }); - - this.log({ describeUpdateResponse }); - - if (!describeUpdateResponse.update) { - throw new Error(`unable to describe update with id "${eksUpdateId}"`); - } - - switch (describeUpdateResponse.update.status) { - case 'InProgress': - return false; - case 'Successful': - return true; - case 'Failed': - case 'Cancelled': - throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); - default: - throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); - } - } - - private generateClusterName() { - const suffix = this.requestId.replace(/-/g, ''); // 32 chars - const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; - const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); - return `${prefix}-${suffix}`; - } -} - -function parseProps(props: any): aws.EKS.CreateClusterRequest { - - const parsed = props?.Config ?? {}; - - // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. - // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' - - if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; - } - - if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; - } - - if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { - parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; - } - - return parsed; - -} - -interface UpdateMap { - replaceName: boolean; // name - replaceVpc: boolean; // resourcesVpcConfig.subnetIds and securityGroupIds - replaceRole: boolean; // roleArn - - updateVersion: boolean; // version - updateLogging: boolean; // logging - updateEncryption: boolean; // encryption (cannot be updated) - updateAccess: boolean; // resourcesVpcConfig.endpointPrivateAccess and endpointPublicAccess -} - -function analyzeUpdate(oldProps: Partial, newProps: aws.EKS.CreateClusterRequest): UpdateMap { - console.log('old props: ', JSON.stringify(oldProps)); - console.log('new props: ', JSON.stringify(newProps)); - - const newVpcProps = newProps.resourcesVpcConfig || {}; - const oldVpcProps = oldProps.resourcesVpcConfig || {}; - - const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); - const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); - const newEnc = newProps.encryptionConfig || {}; - const oldEnc = oldProps.encryptionConfig || {}; - - return { - replaceName: newProps.name !== oldProps.name, - replaceVpc: - JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), - updateAccess: - newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || - newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || - !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), - replaceRole: newProps.roleArn !== oldProps.roleArn, - updateVersion: newProps.version !== oldProps.version, - updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), - updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), - }; -} - -function setsEqual(first: Set, second: Set) { - return first.size === second.size || [...first].every((e: string) => second.has(e)); -} diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/cfn-response.js b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/cfn-response.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/cfn-response.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/cfn-response.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/consts.js b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/consts.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/consts.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/consts.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/framework.js b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/framework.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/framework.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/framework.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/outbound.js b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/outbound.js new file mode 100644 index 0000000000000..cc0667d42f0e8 --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/outbound.js @@ -0,0 +1,69 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.httpRequest = exports.invokeFunction = exports.startExecution = void 0; +/* istanbul ignore file */ +const https = require("https"); +// eslint-disable-next-line import/no-extraneous-dependencies +const AWS = require("aws-sdk"); +const FRAMEWORK_HANDLER_TIMEOUT = 900000; // 15 minutes +// In order to honor the overall maximum timeout set for the target process, +// the default 2 minutes from AWS SDK has to be overriden: +// https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html#httpOptions-property +const 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; +let lambda; +async function defaultStartExecution(req) { + if (!sfn) { + sfn = new AWS.StepFunctions(awsSdkConfig); + } + return sfn.startExecution(req).promise(); +} +async function defaultInvokeFunction(req) { + if (!lambda) { + lambda = new AWS.Lambda(awsSdkConfig); + } + try { + /** + * Try an initial invoke. + * + * When you try to invoke a function that is inactive, the invocation fails and Lambda sets + * the function to pending state until the function resources are recreated. + * If Lambda fails to recreate the resources, the function is set to the inactive state. + * + * We're using invoke first because `waitFor` doesn't trigger an inactive function to do anything, + * it just runs `getFunction` and checks the state. + */ + return await lambda.invoke(req).promise(); + } + catch (error) { + /** + * The status of the Lambda function is checked every second for up to 300 seconds. + * Exits the loop on 'Active' state and throws an error on 'Inactive' or 'Failed'. + * + * And now we wait. + */ + await lambda.waitFor('functionActiveV2', { + FunctionName: req.FunctionName, + }).promise(); + return await lambda.invoke(req).promise(); + } +} +exports.startExecution = defaultStartExecution; +exports.invokeFunction = defaultInvokeFunction; +exports.httpRequest = defaultHttpRequest; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3V0Ym91bmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJvdXRib3VuZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwwQkFBMEI7QUFDMUIsK0JBQStCO0FBQy9CLDZEQUE2RDtBQUM3RCwrQkFBK0I7QUFJL0IsTUFBTSx5QkFBeUIsR0FBRyxNQUFNLENBQUMsQ0FBQyxhQUFhO0FBRXZELDRFQUE0RTtBQUM1RSwwREFBMEQ7QUFDMUQsMkZBQTJGO0FBQzNGLE1BQU0sWUFBWSxHQUF5QjtJQUN6QyxXQUFXLEVBQUUsRUFBRSxPQUFPLEVBQUUseUJBQXlCLEVBQUU7Q0FDcEQsQ0FBQztBQUVGLEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxPQUE2QixFQUFFLFlBQW9CO0lBQ25GLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDckMsSUFBSTtZQUNGLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ2hELE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDNUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1NBQ2Y7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNYO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsSUFBSSxHQUFzQixDQUFDO0FBQzNCLElBQUksTUFBa0IsQ0FBQztBQUV2QixLQUFLLFVBQVUscUJBQXFCLENBQUMsR0FBMEM7SUFDN0UsSUFBSSxDQUFDLEdBQUcsRUFBRTtRQUNSLEdBQUcsR0FBRyxJQUFJLEdBQUcsQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUM7S0FDM0M7SUFFRCxPQUFPLEdBQUcsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7QUFDM0MsQ0FBQztBQUVELEtBQUssVUFBVSxxQkFBcUIsQ0FBQyxHQUFpQztJQUNwRSxJQUFJLENBQUMsTUFBTSxFQUFFO1FBQ1gsTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztLQUN2QztJQUVELElBQUk7UUFDRjs7Ozs7Ozs7O1dBU0c7UUFDSCxPQUFPLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztLQUMzQztJQUFDLE9BQU8sS0FBSyxFQUFFO1FBRWQ7Ozs7O1dBS0c7UUFDSCxNQUFNLE1BQU0sQ0FBQyxPQUFPLENBQUMsa0JBQWtCLEVBQUU7WUFDdkMsWUFBWSxFQUFFLEdBQUcsQ0FBQyxZQUFZO1NBQy9CLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNiLE9BQU8sTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDO0tBQzNDO0FBQ0gsQ0FBQztBQUVVLFFBQUEsY0FBYyxHQUFHLHFCQUFxQixDQUFDO0FBQ3ZDLFFBQUEsY0FBYyxHQUFHLHFCQUFxQixDQUFDO0FBQ3ZDLFFBQUEsV0FBVyxHQUFHLGtCQUFrQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogaXN0YW5idWwgaWdub3JlIGZpbGUgKi9cbmltcG9ydCAqIGFzIGh0dHBzIGZyb20gJ2h0dHBzJztcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcbmltcG9ydCAqIGFzIEFXUyBmcm9tICdhd3Mtc2RrJztcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcbmltcG9ydCB0eXBlIHsgQ29uZmlndXJhdGlvbk9wdGlvbnMgfSBmcm9tICdhd3Mtc2RrL2xpYi9jb25maWctYmFzZSc7XG5cbmNvbnN0IEZSQU1FV09SS19IQU5ETEVSX1RJTUVPVVQgPSA5MDAwMDA7IC8vIDE1IG1pbnV0ZXNcblxuLy8gSW4gb3JkZXIgdG8gaG9ub3IgdGhlIG92ZXJhbGwgbWF4aW11bSB0aW1lb3V0IHNldCBmb3IgdGhlIHRhcmdldCBwcm9jZXNzLFxuLy8gdGhlIGRlZmF1bHQgMiBtaW51dGVzIGZyb20gQVdTIFNESyBoYXMgdG8gYmUgb3ZlcnJpZGVuOlxuLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0phdmFTY3JpcHRTREsvbGF0ZXN0L0FXUy9Db25maWcuaHRtbCNodHRwT3B0aW9ucy1wcm9wZXJ0eVxuY29uc3QgYXdzU2RrQ29uZmlnOiBDb25maWd1cmF0aW9uT3B0aW9ucyA9IHtcbiAgaHR0cE9wdGlvbnM6IHsgdGltZW91dDogRlJBTUVXT1JLX0hBTkRMRVJfVElNRU9VVCB9LFxufTtcblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdEh0dHBSZXF1ZXN0KG9wdGlvbnM6IGh0dHBzLlJlcXVlc3RPcHRpb25zLCByZXNwb25zZUJvZHk6IHN0cmluZykge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gaHR0cHMucmVxdWVzdChvcHRpb25zLCByZXNvbHZlKTtcbiAgICAgIHJlcXVlc3Qub24oJ2Vycm9yJywgcmVqZWN0KTtcbiAgICAgIHJlcXVlc3Qud3JpdGUocmVzcG9uc2VCb2R5KTtcbiAgICAgIHJlcXVlc3QuZW5kKCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmVqZWN0KGUpO1xuICAgIH1cbiAgfSk7XG59XG5cbmxldCBzZm46IEFXUy5TdGVwRnVuY3Rpb25zO1xubGV0IGxhbWJkYTogQVdTLkxhbWJkYTtcblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdFN0YXJ0RXhlY3V0aW9uKHJlcTogQVdTLlN0ZXBGdW5jdGlvbnMuU3RhcnRFeGVjdXRpb25JbnB1dCk6IFByb21pc2U8QVdTLlN0ZXBGdW5jdGlvbnMuU3RhcnRFeGVjdXRpb25PdXRwdXQ+IHtcbiAgaWYgKCFzZm4pIHtcbiAgICBzZm4gPSBuZXcgQVdTLlN0ZXBGdW5jdGlvbnMoYXdzU2RrQ29uZmlnKTtcbiAgfVxuXG4gIHJldHVybiBzZm4uc3RhcnRFeGVjdXRpb24ocmVxKS5wcm9taXNlKCk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGRlZmF1bHRJbnZva2VGdW5jdGlvbihyZXE6IEFXUy5MYW1iZGEuSW52b2NhdGlvblJlcXVlc3QpOiBQcm9taXNlPEFXUy5MYW1iZGEuSW52b2NhdGlvblJlc3BvbnNlPiB7XG4gIGlmICghbGFtYmRhKSB7XG4gICAgbGFtYmRhID0gbmV3IEFXUy5MYW1iZGEoYXdzU2RrQ29uZmlnKTtcbiAgfVxuXG4gIHRyeSB7XG4gICAgLyoqXG4gICAgICogVHJ5IGFuIGluaXRpYWwgaW52b2tlLlxuICAgICAqXG4gICAgICogV2hlbiB5b3UgdHJ5IHRvIGludm9rZSBhIGZ1bmN0aW9uIHRoYXQgaXMgaW5hY3RpdmUsIHRoZSBpbnZvY2F0aW9uIGZhaWxzIGFuZCBMYW1iZGEgc2V0c1xuICAgICAqIHRoZSBmdW5jdGlvbiB0byBwZW5kaW5nIHN0YXRlIHVudGlsIHRoZSBmdW5jdGlvbiByZXNvdXJjZXMgYXJlIHJlY3JlYXRlZC5cbiAgICAgKiBJZiBMYW1iZGEgZmFpbHMgdG8gcmVjcmVhdGUgdGhlIHJlc291cmNlcywgdGhlIGZ1bmN0aW9uIGlzIHNldCB0byB0aGUgaW5hY3RpdmUgc3RhdGUuXG4gICAgICpcbiAgICAgKiBXZSdyZSB1c2luZyBpbnZva2UgZmlyc3QgYmVjYXVzZSBgd2FpdEZvcmAgZG9lc24ndCB0cmlnZ2VyIGFuIGluYWN0aXZlIGZ1bmN0aW9uIHRvIGRvIGFueXRoaW5nLFxuICAgICAqIGl0IGp1c3QgcnVucyBgZ2V0RnVuY3Rpb25gIGFuZCBjaGVja3MgdGhlIHN0YXRlLlxuICAgICAqL1xuICAgIHJldHVybiBhd2FpdCBsYW1iZGEuaW52b2tlKHJlcSkucHJvbWlzZSgpO1xuICB9IGNhdGNoIChlcnJvcikge1xuXG4gICAgLyoqXG4gICAgICogVGhlIHN0YXR1cyBvZiB0aGUgTGFtYmRhIGZ1bmN0aW9uIGlzIGNoZWNrZWQgZXZlcnkgc2Vjb25kIGZvciB1cCB0byAzMDAgc2Vjb25kcy5cbiAgICAgKiBFeGl0cyB0aGUgbG9vcCBvbiAnQWN0aXZlJyBzdGF0ZSBhbmQgdGhyb3dzIGFuIGVycm9yIG9uICdJbmFjdGl2ZScgb3IgJ0ZhaWxlZCcuXG4gICAgICpcbiAgICAgKiBBbmQgbm93IHdlIHdhaXQuXG4gICAgICovXG4gICAgYXdhaXQgbGFtYmRhLndhaXRGb3IoJ2Z1bmN0aW9uQWN0aXZlVjInLCB7XG4gICAgICBGdW5jdGlvbk5hbWU6IHJlcS5GdW5jdGlvbk5hbWUsXG4gICAgfSkucHJvbWlzZSgpO1xuICAgIHJldHVybiBhd2FpdCBsYW1iZGEuaW52b2tlKHJlcSkucHJvbWlzZSgpO1xuICB9XG59XG5cbmV4cG9ydCBsZXQgc3RhcnRFeGVjdXRpb24gPSBkZWZhdWx0U3RhcnRFeGVjdXRpb247XG5leHBvcnQgbGV0IGludm9rZUZ1bmN0aW9uID0gZGVmYXVsdEludm9rZUZ1bmN0aW9uO1xuZXhwb3J0IGxldCBodHRwUmVxdWVzdCA9IGRlZmF1bHRIdHRwUmVxdWVzdDtcbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/util.js b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/util.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/util.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/util.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip index b64a5034e3b6c..13983109fc5f5 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/apply/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/apply/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/get/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/get/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/helm/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py similarity index 99% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/helm/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py index c9120c1926e03..286976ced219a 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/helm/__init__.py +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py @@ -111,7 +111,7 @@ def get_oci_cmd(repository, version): region = os.environ.get('AWS_REGION', 'us-east-1') cmnd = [ - f"aws ecr-public get-login-password --region {region} | " \ + f"aws ecr-public get-login-password --region us-east-1 | " \ f"helm registry login --username AWS --password-stdin {public_registry['registry']}; helm pull {repository} --version {version} --untar" ] else: diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/index.py b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/index.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/patch/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/patch/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip index a0efa36e0518a..9bf8ba72b34ab 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/aws-cdk-eks-cluster-bottlerocket-ng-test.assets.json b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/aws-cdk-eks-cluster-bottlerocket-ng-test.assets.json index 9d9abb323393a..b5e210755f57d 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/aws-cdk-eks-cluster-bottlerocket-ng-test.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/aws-cdk-eks-cluster-bottlerocket-ng-test.assets.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "files": { "c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064": { "source": { @@ -27,41 +27,41 @@ } } }, - "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517": { + "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee": { "source": { - "path": "asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517", + "path": "asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip", + "objectKey": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037": { + "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585": { "source": { - "path": "asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037", + "path": "asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip", + "objectKey": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33": { + "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8": { "source": { - "path": "asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33", + "path": "asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33.zip", + "objectKey": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -79,7 +79,7 @@ } } }, - "71f37ec27bcc91052d7473953ff26acaf0809e05a170be3ea94b703361a557cb": { + "602a5f56132ce40b3837cfc90899cf3dfffef616ddea302f36368310f5930f21": { "source": { "path": "awscdkeksclusterbottlerocketngtestawscdkawseksClusterResourceProvider7EC04E81.nested.template.json", "packaging": "file" @@ -87,12 +87,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "71f37ec27bcc91052d7473953ff26acaf0809e05a170be3ea94b703361a557cb.json", + "objectKey": "602a5f56132ce40b3837cfc90899cf3dfffef616ddea302f36368310f5930f21.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "3043a1b67672745d02056ba21b9def813297bf697c51a24b94893c965615f0f6": { + "f4a0d15495e5534e3967ea2dbcee03861acd5cfd9e49b6997e630ce217892bbc": { "source": { "path": "awscdkeksclusterbottlerocketngtestawscdkawseksKubectlProviderE02BC096.nested.template.json", "packaging": "file" @@ -100,12 +100,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "3043a1b67672745d02056ba21b9def813297bf697c51a24b94893c965615f0f6.json", + "objectKey": "f4a0d15495e5534e3967ea2dbcee03861acd5cfd9e49b6997e630ce217892bbc.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "f8c8cae88a0f7b3e8365a60472d52583c4da2ee27967b80773df43fa3cd490e5": { + "472d22c46dfe23885a333c3b0f678fea3bb7a085b48bc37ab8f584c33d03c605": { "source": { "path": "aws-cdk-eks-cluster-bottlerocket-ng-test.template.json", "packaging": "file" @@ -113,7 +113,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "f8c8cae88a0f7b3e8365a60472d52583c4da2ee27967b80773df43fa3cd490e5.json", + "objectKey": "472d22c46dfe23885a333c3b0f678fea3bb7a085b48bc37ab8f584c33d03c605.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/aws-cdk-eks-cluster-bottlerocket-ng-test.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/aws-cdk-eks-cluster-bottlerocket-ng-test.template.json index bcdf76171b89a..b5630c3b38c59 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/aws-cdk-eks-cluster-bottlerocket-ng-test.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/aws-cdk-eks-cluster-bottlerocket-ng-test.template.json @@ -972,7 +972,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/71f37ec27bcc91052d7473953ff26acaf0809e05a170be3ea94b703361a557cb.json" + "/602a5f56132ce40b3837cfc90899cf3dfffef616ddea302f36368310f5930f21.json" ] ] }, @@ -1007,7 +1007,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/3043a1b67672745d02056ba21b9def813297bf697c51a24b94893c965615f0f6.json" + "/f4a0d15495e5534e3967ea2dbcee03861acd5cfd9e49b6997e630ce217892bbc.json" ] ] }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/awscdkeksclusterbottlerocketngDefaultTestDeployAssert6C42FFE7.assets.json b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/awscdkeksclusterbottlerocketngDefaultTestDeployAssert6C42FFE7.assets.json index 8348bb6274bae..36c8c84cad7d1 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/awscdkeksclusterbottlerocketngDefaultTestDeployAssert6C42FFE7.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/awscdkeksclusterbottlerocketngDefaultTestDeployAssert6C42FFE7.assets.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/awscdkeksclusterbottlerocketngtestawscdkawseksClusterResourceProvider7EC04E81.nested.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/awscdkeksclusterbottlerocketngtestawscdkawseksClusterResourceProvider7EC04E81.nested.template.json index 982eaefa64f77..08e97342578f9 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/awscdkeksclusterbottlerocketngtestawscdkawseksClusterResourceProvider7EC04E81.nested.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/awscdkeksclusterbottlerocketngtestawscdkawseksClusterResourceProvider7EC04E81.nested.template.json @@ -73,7 +73,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ @@ -162,7 +162,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ @@ -297,7 +297,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ @@ -434,7 +434,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ @@ -568,7 +568,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/awscdkeksclusterbottlerocketngtestawscdkawseksKubectlProviderE02BC096.nested.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/awscdkeksclusterbottlerocketngtestawscdkawseksKubectlProviderE02BC096.nested.template.json index f2d8c78e535c2..6da4c4c6ca618 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/awscdkeksclusterbottlerocketngtestawscdkawseksKubectlProviderE02BC096.nested.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/awscdkeksclusterbottlerocketngtestawscdkawseksKubectlProviderE02BC096.nested.template.json @@ -51,6 +51,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -92,7 +104,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33.zip" + "S3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "Role": { "Fn::GetAtt": [ @@ -238,7 +250,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/cdk.out b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/cdk.out index 8ecc185e9dbee..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"21.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/integ.json b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/integ.json index b8ce47e7ddcd5..3334c295278bd 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "testCases": { "aws-cdk-eks-cluster-bottlerocket-ng/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/manifest.json b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/manifest.json index d4b2c9f465bd8..e59997687c474 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "artifacts": { "aws-cdk-eks-cluster-bottlerocket-ng-test.assets": { "type": "cdk:asset-manifest", @@ -17,7 +17,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/f8c8cae88a0f7b3e8365a60472d52583c4da2ee27967b80773df43fa3cd490e5.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/472d22c46dfe23885a333c3b0f678fea3bb7a085b48bc37ab8f584c33d03c605.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -168,10 +168,7 @@ "/aws-cdk-eks-cluster-bottlerocket-ng-test/KubectlLayer/Resource": [ { "type": "aws:cdk:logicalId", - "data": "KubectlLayer600207B5", - "trace": [ - "!!DESTRUCTIVE_CHANGES: WILL_REPLACE" - ] + "data": "KubectlLayer600207B5" } ], "/aws-cdk-eks-cluster-bottlerocket-ng-test/Cluster/Role/Resource": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/tree.json b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/tree.json index 7bebb85d179e0..250748206d212 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/tree.json @@ -755,7 +755,7 @@ }, "constructInfo": { "fqn": "@aws-cdk/lambda-layer-kubectl-v24.KubectlV24Layer", - "version": "2.0.27" + "version": "2.0.100" } }, "Cluster": { @@ -1019,7 +1019,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "KubectlReadyBarrier": { @@ -1552,7 +1552,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -1725,7 +1725,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -1948,7 +1948,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -2169,7 +2169,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -2387,7 +2387,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -2566,7 +2566,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } } }, @@ -2623,7 +2623,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/71f37ec27bcc91052d7473953ff26acaf0809e05a170be3ea94b703361a557cb.json" + "/602a5f56132ce40b3837cfc90899cf3dfffef616ddea302f36368310f5930f21.json" ] ] }, @@ -2645,7 +2645,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "@aws-cdk--aws-eks.KubectlProvider": { @@ -2722,6 +2722,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -2821,7 +2833,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33.zip" + "s3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "role": { "Fn::GetAtt": [ @@ -3099,7 +3111,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -3243,7 +3255,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/3043a1b67672745d02056ba21b9def813297bf697c51a24b94893c965615f0f6.json" + "/f4a0d15495e5534e3967ea2dbcee03861acd5cfd9e49b6997e630ce217892bbc.json" ] ] }, @@ -3286,7 +3298,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "BootstrapVersion": { @@ -3324,7 +3336,7 @@ "path": "aws-cdk-eks-cluster-bottlerocket-ng/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "DeployAssert": { @@ -3370,7 +3382,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } } }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/helm/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/helm/__init__.py deleted file mode 100644 index b9a741c8972c4..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/helm/__init__.py +++ /dev/null @@ -1,187 +0,0 @@ -import json -import logging -import os -import re -import subprocess -import shutil -import tempfile -import zipfile -from urllib.parse import urlparse, unquote - -logger = logging.getLogger() -logger.setLevel(logging.INFO) - -# these are coming from the kubectl layer -os.environ['PATH'] = '/opt/helm:/opt/awscli:' + os.environ['PATH'] - -outdir = os.environ.get('TEST_OUTDIR', '/tmp') -kubeconfig = os.path.join(outdir, 'kubeconfig') - -def get_chart_asset_from_url(chart_asset_url): - chart_zip = os.path.join(outdir, 'chart.zip') - shutil.rmtree(chart_zip, ignore_errors=True) - subprocess.check_call(['aws', 's3', 'cp', chart_asset_url, chart_zip]) - chart_dir = os.path.join(outdir, 'chart') - shutil.rmtree(chart_dir, ignore_errors=True) - os.mkdir(chart_dir) - with zipfile.ZipFile(chart_zip, 'r') as zip_ref: - zip_ref.extractall(chart_dir) - return chart_dir - -def helm_handler(event, context): - logger.info(json.dumps(dict(event, ResponseURL='...'))) - - request_type = event['RequestType'] - props = event['ResourceProperties'] - - # resource properties - cluster_name = props['ClusterName'] - role_arn = props['RoleArn'] - release = props['Release'] - chart = props.get('Chart', None) - chart_asset_url = props.get('ChartAssetURL', None) - version = props.get('Version', None) - wait = props.get('Wait', False) - timeout = props.get('Timeout', None) - namespace = props.get('Namespace', None) - create_namespace = props.get('CreateNamespace', None) - repository = props.get('Repository', None) - values_text = props.get('Values', None) - - # "log in" to the cluster - subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig', - '--role-arn', role_arn, - '--name', cluster_name, - '--kubeconfig', kubeconfig - ]) - - if os.path.isfile(kubeconfig): - os.chmod(kubeconfig, 0o600) - - # Write out the values to a file and include them with the install and upgrade - values_file = None - if not request_type == "Delete" and not values_text is None: - values = json.loads(values_text) - values_file = os.path.join(outdir, 'values.yaml') - with open(values_file, "w") as f: - f.write(json.dumps(values, indent=2)) - - if request_type == 'Create' or request_type == 'Update': - # Ensure chart or chart_asset_url are set - if chart == None and chart_asset_url == None: - raise RuntimeError(f'chart or chartAsset must be specified') - - if chart_asset_url != None: - assert(chart==None) - assert(repository==None) - assert(version==None) - if not chart_asset_url.startswith('s3://'): - raise RuntimeError(f'ChartAssetURL must point to as s3 location but is {chart_asset_url}') - # future work: support versions from s3 assets - chart = get_chart_asset_from_url(chart_asset_url) - - if repository is not None and repository.startswith('oci://'): - tmpdir = tempfile.TemporaryDirectory() - chart_dir = get_chart_from_oci(tmpdir.name, release, repository, version) - chart = chart_dir - - helm('upgrade', release, chart, repository, values_file, namespace, version, wait, timeout, create_namespace) - elif request_type == "Delete": - try: - helm('uninstall', release, namespace=namespace, timeout=timeout) - except Exception as e: - logger.info("delete error: %s" % e) - - -def get_oci_cmd(repository, version): - # Generates OCI command based on pattern. Public ECR vs Private ECR are treated differently. - cmnd = [] - private_ecr_pattern = '\d+.dkr.ecr.[a-z]+-[a-z]+-\d.amazonaws.com' - public_ecr = 'public.ecr.aws' - - registry = repository.rsplit('/', 1)[0].replace('oci://', '') - - if re.fullmatch(private_ecr_pattern, registry) is not None: - logger.info("Found AWS private repository") - region = registry.replace('.amazonaws.com', '').split('.')[-1] - cmnd = [ - f"aws ecr get-login-password --region {region} | " \ - f"helm registry login --username AWS --password-stdin {registry}; helm pull {repository} --version {version} --untar" - ] - elif registry.startswith(public_ecr): - logger.info("Found AWS public repository, will use default region as deployment") - region = os.environ.get('AWS_REGION', 'us-east-1') - - cmnd = [ - f"aws ecr-public get-login-password --region {region} | " \ - f"helm registry login --username AWS --password-stdin {public_ecr}; helm pull {repository} --version {version} --untar" - ] - else: - logger.error("OCI repository format not recognized, falling back to helm pull") - cmnd = ['helm', 'pull', repository, '--version', version, '--untar'] - - return cmnd - - -def get_chart_from_oci(tmpdir, release, repository = None, version = None): - - cmnd = get_oci_cmd(repository, version) - - maxAttempts = 3 - retry = maxAttempts - while retry > 0: - try: - logger.info(cmnd) - output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=tmpdir, shell=True) - logger.info(output) - - return os.path.join(tmpdir, release) - except subprocess.CalledProcessError as exc: - output = exc.output - if b'Broken pipe' in output: - retry = retry - 1 - logger.info("Broken pipe, retries left: %s" % retry) - else: - raise Exception(output) - raise Exception(f'Operation failed after {maxAttempts} attempts: {output}') - - -def helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None): - import subprocess - - cmnd = ['helm', verb, release] - if not chart is None: - cmnd.append(chart) - if verb == 'upgrade': - cmnd.append('--install') - if create_namespace: - cmnd.append('--create-namespace') - if not repo is None: - cmnd.extend(['--repo', repo]) - if not file is None: - cmnd.extend(['--values', file]) - if not version is None: - cmnd.extend(['--version', version]) - if not namespace is None: - cmnd.extend(['--namespace', namespace]) - if wait: - cmnd.append('--wait') - if not timeout is None: - cmnd.extend(['--timeout', timeout]) - cmnd.extend(['--kubeconfig', kubeconfig]) - - maxAttempts = 3 - retry = maxAttempts - while retry > 0: - try: - output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir) - logger.info(output) - return - except subprocess.CalledProcessError as exc: - output = exc.output - if b'Broken pipe' in output: - retry = retry - 1 - logger.info("Broken pipe, retries left: %s" % retry) - else: - raise Exception(output) - raise Exception(f'Operation failed after {maxAttempts} attempts: {output}') diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js similarity index 55% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js index 1d08e9d7b865b..c9dc1b8d2c19a 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js @@ -256,8 +256,8 @@ function analyzeUpdate(oldProps, newProps) { const oldEnc = oldProps.encryptionConfig || {}; return { replaceName: newProps.name !== oldProps.name, - replaceVpc: JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), + replaceVpc: JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), @@ -270,4 +270,4 @@ function analyzeUpdate(oldProps, newProps) { function setsEqual(first, second) { return first.size === second.size && [...first].every((e) => second.has(e)); } -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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SSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBa0IsRUFBRSxNQUFtQjtJQUN4RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgRWtzQ2xpZW50LCBSZXNvdXJjZUV2ZW50LCBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX05BTUVfTEVOID0gMTAwO1xuXG5leHBvcnQgY2xhc3MgQ2x1c3RlclJlc291cmNlSGFuZGxlciBleHRlbmRzIFJlc291cmNlSGFuZGxlciB7XG4gIHB1YmxpYyBnZXQgY2x1c3Rlck5hbWUoKSB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZGV0ZXJtaW5lIGNsdXN0ZXIgbmFtZSB3aXRob3V0IHBoeXNpY2FsIHJlc291cmNlIElEJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PjtcblxuICBjb25zdHJ1Y3Rvcihla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICBzdXBlcihla3MsIGV2ZW50KTtcblxuICAgIHRoaXMubmV3UHJvcHMgPSBwYXJzZVByb3BzKHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLm9sZFByb3BzID0gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnID8gcGFyc2VQcm9wcyhldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMpIDoge307XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gQ1JFQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCdvbkNyZWF0ZTogY3JlYXRpbmcgY2x1c3RlciB3aXRoIG9wdGlvbnM6JywgSlNPTi5zdHJpbmdpZnkodGhpcy5uZXdQcm9wcywgdW5kZWZpbmVkLCAyKSk7XG4gICAgaWYgKCF0aGlzLm5ld1Byb3BzLnJvbGVBcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJyb2xlQXJuXCIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyTmFtZSA9IHRoaXMubmV3UHJvcHMubmFtZSB8fCB0aGlzLmdlbmVyYXRlQ2x1c3Rlck5hbWUoKTtcblxuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmVrcy5jcmVhdGVDbHVzdGVyKHtcbiAgICAgIC4uLnRoaXMubmV3UHJvcHMsXG4gICAgICBuYW1lOiBjbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcC5jbHVzdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBjbHVzdGVyICR7Y2x1c3Rlck5hbWV9OiBDcmVhdGVDbHVzdGVyIHJldHVybmVkIHdpdGhvdXQgY2x1c3RlciBpbmZvcm1hdGlvbmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHJlc3AuY2x1c3Rlci5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIERFTEVURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25EZWxldGUoKTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgb25EZWxldGU6IGRlbGV0aW5nIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfWApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVrcy5kZWxldGVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyICR7dGhpcy5jbHVzdGVyTmFtZX0gbm90IGZvdW5kLCBpZGVtcG90ZW50bHkgc3VjY2VlZGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coYGlzRGVsZXRlQ29tcGxldGU6IHdhaXRpbmcgZm9yIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSB0byBiZSBkZWxldGVkYCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJldHVybmVkOicsIEpTT04uc3RyaW5naWZ5KHJlc3AsIHVuZGVmaW5lZCwgMikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICBjb25zb2xlLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgY2x1c3RlciBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0cnVlIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgZXJyb3I6JywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIFVQREFURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IGFuYWx5emVVcGRhdGUodGhpcy5vbGRQcm9wcywgdGhpcy5uZXdQcm9wcyk7XG4gICAgY29uc29sZS5sb2coJ29uVXBkYXRlOicsIEpTT04uc3RyaW5naWZ5KHsgdXBkYXRlcyB9LCB1bmRlZmluZWQsIDIpKTtcblxuICAgIC8vIHVwZGF0ZXMgdG8gZW5jcnlwdGlvbiBjb25maWcgaXMgbm90IHN1cHBvcnRlZFxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUVuY3J5cHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHVwZGF0ZSBjbHVzdGVyIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZXJlIGlzIGFuIHVwZGF0ZSB0aGF0IHJlcXVpcmVzIHJlcGxhY2VtZW50LCBnbyBhaGVhZCBhbmQganVzdCBjcmVhdGVcbiAgICAvLyBhIG5ldyBjbHVzdGVyIHdpdGggdGhlIG5ldyBjb25maWcuIFRoZSBvbGQgY2x1c3RlciB3aWxsIGF1dG9tYXRpY2FsbHkgYmVcbiAgICAvLyBkZWxldGVkIGJ5IGNsb3VkZm9ybWF0aW9uIHVwb24gc3VjY2Vzcy5cbiAgICBpZiAodXBkYXRlcy5yZXBsYWNlTmFtZSB8fCB1cGRhdGVzLnJlcGxhY2VSb2xlIHx8IHVwZGF0ZXMucmVwbGFjZVZwYykge1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgcmVwbGFjaW5nIHRoaXMgY2x1c3RlciBhbmQgdGhlIGNsdXN0ZXIgaGFzIGFuIGV4cGxpY2l0XG4gICAgICAvLyBwaHlzaWNhbCBuYW1lLCB0aGUgY3JlYXRpb24gb2YgdGhlIG5ldyBjbHVzdGVyIHdpbGwgZmFpbCB3aXRoIFwidGhlcmUgaXNcbiAgICAgIC8vIGFscmVhZHkgYSBjbHVzdGVyIHdpdGggdGhhdCBuYW1lXCIuIHRoaXMgaXMgYSBjb21tb24gYmVoYXZpb3IgZm9yXG4gICAgICAvLyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZXMgdGhhdCBzdXBwb3J0IHNwZWNpZnlpbmcgYSBwaHlzaWNhbCBuYW1lLlxuICAgICAgaWYgKHRoaXMub2xkUHJvcHMubmFtZSA9PT0gdGhpcy5uZXdQcm9wcy5uYW1lICYmIHRoaXMub2xkUHJvcHMubmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXBsYWNlIGNsdXN0ZXIgXCIke3RoaXMub2xkUHJvcHMubmFtZX1cIiBzaW5jZSBpdCBoYXMgYW4gZXhwbGljaXQgcGh5c2ljYWwgbmFtZS4gRWl0aGVyIHJlbmFtZSB0aGUgY2x1c3RlciBvciByZW1vdmUgdGhlIFwibmFtZVwiIGNvbmZpZ3VyYXRpb25gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub25DcmVhdGUoKTtcbiAgICB9XG5cbiAgICAvLyBpZiBhIHZlcnNpb24gdXBkYXRlIGlzIHJlcXVpcmVkLCBpc3N1ZSB0aGUgdmVyc2lvbiB1cGRhdGVcbiAgICBpZiAodXBkYXRlcy51cGRhdGVWZXJzaW9uKSB7XG4gICAgICBpZiAoIXRoaXMubmV3UHJvcHMudmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZW1vdmUgY2x1c3RlciB2ZXJzaW9uIGNvbmZpZ3VyYXRpb24uIEN1cnJlbnQgdmVyc2lvbiBpcyAke3RoaXMub2xkUHJvcHMudmVyc2lvbn1gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlQ2x1c3RlclZlcnNpb24odGhpcy5uZXdQcm9wcy52ZXJzaW9uKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nICYmIHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1cGRhdGUgbG9nZ2luZyBhbmQgYWNjZXNzIGF0IHRoZSBzYW1lIHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nIHx8IHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICBjb25zdCBjb25maWc6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QgPSB7XG4gICAgICAgIG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgICB9O1xuICAgICAgaWYgKHVwZGF0ZXMudXBkYXRlTG9nZ2luZykge1xuICAgICAgICBjb25maWcubG9nZ2luZyA9IHRoaXMubmV3UHJvcHMubG9nZ2luZztcbiAgICAgIH07XG4gICAgICBpZiAodXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIGNsdXN0ZXIgd2l0aCBzZWN1cml0eUdyb3VwSWRzIGFuZCBzdWJuZXRJZHMgKGFzIHNwZWNpZmllZCBpbiB0aGUgd2FybmluZyBoZXJlOlxuICAgICAgICAvLyBodHRwczovL2F3c2NsaS5hbWF6b25hd3MuY29tL3YyL2RvY3VtZW50YXRpb24vYXBpL2xhdGVzdC9yZWZlcmVuY2UvZWtzL3VwZGF0ZS1jbHVzdGVyLWNvbmZpZy5odG1sKVxuICAgICAgICAvLyB3aWxsIGZhaWwsIHRoZXJlZm9yZSB3ZSB0YWtlIG9ubHkgdGhlIGFjY2VzcyBmaWVsZHMgZXhwbGljaXRseVxuICAgICAgICBjb25maWcucmVzb3VyY2VzVnBjQ29uZmlnID0ge1xuICAgICAgICAgIGVuZHBvaW50UHJpdmF0ZUFjY2VzczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzLFxuICAgICAgICAgIGVuZHBvaW50UHVibGljQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyxcbiAgICAgICAgICBwdWJsaWNBY2Nlc3NDaWRyczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcucHVibGljQWNjZXNzQ2lkcnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgICB9XG5cbiAgICAvLyBubyB1cGRhdGVzXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc29sZS5sb2coJ2lzVXBkYXRlQ29tcGxldGUnKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYW4gRUtTIHVwZGF0ZSwgd2Ugd2lsbCBtb25pdG9yIHRoZSB1cGRhdGUgZXZlbnQgaXRzZWxmXG4gICAgaWYgKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gYXdhaXQgdGhpcy5pc0Vrc1VwZGF0ZUNvbXBsZXRlKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpO1xuICAgICAgaWYgKCFjb21wbGV0ZSkge1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiBmYWxzZSB9O1xuICAgICAgfVxuXG4gICAgICAvLyBmYWxsIHRocm91Z2g6IGlmIHRoZSB1cGRhdGUgaXMgZG9uZSwgd2Ugc2ltcGx5IGRlbGVnYXRlIHRvIGlzQWN0aXZlKClcbiAgICAgIC8vIGluIG9yZGVyIHRvIGV4dHJhY3QgYXR0cmlidXRlcyBhbmQgc3RhdGUgZnJvbSB0aGUgY2x1c3RlciBpdHNlbGYsIHdoaWNoXG4gICAgICAvLyBpcyBzdXBwb3NlZCB0byBiZSBpbiBhbiBBQ1RJVkUgc3RhdGUgYWZ0ZXIgdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbHVzdGVyVmVyc2lvbihuZXdWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgdXBkYXRpbmcgY2x1c3RlciB2ZXJzaW9uIHRvICR7bmV3VmVyc2lvbn1gKTtcblxuICAgIC8vIHVwZGF0ZS1jbHVzdGVyLXZlcnNpb24gd2lsbCBmYWlsIGlmIHdlIHRyeSB0byB1cGRhdGUgdG8gdGhlIHNhbWUgdmVyc2lvbixcbiAgICAvLyBzbyBza2lwIGluIHRoaXMgY2FzZS5cbiAgICBjb25zdCBjbHVzdGVyID0gKGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSkpLmNsdXN0ZXI7XG4gICAgaWYgKGNsdXN0ZXI/LnZlcnNpb24gPT09IG5ld1ZlcnNpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyIGFscmVhZHkgYXQgdmVyc2lvbiAke2NsdXN0ZXIudmVyc2lvbn0sIHNraXBwaW5nIHZlcnNpb24gdXBkYXRlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy51cGRhdGVDbHVzdGVyVmVyc2lvbih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsIHZlcnNpb246IG5ld1ZlcnNpb24gfSk7XG4gICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNBY3RpdmUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZygnd2FpdGluZyBmb3IgY2x1c3RlciB0byBiZWNvbWUgQUNUSVZFJyk7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciByZXN1bHQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgY29uc3QgY2x1c3RlciA9IHJlc3AuY2x1c3RlcjtcblxuICAgIC8vIGlmIGNsdXN0ZXIgaXMgdW5kZWZpbmVkIChzaG91bGRudCBoYXBwZW4pIG9yIHN0YXR1cyBpcyBub3QgQUNUSVZFLCB3ZSBhcmVcbiAgICAvLyBub3QgY29tcGxldGUuIG5vdGUgdGhhdCB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZyYW1ld29yayBmb3JiaWRzXG4gICAgLy8gcmV0dXJuaW5nIGF0dHJpYnV0ZXMgKERhdGEpIGlmIGlzQ29tcGxldGUgaXMgZmFsc2UuXG4gICAgaWYgKGNsdXN0ZXI/LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgIC8vIG5vdCB2ZXJ5IGluZm9ybWF0aXZlLCB1bmZvcnR1bmF0ZWx5IHRoZSByZXNwb25zZSBkb2Vzbid0IGNvbnRhaW4gYW55IGVycm9yXG4gICAgICAvLyBpbmZvcm1hdGlvbiA6XFxcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2x1c3RlciBpcyBpbiBhIEZBSUxFRCBzdGF0dXMnKTtcbiAgICB9IGVsc2UgaWYgKGNsdXN0ZXI/LnN0YXR1cyAhPT0gJ0FDVElWRScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIE5hbWU6IGNsdXN0ZXIubmFtZSxcbiAgICAgICAgICBFbmRwb2ludDogY2x1c3Rlci5lbmRwb2ludCxcbiAgICAgICAgICBBcm46IGNsdXN0ZXIuYXJuLFxuXG4gICAgICAgICAgLy8gSU1QT1JUQU5UOiBDRk4gZXhwZWN0cyB0aGF0IGF0dHJpYnV0ZXMgd2lsbCAqYWx3YXlzKiBoYXZlIHZhbHVlcyxcbiAgICAgICAgICAvLyBzbyByZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGluIGNhc2UgdGhlIHZhbHVlIGlzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQ0ZOIHdpbGwgdGhyb3cgd2l0aCBgVmVuZG9yIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpblxuICAgICAgICAgIC8vIFhYWFgga2V5YC5cblxuICAgICAgICAgIENlcnRpZmljYXRlQXV0aG9yaXR5RGF0YTogY2x1c3Rlci5jZXJ0aWZpY2F0ZUF1dGhvcml0eT8uZGF0YSA/PyAnJyxcbiAgICAgICAgICBDbHVzdGVyU2VjdXJpdHlHcm91cElkOiBjbHVzdGVyLnJlc291cmNlc1ZwY0NvbmZpZz8uY2x1c3RlclNlY3VyaXR5R3JvdXBJZCA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyVXJsOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXIgPz8gJycsXG4gICAgICAgICAgT3BlbklkQ29ubmVjdElzc3VlcjogY2x1c3Rlci5pZGVudGl0eT8ub2lkYz8uaXNzdWVyPy5zdWJzdHJpbmcoOCkgPz8gJycsIC8vIFN0cmlwcyBvZmYgaHR0cHM6Ly8gZnJvbSB0aGUgaXNzdWVyIHVybFxuXG4gICAgICAgICAgLy8gV2UgY2FuIHNhZmVseSByZXR1cm4gdGhlIGZpcnN0IGl0ZW0gZnJvbSBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gYXJyYXksIGJlY2F1c2UgaXQgaGFzIGEgbGltaXQgb2YgMSBpdGVtXG4gICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vrcy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDbHVzdGVyLmh0bWwjQW1hem9uRUtTLUNyZWF0ZUNsdXN0ZXItcmVxdWVzdC1lbmNyeXB0aW9uQ29uZmlnXG4gICAgICAgICAgRW5jcnlwdGlvbkNvbmZpZ0tleUFybjogY2x1c3Rlci5lbmNyeXB0aW9uQ29uZmlnPy5zaGlmdCgpPy5wcm92aWRlcj8ua2V5QXJuID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzRWtzVXBkYXRlQ29tcGxldGUoZWtzVXBkYXRlSWQ6IHN0cmluZykge1xuICAgIHRoaXMubG9nKHsgaXNFa3NVcGRhdGVDb21wbGV0ZTogZWtzVXBkYXRlSWQgfSk7XG5cbiAgICBjb25zdCBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVVcGRhdGUoe1xuICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgIHVwZGF0ZUlkOiBla3NVcGRhdGVJZCxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nKHsgZGVzY3JpYmVVcGRhdGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5hYmxlIHRvIGRlc2NyaWJlIHVwZGF0ZSB3aXRoIGlkIFwiJHtla3NVcGRhdGVJZH1cImApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzKSB7XG4gICAgICBjYXNlICdJblByb2dyZXNzJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgY2FzZSAnU3VjY2Vzc2Z1bCc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnRmFpbGVkJzpcbiAgICAgIGNhc2UgJ0NhbmNlbGxlZCc6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2x1c3RlciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiIGZhaWxlZCB3aXRoIGVycm9yczogJHtKU09OLnN0cmluZ2lmeShkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5lcnJvcnMpfWApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIHN0YXR1cyBcIiR7ZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzfVwiIGZvciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNsdXN0ZXJOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9DTFVTVEVSX05BTUVfTEVOIC0gc3VmZml4Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5sb2dpY2FsUmVzb3VyY2VJZC5zbGljZSgwLCBvZmZzZXQgPiAwID8gb2Zmc2V0IDogMCk7XG4gICAgcmV0dXJuIGAke3ByZWZpeH0tJHtzdWZmaXh9YDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3BzKHByb3BzOiBhbnkpOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0IHtcblxuICBjb25zdCBwYXJzZWQgPSBwcm9wcz8uQ29uZmlnID8/IHt9O1xuXG4gIC8vIHRoaXMgaXMgd2VpcmQgYnV0IHRoZXNlIGJvb2xlYW4gcHJvcGVydGllcyBhcmUgcGFzc2VkIGJ5IENGTiBhcyBhIHN0cmluZywgYW5kIHdlIG5lZWQgdGhlbSB0byBiZSBib29sZWFuaWMgZm9yIHRoZSBTREsuXG4gIC8vIE90aGVyd2lzZSBpdCBmYWlscyB3aXRoICdVbmV4cGVjdGVkIFBhcmFtZXRlcjogcGFyYW1zLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgaXMgZXhwZWN0ZWQgdG8gYmUgYSBib29sZWFuJ1xuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWc/LmVuZHBvaW50UHJpdmF0ZUFjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9PT0gJ3RydWUnO1xuICB9XG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQdWJsaWNBY2Nlc3MpID09PSAnc3RyaW5nJykge1xuICAgIHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQubG9nZ2luZz8uY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCkgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9IHBhcnNlZC5sb2dnaW5nLmNsdXN0ZXJMb2dnaW5nWzBdLmVuYWJsZWQgPT09ICd0cnVlJztcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQ7XG5cbn1cblxuaW50ZXJmYWNlIFVwZGF0ZU1hcCB7XG4gIHJlcGxhY2VOYW1lOiBib29sZWFuOyAvLyBuYW1lXG4gIHJlcGxhY2VWcGM6IGJvb2xlYW47IC8vIHJlc291cmNlc1ZwY0NvbmZpZy5zdWJuZXRJZHMgYW5kIHNlY3VyaXR5R3JvdXBJZHNcbiAgcmVwbGFjZVJvbGU6IGJvb2xlYW47IC8vIHJvbGVBcm5cblxuICB1cGRhdGVWZXJzaW9uOiBib29sZWFuOyAvLyB2ZXJzaW9uXG4gIHVwZGF0ZUxvZ2dpbmc6IGJvb2xlYW47IC8vIGxvZ2dpbmdcbiAgdXBkYXRlRW5jcnlwdGlvbjogYm9vbGVhbjsgLy8gZW5jcnlwdGlvbiAoY2Fubm90IGJlIHVwZGF0ZWQpXG4gIHVwZGF0ZUFjY2VzczogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBhbmQgZW5kcG9pbnRQdWJsaWNBY2Nlc3Ncbn1cblxuZnVuY3Rpb24gYW5hbHl6ZVVwZGF0ZShvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PiwgbmV3UHJvcHM6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBVcGRhdGVNYXAge1xuICBjb25zb2xlLmxvZygnb2xkIHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShvbGRQcm9wcykpO1xuICBjb25zb2xlLmxvZygnbmV3IHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShuZXdQcm9wcykpO1xuXG4gIGNvbnN0IG5ld1ZwY1Byb3BzID0gbmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRWcGNQcm9wcyA9IG9sZFByb3BzLnJlc291cmNlc1ZwY0NvbmZpZyB8fCB7fTtcblxuICBjb25zdCBvbGRQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQob2xkVnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQobmV3VnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdFbmMgPSBuZXdQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRFbmMgPSBvbGRQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgcmVwbGFjZU5hbWU6IG5ld1Byb3BzLm5hbWUgIT09IG9sZFByb3BzLm5hbWUsXG4gICAgcmVwbGFjZVZwYzpcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnN1Ym5ldElkcykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFZwY1Byb3BzLnN1Ym5ldElkcykgfHxcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnNlY3VyaXR5R3JvdXBJZHMpICE9PSBKU09OLnN0cmluZ2lmeShvbGRWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzKSxcbiAgICB1cGRhdGVBY2Nlc3M6XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgIT09IG9sZFZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyB8fFxuICAgICAgbmV3VnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgIT09IG9sZFZwY1Byb3BzLmVuZHBvaW50UHVibGljQWNjZXNzIHx8XG4gICAgICAhc2V0c0VxdWFsKG5ld1B1YmxpY0FjY2Vzc0NpZHJzLCBvbGRQdWJsaWNBY2Nlc3NDaWRycyksXG4gICAgcmVwbGFjZVJvbGU6IG5ld1Byb3BzLnJvbGVBcm4gIT09IG9sZFByb3BzLnJvbGVBcm4sXG4gICAgdXBkYXRlVmVyc2lvbjogbmV3UHJvcHMudmVyc2lvbiAhPT0gb2xkUHJvcHMudmVyc2lvbixcbiAgICB1cGRhdGVFbmNyeXB0aW9uOiBKU09OLnN0cmluZ2lmeShuZXdFbmMpICE9PSBKU09OLnN0cmluZ2lmeShvbGRFbmMpLFxuICAgIHVwZGF0ZUxvZ2dpbmc6IEpTT04uc3RyaW5naWZ5KG5ld1Byb3BzLmxvZ2dpbmcpICE9PSBKU09OLnN0cmluZ2lmeShvbGRQcm9wcy5sb2dnaW5nKSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gc2V0c0VxdWFsKGZpcnN0OiBTZXQ8c3RyaW5nPiwgc2Vjb25kOiBTZXQ8c3RyaW5nPikge1xuICByZXR1cm4gZmlyc3Quc2l6ZSA9PT0gc2Vjb25kLnNpemUgJiYgWy4uLmZpcnN0XS5ldmVyeSgoZTogc3RyaW5nKSA9PiBzZWNvbmQuaGFzKGUpKTtcbn1cbiJdfQ== \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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LENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztRQUNuRSxhQUFhLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBa0IsRUFBRSxNQUFtQjtJQUN4RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgRWtzQ2xpZW50LCBSZXNvdXJjZUV2ZW50LCBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX05BTUVfTEVOID0gMTAwO1xuXG5leHBvcnQgY2xhc3MgQ2x1c3RlclJlc291cmNlSGFuZGxlciBleHRlbmRzIFJlc291cmNlSGFuZGxlciB7XG4gIHB1YmxpYyBnZXQgY2x1c3Rlck5hbWUoKSB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZGV0ZXJtaW5lIGNsdXN0ZXIgbmFtZSB3aXRob3V0IHBoeXNpY2FsIHJlc291cmNlIElEJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PjtcblxuICBjb25zdHJ1Y3Rvcihla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICBzdXBlcihla3MsIGV2ZW50KTtcblxuICAgIHRoaXMubmV3UHJvcHMgPSBwYXJzZVByb3BzKHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLm9sZFByb3BzID0gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnID8gcGFyc2VQcm9wcyhldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMpIDoge307XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gQ1JFQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCdvbkNyZWF0ZTogY3JlYXRpbmcgY2x1c3RlciB3aXRoIG9wdGlvbnM6JywgSlNPTi5zdHJpbmdpZnkodGhpcy5uZXdQcm9wcywgdW5kZWZpbmVkLCAyKSk7XG4gICAgaWYgKCF0aGlzLm5ld1Byb3BzLnJvbGVBcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJyb2xlQXJuXCIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyTmFtZSA9IHRoaXMubmV3UHJvcHMubmFtZSB8fCB0aGlzLmdlbmVyYXRlQ2x1c3Rlck5hbWUoKTtcblxuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmVrcy5jcmVhdGVDbHVzdGVyKHtcbiAgICAgIC4uLnRoaXMubmV3UHJvcHMsXG4gICAgICBuYW1lOiBjbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcC5jbHVzdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBjbHVzdGVyICR7Y2x1c3Rlck5hbWV9OiBDcmVhdGVDbHVzdGVyIHJldHVybmVkIHdpdGhvdXQgY2x1c3RlciBpbmZvcm1hdGlvbmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHJlc3AuY2x1c3Rlci5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIERFTEVURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25EZWxldGUoKTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgb25EZWxldGU6IGRlbGV0aW5nIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfWApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVrcy5kZWxldGVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyICR7dGhpcy5jbHVzdGVyTmFtZX0gbm90IGZvdW5kLCBpZGVtcG90ZW50bHkgc3VjY2VlZGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coYGlzRGVsZXRlQ29tcGxldGU6IHdhaXRpbmcgZm9yIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSB0byBiZSBkZWxldGVkYCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJldHVybmVkOicsIEpTT04uc3RyaW5naWZ5KHJlc3AsIHVuZGVmaW5lZCwgMikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICBjb25zb2xlLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgY2x1c3RlciBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0cnVlIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgZXJyb3I6JywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIFVQREFURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IGFuYWx5emVVcGRhdGUodGhpcy5vbGRQcm9wcywgdGhpcy5uZXdQcm9wcyk7XG4gICAgY29uc29sZS5sb2coJ29uVXBkYXRlOicsIEpTT04uc3RyaW5naWZ5KHsgdXBkYXRlcyB9LCB1bmRlZmluZWQsIDIpKTtcblxuICAgIC8vIHVwZGF0ZXMgdG8gZW5jcnlwdGlvbiBjb25maWcgaXMgbm90IHN1cHBvcnRlZFxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUVuY3J5cHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHVwZGF0ZSBjbHVzdGVyIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZXJlIGlzIGFuIHVwZGF0ZSB0aGF0IHJlcXVpcmVzIHJlcGxhY2VtZW50LCBnbyBhaGVhZCBhbmQganVzdCBjcmVhdGVcbiAgICAvLyBhIG5ldyBjbHVzdGVyIHdpdGggdGhlIG5ldyBjb25maWcuIFRoZSBvbGQgY2x1c3RlciB3aWxsIGF1dG9tYXRpY2FsbHkgYmVcbiAgICAvLyBkZWxldGVkIGJ5IGNsb3VkZm9ybWF0aW9uIHVwb24gc3VjY2Vzcy5cbiAgICBpZiAodXBkYXRlcy5yZXBsYWNlTmFtZSB8fCB1cGRhdGVzLnJlcGxhY2VSb2xlIHx8IHVwZGF0ZXMucmVwbGFjZVZwYykge1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgcmVwbGFjaW5nIHRoaXMgY2x1c3RlciBhbmQgdGhlIGNsdXN0ZXIgaGFzIGFuIGV4cGxpY2l0XG4gICAgICAvLyBwaHlzaWNhbCBuYW1lLCB0aGUgY3JlYXRpb24gb2YgdGhlIG5ldyBjbHVzdGVyIHdpbGwgZmFpbCB3aXRoIFwidGhlcmUgaXNcbiAgICAgIC8vIGFscmVhZHkgYSBjbHVzdGVyIHdpdGggdGhhdCBuYW1lXCIuIHRoaXMgaXMgYSBjb21tb24gYmVoYXZpb3IgZm9yXG4gICAgICAvLyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZXMgdGhhdCBzdXBwb3J0IHNwZWNpZnlpbmcgYSBwaHlzaWNhbCBuYW1lLlxuICAgICAgaWYgKHRoaXMub2xkUHJvcHMubmFtZSA9PT0gdGhpcy5uZXdQcm9wcy5uYW1lICYmIHRoaXMub2xkUHJvcHMubmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXBsYWNlIGNsdXN0ZXIgXCIke3RoaXMub2xkUHJvcHMubmFtZX1cIiBzaW5jZSBpdCBoYXMgYW4gZXhwbGljaXQgcGh5c2ljYWwgbmFtZS4gRWl0aGVyIHJlbmFtZSB0aGUgY2x1c3RlciBvciByZW1vdmUgdGhlIFwibmFtZVwiIGNvbmZpZ3VyYXRpb25gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub25DcmVhdGUoKTtcbiAgICB9XG5cbiAgICAvLyBpZiBhIHZlcnNpb24gdXBkYXRlIGlzIHJlcXVpcmVkLCBpc3N1ZSB0aGUgdmVyc2lvbiB1cGRhdGVcbiAgICBpZiAodXBkYXRlcy51cGRhdGVWZXJzaW9uKSB7XG4gICAgICBpZiAoIXRoaXMubmV3UHJvcHMudmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZW1vdmUgY2x1c3RlciB2ZXJzaW9uIGNvbmZpZ3VyYXRpb24uIEN1cnJlbnQgdmVyc2lvbiBpcyAke3RoaXMub2xkUHJvcHMudmVyc2lvbn1gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlQ2x1c3RlclZlcnNpb24odGhpcy5uZXdQcm9wcy52ZXJzaW9uKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nICYmIHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1cGRhdGUgbG9nZ2luZyBhbmQgYWNjZXNzIGF0IHRoZSBzYW1lIHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nIHx8IHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICBjb25zdCBjb25maWc6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QgPSB7XG4gICAgICAgIG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgICB9O1xuICAgICAgaWYgKHVwZGF0ZXMudXBkYXRlTG9nZ2luZykge1xuICAgICAgICBjb25maWcubG9nZ2luZyA9IHRoaXMubmV3UHJvcHMubG9nZ2luZztcbiAgICAgIH07XG4gICAgICBpZiAodXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIGNsdXN0ZXIgd2l0aCBzZWN1cml0eUdyb3VwSWRzIGFuZCBzdWJuZXRJZHMgKGFzIHNwZWNpZmllZCBpbiB0aGUgd2FybmluZyBoZXJlOlxuICAgICAgICAvLyBodHRwczovL2F3c2NsaS5hbWF6b25hd3MuY29tL3YyL2RvY3VtZW50YXRpb24vYXBpL2xhdGVzdC9yZWZlcmVuY2UvZWtzL3VwZGF0ZS1jbHVzdGVyLWNvbmZpZy5odG1sKVxuICAgICAgICAvLyB3aWxsIGZhaWwsIHRoZXJlZm9yZSB3ZSB0YWtlIG9ubHkgdGhlIGFjY2VzcyBmaWVsZHMgZXhwbGljaXRseVxuICAgICAgICBjb25maWcucmVzb3VyY2VzVnBjQ29uZmlnID0ge1xuICAgICAgICAgIGVuZHBvaW50UHJpdmF0ZUFjY2VzczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzLFxuICAgICAgICAgIGVuZHBvaW50UHVibGljQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyxcbiAgICAgICAgICBwdWJsaWNBY2Nlc3NDaWRyczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcucHVibGljQWNjZXNzQ2lkcnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgICB9XG5cbiAgICAvLyBubyB1cGRhdGVzXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc29sZS5sb2coJ2lzVXBkYXRlQ29tcGxldGUnKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYW4gRUtTIHVwZGF0ZSwgd2Ugd2lsbCBtb25pdG9yIHRoZSB1cGRhdGUgZXZlbnQgaXRzZWxmXG4gICAgaWYgKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gYXdhaXQgdGhpcy5pc0Vrc1VwZGF0ZUNvbXBsZXRlKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpO1xuICAgICAgaWYgKCFjb21wbGV0ZSkge1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiBmYWxzZSB9O1xuICAgICAgfVxuXG4gICAgICAvLyBmYWxsIHRocm91Z2g6IGlmIHRoZSB1cGRhdGUgaXMgZG9uZSwgd2Ugc2ltcGx5IGRlbGVnYXRlIHRvIGlzQWN0aXZlKClcbiAgICAgIC8vIGluIG9yZGVyIHRvIGV4dHJhY3QgYXR0cmlidXRlcyBhbmQgc3RhdGUgZnJvbSB0aGUgY2x1c3RlciBpdHNlbGYsIHdoaWNoXG4gICAgICAvLyBpcyBzdXBwb3NlZCB0byBiZSBpbiBhbiBBQ1RJVkUgc3RhdGUgYWZ0ZXIgdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbHVzdGVyVmVyc2lvbihuZXdWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgdXBkYXRpbmcgY2x1c3RlciB2ZXJzaW9uIHRvICR7bmV3VmVyc2lvbn1gKTtcblxuICAgIC8vIHVwZGF0ZS1jbHVzdGVyLXZlcnNpb24gd2lsbCBmYWlsIGlmIHdlIHRyeSB0byB1cGRhdGUgdG8gdGhlIHNhbWUgdmVyc2lvbixcbiAgICAvLyBzbyBza2lwIGluIHRoaXMgY2FzZS5cbiAgICBjb25zdCBjbHVzdGVyID0gKGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSkpLmNsdXN0ZXI7XG4gICAgaWYgKGNsdXN0ZXI/LnZlcnNpb24gPT09IG5ld1ZlcnNpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyIGFscmVhZHkgYXQgdmVyc2lvbiAke2NsdXN0ZXIudmVyc2lvbn0sIHNraXBwaW5nIHZlcnNpb24gdXBkYXRlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy51cGRhdGVDbHVzdGVyVmVyc2lvbih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsIHZlcnNpb246IG5ld1ZlcnNpb24gfSk7XG4gICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNBY3RpdmUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZygnd2FpdGluZyBmb3IgY2x1c3RlciB0byBiZWNvbWUgQUNUSVZFJyk7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciByZXN1bHQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgY29uc3QgY2x1c3RlciA9IHJlc3AuY2x1c3RlcjtcblxuICAgIC8vIGlmIGNsdXN0ZXIgaXMgdW5kZWZpbmVkIChzaG91bGRudCBoYXBwZW4pIG9yIHN0YXR1cyBpcyBub3QgQUNUSVZFLCB3ZSBhcmVcbiAgICAvLyBub3QgY29tcGxldGUuIG5vdGUgdGhhdCB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZyYW1ld29yayBmb3JiaWRzXG4gICAgLy8gcmV0dXJuaW5nIGF0dHJpYnV0ZXMgKERhdGEpIGlmIGlzQ29tcGxldGUgaXMgZmFsc2UuXG4gICAgaWYgKGNsdXN0ZXI/LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgIC8vIG5vdCB2ZXJ5IGluZm9ybWF0aXZlLCB1bmZvcnR1bmF0ZWx5IHRoZSByZXNwb25zZSBkb2Vzbid0IGNvbnRhaW4gYW55IGVycm9yXG4gICAgICAvLyBpbmZvcm1hdGlvbiA6XFxcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2x1c3RlciBpcyBpbiBhIEZBSUxFRCBzdGF0dXMnKTtcbiAgICB9IGVsc2UgaWYgKGNsdXN0ZXI/LnN0YXR1cyAhPT0gJ0FDVElWRScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIE5hbWU6IGNsdXN0ZXIubmFtZSxcbiAgICAgICAgICBFbmRwb2ludDogY2x1c3Rlci5lbmRwb2ludCxcbiAgICAgICAgICBBcm46IGNsdXN0ZXIuYXJuLFxuXG4gICAgICAgICAgLy8gSU1QT1JUQU5UOiBDRk4gZXhwZWN0cyB0aGF0IGF0dHJpYnV0ZXMgd2lsbCAqYWx3YXlzKiBoYXZlIHZhbHVlcyxcbiAgICAgICAgICAvLyBzbyByZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGluIGNhc2UgdGhlIHZhbHVlIGlzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQ0ZOIHdpbGwgdGhyb3cgd2l0aCBgVmVuZG9yIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpblxuICAgICAgICAgIC8vIFhYWFgga2V5YC5cblxuICAgICAgICAgIENlcnRpZmljYXRlQXV0aG9yaXR5RGF0YTogY2x1c3Rlci5jZXJ0aWZpY2F0ZUF1dGhvcml0eT8uZGF0YSA/PyAnJyxcbiAgICAgICAgICBDbHVzdGVyU2VjdXJpdHlHcm91cElkOiBjbHVzdGVyLnJlc291cmNlc1ZwY0NvbmZpZz8uY2x1c3RlclNlY3VyaXR5R3JvdXBJZCA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyVXJsOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXIgPz8gJycsXG4gICAgICAgICAgT3BlbklkQ29ubmVjdElzc3VlcjogY2x1c3Rlci5pZGVudGl0eT8ub2lkYz8uaXNzdWVyPy5zdWJzdHJpbmcoOCkgPz8gJycsIC8vIFN0cmlwcyBvZmYgaHR0cHM6Ly8gZnJvbSB0aGUgaXNzdWVyIHVybFxuXG4gICAgICAgICAgLy8gV2UgY2FuIHNhZmVseSByZXR1cm4gdGhlIGZpcnN0IGl0ZW0gZnJvbSBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gYXJyYXksIGJlY2F1c2UgaXQgaGFzIGEgbGltaXQgb2YgMSBpdGVtXG4gICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vrcy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDbHVzdGVyLmh0bWwjQW1hem9uRUtTLUNyZWF0ZUNsdXN0ZXItcmVxdWVzdC1lbmNyeXB0aW9uQ29uZmlnXG4gICAgICAgICAgRW5jcnlwdGlvbkNvbmZpZ0tleUFybjogY2x1c3Rlci5lbmNyeXB0aW9uQ29uZmlnPy5zaGlmdCgpPy5wcm92aWRlcj8ua2V5QXJuID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzRWtzVXBkYXRlQ29tcGxldGUoZWtzVXBkYXRlSWQ6IHN0cmluZykge1xuICAgIHRoaXMubG9nKHsgaXNFa3NVcGRhdGVDb21wbGV0ZTogZWtzVXBkYXRlSWQgfSk7XG5cbiAgICBjb25zdCBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVVcGRhdGUoe1xuICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgIHVwZGF0ZUlkOiBla3NVcGRhdGVJZCxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nKHsgZGVzY3JpYmVVcGRhdGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5hYmxlIHRvIGRlc2NyaWJlIHVwZGF0ZSB3aXRoIGlkIFwiJHtla3NVcGRhdGVJZH1cImApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzKSB7XG4gICAgICBjYXNlICdJblByb2dyZXNzJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgY2FzZSAnU3VjY2Vzc2Z1bCc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnRmFpbGVkJzpcbiAgICAgIGNhc2UgJ0NhbmNlbGxlZCc6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2x1c3RlciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiIGZhaWxlZCB3aXRoIGVycm9yczogJHtKU09OLnN0cmluZ2lmeShkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5lcnJvcnMpfWApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIHN0YXR1cyBcIiR7ZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzfVwiIGZvciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNsdXN0ZXJOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9DTFVTVEVSX05BTUVfTEVOIC0gc3VmZml4Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5sb2dpY2FsUmVzb3VyY2VJZC5zbGljZSgwLCBvZmZzZXQgPiAwID8gb2Zmc2V0IDogMCk7XG4gICAgcmV0dXJuIGAke3ByZWZpeH0tJHtzdWZmaXh9YDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3BzKHByb3BzOiBhbnkpOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0IHtcblxuICBjb25zdCBwYXJzZWQgPSBwcm9wcz8uQ29uZmlnID8/IHt9O1xuXG4gIC8vIHRoaXMgaXMgd2VpcmQgYnV0IHRoZXNlIGJvb2xlYW4gcHJvcGVydGllcyBhcmUgcGFzc2VkIGJ5IENGTiBhcyBhIHN0cmluZywgYW5kIHdlIG5lZWQgdGhlbSB0byBiZSBib29sZWFuaWMgZm9yIHRoZSBTREsuXG4gIC8vIE90aGVyd2lzZSBpdCBmYWlscyB3aXRoICdVbmV4cGVjdGVkIFBhcmFtZXRlcjogcGFyYW1zLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgaXMgZXhwZWN0ZWQgdG8gYmUgYSBib29sZWFuJ1xuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWc/LmVuZHBvaW50UHJpdmF0ZUFjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9PT0gJ3RydWUnO1xuICB9XG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQdWJsaWNBY2Nlc3MpID09PSAnc3RyaW5nJykge1xuICAgIHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQubG9nZ2luZz8uY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCkgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9IHBhcnNlZC5sb2dnaW5nLmNsdXN0ZXJMb2dnaW5nWzBdLmVuYWJsZWQgPT09ICd0cnVlJztcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQ7XG5cbn1cblxuaW50ZXJmYWNlIFVwZGF0ZU1hcCB7XG4gIHJlcGxhY2VOYW1lOiBib29sZWFuOyAvLyBuYW1lXG4gIHJlcGxhY2VWcGM6IGJvb2xlYW47IC8vIHJlc291cmNlc1ZwY0NvbmZpZy5zdWJuZXRJZHMgYW5kIHNlY3VyaXR5R3JvdXBJZHNcbiAgcmVwbGFjZVJvbGU6IGJvb2xlYW47IC8vIHJvbGVBcm5cblxuICB1cGRhdGVWZXJzaW9uOiBib29sZWFuOyAvLyB2ZXJzaW9uXG4gIHVwZGF0ZUxvZ2dpbmc6IGJvb2xlYW47IC8vIGxvZ2dpbmdcbiAgdXBkYXRlRW5jcnlwdGlvbjogYm9vbGVhbjsgLy8gZW5jcnlwdGlvbiAoY2Fubm90IGJlIHVwZGF0ZWQpXG4gIHVwZGF0ZUFjY2VzczogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBhbmQgZW5kcG9pbnRQdWJsaWNBY2Nlc3Ncbn1cblxuZnVuY3Rpb24gYW5hbHl6ZVVwZGF0ZShvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PiwgbmV3UHJvcHM6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBVcGRhdGVNYXAge1xuICBjb25zb2xlLmxvZygnb2xkIHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShvbGRQcm9wcykpO1xuICBjb25zb2xlLmxvZygnbmV3IHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShuZXdQcm9wcykpO1xuXG4gIGNvbnN0IG5ld1ZwY1Byb3BzID0gbmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRWcGNQcm9wcyA9IG9sZFByb3BzLnJlc291cmNlc1ZwY0NvbmZpZyB8fCB7fTtcblxuICBjb25zdCBvbGRQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQob2xkVnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQobmV3VnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdFbmMgPSBuZXdQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRFbmMgPSBvbGRQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgcmVwbGFjZU5hbWU6IG5ld1Byb3BzLm5hbWUgIT09IG9sZFByb3BzLm5hbWUsXG4gICAgcmVwbGFjZVZwYzpcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnN1Ym5ldElkcz8uc29ydCgpKSAhPT0gSlNPTi5zdHJpbmdpZnkob2xkVnBjUHJvcHMuc3VibmV0SWRzPy5zb3J0KCkpIHx8XG4gICAgICBKU09OLnN0cmluZ2lmeShuZXdWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpICE9PSBKU09OLnN0cmluZ2lmeShvbGRWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpLFxuICAgIHVwZGF0ZUFjY2VzczpcbiAgICAgIG5ld1ZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQcml2YXRlQWNjZXNzIHx8XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFB1YmxpY0FjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgfHxcbiAgICAgICFzZXRzRXF1YWwobmV3UHVibGljQWNjZXNzQ2lkcnMsIG9sZFB1YmxpY0FjY2Vzc0NpZHJzKSxcbiAgICByZXBsYWNlUm9sZTogbmV3UHJvcHMucm9sZUFybiAhPT0gb2xkUHJvcHMucm9sZUFybixcbiAgICB1cGRhdGVWZXJzaW9uOiBuZXdQcm9wcy52ZXJzaW9uICE9PSBvbGRQcm9wcy52ZXJzaW9uLFxuICAgIHVwZGF0ZUVuY3J5cHRpb246IEpTT04uc3RyaW5naWZ5KG5ld0VuYykgIT09IEpTT04uc3RyaW5naWZ5KG9sZEVuYyksXG4gICAgdXBkYXRlTG9nZ2luZzogSlNPTi5zdHJpbmdpZnkobmV3UHJvcHMubG9nZ2luZykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFByb3BzLmxvZ2dpbmcpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzZXRzRXF1YWwoZmlyc3Q6IFNldDxzdHJpbmc+LCBzZWNvbmQ6IFNldDxzdHJpbmc+KSB7XG4gIHJldHVybiBmaXJzdC5zaXplID09PSBzZWNvbmQuc2l6ZSAmJiBbLi4uZmlyc3RdLmV2ZXJ5KChlOiBzdHJpbmcpID0+IHNlY29uZC5oYXMoZSkpO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts similarity index 98% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts index e6930b7844d32..4b7fdda6d1dd1 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.ts +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts @@ -326,8 +326,8 @@ function analyzeUpdate(oldProps: Partial, newProps return { replaceName: newProps.name !== oldProps.name, replaceVpc: - JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), + JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip index 593043af0139a..f62fe1e5a06d6 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js deleted file mode 100644 index 70203dcc42f3f..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js +++ /dev/null @@ -1,45 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.httpRequest = exports.invokeFunction = exports.startExecution = void 0; -/* istanbul ignore file */ -const https = require("https"); -// eslint-disable-next-line import/no-extraneous-dependencies -const AWS = require("aws-sdk"); -const FRAMEWORK_HANDLER_TIMEOUT = 900000; // 15 minutes -// In order to honor the overall maximum timeout set for the target process, -// the default 2 minutes from AWS SDK has to be overriden: -// https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html#httpOptions-property -const 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; -let lambda; -async function defaultStartExecution(req) { - if (!sfn) { - sfn = new AWS.StepFunctions(awsSdkConfig); - } - return sfn.startExecution(req).promise(); -} -async function defaultInvokeFunction(req) { - if (!lambda) { - lambda = new AWS.Lambda(awsSdkConfig); - } - return lambda.invoke(req).promise(); -} -exports.startExecution = defaultStartExecution; -exports.invokeFunction = defaultInvokeFunction; -exports.httpRequest = defaultHttpRequest; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3V0Ym91bmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJvdXRib3VuZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwwQkFBMEI7QUFDMUIsK0JBQStCO0FBQy9CLDZEQUE2RDtBQUM3RCwrQkFBK0I7QUFJL0IsTUFBTSx5QkFBeUIsR0FBRyxNQUFNLENBQUMsQ0FBQyxhQUFhO0FBRXZELDRFQUE0RTtBQUM1RSwwREFBMEQ7QUFDMUQsMkZBQTJGO0FBQzNGLE1BQU0sWUFBWSxHQUF5QjtJQUN6QyxXQUFXLEVBQUUsRUFBRSxPQUFPLEVBQUUseUJBQXlCLEVBQUU7Q0FDcEQsQ0FBQztBQUVGLEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxPQUE2QixFQUFFLFlBQW9CO0lBQ25GLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDckMsSUFBSTtZQUNGLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ2hELE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDNUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1NBQ2Y7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNYO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsSUFBSSxHQUFzQixDQUFDO0FBQzNCLElBQUksTUFBa0IsQ0FBQztBQUV2QixLQUFLLFVBQVUscUJBQXFCLENBQUMsR0FBMEM7SUFDN0UsSUFBSSxDQUFDLEdBQUcsRUFBRTtRQUNSLEdBQUcsR0FBRyxJQUFJLEdBQUcsQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUM7S0FDM0M7SUFFRCxPQUFPLEdBQUcsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7QUFDM0MsQ0FBQztBQUVELEtBQUssVUFBVSxxQkFBcUIsQ0FBQyxHQUFpQztJQUNwRSxJQUFJLENBQUMsTUFBTSxFQUFFO1FBQ1gsTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztLQUN2QztJQUVELE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztBQUN0QyxDQUFDO0FBRVUsUUFBQSxjQUFjLEdBQUcscUJBQXFCLENBQUM7QUFDdkMsUUFBQSxjQUFjLEdBQUcscUJBQXFCLENBQUM7QUFDdkMsUUFBQSxXQUFXLEdBQUcsa0JBQWtCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBpc3RhbmJ1bCBpZ25vcmUgZmlsZSAqL1xuaW1wb3J0ICogYXMgaHR0cHMgZnJvbSAnaHR0cHMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgQVdTIGZyb20gJ2F3cy1zZGsnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHR5cGUgeyBDb25maWd1cmF0aW9uT3B0aW9ucyB9IGZyb20gJ2F3cy1zZGsvbGliL2NvbmZpZy1iYXNlJztcblxuY29uc3QgRlJBTUVXT1JLX0hBTkRMRVJfVElNRU9VVCA9IDkwMDAwMDsgLy8gMTUgbWludXRlc1xuXG4vLyBJbiBvcmRlciB0byBob25vciB0aGUgb3ZlcmFsbCBtYXhpbXVtIHRpbWVvdXQgc2V0IGZvciB0aGUgdGFyZ2V0IHByb2Nlc3MsXG4vLyB0aGUgZGVmYXVsdCAyIG1pbnV0ZXMgZnJvbSBBV1MgU0RLIGhhcyB0byBiZSBvdmVycmlkZW46XG4vLyBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTSmF2YVNjcmlwdFNESy9sYXRlc3QvQVdTL0NvbmZpZy5odG1sI2h0dHBPcHRpb25zLXByb3BlcnR5XG5jb25zdCBhd3NTZGtDb25maWc6IENvbmZpZ3VyYXRpb25PcHRpb25zID0ge1xuICBodHRwT3B0aW9uczogeyB0aW1lb3V0OiBGUkFNRVdPUktfSEFORExFUl9USU1FT1VUIH0sXG59O1xuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0SHR0cFJlcXVlc3Qob3B0aW9uczogaHR0cHMuUmVxdWVzdE9wdGlvbnMsIHJlc3BvbnNlQm9keTogc3RyaW5nKSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlcXVlc3QgPSBodHRwcy5yZXF1ZXN0KG9wdGlvbnMsIHJlc29sdmUpO1xuICAgICAgcmVxdWVzdC5vbignZXJyb3InLCByZWplY3QpO1xuICAgICAgcmVxdWVzdC53cml0ZShyZXNwb25zZUJvZHkpO1xuICAgICAgcmVxdWVzdC5lbmQoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZWplY3QoZSk7XG4gICAgfVxuICB9KTtcbn1cblxubGV0IHNmbjogQVdTLlN0ZXBGdW5jdGlvbnM7XG5sZXQgbGFtYmRhOiBBV1MuTGFtYmRhO1xuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0U3RhcnRFeGVjdXRpb24ocmVxOiBBV1MuU3RlcEZ1bmN0aW9ucy5TdGFydEV4ZWN1dGlvbklucHV0KTogUHJvbWlzZTxBV1MuU3RlcEZ1bmN0aW9ucy5TdGFydEV4ZWN1dGlvbk91dHB1dD4ge1xuICBpZiAoIXNmbikge1xuICAgIHNmbiA9IG5ldyBBV1MuU3RlcEZ1bmN0aW9ucyhhd3NTZGtDb25maWcpO1xuICB9XG5cbiAgcmV0dXJuIHNmbi5zdGFydEV4ZWN1dGlvbihyZXEpLnByb21pc2UoKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdEludm9rZUZ1bmN0aW9uKHJlcTogQVdTLkxhbWJkYS5JbnZvY2F0aW9uUmVxdWVzdCk6IFByb21pc2U8QVdTLkxhbWJkYS5JbnZvY2F0aW9uUmVzcG9uc2U+IHtcbiAgaWYgKCFsYW1iZGEpIHtcbiAgICBsYW1iZGEgPSBuZXcgQVdTLkxhbWJkYShhd3NTZGtDb25maWcpO1xuICB9XG5cbiAgcmV0dXJuIGxhbWJkYS5pbnZva2UocmVxKS5wcm9taXNlKCk7XG59XG5cbmV4cG9ydCBsZXQgc3RhcnRFeGVjdXRpb24gPSBkZWZhdWx0U3RhcnRFeGVjdXRpb247XG5leHBvcnQgbGV0IGludm9rZUZ1bmN0aW9uID0gZGVmYXVsdEludm9rZUZ1bmN0aW9uO1xuZXhwb3J0IGxldCBodHRwUmVxdWVzdCA9IGRlZmF1bHRIdHRwUmVxdWVzdDtcbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.js deleted file mode 100644 index 6efe7fd22e321..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.js +++ /dev/null @@ -1,267 +0,0 @@ -"use strict"; -/* eslint-disable no-console */ -Object.defineProperty(exports, "__esModule", { value: true }); -exports.ClusterResourceHandler = void 0; -const common_1 = require("./common"); -const MAX_CLUSTER_NAME_LEN = 100; -class ClusterResourceHandler extends common_1.ResourceHandler { - constructor(eks, event) { - super(eks, event); - this.newProps = parseProps(this.event.ResourceProperties); - this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; - } - get clusterName() { - if (!this.physicalResourceId) { - throw new Error('Cannot determine cluster name without physical resource ID'); - } - return this.physicalResourceId; - } - // ------ - // CREATE - // ------ - async onCreate() { - console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); - if (!this.newProps.roleArn) { - throw new Error('"roleArn" is required'); - } - const clusterName = this.newProps.name || this.generateClusterName(); - const resp = await this.eks.createCluster({ - ...this.newProps, - name: clusterName, - }); - if (!resp.cluster) { - throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); - } - return { - PhysicalResourceId: resp.cluster.name, - }; - } - async isCreateComplete() { - return this.isActive(); - } - // ------ - // DELETE - // ------ - async onDelete() { - console.log(`onDelete: deleting cluster ${this.clusterName}`); - try { - await this.eks.deleteCluster({ name: this.clusterName }); - } - catch (e) { - if (e.code !== 'ResourceNotFoundException') { - throw e; - } - else { - console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); - } - } - return { - PhysicalResourceId: this.clusterName, - }; - } - async isDeleteComplete() { - console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); - try { - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); - } - catch (e) { - if (e.code === 'ResourceNotFoundException') { - console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); - return { IsComplete: true }; - } - console.log('describeCluster error:', e); - throw e; - } - return { - IsComplete: false, - }; - } - // ------ - // UPDATE - // ------ - async onUpdate() { - const updates = analyzeUpdate(this.oldProps, this.newProps); - console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); - // updates to encryption config is not supported - if (updates.updateEncryption) { - throw new Error('Cannot update cluster encryption configuration'); - } - // if there is an update that requires replacement, go ahead and just create - // a new cluster with the new config. The old cluster will automatically be - // deleted by cloudformation upon success. - if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { - // if we are replacing this cluster and the cluster has an explicit - // physical name, the creation of the new cluster will fail with "there is - // already a cluster with that name". this is a common behavior for - // CloudFormation resources that support specifying a physical name. - if (this.oldProps.name === this.newProps.name && this.oldProps.name) { - throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); - } - return this.onCreate(); - } - // if a version update is required, issue the version update - if (updates.updateVersion) { - if (!this.newProps.version) { - throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); - } - return this.updateClusterVersion(this.newProps.version); - } - if (updates.updateLogging || updates.updateAccess) { - const config = { - name: this.clusterName, - logging: this.newProps.logging, - }; - if (updates.updateAccess) { - // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: - // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) - // will fail, therefore we take only the access fields explicitly - config.resourcesVpcConfig = { - endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, - endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, - publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, - }; - } - const updateResponse = await this.eks.updateClusterConfig(config); - return { EksUpdateId: updateResponse.update?.id }; - } - // no updates - return; - } - async isUpdateComplete() { - console.log('isUpdateComplete'); - // if this is an EKS update, we will monitor the update event itself - if (this.event.EksUpdateId) { - const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); - if (!complete) { - return { IsComplete: false }; - } - // fall through: if the update is done, we simply delegate to isActive() - // in order to extract attributes and state from the cluster itself, which - // is supposed to be in an ACTIVE state after the update is complete. - } - return this.isActive(); - } - async updateClusterVersion(newVersion) { - console.log(`updating cluster version to ${newVersion}`); - // update-cluster-version will fail if we try to update to the same version, - // so skip in this case. - const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; - if (cluster?.version === newVersion) { - console.log(`cluster already at version ${cluster.version}, skipping version update`); - return; - } - const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); - return { EksUpdateId: updateResponse.update?.id }; - } - async isActive() { - console.log('waiting for cluster to become ACTIVE'); - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); - const cluster = resp.cluster; - // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are - // not complete. note that the custom resource provider framework forbids - // returning attributes (Data) if isComplete is false. - if (cluster?.status === 'FAILED') { - // not very informative, unfortunately the response doesn't contain any error - // information :\ - throw new Error('Cluster is in a FAILED status'); - } - else if (cluster?.status !== 'ACTIVE') { - return { - IsComplete: false, - }; - } - else { - return { - IsComplete: true, - Data: { - Name: cluster.name, - Endpoint: cluster.endpoint, - Arn: cluster.arn, - // IMPORTANT: CFN expects that attributes will *always* have values, - // so return an empty string in case the value is not defined. - // Otherwise, CFN will throw with `Vendor response doesn't contain - // XXXX key`. - CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', - ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', - OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', - OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', - // We can safely return the first item from encryption configuration array, because it has a limit of 1 item - // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig - EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', - }, - }; - } - } - async isEksUpdateComplete(eksUpdateId) { - this.log({ isEksUpdateComplete: eksUpdateId }); - const describeUpdateResponse = await this.eks.describeUpdate({ - name: this.clusterName, - updateId: eksUpdateId, - }); - this.log({ describeUpdateResponse }); - if (!describeUpdateResponse.update) { - throw new Error(`unable to describe update with id "${eksUpdateId}"`); - } - switch (describeUpdateResponse.update.status) { - case 'InProgress': - return false; - case 'Successful': - return true; - case 'Failed': - case 'Cancelled': - throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); - default: - throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); - } - } - generateClusterName() { - const suffix = this.requestId.replace(/-/g, ''); // 32 chars - const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; - const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); - return `${prefix}-${suffix}`; - } -} -exports.ClusterResourceHandler = ClusterResourceHandler; -function parseProps(props) { - const parsed = props?.Config ?? {}; - // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. - // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' - if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; - } - if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; - } - if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { - parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; - } - return parsed; -} -function analyzeUpdate(oldProps, newProps) { - console.log('old props: ', JSON.stringify(oldProps)); - console.log('new props: ', JSON.stringify(newProps)); - const newVpcProps = newProps.resourcesVpcConfig || {}; - const oldVpcProps = oldProps.resourcesVpcConfig || {}; - const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); - const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); - const newEnc = newProps.encryptionConfig || {}; - const oldEnc = oldProps.encryptionConfig || {}; - return { - replaceName: newProps.name !== oldProps.name, - replaceVpc: JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), - updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || - newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || - !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), - replaceRole: newProps.roleArn !== oldProps.roleArn, - updateVersion: newProps.version !== oldProps.version, - updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), - updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), - }; -} -function setsEqual(first, second) { - return first.size === second.size || [...first].every((e) => second.has(e)); -} -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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LElBQUksS0FBSyxNQUFNLENBQUMsSUFBSSxJQUFJLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFTLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUN0RixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgbm8tY29uc29sZSAqL1xuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzXG5pbXBvcnQgeyBJc0NvbXBsZXRlUmVzcG9uc2UsIE9uRXZlbnRSZXNwb25zZSB9IGZyb20gJ0Bhd3MtY2RrL2N1c3RvbS1yZXNvdXJjZXMvbGliL3Byb3ZpZGVyLWZyYW1ld29yay90eXBlcyc7XG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzXG5pbXBvcnQgKiBhcyBhd3MgZnJvbSAnYXdzLXNkayc7XG5pbXBvcnQgeyBFa3NDbGllbnQsIFJlc291cmNlRXZlbnQsIFJlc291cmNlSGFuZGxlciB9IGZyb20gJy4vY29tbW9uJztcblxuY29uc3QgTUFYX0NMVVNURVJfTkFNRV9MRU4gPSAxMDA7XG5cbmV4cG9ydCBjbGFzcyBDbHVzdGVyUmVzb3VyY2VIYW5kbGVyIGV4dGVuZHMgUmVzb3VyY2VIYW5kbGVyIHtcbiAgcHVibGljIGdldCBjbHVzdGVyTmFtZSgpIHtcbiAgICBpZiAoIXRoaXMucGh5c2ljYWxSZXNvdXJjZUlkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBkZXRlcm1pbmUgY2x1c3RlciBuYW1lIHdpdGhvdXQgcGh5c2ljYWwgcmVzb3VyY2UgSUQnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5waHlzaWNhbFJlc291cmNlSWQ7XG4gIH1cblxuICBwcml2YXRlIHJlYWRvbmx5IG5ld1Byb3BzOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0O1xuICBwcml2YXRlIHJlYWRvbmx5IG9sZFByb3BzOiBQYXJ0aWFsPGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3Q+O1xuXG4gIGNvbnN0cnVjdG9yKGVrczogRWtzQ2xpZW50LCBldmVudDogUmVzb3VyY2VFdmVudCkge1xuICAgIHN1cGVyKGVrcywgZXZlbnQpO1xuXG4gICAgdGhpcy5uZXdQcm9wcyA9IHBhcnNlUHJvcHModGhpcy5ldmVudC5SZXNvdXJjZVByb3BlcnRpZXMpO1xuICAgIHRoaXMub2xkUHJvcHMgPSBldmVudC5SZXF1ZXN0VHlwZSA9PT0gJ1VwZGF0ZScgPyBwYXJzZVByb3BzKGV2ZW50Lk9sZFJlc291cmNlUHJvcGVydGllcykgOiB7fTtcbiAgfVxuXG4gIC8vIC0tLS0tLVxuICAvLyBDUkVBVEVcbiAgLy8gLS0tLS0tXG5cbiAgcHJvdGVjdGVkIGFzeW5jIG9uQ3JlYXRlKCk6IFByb21pc2U8T25FdmVudFJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coJ29uQ3JlYXRlOiBjcmVhdGluZyBjbHVzdGVyIHdpdGggb3B0aW9uczonLCBKU09OLnN0cmluZ2lmeSh0aGlzLm5ld1Byb3BzLCB1bmRlZmluZWQsIDIpKTtcbiAgICBpZiAoIXRoaXMubmV3UHJvcHMucm9sZUFybikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdcInJvbGVBcm5cIiBpcyByZXF1aXJlZCcpO1xuICAgIH1cblxuICAgIGNvbnN0IGNsdXN0ZXJOYW1lID0gdGhpcy5uZXdQcm9wcy5uYW1lIHx8IHRoaXMuZ2VuZXJhdGVDbHVzdGVyTmFtZSgpO1xuXG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmNyZWF0ZUNsdXN0ZXIoe1xuICAgICAgLi4udGhpcy5uZXdQcm9wcyxcbiAgICAgIG5hbWU6IGNsdXN0ZXJOYW1lLFxuICAgIH0pO1xuXG4gICAgaWYgKCFyZXNwLmNsdXN0ZXIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3Igd2hlbiB0cnlpbmcgdG8gY3JlYXRlIGNsdXN0ZXIgJHtjbHVzdGVyTmFtZX06IENyZWF0ZUNsdXN0ZXIgcmV0dXJuZWQgd2l0aG91dCBjbHVzdGVyIGluZm9ybWF0aW9uYCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogcmVzcC5jbHVzdGVyLm5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0NyZWF0ZUNvbXBsZXRlKCkge1xuICAgIHJldHVybiB0aGlzLmlzQWN0aXZlKCk7XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gREVMRVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkRlbGV0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKGBvbkRlbGV0ZTogZGVsZXRpbmcgY2x1c3RlciAke3RoaXMuY2x1c3Rlck5hbWV9YCk7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuZWtzLmRlbGV0ZUNsdXN0ZXIoeyBuYW1lOiB0aGlzLmNsdXN0ZXJOYW1lIH0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgIT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc29sZS5sb2coYGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSBub3QgZm91bmQsIGlkZW1wb3RlbnRseSBzdWNjZWVkZWRgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICB9O1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzRGVsZXRlQ29tcGxldGUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgaXNEZWxldGVDb21wbGV0ZTogd2FpdGluZyBmb3IgY2x1c3RlciAke3RoaXMuY2x1c3Rlck5hbWV9IHRvIGJlIGRlbGV0ZWRgKTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXNwID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgcmV0dXJuZWQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKGUuY29kZSA9PT0gJ1Jlc291cmNlTm90Rm91bmRFeGNlcHRpb24nKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdyZWNlaXZlZCBSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uLCB0aGlzIG1lYW5zIHRoZSBjbHVzdGVyIGhhcyBiZWVuIGRlbGV0ZWQgKG9yIG5ldmVyIGV4aXN0ZWQpJyk7XG4gICAgICAgIHJldHVybiB7IElzQ29tcGxldGU6IHRydWUgfTtcbiAgICAgIH1cblxuICAgICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciBlcnJvcjonLCBlKTtcbiAgICAgIHRocm93IGU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgIH07XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gVVBEQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvblVwZGF0ZSgpIHtcbiAgICBjb25zdCB1cGRhdGVzID0gYW5hbHl6ZVVwZGF0ZSh0aGlzLm9sZFByb3BzLCB0aGlzLm5ld1Byb3BzKTtcbiAgICBjb25zb2xlLmxvZygnb25VcGRhdGU6JywgSlNPTi5zdHJpbmdpZnkoeyB1cGRhdGVzIH0sIHVuZGVmaW5lZCwgMikpO1xuXG4gICAgLy8gdXBkYXRlcyB0byBlbmNyeXB0aW9uIGNvbmZpZyBpcyBub3Qgc3VwcG9ydGVkXG4gICAgaWYgKHVwZGF0ZXMudXBkYXRlRW5jcnlwdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgdXBkYXRlIGNsdXN0ZXIgZW5jcnlwdGlvbiBjb25maWd1cmF0aW9uJyk7XG4gICAgfVxuXG4gICAgLy8gaWYgdGhlcmUgaXMgYW4gdXBkYXRlIHRoYXQgcmVxdWlyZXMgcmVwbGFjZW1lbnQsIGdvIGFoZWFkIGFuZCBqdXN0IGNyZWF0ZVxuICAgIC8vIGEgbmV3IGNsdXN0ZXIgd2l0aCB0aGUgbmV3IGNvbmZpZy4gVGhlIG9sZCBjbHVzdGVyIHdpbGwgYXV0b21hdGljYWxseSBiZVxuICAgIC8vIGRlbGV0ZWQgYnkgY2xvdWRmb3JtYXRpb24gdXBvbiBzdWNjZXNzLlxuICAgIGlmICh1cGRhdGVzLnJlcGxhY2VOYW1lIHx8IHVwZGF0ZXMucmVwbGFjZVJvbGUgfHwgdXBkYXRlcy5yZXBsYWNlVnBjKSB7XG5cbiAgICAgIC8vIGlmIHdlIGFyZSByZXBsYWNpbmcgdGhpcyBjbHVzdGVyIGFuZCB0aGUgY2x1c3RlciBoYXMgYW4gZXhwbGljaXRcbiAgICAgIC8vIHBoeXNpY2FsIG5hbWUsIHRoZSBjcmVhdGlvbiBvZiB0aGUgbmV3IGNsdXN0ZXIgd2lsbCBmYWlsIHdpdGggXCJ0aGVyZSBpc1xuICAgICAgLy8gYWxyZWFkeSBhIGNsdXN0ZXIgd2l0aCB0aGF0IG5hbWVcIi4gdGhpcyBpcyBhIGNvbW1vbiBiZWhhdmlvciBmb3JcbiAgICAgIC8vIENsb3VkRm9ybWF0aW9uIHJlc291cmNlcyB0aGF0IHN1cHBvcnQgc3BlY2lmeWluZyBhIHBoeXNpY2FsIG5hbWUuXG4gICAgICBpZiAodGhpcy5vbGRQcm9wcy5uYW1lID09PSB0aGlzLm5ld1Byb3BzLm5hbWUgJiYgdGhpcy5vbGRQcm9wcy5uYW1lKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IHJlcGxhY2UgY2x1c3RlciBcIiR7dGhpcy5vbGRQcm9wcy5uYW1lfVwiIHNpbmNlIGl0IGhhcyBhbiBleHBsaWNpdCBwaHlzaWNhbCBuYW1lLiBFaXRoZXIgcmVuYW1lIHRoZSBjbHVzdGVyIG9yIHJlbW92ZSB0aGUgXCJuYW1lXCIgY29uZmlndXJhdGlvbmApO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy5vbkNyZWF0ZSgpO1xuICAgIH1cblxuICAgIC8vIGlmIGEgdmVyc2lvbiB1cGRhdGUgaXMgcmVxdWlyZWQsIGlzc3VlIHRoZSB2ZXJzaW9uIHVwZGF0ZVxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZVZlcnNpb24pIHtcbiAgICAgIGlmICghdGhpcy5uZXdQcm9wcy52ZXJzaW9uKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IHJlbW92ZSBjbHVzdGVyIHZlcnNpb24gY29uZmlndXJhdGlvbi4gQ3VycmVudCB2ZXJzaW9uIGlzICR7dGhpcy5vbGRQcm9wcy52ZXJzaW9ufWApO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy51cGRhdGVDbHVzdGVyVmVyc2lvbih0aGlzLm5ld1Byb3BzLnZlcnNpb24pO1xuICAgIH1cblxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUxvZ2dpbmcgfHwgdXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgIGNvbnN0IGNvbmZpZzogYXdzLkVLUy5VcGRhdGVDbHVzdGVyQ29uZmlnUmVxdWVzdCA9IHtcbiAgICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgICAgbG9nZ2luZzogdGhpcy5uZXdQcm9wcy5sb2dnaW5nLFxuICAgICAgfTtcbiAgICAgIGlmICh1cGRhdGVzLnVwZGF0ZUFjY2Vzcykge1xuICAgICAgICAvLyBVcGRhdGluZyB0aGUgY2x1c3RlciB3aXRoIHNlY3VyaXR5R3JvdXBJZHMgYW5kIHN1Ym5ldElkcyAoYXMgc3BlY2lmaWVkIGluIHRoZSB3YXJuaW5nIGhlcmU6XG4gICAgICAgIC8vIGh0dHBzOi8vYXdzY2xpLmFtYXpvbmF3cy5jb20vdjIvZG9jdW1lbnRhdGlvbi9hcGkvbGF0ZXN0L3JlZmVyZW5jZS9la3MvdXBkYXRlLWNsdXN0ZXItY29uZmlnLmh0bWwpXG4gICAgICAgIC8vIHdpbGwgZmFpbCwgdGhlcmVmb3JlIHdlIHRha2Ugb25seSB0aGUgYWNjZXNzIGZpZWxkcyBleHBsaWNpdGx5XG4gICAgICAgIGNvbmZpZy5yZXNvdXJjZXNWcGNDb25maWcgPSB7XG4gICAgICAgICAgZW5kcG9pbnRQcml2YXRlQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MsXG4gICAgICAgICAgZW5kcG9pbnRQdWJsaWNBY2Nlc3M6IHRoaXMubmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzLFxuICAgICAgICAgIHB1YmxpY0FjY2Vzc0NpZHJzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5wdWJsaWNBY2Nlc3NDaWRycyxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MudXBkYXRlQ2x1c3RlckNvbmZpZyhjb25maWcpO1xuXG4gICAgICByZXR1cm4geyBFa3NVcGRhdGVJZDogdXBkYXRlUmVzcG9uc2UudXBkYXRlPy5pZCB9O1xuICAgIH1cblxuICAgIC8vIG5vIHVwZGF0ZXNcbiAgICByZXR1cm47XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNVcGRhdGVDb21wbGV0ZSgpIHtcbiAgICBjb25zb2xlLmxvZygnaXNVcGRhdGVDb21wbGV0ZScpO1xuXG4gICAgLy8gaWYgdGhpcyBpcyBhbiBFS1MgdXBkYXRlLCB3ZSB3aWxsIG1vbml0b3IgdGhlIHVwZGF0ZSBldmVudCBpdHNlbGZcbiAgICBpZiAodGhpcy5ldmVudC5Fa3NVcGRhdGVJZCkge1xuICAgICAgY29uc3QgY29tcGxldGUgPSBhd2FpdCB0aGlzLmlzRWtzVXBkYXRlQ29tcGxldGUodGhpcy5ldmVudC5Fa3NVcGRhdGVJZCk7XG4gICAgICBpZiAoIWNvbXBsZXRlKSB7XG4gICAgICAgIHJldHVybiB7IElzQ29tcGxldGU6IGZhbHNlIH07XG4gICAgICB9XG5cbiAgICAgIC8vIGZhbGwgdGhyb3VnaDogaWYgdGhlIHVwZGF0ZSBpcyBkb25lLCB3ZSBzaW1wbHkgZGVsZWdhdGUgdG8gaXNBY3RpdmUoKVxuICAgICAgLy8gaW4gb3JkZXIgdG8gZXh0cmFjdCBhdHRyaWJ1dGVzIGFuZCBzdGF0ZSBmcm9tIHRoZSBjbHVzdGVyIGl0c2VsZiwgd2hpY2hcbiAgICAgIC8vIGlzIHN1cHBvc2VkIHRvIGJlIGluIGFuIEFDVElWRSBzdGF0ZSBhZnRlciB0aGUgdXBkYXRlIGlzIGNvbXBsZXRlLlxuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmlzQWN0aXZlKCk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHVwZGF0ZUNsdXN0ZXJWZXJzaW9uKG5ld1ZlcnNpb246IHN0cmluZykge1xuICAgIGNvbnNvbGUubG9nKGB1cGRhdGluZyBjbHVzdGVyIHZlcnNpb24gdG8gJHtuZXdWZXJzaW9ufWApO1xuXG4gICAgLy8gdXBkYXRlLWNsdXN0ZXItdmVyc2lvbiB3aWxsIGZhaWwgaWYgd2UgdHJ5IHRvIHVwZGF0ZSB0byB0aGUgc2FtZSB2ZXJzaW9uLFxuICAgIC8vIHNvIHNraXAgaW4gdGhpcyBjYXNlLlxuICAgIGNvbnN0IGNsdXN0ZXIgPSAoYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KSkuY2x1c3RlcjtcbiAgICBpZiAoY2x1c3Rlcj8udmVyc2lvbiA9PT0gbmV3VmVyc2lvbikge1xuICAgICAgY29uc29sZS5sb2coYGNsdXN0ZXIgYWxyZWFkeSBhdCB2ZXJzaW9uICR7Y2x1c3Rlci52ZXJzaW9ufSwgc2tpcHBpbmcgdmVyc2lvbiB1cGRhdGVgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJWZXJzaW9uKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSwgdmVyc2lvbjogbmV3VmVyc2lvbiB9KTtcbiAgICByZXR1cm4geyBFa3NVcGRhdGVJZDogdXBkYXRlUmVzcG9uc2UudXBkYXRlPy5pZCB9O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBpc0FjdGl2ZSgpOiBQcm9taXNlPElzQ29tcGxldGVSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCd3YWl0aW5nIGZvciBjbHVzdGVyIHRvIGJlY29tZSBBQ1RJVkUnKTtcbiAgICBjb25zdCByZXNwID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJlc3VsdDonLCBKU09OLnN0cmluZ2lmeShyZXNwLCB1bmRlZmluZWQsIDIpKTtcbiAgICBjb25zdCBjbHVzdGVyID0gcmVzcC5jbHVzdGVyO1xuXG4gICAgLy8gaWYgY2x1c3RlciBpcyB1bmRlZmluZWQgKHNob3VsZG50IGhhcHBlbikgb3Igc3RhdHVzIGlzIG5vdCBBQ1RJVkUsIHdlIGFyZVxuICAgIC8vIG5vdCBjb21wbGV0ZS4gbm90ZSB0aGF0IHRoZSBjdXN0b20gcmVzb3VyY2UgcHJvdmlkZXIgZnJhbWV3b3JrIGZvcmJpZHNcbiAgICAvLyByZXR1cm5pbmcgYXR0cmlidXRlcyAoRGF0YSkgaWYgaXNDb21wbGV0ZSBpcyBmYWxzZS5cbiAgICBpZiAoY2x1c3Rlcj8uc3RhdHVzID09PSAnRkFJTEVEJykge1xuICAgICAgLy8gbm90IHZlcnkgaW5mb3JtYXRpdmUsIHVuZm9ydHVuYXRlbHkgdGhlIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpbiBhbnkgZXJyb3JcbiAgICAgIC8vIGluZm9ybWF0aW9uIDpcXFxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDbHVzdGVyIGlzIGluIGEgRkFJTEVEIHN0YXR1cycpO1xuICAgIH0gZWxzZSBpZiAoY2x1c3Rlcj8uc3RhdHVzICE9PSAnQUNUSVZFJykge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogZmFsc2UsXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBJc0NvbXBsZXRlOiB0cnVlLFxuICAgICAgICBEYXRhOiB7XG4gICAgICAgICAgTmFtZTogY2x1c3Rlci5uYW1lLFxuICAgICAgICAgIEVuZHBvaW50OiBjbHVzdGVyLmVuZHBvaW50LFxuICAgICAgICAgIEFybjogY2x1c3Rlci5hcm4sXG5cbiAgICAgICAgICAvLyBJTVBPUlRBTlQ6IENGTiBleHBlY3RzIHRoYXQgYXR0cmlidXRlcyB3aWxsICphbHdheXMqIGhhdmUgdmFsdWVzLFxuICAgICAgICAgIC8vIHNvIHJldHVybiBhbiBlbXB0eSBzdHJpbmcgaW4gY2FzZSB0aGUgdmFsdWUgaXMgbm90IGRlZmluZWQuXG4gICAgICAgICAgLy8gT3RoZXJ3aXNlLCBDRk4gd2lsbCB0aHJvdyB3aXRoIGBWZW5kb3IgcmVzcG9uc2UgZG9lc24ndCBjb250YWluXG4gICAgICAgICAgLy8gWFhYWCBrZXlgLlxuXG4gICAgICAgICAgQ2VydGlmaWNhdGVBdXRob3JpdHlEYXRhOiBjbHVzdGVyLmNlcnRpZmljYXRlQXV0aG9yaXR5Py5kYXRhID8/ICcnLFxuICAgICAgICAgIENsdXN0ZXJTZWN1cml0eUdyb3VwSWQ6IGNsdXN0ZXIucmVzb3VyY2VzVnBjQ29uZmlnPy5jbHVzdGVyU2VjdXJpdHlHcm91cElkID8/ICcnLFxuICAgICAgICAgIE9wZW5JZENvbm5lY3RJc3N1ZXJVcmw6IGNsdXN0ZXIuaWRlbnRpdHk/Lm9pZGM/Lmlzc3VlciA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXI/LnN1YnN0cmluZyg4KSA/PyAnJywgLy8gU3RyaXBzIG9mZiBodHRwczovLyBmcm9tIHRoZSBpc3N1ZXIgdXJsXG5cbiAgICAgICAgICAvLyBXZSBjYW4gc2FmZWx5IHJldHVybiB0aGUgZmlyc3QgaXRlbSBmcm9tIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbiBhcnJheSwgYmVjYXVzZSBpdCBoYXMgYSBsaW1pdCBvZiAxIGl0ZW1cbiAgICAgICAgICAvLyBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vZWtzL2xhdGVzdC9BUElSZWZlcmVuY2UvQVBJX0NyZWF0ZUNsdXN0ZXIuaHRtbCNBbWF6b25FS1MtQ3JlYXRlQ2x1c3Rlci1yZXF1ZXN0LWVuY3J5cHRpb25Db25maWdcbiAgICAgICAgICBFbmNyeXB0aW9uQ29uZmlnS2V5QXJuOiBjbHVzdGVyLmVuY3J5cHRpb25Db25maWc/LnNoaWZ0KCk/LnByb3ZpZGVyPy5rZXlBcm4gPz8gJycsXG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNFa3NVcGRhdGVDb21wbGV0ZShla3NVcGRhdGVJZDogc3RyaW5nKSB7XG4gICAgdGhpcy5sb2coeyBpc0Vrc1VwZGF0ZUNvbXBsZXRlOiBla3NVcGRhdGVJZCB9KTtcblxuICAgIGNvbnN0IGRlc2NyaWJlVXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy5kZXNjcmliZVVwZGF0ZSh7XG4gICAgICBuYW1lOiB0aGlzLmNsdXN0ZXJOYW1lLFxuICAgICAgdXBkYXRlSWQ6IGVrc1VwZGF0ZUlkLFxuICAgIH0pO1xuXG4gICAgdGhpcy5sb2coeyBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlIH0pO1xuXG4gICAgaWYgKCFkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmFibGUgdG8gZGVzY3JpYmUgdXBkYXRlIHdpdGggaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuXG4gICAgc3dpdGNoIChkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5zdGF0dXMpIHtcbiAgICAgIGNhc2UgJ0luUHJvZ3Jlc3MnOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBjYXNlICdTdWNjZXNzZnVsJzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlICdGYWlsZWQnOlxuICAgICAgY2FzZSAnQ2FuY2VsbGVkJzpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBjbHVzdGVyIHVwZGF0ZSBpZCBcIiR7ZWtzVXBkYXRlSWR9XCIgZmFpbGVkIHdpdGggZXJyb3JzOiAke0pTT04uc3RyaW5naWZ5KGRlc2NyaWJlVXBkYXRlUmVzcG9uc2UudXBkYXRlLmVycm9ycyl9YCk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHVua25vd24gc3RhdHVzIFwiJHtkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5zdGF0dXN9XCIgZm9yIHVwZGF0ZSBpZCBcIiR7ZWtzVXBkYXRlSWR9XCJgKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGdlbmVyYXRlQ2x1c3Rlck5hbWUoKSB7XG4gICAgY29uc3Qgc3VmZml4ID0gdGhpcy5yZXF1ZXN0SWQucmVwbGFjZSgvLS9nLCAnJyk7IC8vIDMyIGNoYXJzXG4gICAgY29uc3Qgb2Zmc2V0ID0gTUFYX0NMVVNURVJfTkFNRV9MRU4gLSBzdWZmaXgubGVuZ3RoIC0gMTtcbiAgICBjb25zdCBwcmVmaXggPSB0aGlzLmxvZ2ljYWxSZXNvdXJjZUlkLnNsaWNlKDAsIG9mZnNldCA+IDAgPyBvZmZzZXQgOiAwKTtcbiAgICByZXR1cm4gYCR7cHJlZml4fS0ke3N1ZmZpeH1gO1xuICB9XG59XG5cbmZ1bmN0aW9uIHBhcnNlUHJvcHMocHJvcHM6IGFueSk6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3Qge1xuXG4gIGNvbnN0IHBhcnNlZCA9IHByb3BzPy5Db25maWcgPz8ge307XG5cbiAgLy8gdGhpcyBpcyB3ZWlyZCBidXQgdGhlc2UgYm9vbGVhbiBwcm9wZXJ0aWVzIGFyZSBwYXNzZWQgYnkgQ0ZOIGFzIGEgc3RyaW5nLCBhbmQgd2UgbmVlZCB0aGVtIHRvIGJlIGJvb2xlYW5pYyBmb3IgdGhlIFNESy5cbiAgLy8gT3RoZXJ3aXNlIGl0IGZhaWxzIHdpdGggJ1VuZXhwZWN0ZWQgUGFyYW1ldGVyOiBwYXJhbXMucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBpcyBleHBlY3RlZCB0byBiZSBhIGJvb2xlYW4nXG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQcml2YXRlQWNjZXNzKSA9PT0gJ3N0cmluZycpIHtcbiAgICBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9IHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnPy5lbmRwb2ludFB1YmxpY0FjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyA9IHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPT09ICd0cnVlJztcbiAgfVxuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5sb2dnaW5nPy5jbHVzdGVyTG9nZ2luZ1swXS5lbmFibGVkKSA9PT0gJ3N0cmluZycpIHtcbiAgICBwYXJzZWQubG9nZ2luZy5jbHVzdGVyTG9nZ2luZ1swXS5lbmFibGVkID0gcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9PT0gJ3RydWUnO1xuICB9XG5cbiAgcmV0dXJuIHBhcnNlZDtcblxufVxuXG5pbnRlcmZhY2UgVXBkYXRlTWFwIHtcbiAgcmVwbGFjZU5hbWU6IGJvb2xlYW47IC8vIG5hbWVcbiAgcmVwbGFjZVZwYzogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLnN1Ym5ldElkcyBhbmQgc2VjdXJpdHlHcm91cElkc1xuICByZXBsYWNlUm9sZTogYm9vbGVhbjsgLy8gcm9sZUFyblxuXG4gIHVwZGF0ZVZlcnNpb246IGJvb2xlYW47IC8vIHZlcnNpb25cbiAgdXBkYXRlTG9nZ2luZzogYm9vbGVhbjsgLy8gbG9nZ2luZ1xuICB1cGRhdGVFbmNyeXB0aW9uOiBib29sZWFuOyAvLyBlbmNyeXB0aW9uIChjYW5ub3QgYmUgdXBkYXRlZClcbiAgdXBkYXRlQWNjZXNzOiBib29sZWFuOyAvLyByZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzIGFuZCBlbmRwb2ludFB1YmxpY0FjY2Vzc1xufVxuXG5mdW5jdGlvbiBhbmFseXplVXBkYXRlKG9sZFByb3BzOiBQYXJ0aWFsPGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3Q+LCBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdCk6IFVwZGF0ZU1hcCB7XG4gIGNvbnNvbGUubG9nKCdvbGQgcHJvcHM6ICcsIEpTT04uc3RyaW5naWZ5KG9sZFByb3BzKSk7XG4gIGNvbnNvbGUubG9nKCduZXcgcHJvcHM6ICcsIEpTT04uc3RyaW5naWZ5KG5ld1Byb3BzKSk7XG5cbiAgY29uc3QgbmV3VnBjUHJvcHMgPSBuZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcgfHwge307XG4gIGNvbnN0IG9sZFZwY1Byb3BzID0gb2xkUHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuXG4gIGNvbnN0IG9sZFB1YmxpY0FjY2Vzc0NpZHJzID0gbmV3IFNldChvbGRWcGNQcm9wcy5wdWJsaWNBY2Nlc3NDaWRycyA/PyBbXSk7XG4gIGNvbnN0IG5ld1B1YmxpY0FjY2Vzc0NpZHJzID0gbmV3IFNldChuZXdWcGNQcm9wcy5wdWJsaWNBY2Nlc3NDaWRycyA/PyBbXSk7XG4gIGNvbnN0IG5ld0VuYyA9IG5ld1Byb3BzLmVuY3J5cHRpb25Db25maWcgfHwge307XG4gIGNvbnN0IG9sZEVuYyA9IG9sZFByb3BzLmVuY3J5cHRpb25Db25maWcgfHwge307XG5cbiAgcmV0dXJuIHtcbiAgICByZXBsYWNlTmFtZTogbmV3UHJvcHMubmFtZSAhPT0gb2xkUHJvcHMubmFtZSxcbiAgICByZXBsYWNlVnBjOlxuICAgICAgSlNPTi5zdHJpbmdpZnkobmV3VnBjUHJvcHMuc3VibmV0SWRzKSAhPT0gSlNPTi5zdHJpbmdpZnkob2xkVnBjUHJvcHMuc3VibmV0SWRzKSB8fFxuICAgICAgSlNPTi5zdHJpbmdpZnkobmV3VnBjUHJvcHMuc2VjdXJpdHlHcm91cElkcykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFZwY1Byb3BzLnNlY3VyaXR5R3JvdXBJZHMpLFxuICAgIHVwZGF0ZUFjY2VzczpcbiAgICAgIG5ld1ZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQcml2YXRlQWNjZXNzIHx8XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFB1YmxpY0FjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgfHxcbiAgICAgICFzZXRzRXF1YWwobmV3UHVibGljQWNjZXNzQ2lkcnMsIG9sZFB1YmxpY0FjY2Vzc0NpZHJzKSxcbiAgICByZXBsYWNlUm9sZTogbmV3UHJvcHMucm9sZUFybiAhPT0gb2xkUHJvcHMucm9sZUFybixcbiAgICB1cGRhdGVWZXJzaW9uOiBuZXdQcm9wcy52ZXJzaW9uICE9PSBvbGRQcm9wcy52ZXJzaW9uLFxuICAgIHVwZGF0ZUVuY3J5cHRpb246IEpTT04uc3RyaW5naWZ5KG5ld0VuYykgIT09IEpTT04uc3RyaW5naWZ5KG9sZEVuYyksXG4gICAgdXBkYXRlTG9nZ2luZzogSlNPTi5zdHJpbmdpZnkobmV3UHJvcHMubG9nZ2luZykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFByb3BzLmxvZ2dpbmcpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzZXRzRXF1YWwoZmlyc3Q6IFNldDxzdHJpbmc+LCBzZWNvbmQ6IFNldDxzdHJpbmc+KSB7XG4gIHJldHVybiBmaXJzdC5zaXplID09PSBzZWNvbmQuc2l6ZSB8fCBbLi4uZmlyc3RdLmV2ZXJ5KChlOiBzdHJpbmcpID0+IHNlY29uZC5oYXMoZSkpO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.ts deleted file mode 100644 index 0177a7e21b695..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.ts +++ /dev/null @@ -1,338 +0,0 @@ -/* eslint-disable no-console */ - -// eslint-disable-next-line import/no-extraneous-dependencies -import { IsCompleteResponse, OnEventResponse } from '@aws-cdk/custom-resources/lib/provider-framework/types'; -// eslint-disable-next-line import/no-extraneous-dependencies -import * as aws from 'aws-sdk'; -import { EksClient, ResourceEvent, ResourceHandler } from './common'; - -const MAX_CLUSTER_NAME_LEN = 100; - -export class ClusterResourceHandler extends ResourceHandler { - public get clusterName() { - if (!this.physicalResourceId) { - throw new Error('Cannot determine cluster name without physical resource ID'); - } - - return this.physicalResourceId; - } - - private readonly newProps: aws.EKS.CreateClusterRequest; - private readonly oldProps: Partial; - - constructor(eks: EksClient, event: ResourceEvent) { - super(eks, event); - - this.newProps = parseProps(this.event.ResourceProperties); - this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; - } - - // ------ - // CREATE - // ------ - - protected async onCreate(): Promise { - console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); - if (!this.newProps.roleArn) { - throw new Error('"roleArn" is required'); - } - - const clusterName = this.newProps.name || this.generateClusterName(); - - const resp = await this.eks.createCluster({ - ...this.newProps, - name: clusterName, - }); - - if (!resp.cluster) { - throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); - } - - return { - PhysicalResourceId: resp.cluster.name, - }; - } - - protected async isCreateComplete() { - return this.isActive(); - } - - // ------ - // DELETE - // ------ - - protected async onDelete(): Promise { - console.log(`onDelete: deleting cluster ${this.clusterName}`); - try { - await this.eks.deleteCluster({ name: this.clusterName }); - } catch (e) { - if (e.code !== 'ResourceNotFoundException') { - throw e; - } else { - console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); - } - } - return { - PhysicalResourceId: this.clusterName, - }; - } - - protected async isDeleteComplete(): Promise { - console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); - - try { - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); - } catch (e) { - if (e.code === 'ResourceNotFoundException') { - console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); - return { IsComplete: true }; - } - - console.log('describeCluster error:', e); - throw e; - } - - return { - IsComplete: false, - }; - } - - // ------ - // UPDATE - // ------ - - protected async onUpdate() { - const updates = analyzeUpdate(this.oldProps, this.newProps); - console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); - - // updates to encryption config is not supported - if (updates.updateEncryption) { - throw new Error('Cannot update cluster encryption configuration'); - } - - // if there is an update that requires replacement, go ahead and just create - // a new cluster with the new config. The old cluster will automatically be - // deleted by cloudformation upon success. - if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { - - // if we are replacing this cluster and the cluster has an explicit - // physical name, the creation of the new cluster will fail with "there is - // already a cluster with that name". this is a common behavior for - // CloudFormation resources that support specifying a physical name. - if (this.oldProps.name === this.newProps.name && this.oldProps.name) { - throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); - } - - return this.onCreate(); - } - - // if a version update is required, issue the version update - if (updates.updateVersion) { - if (!this.newProps.version) { - throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); - } - - return this.updateClusterVersion(this.newProps.version); - } - - if (updates.updateLogging || updates.updateAccess) { - const config: aws.EKS.UpdateClusterConfigRequest = { - name: this.clusterName, - logging: this.newProps.logging, - }; - if (updates.updateAccess) { - // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: - // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) - // will fail, therefore we take only the access fields explicitly - config.resourcesVpcConfig = { - endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, - endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, - publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, - }; - } - const updateResponse = await this.eks.updateClusterConfig(config); - - return { EksUpdateId: updateResponse.update?.id }; - } - - // no updates - return; - } - - protected async isUpdateComplete() { - console.log('isUpdateComplete'); - - // if this is an EKS update, we will monitor the update event itself - if (this.event.EksUpdateId) { - const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); - if (!complete) { - return { IsComplete: false }; - } - - // fall through: if the update is done, we simply delegate to isActive() - // in order to extract attributes and state from the cluster itself, which - // is supposed to be in an ACTIVE state after the update is complete. - } - - return this.isActive(); - } - - private async updateClusterVersion(newVersion: string) { - console.log(`updating cluster version to ${newVersion}`); - - // update-cluster-version will fail if we try to update to the same version, - // so skip in this case. - const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; - if (cluster?.version === newVersion) { - console.log(`cluster already at version ${cluster.version}, skipping version update`); - return; - } - - const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); - return { EksUpdateId: updateResponse.update?.id }; - } - - private async isActive(): Promise { - console.log('waiting for cluster to become ACTIVE'); - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); - const cluster = resp.cluster; - - // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are - // not complete. note that the custom resource provider framework forbids - // returning attributes (Data) if isComplete is false. - if (cluster?.status === 'FAILED') { - // not very informative, unfortunately the response doesn't contain any error - // information :\ - throw new Error('Cluster is in a FAILED status'); - } else if (cluster?.status !== 'ACTIVE') { - return { - IsComplete: false, - }; - } else { - return { - IsComplete: true, - Data: { - Name: cluster.name, - Endpoint: cluster.endpoint, - Arn: cluster.arn, - - // IMPORTANT: CFN expects that attributes will *always* have values, - // so return an empty string in case the value is not defined. - // Otherwise, CFN will throw with `Vendor response doesn't contain - // XXXX key`. - - CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', - ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', - OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', - OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', // Strips off https:// from the issuer url - - // We can safely return the first item from encryption configuration array, because it has a limit of 1 item - // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig - EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', - }, - }; - } - } - - private async isEksUpdateComplete(eksUpdateId: string) { - this.log({ isEksUpdateComplete: eksUpdateId }); - - const describeUpdateResponse = await this.eks.describeUpdate({ - name: this.clusterName, - updateId: eksUpdateId, - }); - - this.log({ describeUpdateResponse }); - - if (!describeUpdateResponse.update) { - throw new Error(`unable to describe update with id "${eksUpdateId}"`); - } - - switch (describeUpdateResponse.update.status) { - case 'InProgress': - return false; - case 'Successful': - return true; - case 'Failed': - case 'Cancelled': - throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); - default: - throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); - } - } - - private generateClusterName() { - const suffix = this.requestId.replace(/-/g, ''); // 32 chars - const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; - const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); - return `${prefix}-${suffix}`; - } -} - -function parseProps(props: any): aws.EKS.CreateClusterRequest { - - const parsed = props?.Config ?? {}; - - // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. - // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' - - if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; - } - - if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; - } - - if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { - parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; - } - - return parsed; - -} - -interface UpdateMap { - replaceName: boolean; // name - replaceVpc: boolean; // resourcesVpcConfig.subnetIds and securityGroupIds - replaceRole: boolean; // roleArn - - updateVersion: boolean; // version - updateLogging: boolean; // logging - updateEncryption: boolean; // encryption (cannot be updated) - updateAccess: boolean; // resourcesVpcConfig.endpointPrivateAccess and endpointPublicAccess -} - -function analyzeUpdate(oldProps: Partial, newProps: aws.EKS.CreateClusterRequest): UpdateMap { - console.log('old props: ', JSON.stringify(oldProps)); - console.log('new props: ', JSON.stringify(newProps)); - - const newVpcProps = newProps.resourcesVpcConfig || {}; - const oldVpcProps = oldProps.resourcesVpcConfig || {}; - - const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); - const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); - const newEnc = newProps.encryptionConfig || {}; - const oldEnc = oldProps.encryptionConfig || {}; - - return { - replaceName: newProps.name !== oldProps.name, - replaceVpc: - JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), - updateAccess: - newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || - newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || - !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), - replaceRole: newProps.roleArn !== oldProps.roleArn, - updateVersion: newProps.version !== oldProps.version, - updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), - updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), - }; -} - -function setsEqual(first: Set, second: Set) { - return first.size === second.size || [...first].every((e: string) => second.has(e)); -} diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/cfn-response.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/cfn-response.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/cfn-response.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/cfn-response.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/consts.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/consts.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/consts.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/consts.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/framework.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/framework.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/framework.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/framework.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/outbound.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/outbound.js new file mode 100644 index 0000000000000..cc0667d42f0e8 --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/outbound.js @@ -0,0 +1,69 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.httpRequest = exports.invokeFunction = exports.startExecution = void 0; +/* istanbul ignore file */ +const https = require("https"); +// eslint-disable-next-line import/no-extraneous-dependencies +const AWS = require("aws-sdk"); +const FRAMEWORK_HANDLER_TIMEOUT = 900000; // 15 minutes +// In order to honor the overall maximum timeout set for the target process, +// the default 2 minutes from AWS SDK has to be overriden: +// https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html#httpOptions-property +const 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; +let lambda; +async function defaultStartExecution(req) { + if (!sfn) { + sfn = new AWS.StepFunctions(awsSdkConfig); + } + return sfn.startExecution(req).promise(); +} +async function defaultInvokeFunction(req) { + if (!lambda) { + lambda = new AWS.Lambda(awsSdkConfig); + } + try { + /** + * Try an initial invoke. + * + * When you try to invoke a function that is inactive, the invocation fails and Lambda sets + * the function to pending state until the function resources are recreated. + * If Lambda fails to recreate the resources, the function is set to the inactive state. + * + * We're using invoke first because `waitFor` doesn't trigger an inactive function to do anything, + * it just runs `getFunction` and checks the state. + */ + return await lambda.invoke(req).promise(); + } + catch (error) { + /** + * The status of the Lambda function is checked every second for up to 300 seconds. + * Exits the loop on 'Active' state and throws an error on 'Inactive' or 'Failed'. + * + * And now we wait. + */ + await lambda.waitFor('functionActiveV2', { + FunctionName: req.FunctionName, + }).promise(); + return await lambda.invoke(req).promise(); + } +} +exports.startExecution = defaultStartExecution; +exports.invokeFunction = defaultInvokeFunction; +exports.httpRequest = defaultHttpRequest; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3V0Ym91bmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJvdXRib3VuZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwwQkFBMEI7QUFDMUIsK0JBQStCO0FBQy9CLDZEQUE2RDtBQUM3RCwrQkFBK0I7QUFJL0IsTUFBTSx5QkFBeUIsR0FBRyxNQUFNLENBQUMsQ0FBQyxhQUFhO0FBRXZELDRFQUE0RTtBQUM1RSwwREFBMEQ7QUFDMUQsMkZBQTJGO0FBQzNGLE1BQU0sWUFBWSxHQUF5QjtJQUN6QyxXQUFXLEVBQUUsRUFBRSxPQUFPLEVBQUUseUJBQXlCLEVBQUU7Q0FDcEQsQ0FBQztBQUVGLEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxPQUE2QixFQUFFLFlBQW9CO0lBQ25GLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDckMsSUFBSTtZQUNGLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ2hELE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDNUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1NBQ2Y7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNYO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsSUFBSSxHQUFzQixDQUFDO0FBQzNCLElBQUksTUFBa0IsQ0FBQztBQUV2QixLQUFLLFVBQVUscUJBQXFCLENBQUMsR0FBMEM7SUFDN0UsSUFBSSxDQUFDLEdBQUcsRUFBRTtRQUNSLEdBQUcsR0FBRyxJQUFJLEdBQUcsQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUM7S0FDM0M7SUFFRCxPQUFPLEdBQUcsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7QUFDM0MsQ0FBQztBQUVELEtBQUssVUFBVSxxQkFBcUIsQ0FBQyxHQUFpQztJQUNwRSxJQUFJLENBQUMsTUFBTSxFQUFFO1FBQ1gsTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztLQUN2QztJQUVELElBQUk7UUFDRjs7Ozs7Ozs7O1dBU0c7UUFDSCxPQUFPLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztLQUMzQztJQUFDLE9BQU8sS0FBSyxFQUFFO1FBRWQ7Ozs7O1dBS0c7UUFDSCxNQUFNLE1BQU0sQ0FBQyxPQUFPLENBQUMsa0JBQWtCLEVBQUU7WUFDdkMsWUFBWSxFQUFFLEdBQUcsQ0FBQyxZQUFZO1NBQy9CLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNiLE9BQU8sTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDO0tBQzNDO0FBQ0gsQ0FBQztBQUVVLFFBQUEsY0FBYyxHQUFHLHFCQUFxQixDQUFDO0FBQ3ZDLFFBQUEsY0FBYyxHQUFHLHFCQUFxQixDQUFDO0FBQ3ZDLFFBQUEsV0FBVyxHQUFHLGtCQUFrQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogaXN0YW5idWwgaWdub3JlIGZpbGUgKi9cbmltcG9ydCAqIGFzIGh0dHBzIGZyb20gJ2h0dHBzJztcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcbmltcG9ydCAqIGFzIEFXUyBmcm9tICdhd3Mtc2RrJztcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcbmltcG9ydCB0eXBlIHsgQ29uZmlndXJhdGlvbk9wdGlvbnMgfSBmcm9tICdhd3Mtc2RrL2xpYi9jb25maWctYmFzZSc7XG5cbmNvbnN0IEZSQU1FV09SS19IQU5ETEVSX1RJTUVPVVQgPSA5MDAwMDA7IC8vIDE1IG1pbnV0ZXNcblxuLy8gSW4gb3JkZXIgdG8gaG9ub3IgdGhlIG92ZXJhbGwgbWF4aW11bSB0aW1lb3V0IHNldCBmb3IgdGhlIHRhcmdldCBwcm9jZXNzLFxuLy8gdGhlIGRlZmF1bHQgMiBtaW51dGVzIGZyb20gQVdTIFNESyBoYXMgdG8gYmUgb3ZlcnJpZGVuOlxuLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0phdmFTY3JpcHRTREsvbGF0ZXN0L0FXUy9Db25maWcuaHRtbCNodHRwT3B0aW9ucy1wcm9wZXJ0eVxuY29uc3QgYXdzU2RrQ29uZmlnOiBDb25maWd1cmF0aW9uT3B0aW9ucyA9IHtcbiAgaHR0cE9wdGlvbnM6IHsgdGltZW91dDogRlJBTUVXT1JLX0hBTkRMRVJfVElNRU9VVCB9LFxufTtcblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdEh0dHBSZXF1ZXN0KG9wdGlvbnM6IGh0dHBzLlJlcXVlc3RPcHRpb25zLCByZXNwb25zZUJvZHk6IHN0cmluZykge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gaHR0cHMucmVxdWVzdChvcHRpb25zLCByZXNvbHZlKTtcbiAgICAgIHJlcXVlc3Qub24oJ2Vycm9yJywgcmVqZWN0KTtcbiAgICAgIHJlcXVlc3Qud3JpdGUocmVzcG9uc2VCb2R5KTtcbiAgICAgIHJlcXVlc3QuZW5kKCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmVqZWN0KGUpO1xuICAgIH1cbiAgfSk7XG59XG5cbmxldCBzZm46IEFXUy5TdGVwRnVuY3Rpb25zO1xubGV0IGxhbWJkYTogQVdTLkxhbWJkYTtcblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdFN0YXJ0RXhlY3V0aW9uKHJlcTogQVdTLlN0ZXBGdW5jdGlvbnMuU3RhcnRFeGVjdXRpb25JbnB1dCk6IFByb21pc2U8QVdTLlN0ZXBGdW5jdGlvbnMuU3RhcnRFeGVjdXRpb25PdXRwdXQ+IHtcbiAgaWYgKCFzZm4pIHtcbiAgICBzZm4gPSBuZXcgQVdTLlN0ZXBGdW5jdGlvbnMoYXdzU2RrQ29uZmlnKTtcbiAgfVxuXG4gIHJldHVybiBzZm4uc3RhcnRFeGVjdXRpb24ocmVxKS5wcm9taXNlKCk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGRlZmF1bHRJbnZva2VGdW5jdGlvbihyZXE6IEFXUy5MYW1iZGEuSW52b2NhdGlvblJlcXVlc3QpOiBQcm9taXNlPEFXUy5MYW1iZGEuSW52b2NhdGlvblJlc3BvbnNlPiB7XG4gIGlmICghbGFtYmRhKSB7XG4gICAgbGFtYmRhID0gbmV3IEFXUy5MYW1iZGEoYXdzU2RrQ29uZmlnKTtcbiAgfVxuXG4gIHRyeSB7XG4gICAgLyoqXG4gICAgICogVHJ5IGFuIGluaXRpYWwgaW52b2tlLlxuICAgICAqXG4gICAgICogV2hlbiB5b3UgdHJ5IHRvIGludm9rZSBhIGZ1bmN0aW9uIHRoYXQgaXMgaW5hY3RpdmUsIHRoZSBpbnZvY2F0aW9uIGZhaWxzIGFuZCBMYW1iZGEgc2V0c1xuICAgICAqIHRoZSBmdW5jdGlvbiB0byBwZW5kaW5nIHN0YXRlIHVudGlsIHRoZSBmdW5jdGlvbiByZXNvdXJjZXMgYXJlIHJlY3JlYXRlZC5cbiAgICAgKiBJZiBMYW1iZGEgZmFpbHMgdG8gcmVjcmVhdGUgdGhlIHJlc291cmNlcywgdGhlIGZ1bmN0aW9uIGlzIHNldCB0byB0aGUgaW5hY3RpdmUgc3RhdGUuXG4gICAgICpcbiAgICAgKiBXZSdyZSB1c2luZyBpbnZva2UgZmlyc3QgYmVjYXVzZSBgd2FpdEZvcmAgZG9lc24ndCB0cmlnZ2VyIGFuIGluYWN0aXZlIGZ1bmN0aW9uIHRvIGRvIGFueXRoaW5nLFxuICAgICAqIGl0IGp1c3QgcnVucyBgZ2V0RnVuY3Rpb25gIGFuZCBjaGVja3MgdGhlIHN0YXRlLlxuICAgICAqL1xuICAgIHJldHVybiBhd2FpdCBsYW1iZGEuaW52b2tlKHJlcSkucHJvbWlzZSgpO1xuICB9IGNhdGNoIChlcnJvcikge1xuXG4gICAgLyoqXG4gICAgICogVGhlIHN0YXR1cyBvZiB0aGUgTGFtYmRhIGZ1bmN0aW9uIGlzIGNoZWNrZWQgZXZlcnkgc2Vjb25kIGZvciB1cCB0byAzMDAgc2Vjb25kcy5cbiAgICAgKiBFeGl0cyB0aGUgbG9vcCBvbiAnQWN0aXZlJyBzdGF0ZSBhbmQgdGhyb3dzIGFuIGVycm9yIG9uICdJbmFjdGl2ZScgb3IgJ0ZhaWxlZCcuXG4gICAgICpcbiAgICAgKiBBbmQgbm93IHdlIHdhaXQuXG4gICAgICovXG4gICAgYXdhaXQgbGFtYmRhLndhaXRGb3IoJ2Z1bmN0aW9uQWN0aXZlVjInLCB7XG4gICAgICBGdW5jdGlvbk5hbWU6IHJlcS5GdW5jdGlvbk5hbWUsXG4gICAgfSkucHJvbWlzZSgpO1xuICAgIHJldHVybiBhd2FpdCBsYW1iZGEuaW52b2tlKHJlcSkucHJvbWlzZSgpO1xuICB9XG59XG5cbmV4cG9ydCBsZXQgc3RhcnRFeGVjdXRpb24gPSBkZWZhdWx0U3RhcnRFeGVjdXRpb247XG5leHBvcnQgbGV0IGludm9rZUZ1bmN0aW9uID0gZGVmYXVsdEludm9rZUZ1bmN0aW9uO1xuZXhwb3J0IGxldCBodHRwUmVxdWVzdCA9IGRlZmF1bHRIdHRwUmVxdWVzdDtcbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/util.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/util.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/util.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/util.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip index b64a5034e3b6c..13983109fc5f5 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/apply/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/apply/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/get/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/get/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/helm/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py similarity index 99% rename from packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/helm/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py index c9120c1926e03..286976ced219a 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/helm/__init__.py +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py @@ -111,7 +111,7 @@ def get_oci_cmd(repository, version): region = os.environ.get('AWS_REGION', 'us-east-1') cmnd = [ - f"aws ecr-public get-login-password --region {region} | " \ + f"aws ecr-public get-login-password --region us-east-1 | " \ f"helm registry login --username AWS --password-stdin {public_registry['registry']}; helm pull {repository} --version {version} --untar" ] else: diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/index.py b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/index.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/patch/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/patch/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip index a0efa36e0518a..9bf8ba72b34ab 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/aws-cdk-eks-handlers-in-vpc-test.assets.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/aws-cdk-eks-handlers-in-vpc-test.assets.json index 88b044b89c570..8300824360b40 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/aws-cdk-eks-handlers-in-vpc-test.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/aws-cdk-eks-handlers-in-vpc-test.assets.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "files": { "c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064": { "source": { @@ -27,41 +27,41 @@ } } }, - "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517": { + "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee": { "source": { - "path": "asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517", + "path": "asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip", + "objectKey": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037": { + "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585": { "source": { - "path": "asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037", + "path": "asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip", + "objectKey": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33": { + "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8": { "source": { - "path": "asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33", + "path": "asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33.zip", + "objectKey": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -79,7 +79,7 @@ } } }, - "6d7f62a36035930aa6da6f24fbf4411286172b5a5f99993d9ab2f4369c81b1a2": { + "323aaa33e7c7e5096218c737137719a45cde44b8c83992ede9a1b43117904f2f": { "source": { "path": "awscdkekshandlersinvpctestawscdkawseksClusterResourceProvider9260AB35.nested.template.json", "packaging": "file" @@ -87,12 +87,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "6d7f62a36035930aa6da6f24fbf4411286172b5a5f99993d9ab2f4369c81b1a2.json", + "objectKey": "323aaa33e7c7e5096218c737137719a45cde44b8c83992ede9a1b43117904f2f.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "2015781075d1958d38e35d6aa73ec41a436e8fac0587130506c16af31360cfae": { + "5e5f54f81d1d2eea8b9f0e0b3d0e2390f842fce6ab429b22de2c0f940c73d848": { "source": { "path": "awscdkekshandlersinvpctestawscdkawseksKubectlProvider72227111.nested.template.json", "packaging": "file" @@ -100,12 +100,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "2015781075d1958d38e35d6aa73ec41a436e8fac0587130506c16af31360cfae.json", + "objectKey": "5e5f54f81d1d2eea8b9f0e0b3d0e2390f842fce6ab429b22de2c0f940c73d848.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "3a846cfa4f8b5686555d2adcd5c5be678aca9eefb4811ec4eff26d96b83eec49": { + "cee66cbd8f13fe7f54a59d3ca58d1f9ee1c9a6da9cc9c9ca39def97f2cfbf8df": { "source": { "path": "aws-cdk-eks-handlers-in-vpc-test.template.json", "packaging": "file" @@ -113,7 +113,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "3a846cfa4f8b5686555d2adcd5c5be678aca9eefb4811ec4eff26d96b83eec49.json", + "objectKey": "cee66cbd8f13fe7f54a59d3ca58d1f9ee1c9a6da9cc9c9ca39def97f2cfbf8df.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/aws-cdk-eks-handlers-in-vpc-test.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/aws-cdk-eks-handlers-in-vpc-test.template.json index c7b8b666bc232..55a9d735753ef 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/aws-cdk-eks-handlers-in-vpc-test.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/aws-cdk-eks-handlers-in-vpc-test.template.json @@ -934,7 +934,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/6d7f62a36035930aa6da6f24fbf4411286172b5a5f99993d9ab2f4369c81b1a2.json" + "/323aaa33e7c7e5096218c737137719a45cde44b8c83992ede9a1b43117904f2f.json" ] ] }, @@ -984,7 +984,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/2015781075d1958d38e35d6aa73ec41a436e8fac0587130506c16af31360cfae.json" + "/5e5f54f81d1d2eea8b9f0e0b3d0e2390f842fce6ab429b22de2c0f940c73d848.json" ] ] }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/awscdkekshandlersinvpcDefaultTestDeployAssert40766711.assets.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/awscdkekshandlersinvpcDefaultTestDeployAssert40766711.assets.json index 5d3cb077014bb..29df24a1d6130 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/awscdkekshandlersinvpcDefaultTestDeployAssert40766711.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/awscdkekshandlersinvpcDefaultTestDeployAssert40766711.assets.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/awscdkekshandlersinvpctestawscdkawseksClusterResourceProvider9260AB35.nested.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/awscdkekshandlersinvpctestawscdkawseksClusterResourceProvider9260AB35.nested.template.json index 40441cb50de4b..bbf66faafafca 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/awscdkekshandlersinvpctestawscdkawseksClusterResourceProvider9260AB35.nested.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/awscdkekshandlersinvpctestawscdkawseksClusterResourceProvider9260AB35.nested.template.json @@ -101,7 +101,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ @@ -236,7 +236,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ @@ -417,7 +417,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ @@ -600,7 +600,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ @@ -780,7 +780,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/awscdkekshandlersinvpctestawscdkawseksKubectlProvider72227111.nested.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/awscdkekshandlersinvpctestawscdkawseksKubectlProvider72227111.nested.template.json index 7ccac52d0e21d..40b8835cd233e 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/awscdkekshandlersinvpctestawscdkawseksKubectlProvider72227111.nested.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/awscdkekshandlersinvpctestawscdkawseksKubectlProvider72227111.nested.template.json @@ -51,6 +51,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -92,7 +104,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33.zip" + "S3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "Role": { "Fn::GetAtt": [ @@ -238,7 +250,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/cdk.out b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/cdk.out index 8ecc185e9dbee..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"21.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/integ.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/integ.json index 2a4f7c7c3bad9..a2586d100f218 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "testCases": { "aws-cdk-eks-handlers-in-vpc/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/manifest.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/manifest.json index 4678d0be66588..5216ffe4108fe 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "artifacts": { "aws-cdk-eks-handlers-in-vpc-test.assets": { "type": "cdk:asset-manifest", @@ -17,7 +17,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/3a846cfa4f8b5686555d2adcd5c5be678aca9eefb4811ec4eff26d96b83eec49.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/cee66cbd8f13fe7f54a59d3ca58d1f9ee1c9a6da9cc9c9ca39def97f2cfbf8df.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -36,10 +36,7 @@ "/aws-cdk-eks-handlers-in-vpc-test/KubectlLayer/Resource": [ { "type": "aws:cdk:logicalId", - "data": "KubectlLayer600207B5", - "trace": [ - "!!DESTRUCTIVE_CHANGES: WILL_REPLACE" - ] + "data": "KubectlLayer600207B5" } ], "/aws-cdk-eks-handlers-in-vpc-test/EksAllHandlersInVpcStack/DefaultVpc/Resource": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/tree.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/tree.json index 78b73de15c95b..d2ff9f9b1fff1 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/tree.json @@ -62,7 +62,7 @@ }, "constructInfo": { "fqn": "@aws-cdk/lambda-layer-kubectl-v24.KubectlV24Layer", - "version": "2.0.27" + "version": "2.0.100" } }, "EksAllHandlersInVpcStack": { @@ -1017,7 +1017,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "KubectlReadyBarrier": { @@ -1529,7 +1529,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -1766,7 +1766,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -2053,7 +2053,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -2338,7 +2338,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -2620,7 +2620,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -2817,7 +2817,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } } }, @@ -2898,7 +2898,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/6d7f62a36035930aa6da6f24fbf4411286172b5a5f99993d9ab2f4369c81b1a2.json" + "/323aaa33e7c7e5096218c737137719a45cde44b8c83992ede9a1b43117904f2f.json" ] ] }, @@ -2929,7 +2929,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "@aws-cdk--aws-eks.KubectlProvider": { @@ -3006,6 +3006,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -3105,7 +3117,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33.zip" + "s3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "role": { "Fn::GetAtt": [ @@ -3383,7 +3395,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -3527,7 +3539,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/2015781075d1958d38e35d6aa73ec41a436e8fac0587130506c16af31360cfae.json" + "/5e5f54f81d1d2eea8b9f0e0b3d0e2390f842fce6ab429b22de2c0f940c73d848.json" ] ] }, @@ -3570,7 +3582,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "BootstrapVersion": { @@ -3608,7 +3620,7 @@ "path": "aws-cdk-eks-handlers-in-vpc/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "DeployAssert": { @@ -3654,7 +3666,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } } }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/helm/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/helm/__init__.py deleted file mode 100644 index b9a741c8972c4..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/helm/__init__.py +++ /dev/null @@ -1,187 +0,0 @@ -import json -import logging -import os -import re -import subprocess -import shutil -import tempfile -import zipfile -from urllib.parse import urlparse, unquote - -logger = logging.getLogger() -logger.setLevel(logging.INFO) - -# these are coming from the kubectl layer -os.environ['PATH'] = '/opt/helm:/opt/awscli:' + os.environ['PATH'] - -outdir = os.environ.get('TEST_OUTDIR', '/tmp') -kubeconfig = os.path.join(outdir, 'kubeconfig') - -def get_chart_asset_from_url(chart_asset_url): - chart_zip = os.path.join(outdir, 'chart.zip') - shutil.rmtree(chart_zip, ignore_errors=True) - subprocess.check_call(['aws', 's3', 'cp', chart_asset_url, chart_zip]) - chart_dir = os.path.join(outdir, 'chart') - shutil.rmtree(chart_dir, ignore_errors=True) - os.mkdir(chart_dir) - with zipfile.ZipFile(chart_zip, 'r') as zip_ref: - zip_ref.extractall(chart_dir) - return chart_dir - -def helm_handler(event, context): - logger.info(json.dumps(dict(event, ResponseURL='...'))) - - request_type = event['RequestType'] - props = event['ResourceProperties'] - - # resource properties - cluster_name = props['ClusterName'] - role_arn = props['RoleArn'] - release = props['Release'] - chart = props.get('Chart', None) - chart_asset_url = props.get('ChartAssetURL', None) - version = props.get('Version', None) - wait = props.get('Wait', False) - timeout = props.get('Timeout', None) - namespace = props.get('Namespace', None) - create_namespace = props.get('CreateNamespace', None) - repository = props.get('Repository', None) - values_text = props.get('Values', None) - - # "log in" to the cluster - subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig', - '--role-arn', role_arn, - '--name', cluster_name, - '--kubeconfig', kubeconfig - ]) - - if os.path.isfile(kubeconfig): - os.chmod(kubeconfig, 0o600) - - # Write out the values to a file and include them with the install and upgrade - values_file = None - if not request_type == "Delete" and not values_text is None: - values = json.loads(values_text) - values_file = os.path.join(outdir, 'values.yaml') - with open(values_file, "w") as f: - f.write(json.dumps(values, indent=2)) - - if request_type == 'Create' or request_type == 'Update': - # Ensure chart or chart_asset_url are set - if chart == None and chart_asset_url == None: - raise RuntimeError(f'chart or chartAsset must be specified') - - if chart_asset_url != None: - assert(chart==None) - assert(repository==None) - assert(version==None) - if not chart_asset_url.startswith('s3://'): - raise RuntimeError(f'ChartAssetURL must point to as s3 location but is {chart_asset_url}') - # future work: support versions from s3 assets - chart = get_chart_asset_from_url(chart_asset_url) - - if repository is not None and repository.startswith('oci://'): - tmpdir = tempfile.TemporaryDirectory() - chart_dir = get_chart_from_oci(tmpdir.name, release, repository, version) - chart = chart_dir - - helm('upgrade', release, chart, repository, values_file, namespace, version, wait, timeout, create_namespace) - elif request_type == "Delete": - try: - helm('uninstall', release, namespace=namespace, timeout=timeout) - except Exception as e: - logger.info("delete error: %s" % e) - - -def get_oci_cmd(repository, version): - # Generates OCI command based on pattern. Public ECR vs Private ECR are treated differently. - cmnd = [] - private_ecr_pattern = '\d+.dkr.ecr.[a-z]+-[a-z]+-\d.amazonaws.com' - public_ecr = 'public.ecr.aws' - - registry = repository.rsplit('/', 1)[0].replace('oci://', '') - - if re.fullmatch(private_ecr_pattern, registry) is not None: - logger.info("Found AWS private repository") - region = registry.replace('.amazonaws.com', '').split('.')[-1] - cmnd = [ - f"aws ecr get-login-password --region {region} | " \ - f"helm registry login --username AWS --password-stdin {registry}; helm pull {repository} --version {version} --untar" - ] - elif registry.startswith(public_ecr): - logger.info("Found AWS public repository, will use default region as deployment") - region = os.environ.get('AWS_REGION', 'us-east-1') - - cmnd = [ - f"aws ecr-public get-login-password --region {region} | " \ - f"helm registry login --username AWS --password-stdin {public_ecr}; helm pull {repository} --version {version} --untar" - ] - else: - logger.error("OCI repository format not recognized, falling back to helm pull") - cmnd = ['helm', 'pull', repository, '--version', version, '--untar'] - - return cmnd - - -def get_chart_from_oci(tmpdir, release, repository = None, version = None): - - cmnd = get_oci_cmd(repository, version) - - maxAttempts = 3 - retry = maxAttempts - while retry > 0: - try: - logger.info(cmnd) - output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=tmpdir, shell=True) - logger.info(output) - - return os.path.join(tmpdir, release) - except subprocess.CalledProcessError as exc: - output = exc.output - if b'Broken pipe' in output: - retry = retry - 1 - logger.info("Broken pipe, retries left: %s" % retry) - else: - raise Exception(output) - raise Exception(f'Operation failed after {maxAttempts} attempts: {output}') - - -def helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None): - import subprocess - - cmnd = ['helm', verb, release] - if not chart is None: - cmnd.append(chart) - if verb == 'upgrade': - cmnd.append('--install') - if create_namespace: - cmnd.append('--create-namespace') - if not repo is None: - cmnd.extend(['--repo', repo]) - if not file is None: - cmnd.extend(['--values', file]) - if not version is None: - cmnd.extend(['--version', version]) - if not namespace is None: - cmnd.extend(['--namespace', namespace]) - if wait: - cmnd.append('--wait') - if not timeout is None: - cmnd.extend(['--timeout', timeout]) - cmnd.extend(['--kubeconfig', kubeconfig]) - - maxAttempts = 3 - retry = maxAttempts - while retry > 0: - try: - output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir) - logger.info(output) - return - except subprocess.CalledProcessError as exc: - output = exc.output - if b'Broken pipe' in output: - retry = retry - 1 - logger.info("Broken pipe, retries left: %s" % retry) - else: - raise Exception(output) - raise Exception(f'Operation failed after {maxAttempts} attempts: {output}') diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js similarity index 55% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js index 1d08e9d7b865b..c9dc1b8d2c19a 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js @@ -256,8 +256,8 @@ function analyzeUpdate(oldProps, newProps) { const oldEnc = oldProps.encryptionConfig || {}; return { replaceName: newProps.name !== oldProps.name, - replaceVpc: JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), + replaceVpc: JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), @@ -270,4 +270,4 @@ function analyzeUpdate(oldProps, newProps) { function setsEqual(first, second) { return first.size === second.size && [...first].every((e) => second.has(e)); } -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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SSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBa0IsRUFBRSxNQUFtQjtJQUN4RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgRWtzQ2xpZW50LCBSZXNvdXJjZUV2ZW50LCBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX05BTUVfTEVOID0gMTAwO1xuXG5leHBvcnQgY2xhc3MgQ2x1c3RlclJlc291cmNlSGFuZGxlciBleHRlbmRzIFJlc291cmNlSGFuZGxlciB7XG4gIHB1YmxpYyBnZXQgY2x1c3Rlck5hbWUoKSB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZGV0ZXJtaW5lIGNsdXN0ZXIgbmFtZSB3aXRob3V0IHBoeXNpY2FsIHJlc291cmNlIElEJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PjtcblxuICBjb25zdHJ1Y3Rvcihla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICBzdXBlcihla3MsIGV2ZW50KTtcblxuICAgIHRoaXMubmV3UHJvcHMgPSBwYXJzZVByb3BzKHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLm9sZFByb3BzID0gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnID8gcGFyc2VQcm9wcyhldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMpIDoge307XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gQ1JFQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCdvbkNyZWF0ZTogY3JlYXRpbmcgY2x1c3RlciB3aXRoIG9wdGlvbnM6JywgSlNPTi5zdHJpbmdpZnkodGhpcy5uZXdQcm9wcywgdW5kZWZpbmVkLCAyKSk7XG4gICAgaWYgKCF0aGlzLm5ld1Byb3BzLnJvbGVBcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJyb2xlQXJuXCIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyTmFtZSA9IHRoaXMubmV3UHJvcHMubmFtZSB8fCB0aGlzLmdlbmVyYXRlQ2x1c3Rlck5hbWUoKTtcblxuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmVrcy5jcmVhdGVDbHVzdGVyKHtcbiAgICAgIC4uLnRoaXMubmV3UHJvcHMsXG4gICAgICBuYW1lOiBjbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcC5jbHVzdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBjbHVzdGVyICR7Y2x1c3Rlck5hbWV9OiBDcmVhdGVDbHVzdGVyIHJldHVybmVkIHdpdGhvdXQgY2x1c3RlciBpbmZvcm1hdGlvbmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHJlc3AuY2x1c3Rlci5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIERFTEVURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25EZWxldGUoKTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgb25EZWxldGU6IGRlbGV0aW5nIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfWApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVrcy5kZWxldGVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyICR7dGhpcy5jbHVzdGVyTmFtZX0gbm90IGZvdW5kLCBpZGVtcG90ZW50bHkgc3VjY2VlZGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coYGlzRGVsZXRlQ29tcGxldGU6IHdhaXRpbmcgZm9yIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSB0byBiZSBkZWxldGVkYCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJldHVybmVkOicsIEpTT04uc3RyaW5naWZ5KHJlc3AsIHVuZGVmaW5lZCwgMikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICBjb25zb2xlLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgY2x1c3RlciBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0cnVlIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgZXJyb3I6JywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIFVQREFURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IGFuYWx5emVVcGRhdGUodGhpcy5vbGRQcm9wcywgdGhpcy5uZXdQcm9wcyk7XG4gICAgY29uc29sZS5sb2coJ29uVXBkYXRlOicsIEpTT04uc3RyaW5naWZ5KHsgdXBkYXRlcyB9LCB1bmRlZmluZWQsIDIpKTtcblxuICAgIC8vIHVwZGF0ZXMgdG8gZW5jcnlwdGlvbiBjb25maWcgaXMgbm90IHN1cHBvcnRlZFxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUVuY3J5cHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHVwZGF0ZSBjbHVzdGVyIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZXJlIGlzIGFuIHVwZGF0ZSB0aGF0IHJlcXVpcmVzIHJlcGxhY2VtZW50LCBnbyBhaGVhZCBhbmQganVzdCBjcmVhdGVcbiAgICAvLyBhIG5ldyBjbHVzdGVyIHdpdGggdGhlIG5ldyBjb25maWcuIFRoZSBvbGQgY2x1c3RlciB3aWxsIGF1dG9tYXRpY2FsbHkgYmVcbiAgICAvLyBkZWxldGVkIGJ5IGNsb3VkZm9ybWF0aW9uIHVwb24gc3VjY2Vzcy5cbiAgICBpZiAodXBkYXRlcy5yZXBsYWNlTmFtZSB8fCB1cGRhdGVzLnJlcGxhY2VSb2xlIHx8IHVwZGF0ZXMucmVwbGFjZVZwYykge1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgcmVwbGFjaW5nIHRoaXMgY2x1c3RlciBhbmQgdGhlIGNsdXN0ZXIgaGFzIGFuIGV4cGxpY2l0XG4gICAgICAvLyBwaHlzaWNhbCBuYW1lLCB0aGUgY3JlYXRpb24gb2YgdGhlIG5ldyBjbHVzdGVyIHdpbGwgZmFpbCB3aXRoIFwidGhlcmUgaXNcbiAgICAgIC8vIGFscmVhZHkgYSBjbHVzdGVyIHdpdGggdGhhdCBuYW1lXCIuIHRoaXMgaXMgYSBjb21tb24gYmVoYXZpb3IgZm9yXG4gICAgICAvLyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZXMgdGhhdCBzdXBwb3J0IHNwZWNpZnlpbmcgYSBwaHlzaWNhbCBuYW1lLlxuICAgICAgaWYgKHRoaXMub2xkUHJvcHMubmFtZSA9PT0gdGhpcy5uZXdQcm9wcy5uYW1lICYmIHRoaXMub2xkUHJvcHMubmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXBsYWNlIGNsdXN0ZXIgXCIke3RoaXMub2xkUHJvcHMubmFtZX1cIiBzaW5jZSBpdCBoYXMgYW4gZXhwbGljaXQgcGh5c2ljYWwgbmFtZS4gRWl0aGVyIHJlbmFtZSB0aGUgY2x1c3RlciBvciByZW1vdmUgdGhlIFwibmFtZVwiIGNvbmZpZ3VyYXRpb25gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub25DcmVhdGUoKTtcbiAgICB9XG5cbiAgICAvLyBpZiBhIHZlcnNpb24gdXBkYXRlIGlzIHJlcXVpcmVkLCBpc3N1ZSB0aGUgdmVyc2lvbiB1cGRhdGVcbiAgICBpZiAodXBkYXRlcy51cGRhdGVWZXJzaW9uKSB7XG4gICAgICBpZiAoIXRoaXMubmV3UHJvcHMudmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZW1vdmUgY2x1c3RlciB2ZXJzaW9uIGNvbmZpZ3VyYXRpb24uIEN1cnJlbnQgdmVyc2lvbiBpcyAke3RoaXMub2xkUHJvcHMudmVyc2lvbn1gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlQ2x1c3RlclZlcnNpb24odGhpcy5uZXdQcm9wcy52ZXJzaW9uKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nICYmIHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1cGRhdGUgbG9nZ2luZyBhbmQgYWNjZXNzIGF0IHRoZSBzYW1lIHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nIHx8IHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICBjb25zdCBjb25maWc6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QgPSB7XG4gICAgICAgIG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgICB9O1xuICAgICAgaWYgKHVwZGF0ZXMudXBkYXRlTG9nZ2luZykge1xuICAgICAgICBjb25maWcubG9nZ2luZyA9IHRoaXMubmV3UHJvcHMubG9nZ2luZztcbiAgICAgIH07XG4gICAgICBpZiAodXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIGNsdXN0ZXIgd2l0aCBzZWN1cml0eUdyb3VwSWRzIGFuZCBzdWJuZXRJZHMgKGFzIHNwZWNpZmllZCBpbiB0aGUgd2FybmluZyBoZXJlOlxuICAgICAgICAvLyBodHRwczovL2F3c2NsaS5hbWF6b25hd3MuY29tL3YyL2RvY3VtZW50YXRpb24vYXBpL2xhdGVzdC9yZWZlcmVuY2UvZWtzL3VwZGF0ZS1jbHVzdGVyLWNvbmZpZy5odG1sKVxuICAgICAgICAvLyB3aWxsIGZhaWwsIHRoZXJlZm9yZSB3ZSB0YWtlIG9ubHkgdGhlIGFjY2VzcyBmaWVsZHMgZXhwbGljaXRseVxuICAgICAgICBjb25maWcucmVzb3VyY2VzVnBjQ29uZmlnID0ge1xuICAgICAgICAgIGVuZHBvaW50UHJpdmF0ZUFjY2VzczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzLFxuICAgICAgICAgIGVuZHBvaW50UHVibGljQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyxcbiAgICAgICAgICBwdWJsaWNBY2Nlc3NDaWRyczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcucHVibGljQWNjZXNzQ2lkcnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgICB9XG5cbiAgICAvLyBubyB1cGRhdGVzXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc29sZS5sb2coJ2lzVXBkYXRlQ29tcGxldGUnKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYW4gRUtTIHVwZGF0ZSwgd2Ugd2lsbCBtb25pdG9yIHRoZSB1cGRhdGUgZXZlbnQgaXRzZWxmXG4gICAgaWYgKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gYXdhaXQgdGhpcy5pc0Vrc1VwZGF0ZUNvbXBsZXRlKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpO1xuICAgICAgaWYgKCFjb21wbGV0ZSkge1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiBmYWxzZSB9O1xuICAgICAgfVxuXG4gICAgICAvLyBmYWxsIHRocm91Z2g6IGlmIHRoZSB1cGRhdGUgaXMgZG9uZSwgd2Ugc2ltcGx5IGRlbGVnYXRlIHRvIGlzQWN0aXZlKClcbiAgICAgIC8vIGluIG9yZGVyIHRvIGV4dHJhY3QgYXR0cmlidXRlcyBhbmQgc3RhdGUgZnJvbSB0aGUgY2x1c3RlciBpdHNlbGYsIHdoaWNoXG4gICAgICAvLyBpcyBzdXBwb3NlZCB0byBiZSBpbiBhbiBBQ1RJVkUgc3RhdGUgYWZ0ZXIgdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbHVzdGVyVmVyc2lvbihuZXdWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgdXBkYXRpbmcgY2x1c3RlciB2ZXJzaW9uIHRvICR7bmV3VmVyc2lvbn1gKTtcblxuICAgIC8vIHVwZGF0ZS1jbHVzdGVyLXZlcnNpb24gd2lsbCBmYWlsIGlmIHdlIHRyeSB0byB1cGRhdGUgdG8gdGhlIHNhbWUgdmVyc2lvbixcbiAgICAvLyBzbyBza2lwIGluIHRoaXMgY2FzZS5cbiAgICBjb25zdCBjbHVzdGVyID0gKGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSkpLmNsdXN0ZXI7XG4gICAgaWYgKGNsdXN0ZXI/LnZlcnNpb24gPT09IG5ld1ZlcnNpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyIGFscmVhZHkgYXQgdmVyc2lvbiAke2NsdXN0ZXIudmVyc2lvbn0sIHNraXBwaW5nIHZlcnNpb24gdXBkYXRlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy51cGRhdGVDbHVzdGVyVmVyc2lvbih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsIHZlcnNpb246IG5ld1ZlcnNpb24gfSk7XG4gICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNBY3RpdmUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZygnd2FpdGluZyBmb3IgY2x1c3RlciB0byBiZWNvbWUgQUNUSVZFJyk7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciByZXN1bHQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgY29uc3QgY2x1c3RlciA9IHJlc3AuY2x1c3RlcjtcblxuICAgIC8vIGlmIGNsdXN0ZXIgaXMgdW5kZWZpbmVkIChzaG91bGRudCBoYXBwZW4pIG9yIHN0YXR1cyBpcyBub3QgQUNUSVZFLCB3ZSBhcmVcbiAgICAvLyBub3QgY29tcGxldGUuIG5vdGUgdGhhdCB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZyYW1ld29yayBmb3JiaWRzXG4gICAgLy8gcmV0dXJuaW5nIGF0dHJpYnV0ZXMgKERhdGEpIGlmIGlzQ29tcGxldGUgaXMgZmFsc2UuXG4gICAgaWYgKGNsdXN0ZXI/LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgIC8vIG5vdCB2ZXJ5IGluZm9ybWF0aXZlLCB1bmZvcnR1bmF0ZWx5IHRoZSByZXNwb25zZSBkb2Vzbid0IGNvbnRhaW4gYW55IGVycm9yXG4gICAgICAvLyBpbmZvcm1hdGlvbiA6XFxcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2x1c3RlciBpcyBpbiBhIEZBSUxFRCBzdGF0dXMnKTtcbiAgICB9IGVsc2UgaWYgKGNsdXN0ZXI/LnN0YXR1cyAhPT0gJ0FDVElWRScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIE5hbWU6IGNsdXN0ZXIubmFtZSxcbiAgICAgICAgICBFbmRwb2ludDogY2x1c3Rlci5lbmRwb2ludCxcbiAgICAgICAgICBBcm46IGNsdXN0ZXIuYXJuLFxuXG4gICAgICAgICAgLy8gSU1QT1JUQU5UOiBDRk4gZXhwZWN0cyB0aGF0IGF0dHJpYnV0ZXMgd2lsbCAqYWx3YXlzKiBoYXZlIHZhbHVlcyxcbiAgICAgICAgICAvLyBzbyByZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGluIGNhc2UgdGhlIHZhbHVlIGlzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQ0ZOIHdpbGwgdGhyb3cgd2l0aCBgVmVuZG9yIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpblxuICAgICAgICAgIC8vIFhYWFgga2V5YC5cblxuICAgICAgICAgIENlcnRpZmljYXRlQXV0aG9yaXR5RGF0YTogY2x1c3Rlci5jZXJ0aWZpY2F0ZUF1dGhvcml0eT8uZGF0YSA/PyAnJyxcbiAgICAgICAgICBDbHVzdGVyU2VjdXJpdHlHcm91cElkOiBjbHVzdGVyLnJlc291cmNlc1ZwY0NvbmZpZz8uY2x1c3RlclNlY3VyaXR5R3JvdXBJZCA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyVXJsOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXIgPz8gJycsXG4gICAgICAgICAgT3BlbklkQ29ubmVjdElzc3VlcjogY2x1c3Rlci5pZGVudGl0eT8ub2lkYz8uaXNzdWVyPy5zdWJzdHJpbmcoOCkgPz8gJycsIC8vIFN0cmlwcyBvZmYgaHR0cHM6Ly8gZnJvbSB0aGUgaXNzdWVyIHVybFxuXG4gICAgICAgICAgLy8gV2UgY2FuIHNhZmVseSByZXR1cm4gdGhlIGZpcnN0IGl0ZW0gZnJvbSBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gYXJyYXksIGJlY2F1c2UgaXQgaGFzIGEgbGltaXQgb2YgMSBpdGVtXG4gICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vrcy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDbHVzdGVyLmh0bWwjQW1hem9uRUtTLUNyZWF0ZUNsdXN0ZXItcmVxdWVzdC1lbmNyeXB0aW9uQ29uZmlnXG4gICAgICAgICAgRW5jcnlwdGlvbkNvbmZpZ0tleUFybjogY2x1c3Rlci5lbmNyeXB0aW9uQ29uZmlnPy5zaGlmdCgpPy5wcm92aWRlcj8ua2V5QXJuID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzRWtzVXBkYXRlQ29tcGxldGUoZWtzVXBkYXRlSWQ6IHN0cmluZykge1xuICAgIHRoaXMubG9nKHsgaXNFa3NVcGRhdGVDb21wbGV0ZTogZWtzVXBkYXRlSWQgfSk7XG5cbiAgICBjb25zdCBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVVcGRhdGUoe1xuICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgIHVwZGF0ZUlkOiBla3NVcGRhdGVJZCxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nKHsgZGVzY3JpYmVVcGRhdGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5hYmxlIHRvIGRlc2NyaWJlIHVwZGF0ZSB3aXRoIGlkIFwiJHtla3NVcGRhdGVJZH1cImApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzKSB7XG4gICAgICBjYXNlICdJblByb2dyZXNzJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgY2FzZSAnU3VjY2Vzc2Z1bCc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnRmFpbGVkJzpcbiAgICAgIGNhc2UgJ0NhbmNlbGxlZCc6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2x1c3RlciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiIGZhaWxlZCB3aXRoIGVycm9yczogJHtKU09OLnN0cmluZ2lmeShkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5lcnJvcnMpfWApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIHN0YXR1cyBcIiR7ZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzfVwiIGZvciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNsdXN0ZXJOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9DTFVTVEVSX05BTUVfTEVOIC0gc3VmZml4Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5sb2dpY2FsUmVzb3VyY2VJZC5zbGljZSgwLCBvZmZzZXQgPiAwID8gb2Zmc2V0IDogMCk7XG4gICAgcmV0dXJuIGAke3ByZWZpeH0tJHtzdWZmaXh9YDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3BzKHByb3BzOiBhbnkpOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0IHtcblxuICBjb25zdCBwYXJzZWQgPSBwcm9wcz8uQ29uZmlnID8/IHt9O1xuXG4gIC8vIHRoaXMgaXMgd2VpcmQgYnV0IHRoZXNlIGJvb2xlYW4gcHJvcGVydGllcyBhcmUgcGFzc2VkIGJ5IENGTiBhcyBhIHN0cmluZywgYW5kIHdlIG5lZWQgdGhlbSB0byBiZSBib29sZWFuaWMgZm9yIHRoZSBTREsuXG4gIC8vIE90aGVyd2lzZSBpdCBmYWlscyB3aXRoICdVbmV4cGVjdGVkIFBhcmFtZXRlcjogcGFyYW1zLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgaXMgZXhwZWN0ZWQgdG8gYmUgYSBib29sZWFuJ1xuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWc/LmVuZHBvaW50UHJpdmF0ZUFjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9PT0gJ3RydWUnO1xuICB9XG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQdWJsaWNBY2Nlc3MpID09PSAnc3RyaW5nJykge1xuICAgIHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQubG9nZ2luZz8uY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCkgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9IHBhcnNlZC5sb2dnaW5nLmNsdXN0ZXJMb2dnaW5nWzBdLmVuYWJsZWQgPT09ICd0cnVlJztcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQ7XG5cbn1cblxuaW50ZXJmYWNlIFVwZGF0ZU1hcCB7XG4gIHJlcGxhY2VOYW1lOiBib29sZWFuOyAvLyBuYW1lXG4gIHJlcGxhY2VWcGM6IGJvb2xlYW47IC8vIHJlc291cmNlc1ZwY0NvbmZpZy5zdWJuZXRJZHMgYW5kIHNlY3VyaXR5R3JvdXBJZHNcbiAgcmVwbGFjZVJvbGU6IGJvb2xlYW47IC8vIHJvbGVBcm5cblxuICB1cGRhdGVWZXJzaW9uOiBib29sZWFuOyAvLyB2ZXJzaW9uXG4gIHVwZGF0ZUxvZ2dpbmc6IGJvb2xlYW47IC8vIGxvZ2dpbmdcbiAgdXBkYXRlRW5jcnlwdGlvbjogYm9vbGVhbjsgLy8gZW5jcnlwdGlvbiAoY2Fubm90IGJlIHVwZGF0ZWQpXG4gIHVwZGF0ZUFjY2VzczogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBhbmQgZW5kcG9pbnRQdWJsaWNBY2Nlc3Ncbn1cblxuZnVuY3Rpb24gYW5hbHl6ZVVwZGF0ZShvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PiwgbmV3UHJvcHM6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBVcGRhdGVNYXAge1xuICBjb25zb2xlLmxvZygnb2xkIHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShvbGRQcm9wcykpO1xuICBjb25zb2xlLmxvZygnbmV3IHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShuZXdQcm9wcykpO1xuXG4gIGNvbnN0IG5ld1ZwY1Byb3BzID0gbmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRWcGNQcm9wcyA9IG9sZFByb3BzLnJlc291cmNlc1ZwY0NvbmZpZyB8fCB7fTtcblxuICBjb25zdCBvbGRQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQob2xkVnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQobmV3VnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdFbmMgPSBuZXdQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRFbmMgPSBvbGRQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgcmVwbGFjZU5hbWU6IG5ld1Byb3BzLm5hbWUgIT09IG9sZFByb3BzLm5hbWUsXG4gICAgcmVwbGFjZVZwYzpcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnN1Ym5ldElkcykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFZwY1Byb3BzLnN1Ym5ldElkcykgfHxcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnNlY3VyaXR5R3JvdXBJZHMpICE9PSBKU09OLnN0cmluZ2lmeShvbGRWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzKSxcbiAgICB1cGRhdGVBY2Nlc3M6XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgIT09IG9sZFZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyB8fFxuICAgICAgbmV3VnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgIT09IG9sZFZwY1Byb3BzLmVuZHBvaW50UHVibGljQWNjZXNzIHx8XG4gICAgICAhc2V0c0VxdWFsKG5ld1B1YmxpY0FjY2Vzc0NpZHJzLCBvbGRQdWJsaWNBY2Nlc3NDaWRycyksXG4gICAgcmVwbGFjZVJvbGU6IG5ld1Byb3BzLnJvbGVBcm4gIT09IG9sZFByb3BzLnJvbGVBcm4sXG4gICAgdXBkYXRlVmVyc2lvbjogbmV3UHJvcHMudmVyc2lvbiAhPT0gb2xkUHJvcHMudmVyc2lvbixcbiAgICB1cGRhdGVFbmNyeXB0aW9uOiBKU09OLnN0cmluZ2lmeShuZXdFbmMpICE9PSBKU09OLnN0cmluZ2lmeShvbGRFbmMpLFxuICAgIHVwZGF0ZUxvZ2dpbmc6IEpTT04uc3RyaW5naWZ5KG5ld1Byb3BzLmxvZ2dpbmcpICE9PSBKU09OLnN0cmluZ2lmeShvbGRQcm9wcy5sb2dnaW5nKSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gc2V0c0VxdWFsKGZpcnN0OiBTZXQ8c3RyaW5nPiwgc2Vjb25kOiBTZXQ8c3RyaW5nPikge1xuICByZXR1cm4gZmlyc3Quc2l6ZSA9PT0gc2Vjb25kLnNpemUgJiYgWy4uLmZpcnN0XS5ldmVyeSgoZTogc3RyaW5nKSA9PiBzZWNvbmQuaGFzKGUpKTtcbn1cbiJdfQ== \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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LENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztRQUNuRSxhQUFhLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBa0IsRUFBRSxNQUFtQjtJQUN4RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgRWtzQ2xpZW50LCBSZXNvdXJjZUV2ZW50LCBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX05BTUVfTEVOID0gMTAwO1xuXG5leHBvcnQgY2xhc3MgQ2x1c3RlclJlc291cmNlSGFuZGxlciBleHRlbmRzIFJlc291cmNlSGFuZGxlciB7XG4gIHB1YmxpYyBnZXQgY2x1c3Rlck5hbWUoKSB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZGV0ZXJtaW5lIGNsdXN0ZXIgbmFtZSB3aXRob3V0IHBoeXNpY2FsIHJlc291cmNlIElEJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PjtcblxuICBjb25zdHJ1Y3Rvcihla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICBzdXBlcihla3MsIGV2ZW50KTtcblxuICAgIHRoaXMubmV3UHJvcHMgPSBwYXJzZVByb3BzKHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLm9sZFByb3BzID0gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnID8gcGFyc2VQcm9wcyhldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMpIDoge307XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gQ1JFQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCdvbkNyZWF0ZTogY3JlYXRpbmcgY2x1c3RlciB3aXRoIG9wdGlvbnM6JywgSlNPTi5zdHJpbmdpZnkodGhpcy5uZXdQcm9wcywgdW5kZWZpbmVkLCAyKSk7XG4gICAgaWYgKCF0aGlzLm5ld1Byb3BzLnJvbGVBcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJyb2xlQXJuXCIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyTmFtZSA9IHRoaXMubmV3UHJvcHMubmFtZSB8fCB0aGlzLmdlbmVyYXRlQ2x1c3Rlck5hbWUoKTtcblxuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmVrcy5jcmVhdGVDbHVzdGVyKHtcbiAgICAgIC4uLnRoaXMubmV3UHJvcHMsXG4gICAgICBuYW1lOiBjbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcC5jbHVzdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBjbHVzdGVyICR7Y2x1c3Rlck5hbWV9OiBDcmVhdGVDbHVzdGVyIHJldHVybmVkIHdpdGhvdXQgY2x1c3RlciBpbmZvcm1hdGlvbmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHJlc3AuY2x1c3Rlci5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIERFTEVURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25EZWxldGUoKTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgb25EZWxldGU6IGRlbGV0aW5nIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfWApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVrcy5kZWxldGVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyICR7dGhpcy5jbHVzdGVyTmFtZX0gbm90IGZvdW5kLCBpZGVtcG90ZW50bHkgc3VjY2VlZGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coYGlzRGVsZXRlQ29tcGxldGU6IHdhaXRpbmcgZm9yIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSB0byBiZSBkZWxldGVkYCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJldHVybmVkOicsIEpTT04uc3RyaW5naWZ5KHJlc3AsIHVuZGVmaW5lZCwgMikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICBjb25zb2xlLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgY2x1c3RlciBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0cnVlIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgZXJyb3I6JywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIFVQREFURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IGFuYWx5emVVcGRhdGUodGhpcy5vbGRQcm9wcywgdGhpcy5uZXdQcm9wcyk7XG4gICAgY29uc29sZS5sb2coJ29uVXBkYXRlOicsIEpTT04uc3RyaW5naWZ5KHsgdXBkYXRlcyB9LCB1bmRlZmluZWQsIDIpKTtcblxuICAgIC8vIHVwZGF0ZXMgdG8gZW5jcnlwdGlvbiBjb25maWcgaXMgbm90IHN1cHBvcnRlZFxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUVuY3J5cHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHVwZGF0ZSBjbHVzdGVyIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZXJlIGlzIGFuIHVwZGF0ZSB0aGF0IHJlcXVpcmVzIHJlcGxhY2VtZW50LCBnbyBhaGVhZCBhbmQganVzdCBjcmVhdGVcbiAgICAvLyBhIG5ldyBjbHVzdGVyIHdpdGggdGhlIG5ldyBjb25maWcuIFRoZSBvbGQgY2x1c3RlciB3aWxsIGF1dG9tYXRpY2FsbHkgYmVcbiAgICAvLyBkZWxldGVkIGJ5IGNsb3VkZm9ybWF0aW9uIHVwb24gc3VjY2Vzcy5cbiAgICBpZiAodXBkYXRlcy5yZXBsYWNlTmFtZSB8fCB1cGRhdGVzLnJlcGxhY2VSb2xlIHx8IHVwZGF0ZXMucmVwbGFjZVZwYykge1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgcmVwbGFjaW5nIHRoaXMgY2x1c3RlciBhbmQgdGhlIGNsdXN0ZXIgaGFzIGFuIGV4cGxpY2l0XG4gICAgICAvLyBwaHlzaWNhbCBuYW1lLCB0aGUgY3JlYXRpb24gb2YgdGhlIG5ldyBjbHVzdGVyIHdpbGwgZmFpbCB3aXRoIFwidGhlcmUgaXNcbiAgICAgIC8vIGFscmVhZHkgYSBjbHVzdGVyIHdpdGggdGhhdCBuYW1lXCIuIHRoaXMgaXMgYSBjb21tb24gYmVoYXZpb3IgZm9yXG4gICAgICAvLyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZXMgdGhhdCBzdXBwb3J0IHNwZWNpZnlpbmcgYSBwaHlzaWNhbCBuYW1lLlxuICAgICAgaWYgKHRoaXMub2xkUHJvcHMubmFtZSA9PT0gdGhpcy5uZXdQcm9wcy5uYW1lICYmIHRoaXMub2xkUHJvcHMubmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXBsYWNlIGNsdXN0ZXIgXCIke3RoaXMub2xkUHJvcHMubmFtZX1cIiBzaW5jZSBpdCBoYXMgYW4gZXhwbGljaXQgcGh5c2ljYWwgbmFtZS4gRWl0aGVyIHJlbmFtZSB0aGUgY2x1c3RlciBvciByZW1vdmUgdGhlIFwibmFtZVwiIGNvbmZpZ3VyYXRpb25gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub25DcmVhdGUoKTtcbiAgICB9XG5cbiAgICAvLyBpZiBhIHZlcnNpb24gdXBkYXRlIGlzIHJlcXVpcmVkLCBpc3N1ZSB0aGUgdmVyc2lvbiB1cGRhdGVcbiAgICBpZiAodXBkYXRlcy51cGRhdGVWZXJzaW9uKSB7XG4gICAgICBpZiAoIXRoaXMubmV3UHJvcHMudmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZW1vdmUgY2x1c3RlciB2ZXJzaW9uIGNvbmZpZ3VyYXRpb24uIEN1cnJlbnQgdmVyc2lvbiBpcyAke3RoaXMub2xkUHJvcHMudmVyc2lvbn1gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlQ2x1c3RlclZlcnNpb24odGhpcy5uZXdQcm9wcy52ZXJzaW9uKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nICYmIHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1cGRhdGUgbG9nZ2luZyBhbmQgYWNjZXNzIGF0IHRoZSBzYW1lIHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nIHx8IHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICBjb25zdCBjb25maWc6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QgPSB7XG4gICAgICAgIG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgICB9O1xuICAgICAgaWYgKHVwZGF0ZXMudXBkYXRlTG9nZ2luZykge1xuICAgICAgICBjb25maWcubG9nZ2luZyA9IHRoaXMubmV3UHJvcHMubG9nZ2luZztcbiAgICAgIH07XG4gICAgICBpZiAodXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIGNsdXN0ZXIgd2l0aCBzZWN1cml0eUdyb3VwSWRzIGFuZCBzdWJuZXRJZHMgKGFzIHNwZWNpZmllZCBpbiB0aGUgd2FybmluZyBoZXJlOlxuICAgICAgICAvLyBodHRwczovL2F3c2NsaS5hbWF6b25hd3MuY29tL3YyL2RvY3VtZW50YXRpb24vYXBpL2xhdGVzdC9yZWZlcmVuY2UvZWtzL3VwZGF0ZS1jbHVzdGVyLWNvbmZpZy5odG1sKVxuICAgICAgICAvLyB3aWxsIGZhaWwsIHRoZXJlZm9yZSB3ZSB0YWtlIG9ubHkgdGhlIGFjY2VzcyBmaWVsZHMgZXhwbGljaXRseVxuICAgICAgICBjb25maWcucmVzb3VyY2VzVnBjQ29uZmlnID0ge1xuICAgICAgICAgIGVuZHBvaW50UHJpdmF0ZUFjY2VzczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzLFxuICAgICAgICAgIGVuZHBvaW50UHVibGljQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyxcbiAgICAgICAgICBwdWJsaWNBY2Nlc3NDaWRyczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcucHVibGljQWNjZXNzQ2lkcnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgICB9XG5cbiAgICAvLyBubyB1cGRhdGVzXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc29sZS5sb2coJ2lzVXBkYXRlQ29tcGxldGUnKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYW4gRUtTIHVwZGF0ZSwgd2Ugd2lsbCBtb25pdG9yIHRoZSB1cGRhdGUgZXZlbnQgaXRzZWxmXG4gICAgaWYgKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gYXdhaXQgdGhpcy5pc0Vrc1VwZGF0ZUNvbXBsZXRlKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpO1xuICAgICAgaWYgKCFjb21wbGV0ZSkge1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiBmYWxzZSB9O1xuICAgICAgfVxuXG4gICAgICAvLyBmYWxsIHRocm91Z2g6IGlmIHRoZSB1cGRhdGUgaXMgZG9uZSwgd2Ugc2ltcGx5IGRlbGVnYXRlIHRvIGlzQWN0aXZlKClcbiAgICAgIC8vIGluIG9yZGVyIHRvIGV4dHJhY3QgYXR0cmlidXRlcyBhbmQgc3RhdGUgZnJvbSB0aGUgY2x1c3RlciBpdHNlbGYsIHdoaWNoXG4gICAgICAvLyBpcyBzdXBwb3NlZCB0byBiZSBpbiBhbiBBQ1RJVkUgc3RhdGUgYWZ0ZXIgdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbHVzdGVyVmVyc2lvbihuZXdWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgdXBkYXRpbmcgY2x1c3RlciB2ZXJzaW9uIHRvICR7bmV3VmVyc2lvbn1gKTtcblxuICAgIC8vIHVwZGF0ZS1jbHVzdGVyLXZlcnNpb24gd2lsbCBmYWlsIGlmIHdlIHRyeSB0byB1cGRhdGUgdG8gdGhlIHNhbWUgdmVyc2lvbixcbiAgICAvLyBzbyBza2lwIGluIHRoaXMgY2FzZS5cbiAgICBjb25zdCBjbHVzdGVyID0gKGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSkpLmNsdXN0ZXI7XG4gICAgaWYgKGNsdXN0ZXI/LnZlcnNpb24gPT09IG5ld1ZlcnNpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyIGFscmVhZHkgYXQgdmVyc2lvbiAke2NsdXN0ZXIudmVyc2lvbn0sIHNraXBwaW5nIHZlcnNpb24gdXBkYXRlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy51cGRhdGVDbHVzdGVyVmVyc2lvbih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsIHZlcnNpb246IG5ld1ZlcnNpb24gfSk7XG4gICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNBY3RpdmUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZygnd2FpdGluZyBmb3IgY2x1c3RlciB0byBiZWNvbWUgQUNUSVZFJyk7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciByZXN1bHQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgY29uc3QgY2x1c3RlciA9IHJlc3AuY2x1c3RlcjtcblxuICAgIC8vIGlmIGNsdXN0ZXIgaXMgdW5kZWZpbmVkIChzaG91bGRudCBoYXBwZW4pIG9yIHN0YXR1cyBpcyBub3QgQUNUSVZFLCB3ZSBhcmVcbiAgICAvLyBub3QgY29tcGxldGUuIG5vdGUgdGhhdCB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZyYW1ld29yayBmb3JiaWRzXG4gICAgLy8gcmV0dXJuaW5nIGF0dHJpYnV0ZXMgKERhdGEpIGlmIGlzQ29tcGxldGUgaXMgZmFsc2UuXG4gICAgaWYgKGNsdXN0ZXI/LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgIC8vIG5vdCB2ZXJ5IGluZm9ybWF0aXZlLCB1bmZvcnR1bmF0ZWx5IHRoZSByZXNwb25zZSBkb2Vzbid0IGNvbnRhaW4gYW55IGVycm9yXG4gICAgICAvLyBpbmZvcm1hdGlvbiA6XFxcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2x1c3RlciBpcyBpbiBhIEZBSUxFRCBzdGF0dXMnKTtcbiAgICB9IGVsc2UgaWYgKGNsdXN0ZXI/LnN0YXR1cyAhPT0gJ0FDVElWRScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIE5hbWU6IGNsdXN0ZXIubmFtZSxcbiAgICAgICAgICBFbmRwb2ludDogY2x1c3Rlci5lbmRwb2ludCxcbiAgICAgICAgICBBcm46IGNsdXN0ZXIuYXJuLFxuXG4gICAgICAgICAgLy8gSU1QT1JUQU5UOiBDRk4gZXhwZWN0cyB0aGF0IGF0dHJpYnV0ZXMgd2lsbCAqYWx3YXlzKiBoYXZlIHZhbHVlcyxcbiAgICAgICAgICAvLyBzbyByZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGluIGNhc2UgdGhlIHZhbHVlIGlzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQ0ZOIHdpbGwgdGhyb3cgd2l0aCBgVmVuZG9yIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpblxuICAgICAgICAgIC8vIFhYWFgga2V5YC5cblxuICAgICAgICAgIENlcnRpZmljYXRlQXV0aG9yaXR5RGF0YTogY2x1c3Rlci5jZXJ0aWZpY2F0ZUF1dGhvcml0eT8uZGF0YSA/PyAnJyxcbiAgICAgICAgICBDbHVzdGVyU2VjdXJpdHlHcm91cElkOiBjbHVzdGVyLnJlc291cmNlc1ZwY0NvbmZpZz8uY2x1c3RlclNlY3VyaXR5R3JvdXBJZCA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyVXJsOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXIgPz8gJycsXG4gICAgICAgICAgT3BlbklkQ29ubmVjdElzc3VlcjogY2x1c3Rlci5pZGVudGl0eT8ub2lkYz8uaXNzdWVyPy5zdWJzdHJpbmcoOCkgPz8gJycsIC8vIFN0cmlwcyBvZmYgaHR0cHM6Ly8gZnJvbSB0aGUgaXNzdWVyIHVybFxuXG4gICAgICAgICAgLy8gV2UgY2FuIHNhZmVseSByZXR1cm4gdGhlIGZpcnN0IGl0ZW0gZnJvbSBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gYXJyYXksIGJlY2F1c2UgaXQgaGFzIGEgbGltaXQgb2YgMSBpdGVtXG4gICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vrcy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDbHVzdGVyLmh0bWwjQW1hem9uRUtTLUNyZWF0ZUNsdXN0ZXItcmVxdWVzdC1lbmNyeXB0aW9uQ29uZmlnXG4gICAgICAgICAgRW5jcnlwdGlvbkNvbmZpZ0tleUFybjogY2x1c3Rlci5lbmNyeXB0aW9uQ29uZmlnPy5zaGlmdCgpPy5wcm92aWRlcj8ua2V5QXJuID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzRWtzVXBkYXRlQ29tcGxldGUoZWtzVXBkYXRlSWQ6IHN0cmluZykge1xuICAgIHRoaXMubG9nKHsgaXNFa3NVcGRhdGVDb21wbGV0ZTogZWtzVXBkYXRlSWQgfSk7XG5cbiAgICBjb25zdCBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVVcGRhdGUoe1xuICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgIHVwZGF0ZUlkOiBla3NVcGRhdGVJZCxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nKHsgZGVzY3JpYmVVcGRhdGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5hYmxlIHRvIGRlc2NyaWJlIHVwZGF0ZSB3aXRoIGlkIFwiJHtla3NVcGRhdGVJZH1cImApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzKSB7XG4gICAgICBjYXNlICdJblByb2dyZXNzJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgY2FzZSAnU3VjY2Vzc2Z1bCc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnRmFpbGVkJzpcbiAgICAgIGNhc2UgJ0NhbmNlbGxlZCc6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2x1c3RlciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiIGZhaWxlZCB3aXRoIGVycm9yczogJHtKU09OLnN0cmluZ2lmeShkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5lcnJvcnMpfWApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIHN0YXR1cyBcIiR7ZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzfVwiIGZvciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNsdXN0ZXJOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9DTFVTVEVSX05BTUVfTEVOIC0gc3VmZml4Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5sb2dpY2FsUmVzb3VyY2VJZC5zbGljZSgwLCBvZmZzZXQgPiAwID8gb2Zmc2V0IDogMCk7XG4gICAgcmV0dXJuIGAke3ByZWZpeH0tJHtzdWZmaXh9YDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3BzKHByb3BzOiBhbnkpOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0IHtcblxuICBjb25zdCBwYXJzZWQgPSBwcm9wcz8uQ29uZmlnID8/IHt9O1xuXG4gIC8vIHRoaXMgaXMgd2VpcmQgYnV0IHRoZXNlIGJvb2xlYW4gcHJvcGVydGllcyBhcmUgcGFzc2VkIGJ5IENGTiBhcyBhIHN0cmluZywgYW5kIHdlIG5lZWQgdGhlbSB0byBiZSBib29sZWFuaWMgZm9yIHRoZSBTREsuXG4gIC8vIE90aGVyd2lzZSBpdCBmYWlscyB3aXRoICdVbmV4cGVjdGVkIFBhcmFtZXRlcjogcGFyYW1zLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgaXMgZXhwZWN0ZWQgdG8gYmUgYSBib29sZWFuJ1xuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWc/LmVuZHBvaW50UHJpdmF0ZUFjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9PT0gJ3RydWUnO1xuICB9XG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQdWJsaWNBY2Nlc3MpID09PSAnc3RyaW5nJykge1xuICAgIHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQubG9nZ2luZz8uY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCkgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9IHBhcnNlZC5sb2dnaW5nLmNsdXN0ZXJMb2dnaW5nWzBdLmVuYWJsZWQgPT09ICd0cnVlJztcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQ7XG5cbn1cblxuaW50ZXJmYWNlIFVwZGF0ZU1hcCB7XG4gIHJlcGxhY2VOYW1lOiBib29sZWFuOyAvLyBuYW1lXG4gIHJlcGxhY2VWcGM6IGJvb2xlYW47IC8vIHJlc291cmNlc1ZwY0NvbmZpZy5zdWJuZXRJZHMgYW5kIHNlY3VyaXR5R3JvdXBJZHNcbiAgcmVwbGFjZVJvbGU6IGJvb2xlYW47IC8vIHJvbGVBcm5cblxuICB1cGRhdGVWZXJzaW9uOiBib29sZWFuOyAvLyB2ZXJzaW9uXG4gIHVwZGF0ZUxvZ2dpbmc6IGJvb2xlYW47IC8vIGxvZ2dpbmdcbiAgdXBkYXRlRW5jcnlwdGlvbjogYm9vbGVhbjsgLy8gZW5jcnlwdGlvbiAoY2Fubm90IGJlIHVwZGF0ZWQpXG4gIHVwZGF0ZUFjY2VzczogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBhbmQgZW5kcG9pbnRQdWJsaWNBY2Nlc3Ncbn1cblxuZnVuY3Rpb24gYW5hbHl6ZVVwZGF0ZShvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PiwgbmV3UHJvcHM6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBVcGRhdGVNYXAge1xuICBjb25zb2xlLmxvZygnb2xkIHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShvbGRQcm9wcykpO1xuICBjb25zb2xlLmxvZygnbmV3IHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShuZXdQcm9wcykpO1xuXG4gIGNvbnN0IG5ld1ZwY1Byb3BzID0gbmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRWcGNQcm9wcyA9IG9sZFByb3BzLnJlc291cmNlc1ZwY0NvbmZpZyB8fCB7fTtcblxuICBjb25zdCBvbGRQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQob2xkVnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQobmV3VnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdFbmMgPSBuZXdQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRFbmMgPSBvbGRQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgcmVwbGFjZU5hbWU6IG5ld1Byb3BzLm5hbWUgIT09IG9sZFByb3BzLm5hbWUsXG4gICAgcmVwbGFjZVZwYzpcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnN1Ym5ldElkcz8uc29ydCgpKSAhPT0gSlNPTi5zdHJpbmdpZnkob2xkVnBjUHJvcHMuc3VibmV0SWRzPy5zb3J0KCkpIHx8XG4gICAgICBKU09OLnN0cmluZ2lmeShuZXdWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpICE9PSBKU09OLnN0cmluZ2lmeShvbGRWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpLFxuICAgIHVwZGF0ZUFjY2VzczpcbiAgICAgIG5ld1ZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQcml2YXRlQWNjZXNzIHx8XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFB1YmxpY0FjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgfHxcbiAgICAgICFzZXRzRXF1YWwobmV3UHVibGljQWNjZXNzQ2lkcnMsIG9sZFB1YmxpY0FjY2Vzc0NpZHJzKSxcbiAgICByZXBsYWNlUm9sZTogbmV3UHJvcHMucm9sZUFybiAhPT0gb2xkUHJvcHMucm9sZUFybixcbiAgICB1cGRhdGVWZXJzaW9uOiBuZXdQcm9wcy52ZXJzaW9uICE9PSBvbGRQcm9wcy52ZXJzaW9uLFxuICAgIHVwZGF0ZUVuY3J5cHRpb246IEpTT04uc3RyaW5naWZ5KG5ld0VuYykgIT09IEpTT04uc3RyaW5naWZ5KG9sZEVuYyksXG4gICAgdXBkYXRlTG9nZ2luZzogSlNPTi5zdHJpbmdpZnkobmV3UHJvcHMubG9nZ2luZykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFByb3BzLmxvZ2dpbmcpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzZXRzRXF1YWwoZmlyc3Q6IFNldDxzdHJpbmc+LCBzZWNvbmQ6IFNldDxzdHJpbmc+KSB7XG4gIHJldHVybiBmaXJzdC5zaXplID09PSBzZWNvbmQuc2l6ZSAmJiBbLi4uZmlyc3RdLmV2ZXJ5KChlOiBzdHJpbmcpID0+IHNlY29uZC5oYXMoZSkpO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts similarity index 98% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts index e6930b7844d32..4b7fdda6d1dd1 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.ts +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts @@ -326,8 +326,8 @@ function analyzeUpdate(oldProps: Partial, newProps return { replaceName: newProps.name !== oldProps.name, replaceVpc: - JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), + JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip index 593043af0139a..f62fe1e5a06d6 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js deleted file mode 100644 index 70203dcc42f3f..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js +++ /dev/null @@ -1,45 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.httpRequest = exports.invokeFunction = exports.startExecution = void 0; -/* istanbul ignore file */ -const https = require("https"); -// eslint-disable-next-line import/no-extraneous-dependencies -const AWS = require("aws-sdk"); -const FRAMEWORK_HANDLER_TIMEOUT = 900000; // 15 minutes -// In order to honor the overall maximum timeout set for the target process, -// the default 2 minutes from AWS SDK has to be overriden: -// https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html#httpOptions-property -const 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; -let lambda; -async function defaultStartExecution(req) { - if (!sfn) { - sfn = new AWS.StepFunctions(awsSdkConfig); - } - return sfn.startExecution(req).promise(); -} -async function defaultInvokeFunction(req) { - if (!lambda) { - lambda = new AWS.Lambda(awsSdkConfig); - } - return lambda.invoke(req).promise(); -} -exports.startExecution = defaultStartExecution; -exports.invokeFunction = defaultInvokeFunction; -exports.httpRequest = defaultHttpRequest; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3V0Ym91bmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJvdXRib3VuZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwwQkFBMEI7QUFDMUIsK0JBQStCO0FBQy9CLDZEQUE2RDtBQUM3RCwrQkFBK0I7QUFJL0IsTUFBTSx5QkFBeUIsR0FBRyxNQUFNLENBQUMsQ0FBQyxhQUFhO0FBRXZELDRFQUE0RTtBQUM1RSwwREFBMEQ7QUFDMUQsMkZBQTJGO0FBQzNGLE1BQU0sWUFBWSxHQUF5QjtJQUN6QyxXQUFXLEVBQUUsRUFBRSxPQUFPLEVBQUUseUJBQXlCLEVBQUU7Q0FDcEQsQ0FBQztBQUVGLEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxPQUE2QixFQUFFLFlBQW9CO0lBQ25GLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDckMsSUFBSTtZQUNGLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ2hELE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDNUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1NBQ2Y7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNYO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsSUFBSSxHQUFzQixDQUFDO0FBQzNCLElBQUksTUFBa0IsQ0FBQztBQUV2QixLQUFLLFVBQVUscUJBQXFCLENBQUMsR0FBMEM7SUFDN0UsSUFBSSxDQUFDLEdBQUcsRUFBRTtRQUNSLEdBQUcsR0FBRyxJQUFJLEdBQUcsQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUM7S0FDM0M7SUFFRCxPQUFPLEdBQUcsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7QUFDM0MsQ0FBQztBQUVELEtBQUssVUFBVSxxQkFBcUIsQ0FBQyxHQUFpQztJQUNwRSxJQUFJLENBQUMsTUFBTSxFQUFFO1FBQ1gsTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztLQUN2QztJQUVELE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztBQUN0QyxDQUFDO0FBRVUsUUFBQSxjQUFjLEdBQUcscUJBQXFCLENBQUM7QUFDdkMsUUFBQSxjQUFjLEdBQUcscUJBQXFCLENBQUM7QUFDdkMsUUFBQSxXQUFXLEdBQUcsa0JBQWtCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBpc3RhbmJ1bCBpZ25vcmUgZmlsZSAqL1xuaW1wb3J0ICogYXMgaHR0cHMgZnJvbSAnaHR0cHMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgQVdTIGZyb20gJ2F3cy1zZGsnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHR5cGUgeyBDb25maWd1cmF0aW9uT3B0aW9ucyB9IGZyb20gJ2F3cy1zZGsvbGliL2NvbmZpZy1iYXNlJztcblxuY29uc3QgRlJBTUVXT1JLX0hBTkRMRVJfVElNRU9VVCA9IDkwMDAwMDsgLy8gMTUgbWludXRlc1xuXG4vLyBJbiBvcmRlciB0byBob25vciB0aGUgb3ZlcmFsbCBtYXhpbXVtIHRpbWVvdXQgc2V0IGZvciB0aGUgdGFyZ2V0IHByb2Nlc3MsXG4vLyB0aGUgZGVmYXVsdCAyIG1pbnV0ZXMgZnJvbSBBV1MgU0RLIGhhcyB0byBiZSBvdmVycmlkZW46XG4vLyBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTSmF2YVNjcmlwdFNESy9sYXRlc3QvQVdTL0NvbmZpZy5odG1sI2h0dHBPcHRpb25zLXByb3BlcnR5XG5jb25zdCBhd3NTZGtDb25maWc6IENvbmZpZ3VyYXRpb25PcHRpb25zID0ge1xuICBodHRwT3B0aW9uczogeyB0aW1lb3V0OiBGUkFNRVdPUktfSEFORExFUl9USU1FT1VUIH0sXG59O1xuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0SHR0cFJlcXVlc3Qob3B0aW9uczogaHR0cHMuUmVxdWVzdE9wdGlvbnMsIHJlc3BvbnNlQm9keTogc3RyaW5nKSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlcXVlc3QgPSBodHRwcy5yZXF1ZXN0KG9wdGlvbnMsIHJlc29sdmUpO1xuICAgICAgcmVxdWVzdC5vbignZXJyb3InLCByZWplY3QpO1xuICAgICAgcmVxdWVzdC53cml0ZShyZXNwb25zZUJvZHkpO1xuICAgICAgcmVxdWVzdC5lbmQoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZWplY3QoZSk7XG4gICAgfVxuICB9KTtcbn1cblxubGV0IHNmbjogQVdTLlN0ZXBGdW5jdGlvbnM7XG5sZXQgbGFtYmRhOiBBV1MuTGFtYmRhO1xuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0U3RhcnRFeGVjdXRpb24ocmVxOiBBV1MuU3RlcEZ1bmN0aW9ucy5TdGFydEV4ZWN1dGlvbklucHV0KTogUHJvbWlzZTxBV1MuU3RlcEZ1bmN0aW9ucy5TdGFydEV4ZWN1dGlvbk91dHB1dD4ge1xuICBpZiAoIXNmbikge1xuICAgIHNmbiA9IG5ldyBBV1MuU3RlcEZ1bmN0aW9ucyhhd3NTZGtDb25maWcpO1xuICB9XG5cbiAgcmV0dXJuIHNmbi5zdGFydEV4ZWN1dGlvbihyZXEpLnByb21pc2UoKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdEludm9rZUZ1bmN0aW9uKHJlcTogQVdTLkxhbWJkYS5JbnZvY2F0aW9uUmVxdWVzdCk6IFByb21pc2U8QVdTLkxhbWJkYS5JbnZvY2F0aW9uUmVzcG9uc2U+IHtcbiAgaWYgKCFsYW1iZGEpIHtcbiAgICBsYW1iZGEgPSBuZXcgQVdTLkxhbWJkYShhd3NTZGtDb25maWcpO1xuICB9XG5cbiAgcmV0dXJuIGxhbWJkYS5pbnZva2UocmVxKS5wcm9taXNlKCk7XG59XG5cbmV4cG9ydCBsZXQgc3RhcnRFeGVjdXRpb24gPSBkZWZhdWx0U3RhcnRFeGVjdXRpb247XG5leHBvcnQgbGV0IGludm9rZUZ1bmN0aW9uID0gZGVmYXVsdEludm9rZUZ1bmN0aW9uO1xuZXhwb3J0IGxldCBodHRwUmVxdWVzdCA9IGRlZmF1bHRIdHRwUmVxdWVzdDtcbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.js deleted file mode 100644 index 6efe7fd22e321..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.js +++ /dev/null @@ -1,267 +0,0 @@ -"use strict"; -/* eslint-disable no-console */ -Object.defineProperty(exports, "__esModule", { value: true }); -exports.ClusterResourceHandler = void 0; -const common_1 = require("./common"); -const MAX_CLUSTER_NAME_LEN = 100; -class ClusterResourceHandler extends common_1.ResourceHandler { - constructor(eks, event) { - super(eks, event); - this.newProps = parseProps(this.event.ResourceProperties); - this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; - } - get clusterName() { - if (!this.physicalResourceId) { - throw new Error('Cannot determine cluster name without physical resource ID'); - } - return this.physicalResourceId; - } - // ------ - // CREATE - // ------ - async onCreate() { - console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); - if (!this.newProps.roleArn) { - throw new Error('"roleArn" is required'); - } - const clusterName = this.newProps.name || this.generateClusterName(); - const resp = await this.eks.createCluster({ - ...this.newProps, - name: clusterName, - }); - if (!resp.cluster) { - throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); - } - return { - PhysicalResourceId: resp.cluster.name, - }; - } - async isCreateComplete() { - return this.isActive(); - } - // ------ - // DELETE - // ------ - async onDelete() { - console.log(`onDelete: deleting cluster ${this.clusterName}`); - try { - await this.eks.deleteCluster({ name: this.clusterName }); - } - catch (e) { - if (e.code !== 'ResourceNotFoundException') { - throw e; - } - else { - console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); - } - } - return { - PhysicalResourceId: this.clusterName, - }; - } - async isDeleteComplete() { - console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); - try { - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); - } - catch (e) { - if (e.code === 'ResourceNotFoundException') { - console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); - return { IsComplete: true }; - } - console.log('describeCluster error:', e); - throw e; - } - return { - IsComplete: false, - }; - } - // ------ - // UPDATE - // ------ - async onUpdate() { - const updates = analyzeUpdate(this.oldProps, this.newProps); - console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); - // updates to encryption config is not supported - if (updates.updateEncryption) { - throw new Error('Cannot update cluster encryption configuration'); - } - // if there is an update that requires replacement, go ahead and just create - // a new cluster with the new config. The old cluster will automatically be - // deleted by cloudformation upon success. - if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { - // if we are replacing this cluster and the cluster has an explicit - // physical name, the creation of the new cluster will fail with "there is - // already a cluster with that name". this is a common behavior for - // CloudFormation resources that support specifying a physical name. - if (this.oldProps.name === this.newProps.name && this.oldProps.name) { - throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); - } - return this.onCreate(); - } - // if a version update is required, issue the version update - if (updates.updateVersion) { - if (!this.newProps.version) { - throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); - } - return this.updateClusterVersion(this.newProps.version); - } - if (updates.updateLogging || updates.updateAccess) { - const config = { - name: this.clusterName, - logging: this.newProps.logging, - }; - if (updates.updateAccess) { - // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: - // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) - // will fail, therefore we take only the access fields explicitly - config.resourcesVpcConfig = { - endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, - endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, - publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, - }; - } - const updateResponse = await this.eks.updateClusterConfig(config); - return { EksUpdateId: updateResponse.update?.id }; - } - // no updates - return; - } - async isUpdateComplete() { - console.log('isUpdateComplete'); - // if this is an EKS update, we will monitor the update event itself - if (this.event.EksUpdateId) { - const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); - if (!complete) { - return { IsComplete: false }; - } - // fall through: if the update is done, we simply delegate to isActive() - // in order to extract attributes and state from the cluster itself, which - // is supposed to be in an ACTIVE state after the update is complete. - } - return this.isActive(); - } - async updateClusterVersion(newVersion) { - console.log(`updating cluster version to ${newVersion}`); - // update-cluster-version will fail if we try to update to the same version, - // so skip in this case. - const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; - if (cluster?.version === newVersion) { - console.log(`cluster already at version ${cluster.version}, skipping version update`); - return; - } - const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); - return { EksUpdateId: updateResponse.update?.id }; - } - async isActive() { - console.log('waiting for cluster to become ACTIVE'); - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); - const cluster = resp.cluster; - // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are - // not complete. note that the custom resource provider framework forbids - // returning attributes (Data) if isComplete is false. - if (cluster?.status === 'FAILED') { - // not very informative, unfortunately the response doesn't contain any error - // information :\ - throw new Error('Cluster is in a FAILED status'); - } - else if (cluster?.status !== 'ACTIVE') { - return { - IsComplete: false, - }; - } - else { - return { - IsComplete: true, - Data: { - Name: cluster.name, - Endpoint: cluster.endpoint, - Arn: cluster.arn, - // IMPORTANT: CFN expects that attributes will *always* have values, - // so return an empty string in case the value is not defined. - // Otherwise, CFN will throw with `Vendor response doesn't contain - // XXXX key`. - CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', - ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', - OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', - OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', - // We can safely return the first item from encryption configuration array, because it has a limit of 1 item - // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig - EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', - }, - }; - } - } - async isEksUpdateComplete(eksUpdateId) { - this.log({ isEksUpdateComplete: eksUpdateId }); - const describeUpdateResponse = await this.eks.describeUpdate({ - name: this.clusterName, - updateId: eksUpdateId, - }); - this.log({ describeUpdateResponse }); - if (!describeUpdateResponse.update) { - throw new Error(`unable to describe update with id "${eksUpdateId}"`); - } - switch (describeUpdateResponse.update.status) { - case 'InProgress': - return false; - case 'Successful': - return true; - case 'Failed': - case 'Cancelled': - throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); - default: - throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); - } - } - generateClusterName() { - const suffix = this.requestId.replace(/-/g, ''); // 32 chars - const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; - const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); - return `${prefix}-${suffix}`; - } -} -exports.ClusterResourceHandler = ClusterResourceHandler; -function parseProps(props) { - const parsed = props?.Config ?? {}; - // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. - // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' - if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; - } - if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; - } - if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { - parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; - } - return parsed; -} -function analyzeUpdate(oldProps, newProps) { - console.log('old props: ', JSON.stringify(oldProps)); - console.log('new props: ', JSON.stringify(newProps)); - const newVpcProps = newProps.resourcesVpcConfig || {}; - const oldVpcProps = oldProps.resourcesVpcConfig || {}; - const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); - const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); - const newEnc = newProps.encryptionConfig || {}; - const oldEnc = oldProps.encryptionConfig || {}; - return { - replaceName: newProps.name !== oldProps.name, - replaceVpc: JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), - updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || - newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || - !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), - replaceRole: newProps.roleArn !== oldProps.roleArn, - updateVersion: newProps.version !== oldProps.version, - updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), - updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), - }; -} -function setsEqual(first, second) { - return first.size === second.size || [...first].every((e) => second.has(e)); -} -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1FBRXJFLE1BQU0sSUFBSSxHQUFHLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUM7WUFDeEMsR0FBRyxJQUFJLENBQUMsUUFBUTtZQUNoQixJQUFJLEVBQUUsV0FBVztTQUNsQixDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRTtZQUNqQixNQUFNLElBQUksS0FBSyxDQUFDLHVDQUF1QyxXQUFXLHNEQUFzRCxDQUFDLENBQUM7U0FDM0g7UUFFRCxPQUFPO1lBQ0wsa0JBQWtCLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJO1NBQ3RDLENBQUM7S0FDSDtJQUVTLEtBQUssQ0FBQyxnQkFBZ0I7UUFDOUIsT0FBTyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7S0FDeEI7SUFFRCxTQUFTO0lBQ1QsU0FBUztJQUNULFNBQVM7SUFFQyxLQUFLLENBQUMsUUFBUTtRQUN0QixPQUFPLENBQUMsR0FBRyxDQUFDLDhCQUE4QixJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztRQUM5RCxJQUFJO1lBQ0YsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLGFBQWEsQ0FBQyxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztTQUMxRDtRQUFDLE9BQU8sQ0FBQyxFQUFFO1lBQ1YsSUFBSSxDQUFDLENBQUMsSUFBSSxLQUFLLDJCQUEyQixFQUFFO2dCQUMxQyxNQUFNLENBQUMsQ0FBQzthQUNUO2lCQUFNO2dCQUNMLE9BQU8sQ0FBQyxHQUFHLENBQUMsV0FBVyxJQUFJLENBQUMsV0FBVyxvQ0FBb0MsQ0FBQyxDQUFDO2FBQzlFO1NBQ0Y7UUFDRCxPQUFPO1lBQ0wsa0JBQWtCLEVBQUUsSUFBSSxDQUFDLFdBQVc7U0FDckMsQ0FBQztLQUNIO0lBRVMsS0FBSyxDQUFDLGdCQUFnQjtRQUM5QixPQUFPLENBQUMsR0FBRyxDQUFDLHlDQUF5QyxJQUFJLENBQUMsV0FBVyxnQkFBZ0IsQ0FBQyxDQUFDO1FBRXZGLElBQUk7WUFDRixNQUFNLElBQUksR0FBRyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1lBQ3hFLE9BQU8sQ0FBQyxHQUFHLENBQUMsMkJBQTJCLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDOUU7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLElBQUksQ0FBQyxDQUFDLElBQUksS0FBSywyQkFBMkIsRUFBRTtnQkFDMUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxnR0FBZ0csQ0FBQyxDQUFDO2dCQUM5RyxPQUFPLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxDQUFDO2FBQzdCO1lBRUQsT0FBTyxDQUFDLEdBQUcsQ0FBQyx3QkFBd0IsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUN6QyxNQUFNLENBQUMsQ0FBQztTQUNUO1FBRUQsT0FBTztZQUNMLFVBQVUsRUFBRSxLQUFLO1NBQ2xCLENBQUM7S0FDSDtJQUVELFNBQVM7SUFDVCxTQUFTO0lBQ1QsU0FBUztJQUVDLEtBQUssQ0FBQyxRQUFRO1FBQ3RCLE1BQU0sT0FBTyxHQUFHLGFBQWEsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUM1RCxPQUFPLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsT0FBTyxFQUFFLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFcEUsZ0RBQWdEO1FBQ2hELElBQUksT0FBTyxDQUFDLGdCQUFnQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsZ0RBQWdELENBQUMsQ0FBQztTQUNuRTtRQUVELDRFQUE0RTtRQUM1RSwyRUFBMkU7UUFDM0UsMENBQTBDO1FBQzFDLElBQUksT0FBTyxDQUFDLFdBQVcsSUFBSSxPQUFPLENBQUMsV0FBVyxJQUFJLE9BQU8sQ0FBQyxVQUFVLEVBQUU7WUFFcEUsbUVBQW1FO1lBQ25FLDBFQUEwRTtZQUMxRSxtRUFBbUU7WUFDbkUsb0VBQW9FO1lBQ3BFLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEtBQUssSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUU7Z0JBQ25FLE1BQU0sSUFBSSxLQUFLLENBQUMsMkJBQTJCLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSx3R0FBd0csQ0FBQyxDQUFDO2FBQ3hLO1lBRUQsT0FBTyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7U0FDeEI7UUFFRCw0REFBNEQ7UUFDNUQsSUFBSSxPQUFPLENBQUMsYUFBYSxFQUFFO1lBQ3pCLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRTtnQkFDMUIsTUFBTSxJQUFJLEtBQUssQ0FBQyxtRUFBbUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO2FBQzdHO1lBRUQsT0FBTyxJQUFJLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztTQUN6RDtRQUVELElBQUksT0FBTyxDQUFDLGFBQWEsSUFBSSxPQUFPLENBQUMsWUFBWSxFQUFFO1lBQ2pELE1BQU0sTUFBTSxHQUF1QztnQkFDakQsSUFBSSxFQUFFLElBQUksQ0FBQyxXQUFXO2dCQUN0QixPQUFPLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPO2FBQy9CLENBQUM7WUFDRixJQUFJLE9BQU8sQ0FBQyxZQUFZLEVBQUU7Z0JBQ3hCLDhGQUE4RjtnQkFDOUYscUdBQXFHO2dCQUNyRyxpRUFBaUU7Z0JBQ2pFLE1BQU0sQ0FBQyxrQkFBa0IsR0FBRztvQkFDMUIscUJBQXFCLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxrQkFBa0IsQ0FBQyxxQkFBcUI7b0JBQzdFLG9CQUFvQixFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsa0JBQWtCLENBQUMsb0JBQW9CO29CQUMzRSxpQkFBaUIsRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLGtCQUFrQixDQUFDLGlCQUFpQjtpQkFDdEUsQ0FBQzthQUNIO1lBQ0QsTUFBTSxjQUFjLEdBQUcsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLG1CQUFtQixDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBRWxFLE9BQU8sRUFBRSxXQUFXLEVBQUUsY0FBYyxDQUFDLE1BQU0sRUFBRSxFQUFFLEVBQUUsQ0FBQztTQUNuRDtRQUVELGFBQWE7UUFDYixPQUFPO0tBQ1I7SUFFUyxLQUFLLENBQUMsZ0JBQWdCO1FBQzlCLE9BQU8sQ0FBQyxHQUFHLENBQUMsa0JBQWtCLENBQUMsQ0FBQztRQUVoQyxvRUFBb0U7UUFDcEUsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFBRTtZQUMxQixNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBQ3hFLElBQUksQ0FBQyxRQUFRLEVBQUU7Z0JBQ2IsT0FBTyxFQUFFLFVBQVUsRUFBRSxLQUFLLEVBQUUsQ0FBQzthQUM5QjtZQUVELHdFQUF3RTtZQUN4RSwwRUFBMEU7WUFDMUUscUVBQXFFO1NBQ3RFO1FBRUQsT0FBTyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7S0FDeEI7SUFFTyxLQUFLLENBQUMsb0JBQW9CLENBQUMsVUFBa0I7UUFDbkQsT0FBTyxDQUFDLEdBQUcsQ0FBQywrQkFBK0IsVUFBVSxFQUFFLENBQUMsQ0FBQztRQUV6RCw0RUFBNEU7UUFDNUUsd0JBQXdCO1FBQ3hCLE1BQU0sT0FBTyxHQUFHLENBQUMsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQztRQUNyRixJQUFJLE9BQU8sRUFBRSxPQUFPLEtBQUssVUFBVSxFQUFFO1lBQ25DLE9BQU8sQ0FBQyxHQUFHLENBQUMsOEJBQThCLE9BQU8sQ0FBQyxPQUFPLDJCQUEyQixDQUFDLENBQUM7WUFDdEYsT0FBTztTQUNSO1FBRUQsTUFBTSxjQUFjLEdBQUcsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLG9CQUFvQixDQUFDLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxXQUFXLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxDQUFDLENBQUM7UUFDNUcsT0FBTyxFQUFFLFdBQVcsRUFBRSxjQUFjLENBQUMsTUFBTSxFQUFFLEVBQUUsRUFBRSxDQUFDO0tBQ25EO0lBRU8sS0FBSyxDQUFDLFFBQVE7UUFDcEIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxzQ0FBc0MsQ0FBQyxDQUFDO1FBQ3BELE1BQU0sSUFBSSxHQUFHLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxlQUFlLENBQUMsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7UUFDeEUsT0FBTyxDQUFDLEdBQUcsQ0FBQyx5QkFBeUIsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMzRSxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDO1FBRTdCLDRFQUE0RTtRQUM1RSx5RUFBeUU7UUFDekUsc0RBQXNEO1FBQ3RELElBQUksT0FBTyxFQUFFLE1BQU0sS0FBSyxRQUFRLEVBQUU7WUFDaEMsNkVBQTZFO1lBQzdFLGlCQUFpQjtZQUNqQixNQUFNLElBQUksS0FBSyxDQUFDLCtCQUErQixDQUFDLENBQUM7U0FDbEQ7YUFBTSxJQUFJLE9BQU8sRUFBRSxNQUFNLEtBQUssUUFBUSxFQUFFO1lBQ3ZDLE9BQU87Z0JBQ0wsVUFBVSxFQUFFLEtBQUs7YUFDbEIsQ0FBQztTQUNIO2FBQU07WUFDTCxPQUFPO2dCQUNMLFVBQVUsRUFBRSxJQUFJO2dCQUNoQixJQUFJLEVBQUU7b0JBQ0osSUFBSSxFQUFFLE9BQU8sQ0FBQyxJQUFJO29CQUNsQixRQUFRLEVBQUUsT0FBTyxDQUFDLFFBQVE7b0JBQzFCLEdBQUcsRUFBRSxPQUFPLENBQUMsR0FBRztvQkFFaEIsb0VBQW9FO29CQUNwRSw4REFBOEQ7b0JBQzlELGtFQUFrRTtvQkFDbEUsYUFBYTtvQkFFYix3QkFBd0IsRUFBRSxPQUFPLENBQUMsb0JBQW9CLEVBQUUsSUFBSSxJQUFJLEVBQUU7b0JBQ2xFLHNCQUFzQixFQUFFLE9BQU8sQ0FBQyxrQkFBa0IsRUFBRSxzQkFBc0IsSUFBSSxFQUFFO29CQUNoRixzQkFBc0IsRUFBRSxPQUFPLENBQUMsUUFBUSxFQUFFLElBQUksRUFBRSxNQUFNLElBQUksRUFBRTtvQkFDNUQsbUJBQW1CLEVBQUUsT0FBTyxDQUFDLFFBQVEsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFO29CQUV2RSw0R0FBNEc7b0JBQzVHLDhIQUE4SDtvQkFDOUgsc0JBQXNCLEVBQUUsT0FBTyxDQUFDLGdCQUFnQixFQUFFLEtBQUssRUFBRSxFQUFFLFFBQVEsRUFBRSxNQUFNLElBQUksRUFBRTtpQkFDbEY7YUFDRixDQUFDO1NBQ0g7S0FDRjtJQUVPLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxXQUFtQjtRQUNuRCxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsbUJBQW1CLEVBQUUsV0FBVyxFQUFFLENBQUMsQ0FBQztRQUUvQyxNQUFNLHNCQUFzQixHQUFHLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQUM7WUFDM0QsSUFBSSxFQUFFLElBQUksQ0FBQyxXQUFXO1lBQ3RCLFFBQVEsRUFBRSxXQUFXO1NBQ3RCLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxzQkFBc0IsRUFBRSxDQUFDLENBQUM7UUFFckMsSUFBSSxDQUFDLHNCQUFzQixDQUFDLE1BQU0sRUFBRTtZQUNsQyxNQUFNLElBQUksS0FBSyxDQUFDLHNDQUFzQyxXQUFXLEdBQUcsQ0FBQyxDQUFDO1NBQ3ZFO1FBRUQsUUFBUSxzQkFBc0IsQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFO1lBQzVDLEtBQUssWUFBWTtnQkFDZixPQUFPLEtBQUssQ0FBQztZQUNmLEtBQUssWUFBWTtnQkFDZixPQUFPLElBQUksQ0FBQztZQUNkLEtBQUssUUFBUSxDQUFDO1lBQ2QsS0FBSyxXQUFXO2dCQUNkLE1BQU0sSUFBSSxLQUFLLENBQUMsc0JBQXNCLFdBQVcseUJBQXlCLElBQUksQ0FBQyxTQUFTLENBQUMsc0JBQXNCLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUNwSTtnQkFDRSxNQUFNLElBQUksS0FBSyxDQUFDLG1CQUFtQixzQkFBc0IsQ0FBQyxNQUFNLENBQUMsTUFBTSxvQkFBb0IsV0FBVyxHQUFHLENBQUMsQ0FBQztTQUM5RztLQUNGO0lBRU8sbUJBQW1CO1FBQ3pCLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLFdBQVc7UUFDNUQsTUFBTSxNQUFNLEdBQUcsb0JBQW9CLEdBQUcsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7UUFDeEQsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN4RSxPQUFPLEdBQUcsTUFBTSxJQUFJLE1BQU0sRUFBRSxDQUFDO0tBQzlCO0NBQ0Y7QUFyUUQsd0RBcVFDO0FBRUQsU0FBUyxVQUFVLENBQUMsS0FBVTtJQUU1QixNQUFNLE1BQU0sR0FBRyxLQUFLLEVBQUUsTUFBTSxJQUFJLEVBQUUsQ0FBQztJQUVuQywwSEFBMEg7SUFDMUgsOEhBQThIO0lBRTlILElBQUksT0FBTyxDQUFDLE1BQU0sQ0FBQyxrQkFBa0IsRUFBRSxxQkFBcUIsQ0FBQyxLQUFLLFFBQVEsRUFBRTtRQUMxRSxNQUFNLENBQUMsa0JBQWtCLENBQUMscUJBQXFCLEdBQUcsTUFBTSxDQUFDLGtCQUFrQixDQUFDLHFCQUFxQixLQUFLLE1BQU0sQ0FBQztLQUM5RztJQUVELElBQUksT0FBTyxDQUFDLE1BQU0sQ0FBQyxrQkFBa0IsRUFBRSxvQkFBb0IsQ0FBQyxLQUFLLFFBQVEsRUFBRTtRQUN6RSxNQUFNLENBQUMsa0JBQWtCLENBQUMsb0JBQW9CLEdBQUcsTUFBTSxDQUFDLGtCQUFrQixDQUFDLG9CQUFvQixLQUFLLE1BQU0sQ0FBQztLQUM1RztJQUVELElBQUksT0FBTyxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxLQUFLLFFBQVEsRUFBRTtRQUNuRSxNQUFNLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxLQUFLLE1BQU0sQ0FBQztLQUNoRztJQUVELE9BQU8sTUFBTSxDQUFDO0FBRWhCLENBQUM7QUFhRCxTQUFTLGFBQWEsQ0FBQyxRQUErQyxFQUFFLFFBQXNDO0lBQzVHLE9BQU8sQ0FBQyxHQUFHLENBQUMsYUFBYSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztJQUNyRCxPQUFPLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7SUFFckQsTUFBTSxXQUFXLEdBQUcsUUFBUSxDQUFDLGtCQUFrQixJQUFJLEVBQUUsQ0FBQztJQUN0RCxNQUFNLFdBQVcsR0FBRyxRQUFRLENBQUMsa0JBQWtCLElBQUksRUFBRSxDQUFDO0lBRXRELE1BQU0sb0JBQW9CLEdBQUcsSUFBSSxHQUFHLENBQUMsV0FBVyxDQUFDLGlCQUFpQixJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQzFFLE1BQU0sb0JBQW9CLEdBQUcsSUFBSSxHQUFHLENBQUMsV0FBVyxDQUFDLGlCQUFpQixJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQzFFLE1BQU0sTUFBTSxHQUFHLFFBQVEsQ0FBQyxnQkFBZ0IsSUFBSSxFQUFFLENBQUM7SUFDL0MsTUFBTSxNQUFNLEdBQUcsUUFBUSxDQUFDLGdCQUFnQixJQUFJLEVBQUUsQ0FBQztJQUUvQyxPQUFPO1FBQ0wsV0FBVyxFQUFFLFFBQVEsQ0FBQyxJQUFJLEtBQUssUUFBUSxDQUFDLElBQUk7UUFDNUMsVUFBVSxFQUNSLElBQUksQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLFNBQVMsQ0FBQyxLQUFLLElBQUksQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLFNBQVMsQ0FBQztZQUMvRSxJQUFJLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLElBQUksQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLGdCQUFnQixDQUFDO1FBQy9GLFlBQVksRUFDVixXQUFXLENBQUMscUJBQXFCLEtBQUssV0FBVyxDQUFDLHFCQUFxQjtZQUN2RSxXQUFXLENBQUMsb0JBQW9CLEtBQUssV0FBVyxDQUFDLG9CQUFvQjtZQUNyRSxDQUFDLFNBQVMsQ0FBQyxvQkFBb0IsRUFBRSxvQkFBb0IsQ0FBQztRQUN4RCxXQUFXLEVBQUUsUUFBUSxDQUFDLE9BQU8sS0FBSyxRQUFRLENBQUMsT0FBTztRQUNsRCxhQUFhLEVBQUUsUUFBUSxDQUFDLE9BQU8sS0FBSyxRQUFRLENBQUMsT0FBTztRQUNwRCxnQkFBZ0IsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDO1FBQ25FLGFBQWEsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUM7S0FDckYsQ0FBQztBQUNKLENBQUM7QUFFRCxTQUFTLFNBQVMsQ0FBQyxLQUFrQixFQUFFLE1BQW1CO0lBQ3hELE9BQU8sS0FBSyxDQUFDLElBQUksS0FBSyxNQUFNLENBQUMsSUFBSSxJQUFJLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFTLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUN0RixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgbm8tY29uc29sZSAqL1xuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzXG5pbXBvcnQgeyBJc0NvbXBsZXRlUmVzcG9uc2UsIE9uRXZlbnRSZXNwb25zZSB9IGZyb20gJ0Bhd3MtY2RrL2N1c3RvbS1yZXNvdXJjZXMvbGliL3Byb3ZpZGVyLWZyYW1ld29yay90eXBlcyc7XG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzXG5pbXBvcnQgKiBhcyBhd3MgZnJvbSAnYXdzLXNkayc7XG5pbXBvcnQgeyBFa3NDbGllbnQsIFJlc291cmNlRXZlbnQsIFJlc291cmNlSGFuZGxlciB9IGZyb20gJy4vY29tbW9uJztcblxuY29uc3QgTUFYX0NMVVNURVJfTkFNRV9MRU4gPSAxMDA7XG5cbmV4cG9ydCBjbGFzcyBDbHVzdGVyUmVzb3VyY2VIYW5kbGVyIGV4dGVuZHMgUmVzb3VyY2VIYW5kbGVyIHtcbiAgcHVibGljIGdldCBjbHVzdGVyTmFtZSgpIHtcbiAgICBpZiAoIXRoaXMucGh5c2ljYWxSZXNvdXJjZUlkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBkZXRlcm1pbmUgY2x1c3RlciBuYW1lIHdpdGhvdXQgcGh5c2ljYWwgcmVzb3VyY2UgSUQnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5waHlzaWNhbFJlc291cmNlSWQ7XG4gIH1cblxuICBwcml2YXRlIHJlYWRvbmx5IG5ld1Byb3BzOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0O1xuICBwcml2YXRlIHJlYWRvbmx5IG9sZFByb3BzOiBQYXJ0aWFsPGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3Q+O1xuXG4gIGNvbnN0cnVjdG9yKGVrczogRWtzQ2xpZW50LCBldmVudDogUmVzb3VyY2VFdmVudCkge1xuICAgIHN1cGVyKGVrcywgZXZlbnQpO1xuXG4gICAgdGhpcy5uZXdQcm9wcyA9IHBhcnNlUHJvcHModGhpcy5ldmVudC5SZXNvdXJjZVByb3BlcnRpZXMpO1xuICAgIHRoaXMub2xkUHJvcHMgPSBldmVudC5SZXF1ZXN0VHlwZSA9PT0gJ1VwZGF0ZScgPyBwYXJzZVByb3BzKGV2ZW50Lk9sZFJlc291cmNlUHJvcGVydGllcykgOiB7fTtcbiAgfVxuXG4gIC8vIC0tLS0tLVxuICAvLyBDUkVBVEVcbiAgLy8gLS0tLS0tXG5cbiAgcHJvdGVjdGVkIGFzeW5jIG9uQ3JlYXRlKCk6IFByb21pc2U8T25FdmVudFJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coJ29uQ3JlYXRlOiBjcmVhdGluZyBjbHVzdGVyIHdpdGggb3B0aW9uczonLCBKU09OLnN0cmluZ2lmeSh0aGlzLm5ld1Byb3BzLCB1bmRlZmluZWQsIDIpKTtcbiAgICBpZiAoIXRoaXMubmV3UHJvcHMucm9sZUFybikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdcInJvbGVBcm5cIiBpcyByZXF1aXJlZCcpO1xuICAgIH1cblxuICAgIGNvbnN0IGNsdXN0ZXJOYW1lID0gdGhpcy5uZXdQcm9wcy5uYW1lIHx8IHRoaXMuZ2VuZXJhdGVDbHVzdGVyTmFtZSgpO1xuXG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmNyZWF0ZUNsdXN0ZXIoe1xuICAgICAgLi4udGhpcy5uZXdQcm9wcyxcbiAgICAgIG5hbWU6IGNsdXN0ZXJOYW1lLFxuICAgIH0pO1xuXG4gICAgaWYgKCFyZXNwLmNsdXN0ZXIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3Igd2hlbiB0cnlpbmcgdG8gY3JlYXRlIGNsdXN0ZXIgJHtjbHVzdGVyTmFtZX06IENyZWF0ZUNsdXN0ZXIgcmV0dXJuZWQgd2l0aG91dCBjbHVzdGVyIGluZm9ybWF0aW9uYCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogcmVzcC5jbHVzdGVyLm5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0NyZWF0ZUNvbXBsZXRlKCkge1xuICAgIHJldHVybiB0aGlzLmlzQWN0aXZlKCk7XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gREVMRVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkRlbGV0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKGBvbkRlbGV0ZTogZGVsZXRpbmcgY2x1c3RlciAke3RoaXMuY2x1c3Rlck5hbWV9YCk7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuZWtzLmRlbGV0ZUNsdXN0ZXIoeyBuYW1lOiB0aGlzLmNsdXN0ZXJOYW1lIH0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgIT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc29sZS5sb2coYGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSBub3QgZm91bmQsIGlkZW1wb3RlbnRseSBzdWNjZWVkZWRgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICB9O1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzRGVsZXRlQ29tcGxldGUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgaXNEZWxldGVDb21wbGV0ZTogd2FpdGluZyBmb3IgY2x1c3RlciAke3RoaXMuY2x1c3Rlck5hbWV9IHRvIGJlIGRlbGV0ZWRgKTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXNwID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgcmV0dXJuZWQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKGUuY29kZSA9PT0gJ1Jlc291cmNlTm90Rm91bmRFeGNlcHRpb24nKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdyZWNlaXZlZCBSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uLCB0aGlzIG1lYW5zIHRoZSBjbHVzdGVyIGhhcyBiZWVuIGRlbGV0ZWQgKG9yIG5ldmVyIGV4aXN0ZWQpJyk7XG4gICAgICAgIHJldHVybiB7IElzQ29tcGxldGU6IHRydWUgfTtcbiAgICAgIH1cblxuICAgICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciBlcnJvcjonLCBlKTtcbiAgICAgIHRocm93IGU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgIH07XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gVVBEQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvblVwZGF0ZSgpIHtcbiAgICBjb25zdCB1cGRhdGVzID0gYW5hbHl6ZVVwZGF0ZSh0aGlzLm9sZFByb3BzLCB0aGlzLm5ld1Byb3BzKTtcbiAgICBjb25zb2xlLmxvZygnb25VcGRhdGU6JywgSlNPTi5zdHJpbmdpZnkoeyB1cGRhdGVzIH0sIHVuZGVmaW5lZCwgMikpO1xuXG4gICAgLy8gdXBkYXRlcyB0byBlbmNyeXB0aW9uIGNvbmZpZyBpcyBub3Qgc3VwcG9ydGVkXG4gICAgaWYgKHVwZGF0ZXMudXBkYXRlRW5jcnlwdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgdXBkYXRlIGNsdXN0ZXIgZW5jcnlwdGlvbiBjb25maWd1cmF0aW9uJyk7XG4gICAgfVxuXG4gICAgLy8gaWYgdGhlcmUgaXMgYW4gdXBkYXRlIHRoYXQgcmVxdWlyZXMgcmVwbGFjZW1lbnQsIGdvIGFoZWFkIGFuZCBqdXN0IGNyZWF0ZVxuICAgIC8vIGEgbmV3IGNsdXN0ZXIgd2l0aCB0aGUgbmV3IGNvbmZpZy4gVGhlIG9sZCBjbHVzdGVyIHdpbGwgYXV0b21hdGljYWxseSBiZVxuICAgIC8vIGRlbGV0ZWQgYnkgY2xvdWRmb3JtYXRpb24gdXBvbiBzdWNjZXNzLlxuICAgIGlmICh1cGRhdGVzLnJlcGxhY2VOYW1lIHx8IHVwZGF0ZXMucmVwbGFjZVJvbGUgfHwgdXBkYXRlcy5yZXBsYWNlVnBjKSB7XG5cbiAgICAgIC8vIGlmIHdlIGFyZSByZXBsYWNpbmcgdGhpcyBjbHVzdGVyIGFuZCB0aGUgY2x1c3RlciBoYXMgYW4gZXhwbGljaXRcbiAgICAgIC8vIHBoeXNpY2FsIG5hbWUsIHRoZSBjcmVhdGlvbiBvZiB0aGUgbmV3IGNsdXN0ZXIgd2lsbCBmYWlsIHdpdGggXCJ0aGVyZSBpc1xuICAgICAgLy8gYWxyZWFkeSBhIGNsdXN0ZXIgd2l0aCB0aGF0IG5hbWVcIi4gdGhpcyBpcyBhIGNvbW1vbiBiZWhhdmlvciBmb3JcbiAgICAgIC8vIENsb3VkRm9ybWF0aW9uIHJlc291cmNlcyB0aGF0IHN1cHBvcnQgc3BlY2lmeWluZyBhIHBoeXNpY2FsIG5hbWUuXG4gICAgICBpZiAodGhpcy5vbGRQcm9wcy5uYW1lID09PSB0aGlzLm5ld1Byb3BzLm5hbWUgJiYgdGhpcy5vbGRQcm9wcy5uYW1lKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IHJlcGxhY2UgY2x1c3RlciBcIiR7dGhpcy5vbGRQcm9wcy5uYW1lfVwiIHNpbmNlIGl0IGhhcyBhbiBleHBsaWNpdCBwaHlzaWNhbCBuYW1lLiBFaXRoZXIgcmVuYW1lIHRoZSBjbHVzdGVyIG9yIHJlbW92ZSB0aGUgXCJuYW1lXCIgY29uZmlndXJhdGlvbmApO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy5vbkNyZWF0ZSgpO1xuICAgIH1cblxuICAgIC8vIGlmIGEgdmVyc2lvbiB1cGRhdGUgaXMgcmVxdWlyZWQsIGlzc3VlIHRoZSB2ZXJzaW9uIHVwZGF0ZVxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZVZlcnNpb24pIHtcbiAgICAgIGlmICghdGhpcy5uZXdQcm9wcy52ZXJzaW9uKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IHJlbW92ZSBjbHVzdGVyIHZlcnNpb24gY29uZmlndXJhdGlvbi4gQ3VycmVudCB2ZXJzaW9uIGlzICR7dGhpcy5vbGRQcm9wcy52ZXJzaW9ufWApO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy51cGRhdGVDbHVzdGVyVmVyc2lvbih0aGlzLm5ld1Byb3BzLnZlcnNpb24pO1xuICAgIH1cblxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUxvZ2dpbmcgfHwgdXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgIGNvbnN0IGNvbmZpZzogYXdzLkVLUy5VcGRhdGVDbHVzdGVyQ29uZmlnUmVxdWVzdCA9IHtcbiAgICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgICAgbG9nZ2luZzogdGhpcy5uZXdQcm9wcy5sb2dnaW5nLFxuICAgICAgfTtcbiAgICAgIGlmICh1cGRhdGVzLnVwZGF0ZUFjY2Vzcykge1xuICAgICAgICAvLyBVcGRhdGluZyB0aGUgY2x1c3RlciB3aXRoIHNlY3VyaXR5R3JvdXBJZHMgYW5kIHN1Ym5ldElkcyAoYXMgc3BlY2lmaWVkIGluIHRoZSB3YXJuaW5nIGhlcmU6XG4gICAgICAgIC8vIGh0dHBzOi8vYXdzY2xpLmFtYXpvbmF3cy5jb20vdjIvZG9jdW1lbnRhdGlvbi9hcGkvbGF0ZXN0L3JlZmVyZW5jZS9la3MvdXBkYXRlLWNsdXN0ZXItY29uZmlnLmh0bWwpXG4gICAgICAgIC8vIHdpbGwgZmFpbCwgdGhlcmVmb3JlIHdlIHRha2Ugb25seSB0aGUgYWNjZXNzIGZpZWxkcyBleHBsaWNpdGx5XG4gICAgICAgIGNvbmZpZy5yZXNvdXJjZXNWcGNDb25maWcgPSB7XG4gICAgICAgICAgZW5kcG9pbnRQcml2YXRlQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MsXG4gICAgICAgICAgZW5kcG9pbnRQdWJsaWNBY2Nlc3M6IHRoaXMubmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzLFxuICAgICAgICAgIHB1YmxpY0FjY2Vzc0NpZHJzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5wdWJsaWNBY2Nlc3NDaWRycyxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MudXBkYXRlQ2x1c3RlckNvbmZpZyhjb25maWcpO1xuXG4gICAgICByZXR1cm4geyBFa3NVcGRhdGVJZDogdXBkYXRlUmVzcG9uc2UudXBkYXRlPy5pZCB9O1xuICAgIH1cblxuICAgIC8vIG5vIHVwZGF0ZXNcbiAgICByZXR1cm47XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNVcGRhdGVDb21wbGV0ZSgpIHtcbiAgICBjb25zb2xlLmxvZygnaXNVcGRhdGVDb21wbGV0ZScpO1xuXG4gICAgLy8gaWYgdGhpcyBpcyBhbiBFS1MgdXBkYXRlLCB3ZSB3aWxsIG1vbml0b3IgdGhlIHVwZGF0ZSBldmVudCBpdHNlbGZcbiAgICBpZiAodGhpcy5ldmVudC5Fa3NVcGRhdGVJZCkge1xuICAgICAgY29uc3QgY29tcGxldGUgPSBhd2FpdCB0aGlzLmlzRWtzVXBkYXRlQ29tcGxldGUodGhpcy5ldmVudC5Fa3NVcGRhdGVJZCk7XG4gICAgICBpZiAoIWNvbXBsZXRlKSB7XG4gICAgICAgIHJldHVybiB7IElzQ29tcGxldGU6IGZhbHNlIH07XG4gICAgICB9XG5cbiAgICAgIC8vIGZhbGwgdGhyb3VnaDogaWYgdGhlIHVwZGF0ZSBpcyBkb25lLCB3ZSBzaW1wbHkgZGVsZWdhdGUgdG8gaXNBY3RpdmUoKVxuICAgICAgLy8gaW4gb3JkZXIgdG8gZXh0cmFjdCBhdHRyaWJ1dGVzIGFuZCBzdGF0ZSBmcm9tIHRoZSBjbHVzdGVyIGl0c2VsZiwgd2hpY2hcbiAgICAgIC8vIGlzIHN1cHBvc2VkIHRvIGJlIGluIGFuIEFDVElWRSBzdGF0ZSBhZnRlciB0aGUgdXBkYXRlIGlzIGNvbXBsZXRlLlxuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmlzQWN0aXZlKCk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHVwZGF0ZUNsdXN0ZXJWZXJzaW9uKG5ld1ZlcnNpb246IHN0cmluZykge1xuICAgIGNvbnNvbGUubG9nKGB1cGRhdGluZyBjbHVzdGVyIHZlcnNpb24gdG8gJHtuZXdWZXJzaW9ufWApO1xuXG4gICAgLy8gdXBkYXRlLWNsdXN0ZXItdmVyc2lvbiB3aWxsIGZhaWwgaWYgd2UgdHJ5IHRvIHVwZGF0ZSB0byB0aGUgc2FtZSB2ZXJzaW9uLFxuICAgIC8vIHNvIHNraXAgaW4gdGhpcyBjYXNlLlxuICAgIGNvbnN0IGNsdXN0ZXIgPSAoYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KSkuY2x1c3RlcjtcbiAgICBpZiAoY2x1c3Rlcj8udmVyc2lvbiA9PT0gbmV3VmVyc2lvbikge1xuICAgICAgY29uc29sZS5sb2coYGNsdXN0ZXIgYWxyZWFkeSBhdCB2ZXJzaW9uICR7Y2x1c3Rlci52ZXJzaW9ufSwgc2tpcHBpbmcgdmVyc2lvbiB1cGRhdGVgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJWZXJzaW9uKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSwgdmVyc2lvbjogbmV3VmVyc2lvbiB9KTtcbiAgICByZXR1cm4geyBFa3NVcGRhdGVJZDogdXBkYXRlUmVzcG9uc2UudXBkYXRlPy5pZCB9O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBpc0FjdGl2ZSgpOiBQcm9taXNlPElzQ29tcGxldGVSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCd3YWl0aW5nIGZvciBjbHVzdGVyIHRvIGJlY29tZSBBQ1RJVkUnKTtcbiAgICBjb25zdCByZXNwID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJlc3VsdDonLCBKU09OLnN0cmluZ2lmeShyZXNwLCB1bmRlZmluZWQsIDIpKTtcbiAgICBjb25zdCBjbHVzdGVyID0gcmVzcC5jbHVzdGVyO1xuXG4gICAgLy8gaWYgY2x1c3RlciBpcyB1bmRlZmluZWQgKHNob3VsZG50IGhhcHBlbikgb3Igc3RhdHVzIGlzIG5vdCBBQ1RJVkUsIHdlIGFyZVxuICAgIC8vIG5vdCBjb21wbGV0ZS4gbm90ZSB0aGF0IHRoZSBjdXN0b20gcmVzb3VyY2UgcHJvdmlkZXIgZnJhbWV3b3JrIGZvcmJpZHNcbiAgICAvLyByZXR1cm5pbmcgYXR0cmlidXRlcyAoRGF0YSkgaWYgaXNDb21wbGV0ZSBpcyBmYWxzZS5cbiAgICBpZiAoY2x1c3Rlcj8uc3RhdHVzID09PSAnRkFJTEVEJykge1xuICAgICAgLy8gbm90IHZlcnkgaW5mb3JtYXRpdmUsIHVuZm9ydHVuYXRlbHkgdGhlIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpbiBhbnkgZXJyb3JcbiAgICAgIC8vIGluZm9ybWF0aW9uIDpcXFxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDbHVzdGVyIGlzIGluIGEgRkFJTEVEIHN0YXR1cycpO1xuICAgIH0gZWxzZSBpZiAoY2x1c3Rlcj8uc3RhdHVzICE9PSAnQUNUSVZFJykge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogZmFsc2UsXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBJc0NvbXBsZXRlOiB0cnVlLFxuICAgICAgICBEYXRhOiB7XG4gICAgICAgICAgTmFtZTogY2x1c3Rlci5uYW1lLFxuICAgICAgICAgIEVuZHBvaW50OiBjbHVzdGVyLmVuZHBvaW50LFxuICAgICAgICAgIEFybjogY2x1c3Rlci5hcm4sXG5cbiAgICAgICAgICAvLyBJTVBPUlRBTlQ6IENGTiBleHBlY3RzIHRoYXQgYXR0cmlidXRlcyB3aWxsICphbHdheXMqIGhhdmUgdmFsdWVzLFxuICAgICAgICAgIC8vIHNvIHJldHVybiBhbiBlbXB0eSBzdHJpbmcgaW4gY2FzZSB0aGUgdmFsdWUgaXMgbm90IGRlZmluZWQuXG4gICAgICAgICAgLy8gT3RoZXJ3aXNlLCBDRk4gd2lsbCB0aHJvdyB3aXRoIGBWZW5kb3IgcmVzcG9uc2UgZG9lc24ndCBjb250YWluXG4gICAgICAgICAgLy8gWFhYWCBrZXlgLlxuXG4gICAgICAgICAgQ2VydGlmaWNhdGVBdXRob3JpdHlEYXRhOiBjbHVzdGVyLmNlcnRpZmljYXRlQXV0aG9yaXR5Py5kYXRhID8/ICcnLFxuICAgICAgICAgIENsdXN0ZXJTZWN1cml0eUdyb3VwSWQ6IGNsdXN0ZXIucmVzb3VyY2VzVnBjQ29uZmlnPy5jbHVzdGVyU2VjdXJpdHlHcm91cElkID8/ICcnLFxuICAgICAgICAgIE9wZW5JZENvbm5lY3RJc3N1ZXJVcmw6IGNsdXN0ZXIuaWRlbnRpdHk/Lm9pZGM/Lmlzc3VlciA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXI/LnN1YnN0cmluZyg4KSA/PyAnJywgLy8gU3RyaXBzIG9mZiBodHRwczovLyBmcm9tIHRoZSBpc3N1ZXIgdXJsXG5cbiAgICAgICAgICAvLyBXZSBjYW4gc2FmZWx5IHJldHVybiB0aGUgZmlyc3QgaXRlbSBmcm9tIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbiBhcnJheSwgYmVjYXVzZSBpdCBoYXMgYSBsaW1pdCBvZiAxIGl0ZW1cbiAgICAgICAgICAvLyBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vZWtzL2xhdGVzdC9BUElSZWZlcmVuY2UvQVBJX0NyZWF0ZUNsdXN0ZXIuaHRtbCNBbWF6b25FS1MtQ3JlYXRlQ2x1c3Rlci1yZXF1ZXN0LWVuY3J5cHRpb25Db25maWdcbiAgICAgICAgICBFbmNyeXB0aW9uQ29uZmlnS2V5QXJuOiBjbHVzdGVyLmVuY3J5cHRpb25Db25maWc/LnNoaWZ0KCk/LnByb3ZpZGVyPy5rZXlBcm4gPz8gJycsXG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNFa3NVcGRhdGVDb21wbGV0ZShla3NVcGRhdGVJZDogc3RyaW5nKSB7XG4gICAgdGhpcy5sb2coeyBpc0Vrc1VwZGF0ZUNvbXBsZXRlOiBla3NVcGRhdGVJZCB9KTtcblxuICAgIGNvbnN0IGRlc2NyaWJlVXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy5kZXNjcmliZVVwZGF0ZSh7XG4gICAgICBuYW1lOiB0aGlzLmNsdXN0ZXJOYW1lLFxuICAgICAgdXBkYXRlSWQ6IGVrc1VwZGF0ZUlkLFxuICAgIH0pO1xuXG4gICAgdGhpcy5sb2coeyBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlIH0pO1xuXG4gICAgaWYgKCFkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmFibGUgdG8gZGVzY3JpYmUgdXBkYXRlIHdpdGggaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuXG4gICAgc3dpdGNoIChkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5zdGF0dXMpIHtcbiAgICAgIGNhc2UgJ0luUHJvZ3Jlc3MnOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBjYXNlICdTdWNjZXNzZnVsJzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlICdGYWlsZWQnOlxuICAgICAgY2FzZSAnQ2FuY2VsbGVkJzpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBjbHVzdGVyIHVwZGF0ZSBpZCBcIiR7ZWtzVXBkYXRlSWR9XCIgZmFpbGVkIHdpdGggZXJyb3JzOiAke0pTT04uc3RyaW5naWZ5KGRlc2NyaWJlVXBkYXRlUmVzcG9uc2UudXBkYXRlLmVycm9ycyl9YCk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHVua25vd24gc3RhdHVzIFwiJHtkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5zdGF0dXN9XCIgZm9yIHVwZGF0ZSBpZCBcIiR7ZWtzVXBkYXRlSWR9XCJgKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGdlbmVyYXRlQ2x1c3Rlck5hbWUoKSB7XG4gICAgY29uc3Qgc3VmZml4ID0gdGhpcy5yZXF1ZXN0SWQucmVwbGFjZSgvLS9nLCAnJyk7IC8vIDMyIGNoYXJzXG4gICAgY29uc3Qgb2Zmc2V0ID0gTUFYX0NMVVNURVJfTkFNRV9MRU4gLSBzdWZmaXgubGVuZ3RoIC0gMTtcbiAgICBjb25zdCBwcmVmaXggPSB0aGlzLmxvZ2ljYWxSZXNvdXJjZUlkLnNsaWNlKDAsIG9mZnNldCA+IDAgPyBvZmZzZXQgOiAwKTtcbiAgICByZXR1cm4gYCR7cHJlZml4fS0ke3N1ZmZpeH1gO1xuICB9XG59XG5cbmZ1bmN0aW9uIHBhcnNlUHJvcHMocHJvcHM6IGFueSk6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3Qge1xuXG4gIGNvbnN0IHBhcnNlZCA9IHByb3BzPy5Db25maWcgPz8ge307XG5cbiAgLy8gdGhpcyBpcyB3ZWlyZCBidXQgdGhlc2UgYm9vbGVhbiBwcm9wZXJ0aWVzIGFyZSBwYXNzZWQgYnkgQ0ZOIGFzIGEgc3RyaW5nLCBhbmQgd2UgbmVlZCB0aGVtIHRvIGJlIGJvb2xlYW5pYyBmb3IgdGhlIFNESy5cbiAgLy8gT3RoZXJ3aXNlIGl0IGZhaWxzIHdpdGggJ1VuZXhwZWN0ZWQgUGFyYW1ldGVyOiBwYXJhbXMucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBpcyBleHBlY3RlZCB0byBiZSBhIGJvb2xlYW4nXG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQcml2YXRlQWNjZXNzKSA9PT0gJ3N0cmluZycpIHtcbiAgICBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9IHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnPy5lbmRwb2ludFB1YmxpY0FjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyA9IHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPT09ICd0cnVlJztcbiAgfVxuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5sb2dnaW5nPy5jbHVzdGVyTG9nZ2luZ1swXS5lbmFibGVkKSA9PT0gJ3N0cmluZycpIHtcbiAgICBwYXJzZWQubG9nZ2luZy5jbHVzdGVyTG9nZ2luZ1swXS5lbmFibGVkID0gcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9PT0gJ3RydWUnO1xuICB9XG5cbiAgcmV0dXJuIHBhcnNlZDtcblxufVxuXG5pbnRlcmZhY2UgVXBkYXRlTWFwIHtcbiAgcmVwbGFjZU5hbWU6IGJvb2xlYW47IC8vIG5hbWVcbiAgcmVwbGFjZVZwYzogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLnN1Ym5ldElkcyBhbmQgc2VjdXJpdHlHcm91cElkc1xuICByZXBsYWNlUm9sZTogYm9vbGVhbjsgLy8gcm9sZUFyblxuXG4gIHVwZGF0ZVZlcnNpb246IGJvb2xlYW47IC8vIHZlcnNpb25cbiAgdXBkYXRlTG9nZ2luZzogYm9vbGVhbjsgLy8gbG9nZ2luZ1xuICB1cGRhdGVFbmNyeXB0aW9uOiBib29sZWFuOyAvLyBlbmNyeXB0aW9uIChjYW5ub3QgYmUgdXBkYXRlZClcbiAgdXBkYXRlQWNjZXNzOiBib29sZWFuOyAvLyByZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzIGFuZCBlbmRwb2ludFB1YmxpY0FjY2Vzc1xufVxuXG5mdW5jdGlvbiBhbmFseXplVXBkYXRlKG9sZFByb3BzOiBQYXJ0aWFsPGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3Q+LCBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdCk6IFVwZGF0ZU1hcCB7XG4gIGNvbnNvbGUubG9nKCdvbGQgcHJvcHM6ICcsIEpTT04uc3RyaW5naWZ5KG9sZFByb3BzKSk7XG4gIGNvbnNvbGUubG9nKCduZXcgcHJvcHM6ICcsIEpTT04uc3RyaW5naWZ5KG5ld1Byb3BzKSk7XG5cbiAgY29uc3QgbmV3VnBjUHJvcHMgPSBuZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcgfHwge307XG4gIGNvbnN0IG9sZFZwY1Byb3BzID0gb2xkUHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuXG4gIGNvbnN0IG9sZFB1YmxpY0FjY2Vzc0NpZHJzID0gbmV3IFNldChvbGRWcGNQcm9wcy5wdWJsaWNBY2Nlc3NDaWRycyA/PyBbXSk7XG4gIGNvbnN0IG5ld1B1YmxpY0FjY2Vzc0NpZHJzID0gbmV3IFNldChuZXdWcGNQcm9wcy5wdWJsaWNBY2Nlc3NDaWRycyA/PyBbXSk7XG4gIGNvbnN0IG5ld0VuYyA9IG5ld1Byb3BzLmVuY3J5cHRpb25Db25maWcgfHwge307XG4gIGNvbnN0IG9sZEVuYyA9IG9sZFByb3BzLmVuY3J5cHRpb25Db25maWcgfHwge307XG5cbiAgcmV0dXJuIHtcbiAgICByZXBsYWNlTmFtZTogbmV3UHJvcHMubmFtZSAhPT0gb2xkUHJvcHMubmFtZSxcbiAgICByZXBsYWNlVnBjOlxuICAgICAgSlNPTi5zdHJpbmdpZnkobmV3VnBjUHJvcHMuc3VibmV0SWRzKSAhPT0gSlNPTi5zdHJpbmdpZnkob2xkVnBjUHJvcHMuc3VibmV0SWRzKSB8fFxuICAgICAgSlNPTi5zdHJpbmdpZnkobmV3VnBjUHJvcHMuc2VjdXJpdHlHcm91cElkcykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFZwY1Byb3BzLnNlY3VyaXR5R3JvdXBJZHMpLFxuICAgIHVwZGF0ZUFjY2VzczpcbiAgICAgIG5ld1ZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQcml2YXRlQWNjZXNzIHx8XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFB1YmxpY0FjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgfHxcbiAgICAgICFzZXRzRXF1YWwobmV3UHVibGljQWNjZXNzQ2lkcnMsIG9sZFB1YmxpY0FjY2Vzc0NpZHJzKSxcbiAgICByZXBsYWNlUm9sZTogbmV3UHJvcHMucm9sZUFybiAhPT0gb2xkUHJvcHMucm9sZUFybixcbiAgICB1cGRhdGVWZXJzaW9uOiBuZXdQcm9wcy52ZXJzaW9uICE9PSBvbGRQcm9wcy52ZXJzaW9uLFxuICAgIHVwZGF0ZUVuY3J5cHRpb246IEpTT04uc3RyaW5naWZ5KG5ld0VuYykgIT09IEpTT04uc3RyaW5naWZ5KG9sZEVuYyksXG4gICAgdXBkYXRlTG9nZ2luZzogSlNPTi5zdHJpbmdpZnkobmV3UHJvcHMubG9nZ2luZykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFByb3BzLmxvZ2dpbmcpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzZXRzRXF1YWwoZmlyc3Q6IFNldDxzdHJpbmc+LCBzZWNvbmQ6IFNldDxzdHJpbmc+KSB7XG4gIHJldHVybiBmaXJzdC5zaXplID09PSBzZWNvbmQuc2l6ZSB8fCBbLi4uZmlyc3RdLmV2ZXJ5KChlOiBzdHJpbmcpID0+IHNlY29uZC5oYXMoZSkpO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.ts deleted file mode 100644 index 0177a7e21b695..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.ts +++ /dev/null @@ -1,338 +0,0 @@ -/* eslint-disable no-console */ - -// eslint-disable-next-line import/no-extraneous-dependencies -import { IsCompleteResponse, OnEventResponse } from '@aws-cdk/custom-resources/lib/provider-framework/types'; -// eslint-disable-next-line import/no-extraneous-dependencies -import * as aws from 'aws-sdk'; -import { EksClient, ResourceEvent, ResourceHandler } from './common'; - -const MAX_CLUSTER_NAME_LEN = 100; - -export class ClusterResourceHandler extends ResourceHandler { - public get clusterName() { - if (!this.physicalResourceId) { - throw new Error('Cannot determine cluster name without physical resource ID'); - } - - return this.physicalResourceId; - } - - private readonly newProps: aws.EKS.CreateClusterRequest; - private readonly oldProps: Partial; - - constructor(eks: EksClient, event: ResourceEvent) { - super(eks, event); - - this.newProps = parseProps(this.event.ResourceProperties); - this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; - } - - // ------ - // CREATE - // ------ - - protected async onCreate(): Promise { - console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); - if (!this.newProps.roleArn) { - throw new Error('"roleArn" is required'); - } - - const clusterName = this.newProps.name || this.generateClusterName(); - - const resp = await this.eks.createCluster({ - ...this.newProps, - name: clusterName, - }); - - if (!resp.cluster) { - throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); - } - - return { - PhysicalResourceId: resp.cluster.name, - }; - } - - protected async isCreateComplete() { - return this.isActive(); - } - - // ------ - // DELETE - // ------ - - protected async onDelete(): Promise { - console.log(`onDelete: deleting cluster ${this.clusterName}`); - try { - await this.eks.deleteCluster({ name: this.clusterName }); - } catch (e) { - if (e.code !== 'ResourceNotFoundException') { - throw e; - } else { - console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); - } - } - return { - PhysicalResourceId: this.clusterName, - }; - } - - protected async isDeleteComplete(): Promise { - console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); - - try { - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); - } catch (e) { - if (e.code === 'ResourceNotFoundException') { - console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); - return { IsComplete: true }; - } - - console.log('describeCluster error:', e); - throw e; - } - - return { - IsComplete: false, - }; - } - - // ------ - // UPDATE - // ------ - - protected async onUpdate() { - const updates = analyzeUpdate(this.oldProps, this.newProps); - console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); - - // updates to encryption config is not supported - if (updates.updateEncryption) { - throw new Error('Cannot update cluster encryption configuration'); - } - - // if there is an update that requires replacement, go ahead and just create - // a new cluster with the new config. The old cluster will automatically be - // deleted by cloudformation upon success. - if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { - - // if we are replacing this cluster and the cluster has an explicit - // physical name, the creation of the new cluster will fail with "there is - // already a cluster with that name". this is a common behavior for - // CloudFormation resources that support specifying a physical name. - if (this.oldProps.name === this.newProps.name && this.oldProps.name) { - throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); - } - - return this.onCreate(); - } - - // if a version update is required, issue the version update - if (updates.updateVersion) { - if (!this.newProps.version) { - throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); - } - - return this.updateClusterVersion(this.newProps.version); - } - - if (updates.updateLogging || updates.updateAccess) { - const config: aws.EKS.UpdateClusterConfigRequest = { - name: this.clusterName, - logging: this.newProps.logging, - }; - if (updates.updateAccess) { - // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: - // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) - // will fail, therefore we take only the access fields explicitly - config.resourcesVpcConfig = { - endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, - endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, - publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, - }; - } - const updateResponse = await this.eks.updateClusterConfig(config); - - return { EksUpdateId: updateResponse.update?.id }; - } - - // no updates - return; - } - - protected async isUpdateComplete() { - console.log('isUpdateComplete'); - - // if this is an EKS update, we will monitor the update event itself - if (this.event.EksUpdateId) { - const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); - if (!complete) { - return { IsComplete: false }; - } - - // fall through: if the update is done, we simply delegate to isActive() - // in order to extract attributes and state from the cluster itself, which - // is supposed to be in an ACTIVE state after the update is complete. - } - - return this.isActive(); - } - - private async updateClusterVersion(newVersion: string) { - console.log(`updating cluster version to ${newVersion}`); - - // update-cluster-version will fail if we try to update to the same version, - // so skip in this case. - const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; - if (cluster?.version === newVersion) { - console.log(`cluster already at version ${cluster.version}, skipping version update`); - return; - } - - const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); - return { EksUpdateId: updateResponse.update?.id }; - } - - private async isActive(): Promise { - console.log('waiting for cluster to become ACTIVE'); - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); - const cluster = resp.cluster; - - // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are - // not complete. note that the custom resource provider framework forbids - // returning attributes (Data) if isComplete is false. - if (cluster?.status === 'FAILED') { - // not very informative, unfortunately the response doesn't contain any error - // information :\ - throw new Error('Cluster is in a FAILED status'); - } else if (cluster?.status !== 'ACTIVE') { - return { - IsComplete: false, - }; - } else { - return { - IsComplete: true, - Data: { - Name: cluster.name, - Endpoint: cluster.endpoint, - Arn: cluster.arn, - - // IMPORTANT: CFN expects that attributes will *always* have values, - // so return an empty string in case the value is not defined. - // Otherwise, CFN will throw with `Vendor response doesn't contain - // XXXX key`. - - CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', - ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', - OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', - OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', // Strips off https:// from the issuer url - - // We can safely return the first item from encryption configuration array, because it has a limit of 1 item - // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig - EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', - }, - }; - } - } - - private async isEksUpdateComplete(eksUpdateId: string) { - this.log({ isEksUpdateComplete: eksUpdateId }); - - const describeUpdateResponse = await this.eks.describeUpdate({ - name: this.clusterName, - updateId: eksUpdateId, - }); - - this.log({ describeUpdateResponse }); - - if (!describeUpdateResponse.update) { - throw new Error(`unable to describe update with id "${eksUpdateId}"`); - } - - switch (describeUpdateResponse.update.status) { - case 'InProgress': - return false; - case 'Successful': - return true; - case 'Failed': - case 'Cancelled': - throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); - default: - throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); - } - } - - private generateClusterName() { - const suffix = this.requestId.replace(/-/g, ''); // 32 chars - const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; - const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); - return `${prefix}-${suffix}`; - } -} - -function parseProps(props: any): aws.EKS.CreateClusterRequest { - - const parsed = props?.Config ?? {}; - - // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. - // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' - - if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; - } - - if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; - } - - if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { - parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; - } - - return parsed; - -} - -interface UpdateMap { - replaceName: boolean; // name - replaceVpc: boolean; // resourcesVpcConfig.subnetIds and securityGroupIds - replaceRole: boolean; // roleArn - - updateVersion: boolean; // version - updateLogging: boolean; // logging - updateEncryption: boolean; // encryption (cannot be updated) - updateAccess: boolean; // resourcesVpcConfig.endpointPrivateAccess and endpointPublicAccess -} - -function analyzeUpdate(oldProps: Partial, newProps: aws.EKS.CreateClusterRequest): UpdateMap { - console.log('old props: ', JSON.stringify(oldProps)); - console.log('new props: ', JSON.stringify(newProps)); - - const newVpcProps = newProps.resourcesVpcConfig || {}; - const oldVpcProps = oldProps.resourcesVpcConfig || {}; - - const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); - const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); - const newEnc = newProps.encryptionConfig || {}; - const oldEnc = oldProps.encryptionConfig || {}; - - return { - replaceName: newProps.name !== oldProps.name, - replaceVpc: - JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), - updateAccess: - newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || - newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || - !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), - replaceRole: newProps.roleArn !== oldProps.roleArn, - updateVersion: newProps.version !== oldProps.version, - updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), - updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), - }; -} - -function setsEqual(first: Set, second: Set) { - return first.size === second.size || [...first].every((e: string) => second.has(e)); -} diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/cfn-response.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/cfn-response.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/cfn-response.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/cfn-response.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/consts.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/consts.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/consts.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/consts.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/framework.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/framework.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/framework.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/framework.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/outbound.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/outbound.js new file mode 100644 index 0000000000000..cc0667d42f0e8 --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/outbound.js @@ -0,0 +1,69 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.httpRequest = exports.invokeFunction = exports.startExecution = void 0; +/* istanbul ignore file */ +const https = require("https"); +// eslint-disable-next-line import/no-extraneous-dependencies +const AWS = require("aws-sdk"); +const FRAMEWORK_HANDLER_TIMEOUT = 900000; // 15 minutes +// In order to honor the overall maximum timeout set for the target process, +// the default 2 minutes from AWS SDK has to be overriden: +// https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html#httpOptions-property +const 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; +let lambda; +async function defaultStartExecution(req) { + if (!sfn) { + sfn = new AWS.StepFunctions(awsSdkConfig); + } + return sfn.startExecution(req).promise(); +} +async function defaultInvokeFunction(req) { + if (!lambda) { + lambda = new AWS.Lambda(awsSdkConfig); + } + try { + /** + * Try an initial invoke. + * + * When you try to invoke a function that is inactive, the invocation fails and Lambda sets + * the function to pending state until the function resources are recreated. + * If Lambda fails to recreate the resources, the function is set to the inactive state. + * + * We're using invoke first because `waitFor` doesn't trigger an inactive function to do anything, + * it just runs `getFunction` and checks the state. + */ + return await lambda.invoke(req).promise(); + } + catch (error) { + /** + * The status of the Lambda function is checked every second for up to 300 seconds. + * Exits the loop on 'Active' state and throws an error on 'Inactive' or 'Failed'. + * + * And now we wait. + */ + await lambda.waitFor('functionActiveV2', { + FunctionName: req.FunctionName, + }).promise(); + return await lambda.invoke(req).promise(); + } +} +exports.startExecution = defaultStartExecution; +exports.invokeFunction = defaultInvokeFunction; +exports.httpRequest = defaultHttpRequest; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3V0Ym91bmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJvdXRib3VuZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwwQkFBMEI7QUFDMUIsK0JBQStCO0FBQy9CLDZEQUE2RDtBQUM3RCwrQkFBK0I7QUFJL0IsTUFBTSx5QkFBeUIsR0FBRyxNQUFNLENBQUMsQ0FBQyxhQUFhO0FBRXZELDRFQUE0RTtBQUM1RSwwREFBMEQ7QUFDMUQsMkZBQTJGO0FBQzNGLE1BQU0sWUFBWSxHQUF5QjtJQUN6QyxXQUFXLEVBQUUsRUFBRSxPQUFPLEVBQUUseUJBQXlCLEVBQUU7Q0FDcEQsQ0FBQztBQUVGLEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxPQUE2QixFQUFFLFlBQW9CO0lBQ25GLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDckMsSUFBSTtZQUNGLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ2hELE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDNUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1NBQ2Y7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNYO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsSUFBSSxHQUFzQixDQUFDO0FBQzNCLElBQUksTUFBa0IsQ0FBQztBQUV2QixLQUFLLFVBQVUscUJBQXFCLENBQUMsR0FBMEM7SUFDN0UsSUFBSSxDQUFDLEdBQUcsRUFBRTtRQUNSLEdBQUcsR0FBRyxJQUFJLEdBQUcsQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUM7S0FDM0M7SUFFRCxPQUFPLEdBQUcsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7QUFDM0MsQ0FBQztBQUVELEtBQUssVUFBVSxxQkFBcUIsQ0FBQyxHQUFpQztJQUNwRSxJQUFJLENBQUMsTUFBTSxFQUFFO1FBQ1gsTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztLQUN2QztJQUVELElBQUk7UUFDRjs7Ozs7Ozs7O1dBU0c7UUFDSCxPQUFPLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztLQUMzQztJQUFDLE9BQU8sS0FBSyxFQUFFO1FBRWQ7Ozs7O1dBS0c7UUFDSCxNQUFNLE1BQU0sQ0FBQyxPQUFPLENBQUMsa0JBQWtCLEVBQUU7WUFDdkMsWUFBWSxFQUFFLEdBQUcsQ0FBQyxZQUFZO1NBQy9CLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNiLE9BQU8sTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDO0tBQzNDO0FBQ0gsQ0FBQztBQUVVLFFBQUEsY0FBYyxHQUFHLHFCQUFxQixDQUFDO0FBQ3ZDLFFBQUEsY0FBYyxHQUFHLHFCQUFxQixDQUFDO0FBQ3ZDLFFBQUEsV0FBVyxHQUFHLGtCQUFrQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogaXN0YW5idWwgaWdub3JlIGZpbGUgKi9cbmltcG9ydCAqIGFzIGh0dHBzIGZyb20gJ2h0dHBzJztcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcbmltcG9ydCAqIGFzIEFXUyBmcm9tICdhd3Mtc2RrJztcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcbmltcG9ydCB0eXBlIHsgQ29uZmlndXJhdGlvbk9wdGlvbnMgfSBmcm9tICdhd3Mtc2RrL2xpYi9jb25maWctYmFzZSc7XG5cbmNvbnN0IEZSQU1FV09SS19IQU5ETEVSX1RJTUVPVVQgPSA5MDAwMDA7IC8vIDE1IG1pbnV0ZXNcblxuLy8gSW4gb3JkZXIgdG8gaG9ub3IgdGhlIG92ZXJhbGwgbWF4aW11bSB0aW1lb3V0IHNldCBmb3IgdGhlIHRhcmdldCBwcm9jZXNzLFxuLy8gdGhlIGRlZmF1bHQgMiBtaW51dGVzIGZyb20gQVdTIFNESyBoYXMgdG8gYmUgb3ZlcnJpZGVuOlxuLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0phdmFTY3JpcHRTREsvbGF0ZXN0L0FXUy9Db25maWcuaHRtbCNodHRwT3B0aW9ucy1wcm9wZXJ0eVxuY29uc3QgYXdzU2RrQ29uZmlnOiBDb25maWd1cmF0aW9uT3B0aW9ucyA9IHtcbiAgaHR0cE9wdGlvbnM6IHsgdGltZW91dDogRlJBTUVXT1JLX0hBTkRMRVJfVElNRU9VVCB9LFxufTtcblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdEh0dHBSZXF1ZXN0KG9wdGlvbnM6IGh0dHBzLlJlcXVlc3RPcHRpb25zLCByZXNwb25zZUJvZHk6IHN0cmluZykge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gaHR0cHMucmVxdWVzdChvcHRpb25zLCByZXNvbHZlKTtcbiAgICAgIHJlcXVlc3Qub24oJ2Vycm9yJywgcmVqZWN0KTtcbiAgICAgIHJlcXVlc3Qud3JpdGUocmVzcG9uc2VCb2R5KTtcbiAgICAgIHJlcXVlc3QuZW5kKCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmVqZWN0KGUpO1xuICAgIH1cbiAgfSk7XG59XG5cbmxldCBzZm46IEFXUy5TdGVwRnVuY3Rpb25zO1xubGV0IGxhbWJkYTogQVdTLkxhbWJkYTtcblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdFN0YXJ0RXhlY3V0aW9uKHJlcTogQVdTLlN0ZXBGdW5jdGlvbnMuU3RhcnRFeGVjdXRpb25JbnB1dCk6IFByb21pc2U8QVdTLlN0ZXBGdW5jdGlvbnMuU3RhcnRFeGVjdXRpb25PdXRwdXQ+IHtcbiAgaWYgKCFzZm4pIHtcbiAgICBzZm4gPSBuZXcgQVdTLlN0ZXBGdW5jdGlvbnMoYXdzU2RrQ29uZmlnKTtcbiAgfVxuXG4gIHJldHVybiBzZm4uc3RhcnRFeGVjdXRpb24ocmVxKS5wcm9taXNlKCk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGRlZmF1bHRJbnZva2VGdW5jdGlvbihyZXE6IEFXUy5MYW1iZGEuSW52b2NhdGlvblJlcXVlc3QpOiBQcm9taXNlPEFXUy5MYW1iZGEuSW52b2NhdGlvblJlc3BvbnNlPiB7XG4gIGlmICghbGFtYmRhKSB7XG4gICAgbGFtYmRhID0gbmV3IEFXUy5MYW1iZGEoYXdzU2RrQ29uZmlnKTtcbiAgfVxuXG4gIHRyeSB7XG4gICAgLyoqXG4gICAgICogVHJ5IGFuIGluaXRpYWwgaW52b2tlLlxuICAgICAqXG4gICAgICogV2hlbiB5b3UgdHJ5IHRvIGludm9rZSBhIGZ1bmN0aW9uIHRoYXQgaXMgaW5hY3RpdmUsIHRoZSBpbnZvY2F0aW9uIGZhaWxzIGFuZCBMYW1iZGEgc2V0c1xuICAgICAqIHRoZSBmdW5jdGlvbiB0byBwZW5kaW5nIHN0YXRlIHVudGlsIHRoZSBmdW5jdGlvbiByZXNvdXJjZXMgYXJlIHJlY3JlYXRlZC5cbiAgICAgKiBJZiBMYW1iZGEgZmFpbHMgdG8gcmVjcmVhdGUgdGhlIHJlc291cmNlcywgdGhlIGZ1bmN0aW9uIGlzIHNldCB0byB0aGUgaW5hY3RpdmUgc3RhdGUuXG4gICAgICpcbiAgICAgKiBXZSdyZSB1c2luZyBpbnZva2UgZmlyc3QgYmVjYXVzZSBgd2FpdEZvcmAgZG9lc24ndCB0cmlnZ2VyIGFuIGluYWN0aXZlIGZ1bmN0aW9uIHRvIGRvIGFueXRoaW5nLFxuICAgICAqIGl0IGp1c3QgcnVucyBgZ2V0RnVuY3Rpb25gIGFuZCBjaGVja3MgdGhlIHN0YXRlLlxuICAgICAqL1xuICAgIHJldHVybiBhd2FpdCBsYW1iZGEuaW52b2tlKHJlcSkucHJvbWlzZSgpO1xuICB9IGNhdGNoIChlcnJvcikge1xuXG4gICAgLyoqXG4gICAgICogVGhlIHN0YXR1cyBvZiB0aGUgTGFtYmRhIGZ1bmN0aW9uIGlzIGNoZWNrZWQgZXZlcnkgc2Vjb25kIGZvciB1cCB0byAzMDAgc2Vjb25kcy5cbiAgICAgKiBFeGl0cyB0aGUgbG9vcCBvbiAnQWN0aXZlJyBzdGF0ZSBhbmQgdGhyb3dzIGFuIGVycm9yIG9uICdJbmFjdGl2ZScgb3IgJ0ZhaWxlZCcuXG4gICAgICpcbiAgICAgKiBBbmQgbm93IHdlIHdhaXQuXG4gICAgICovXG4gICAgYXdhaXQgbGFtYmRhLndhaXRGb3IoJ2Z1bmN0aW9uQWN0aXZlVjInLCB7XG4gICAgICBGdW5jdGlvbk5hbWU6IHJlcS5GdW5jdGlvbk5hbWUsXG4gICAgfSkucHJvbWlzZSgpO1xuICAgIHJldHVybiBhd2FpdCBsYW1iZGEuaW52b2tlKHJlcSkucHJvbWlzZSgpO1xuICB9XG59XG5cbmV4cG9ydCBsZXQgc3RhcnRFeGVjdXRpb24gPSBkZWZhdWx0U3RhcnRFeGVjdXRpb247XG5leHBvcnQgbGV0IGludm9rZUZ1bmN0aW9uID0gZGVmYXVsdEludm9rZUZ1bmN0aW9uO1xuZXhwb3J0IGxldCBodHRwUmVxdWVzdCA9IGRlZmF1bHRIdHRwUmVxdWVzdDtcbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/util.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/util.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/util.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/util.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip index b64a5034e3b6c..13983109fc5f5 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/apply/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/apply/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/get/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/get/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/helm/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py similarity index 89% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/helm/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py index a7b26b264118b..286976ced219a 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/helm/__init__.py +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py @@ -6,7 +6,6 @@ import shutil import tempfile import zipfile -from urllib.parse import urlparse, unquote logger = logging.getLogger() logger.setLevel(logging.INFO) @@ -95,26 +94,25 @@ def helm_handler(event, context): def get_oci_cmd(repository, version): # Generates OCI command based on pattern. Public ECR vs Private ECR are treated differently. - cmnd = [] - private_ecr_pattern = '\d+.dkr.ecr.[a-z]+-[a-z]+-\d.amazonaws.com' - public_ecr = 'public.ecr.aws' + private_ecr_pattern = 'oci://(?P\d+.dkr.ecr.(?P[a-z]+-[a-z]+-\d).amazonaws.com)*' + public_ecr_pattern = 'oci://(?Ppublic.ecr.aws)*' - registry = repository.rsplit('/', 1)[0].replace('oci://', '') + private_registry = re.match(private_ecr_pattern, repository).groupdict() + public_registry = re.match(public_ecr_pattern, repository).groupdict() - if re.fullmatch(private_ecr_pattern, registry) is not None: + if private_registry['registry'] is not None: logger.info("Found AWS private repository") - region = registry.replace('.amazonaws.com', '').split('.')[-1] cmnd = [ - f"aws ecr get-login-password --region {region} | " \ - f"helm registry login --username AWS --password-stdin {registry}; helm pull {repository} --version {version} --untar" + f"aws ecr get-login-password --region {private_registry['region']} | " \ + f"helm registry login --username AWS --password-stdin {private_registry['registry']}; helm pull {repository} --version {version} --untar" ] - elif registry.startswith(public_ecr): + elif public_registry['registry'] is not None: logger.info("Found AWS public repository, will use default region as deployment") region = os.environ.get('AWS_REGION', 'us-east-1') cmnd = [ - f"aws ecr-public get-login-password --region {region} | " \ - f"helm registry login --username AWS --password-stdin {public_ecr}; helm pull {repository} --version {version} --untar" + f"aws ecr-public get-login-password --region us-east-1 | " \ + f"helm registry login --username AWS --password-stdin {public_registry['registry']}; helm pull {repository} --version {version} --untar" ] else: logger.error("OCI repository format not recognized, falling back to helm pull") diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/index.py b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/index.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/patch/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/patch/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip index a0efa36e0518a..9bf8ba72b34ab 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/aws-cdk-eks-cluster-private-endpoint-test.assets.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/aws-cdk-eks-cluster-private-endpoint-test.assets.json index c96b2ce8495ef..10ebb34df6932 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/aws-cdk-eks-cluster-private-endpoint-test.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/aws-cdk-eks-cluster-private-endpoint-test.assets.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "files": { "c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064": { "source": { @@ -27,41 +27,41 @@ } } }, - "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517": { + "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee": { "source": { - "path": "asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517", + "path": "asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip", + "objectKey": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037": { + "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585": { "source": { - "path": "asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037", + "path": "asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip", + "objectKey": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33": { + "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8": { "source": { - "path": "asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33", + "path": "asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33.zip", + "objectKey": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -79,7 +79,7 @@ } } }, - "c48cc5dc50de353455d7c81c66e9a3b94e3e31fe9fb5e198c917ed652e8d500e": { + "a7eab24563c84871b9595c7f0cab44a26fdb5fd2c4b18e18e6b5f040da855b4b": { "source": { "path": "awscdkeksclusterprivateendpointtestawscdkawseksClusterResourceProvider67118CB1.nested.template.json", "packaging": "file" @@ -87,12 +87,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "c48cc5dc50de353455d7c81c66e9a3b94e3e31fe9fb5e198c917ed652e8d500e.json", + "objectKey": "a7eab24563c84871b9595c7f0cab44a26fdb5fd2c4b18e18e6b5f040da855b4b.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "becb250c0b730554cf1721996e6dacde9acf883666917d84e9297f19fff30989": { + "1a26a8f46752d564666f4e1c76938eb1338d79a9b65f4bf52da9ed8ad85aa837": { "source": { "path": "awscdkeksclusterprivateendpointtestawscdkawseksKubectlProvider421F287E.nested.template.json", "packaging": "file" @@ -100,12 +100,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "becb250c0b730554cf1721996e6dacde9acf883666917d84e9297f19fff30989.json", + "objectKey": "1a26a8f46752d564666f4e1c76938eb1338d79a9b65f4bf52da9ed8ad85aa837.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "5ba2b041eec65cdf5d2382e1e12a8cb1576ec0e47352c39ba040b33cecddd2ab": { + "a9f315c998f5e5adceb3622a38be1e2c87b491c01978168eb8699d5ebe940137": { "source": { "path": "aws-cdk-eks-cluster-private-endpoint-test.template.json", "packaging": "file" @@ -113,7 +113,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "5ba2b041eec65cdf5d2382e1e12a8cb1576ec0e47352c39ba040b33cecddd2ab.json", + "objectKey": "a9f315c998f5e5adceb3622a38be1e2c87b491c01978168eb8699d5ebe940137.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/aws-cdk-eks-cluster-private-endpoint-test.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/aws-cdk-eks-cluster-private-endpoint-test.template.json index e3542cd246d0f..95fc9ba0ebba6 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/aws-cdk-eks-cluster-private-endpoint-test.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/aws-cdk-eks-cluster-private-endpoint-test.template.json @@ -909,7 +909,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/c48cc5dc50de353455d7c81c66e9a3b94e3e31fe9fb5e198c917ed652e8d500e.json" + "/a7eab24563c84871b9595c7f0cab44a26fdb5fd2c4b18e18e6b5f040da855b4b.json" ] ] }, @@ -944,7 +944,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/becb250c0b730554cf1721996e6dacde9acf883666917d84e9297f19fff30989.json" + "/1a26a8f46752d564666f4e1c76938eb1338d79a9b65f4bf52da9ed8ad85aa837.json" ] ] }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/awscdkeksclusterprivateendpointDefaultTestDeployAssert3C16DBEA.assets.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/awscdkeksclusterprivateendpointDefaultTestDeployAssert3C16DBEA.assets.json index 0cedfa6de9dfe..14657cf84d7b9 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/awscdkeksclusterprivateendpointDefaultTestDeployAssert3C16DBEA.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/awscdkeksclusterprivateendpointDefaultTestDeployAssert3C16DBEA.assets.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/awscdkeksclusterprivateendpointtestawscdkawseksClusterResourceProvider67118CB1.nested.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/awscdkeksclusterprivateendpointtestawscdkawseksClusterResourceProvider67118CB1.nested.template.json index a51e8c9e7215f..4d2bc59791218 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/awscdkeksclusterprivateendpointtestawscdkawseksClusterResourceProvider67118CB1.nested.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/awscdkeksclusterprivateendpointtestawscdkawseksClusterResourceProvider67118CB1.nested.template.json @@ -73,7 +73,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ @@ -162,7 +162,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ @@ -297,7 +297,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ @@ -434,7 +434,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ @@ -568,7 +568,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/awscdkeksclusterprivateendpointtestawscdkawseksKubectlProvider421F287E.nested.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/awscdkeksclusterprivateendpointtestawscdkawseksKubectlProvider421F287E.nested.template.json index 232c040f9337b..cc6d89c4e5bf6 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/awscdkeksclusterprivateendpointtestawscdkawseksKubectlProvider421F287E.nested.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/awscdkeksclusterprivateendpointtestawscdkawseksKubectlProvider421F287E.nested.template.json @@ -51,6 +51,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -92,7 +104,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33.zip" + "S3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "Role": { "Fn::GetAtt": [ @@ -238,7 +250,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/cdk.out b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/cdk.out index 8ecc185e9dbee..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"21.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/integ.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/integ.json index c1b77c8108a74..07cb844511a09 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "testCases": { "aws-cdk-eks-cluster-private-endpoint/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/manifest.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/manifest.json index cde3142275691..1dda241f27a5e 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "artifacts": { "aws-cdk-eks-cluster-private-endpoint-test.assets": { "type": "cdk:asset-manifest", @@ -17,7 +17,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/5ba2b041eec65cdf5d2382e1e12a8cb1576ec0e47352c39ba040b33cecddd2ab.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/a9f315c998f5e5adceb3622a38be1e2c87b491c01978168eb8699d5ebe940137.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -168,10 +168,7 @@ "/aws-cdk-eks-cluster-private-endpoint-test/KubectlLayer/Resource": [ { "type": "aws:cdk:logicalId", - "data": "KubectlLayer600207B5", - "trace": [ - "!!DESTRUCTIVE_CHANGES: WILL_REPLACE" - ] + "data": "KubectlLayer600207B5" } ], "/aws-cdk-eks-cluster-private-endpoint-test/Cluster/Role/Resource": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/tree.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/tree.json index 21844ef06085c..b3f20eb5672a8 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/tree.json @@ -755,7 +755,7 @@ }, "constructInfo": { "fqn": "@aws-cdk/lambda-layer-kubectl-v24.KubectlV24Layer", - "version": "2.0.27" + "version": "2.0.100" } }, "Cluster": { @@ -1019,7 +1019,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "KubectlReadyBarrier": { @@ -1455,7 +1455,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -1628,7 +1628,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -1851,7 +1851,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -2072,7 +2072,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -2290,7 +2290,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -2469,7 +2469,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } } }, @@ -2526,7 +2526,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/c48cc5dc50de353455d7c81c66e9a3b94e3e31fe9fb5e198c917ed652e8d500e.json" + "/a7eab24563c84871b9595c7f0cab44a26fdb5fd2c4b18e18e6b5f040da855b4b.json" ] ] }, @@ -2548,7 +2548,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "@aws-cdk--aws-eks.KubectlProvider": { @@ -2625,6 +2625,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -2724,7 +2736,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33.zip" + "s3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "role": { "Fn::GetAtt": [ @@ -3002,7 +3014,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -3146,7 +3158,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/becb250c0b730554cf1721996e6dacde9acf883666917d84e9297f19fff30989.json" + "/1a26a8f46752d564666f4e1c76938eb1338d79a9b65f4bf52da9ed8ad85aa837.json" ] ] }, @@ -3189,7 +3201,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "BootstrapVersion": { @@ -3227,7 +3239,7 @@ "path": "aws-cdk-eks-cluster-private-endpoint/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "DeployAssert": { @@ -3273,7 +3285,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } } }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip index 298edd40a09fc..f62fe1e5a06d6 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip index ce3ea448ac19d..13983109fc5f5 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/apply/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/apply/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/get/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/get/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py new file mode 100644 index 0000000000000..286976ced219a --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py @@ -0,0 +1,187 @@ +import json +import logging +import os +import re +import subprocess +import shutil +import tempfile +import zipfile + +logger = logging.getLogger() +logger.setLevel(logging.INFO) + +# these are coming from the kubectl layer +os.environ['PATH'] = '/opt/helm:/opt/awscli:' + os.environ['PATH'] + +outdir = os.environ.get('TEST_OUTDIR', '/tmp') +kubeconfig = os.path.join(outdir, 'kubeconfig') + +def get_chart_asset_from_url(chart_asset_url): + chart_zip = os.path.join(outdir, 'chart.zip') + shutil.rmtree(chart_zip, ignore_errors=True) + subprocess.check_call(['aws', 's3', 'cp', chart_asset_url, chart_zip]) + chart_dir = os.path.join(outdir, 'chart') + shutil.rmtree(chart_dir, ignore_errors=True) + os.mkdir(chart_dir) + with zipfile.ZipFile(chart_zip, 'r') as zip_ref: + zip_ref.extractall(chart_dir) + return chart_dir + +def helm_handler(event, context): + logger.info(json.dumps(dict(event, ResponseURL='...'))) + + request_type = event['RequestType'] + props = event['ResourceProperties'] + + # resource properties + cluster_name = props['ClusterName'] + role_arn = props['RoleArn'] + release = props['Release'] + chart = props.get('Chart', None) + chart_asset_url = props.get('ChartAssetURL', None) + version = props.get('Version', None) + wait = props.get('Wait', False) + timeout = props.get('Timeout', None) + namespace = props.get('Namespace', None) + create_namespace = props.get('CreateNamespace', None) + repository = props.get('Repository', None) + values_text = props.get('Values', None) + + # "log in" to the cluster + subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig', + '--role-arn', role_arn, + '--name', cluster_name, + '--kubeconfig', kubeconfig + ]) + + if os.path.isfile(kubeconfig): + os.chmod(kubeconfig, 0o600) + + # Write out the values to a file and include them with the install and upgrade + values_file = None + if not request_type == "Delete" and not values_text is None: + values = json.loads(values_text) + values_file = os.path.join(outdir, 'values.yaml') + with open(values_file, "w") as f: + f.write(json.dumps(values, indent=2)) + + if request_type == 'Create' or request_type == 'Update': + # Ensure chart or chart_asset_url are set + if chart == None and chart_asset_url == None: + raise RuntimeError(f'chart or chartAsset must be specified') + + if chart_asset_url != None: + assert(chart==None) + assert(repository==None) + assert(version==None) + if not chart_asset_url.startswith('s3://'): + raise RuntimeError(f'ChartAssetURL must point to as s3 location but is {chart_asset_url}') + # future work: support versions from s3 assets + chart = get_chart_asset_from_url(chart_asset_url) + + if repository is not None and repository.startswith('oci://'): + tmpdir = tempfile.TemporaryDirectory() + chart_dir = get_chart_from_oci(tmpdir.name, repository, version) + chart = chart_dir + + helm('upgrade', release, chart, repository, values_file, namespace, version, wait, timeout, create_namespace) + elif request_type == "Delete": + try: + helm('uninstall', release, namespace=namespace, timeout=timeout) + except Exception as e: + logger.info("delete error: %s" % e) + + +def get_oci_cmd(repository, version): + # Generates OCI command based on pattern. Public ECR vs Private ECR are treated differently. + private_ecr_pattern = 'oci://(?P\d+.dkr.ecr.(?P[a-z]+-[a-z]+-\d).amazonaws.com)*' + public_ecr_pattern = 'oci://(?Ppublic.ecr.aws)*' + + private_registry = re.match(private_ecr_pattern, repository).groupdict() + public_registry = re.match(public_ecr_pattern, repository).groupdict() + + if private_registry['registry'] is not None: + logger.info("Found AWS private repository") + cmnd = [ + f"aws ecr get-login-password --region {private_registry['region']} | " \ + f"helm registry login --username AWS --password-stdin {private_registry['registry']}; helm pull {repository} --version {version} --untar" + ] + elif public_registry['registry'] is not None: + logger.info("Found AWS public repository, will use default region as deployment") + region = os.environ.get('AWS_REGION', 'us-east-1') + + cmnd = [ + f"aws ecr-public get-login-password --region us-east-1 | " \ + f"helm registry login --username AWS --password-stdin {public_registry['registry']}; helm pull {repository} --version {version} --untar" + ] + else: + logger.error("OCI repository format not recognized, falling back to helm pull") + cmnd = ['helm', 'pull', repository, '--version', version, '--untar'] + + return cmnd + + +def get_chart_from_oci(tmpdir, repository = None, version = None): + + cmnd = get_oci_cmd(repository, version) + + maxAttempts = 3 + retry = maxAttempts + while retry > 0: + try: + logger.info(cmnd) + output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=tmpdir, shell=True) + logger.info(output) + + # effectively returns "$tmpDir/$lastPartOfOCIUrl", because this is how helm pull saves OCI artifact. + # Eg. if we have oci://9999999999.dkr.ecr.us-east-1.amazonaws.com/foo/bar/pet-service repository, helm saves artifact under $tmpDir/pet-service + return os.path.join(tmpdir, repository.rpartition('/')[-1]) + except subprocess.CalledProcessError as exc: + output = exc.output + if b'Broken pipe' in output: + retry = retry - 1 + logger.info("Broken pipe, retries left: %s" % retry) + else: + raise Exception(output) + raise Exception(f'Operation failed after {maxAttempts} attempts: {output}') + + +def helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None): + import subprocess + + cmnd = ['helm', verb, release] + if not chart is None: + cmnd.append(chart) + if verb == 'upgrade': + cmnd.append('--install') + if create_namespace: + cmnd.append('--create-namespace') + if not repo is None: + cmnd.extend(['--repo', repo]) + if not file is None: + cmnd.extend(['--values', file]) + if not version is None: + cmnd.extend(['--version', version]) + if not namespace is None: + cmnd.extend(['--namespace', namespace]) + if wait: + cmnd.append('--wait') + if not timeout is None: + cmnd.extend(['--timeout', timeout]) + cmnd.extend(['--kubeconfig', kubeconfig]) + + maxAttempts = 3 + retry = maxAttempts + while retry > 0: + try: + output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir) + logger.info(output) + return + except subprocess.CalledProcessError as exc: + output = exc.output + if b'Broken pipe' in output: + retry = retry - 1 + logger.info("Broken pipe, retries left: %s" % retry) + else: + raise Exception(output) + raise Exception(f'Operation failed after {maxAttempts} attempts: {output}') diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/index.py b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/index.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/patch/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/patch/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip index 5cefa4cfa936b..9bf8ba72b34ab 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/aws-cdk-eks-cluster-test.assets.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/aws-cdk-eks-cluster-test.assets.json index e05b8a67fb222..1c482d6bacdb4 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/aws-cdk-eks-cluster-test.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/aws-cdk-eks-cluster-test.assets.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "files": { "c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064": { "source": { @@ -57,15 +57,15 @@ } } }, - "e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9": { + "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8": { "source": { - "path": "asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9", + "path": "asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8", "packaging": "zip" }, "destinations": { "current_account-us-east-1": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1", - "objectKey": "e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9.zip", + "objectKey": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip", "region": "us-east-1", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-us-east-1" } @@ -141,7 +141,7 @@ } } }, - "5ae9306474c5c23767a5fd25baabe8b6bc0784ab276ad7318f1a2152323b253a": { + "8036bc5a59e7909aeeb9b09610d5b223033cd2bff3abae01c6b616800daf868f": { "source": { "path": "awscdkeksclustertestawscdkawseksKubectlProviderE05943BF.nested.template.json", "packaging": "file" @@ -149,13 +149,13 @@ "destinations": { "current_account-us-east-1": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1", - "objectKey": "5ae9306474c5c23767a5fd25baabe8b6bc0784ab276ad7318f1a2152323b253a.json", + "objectKey": "8036bc5a59e7909aeeb9b09610d5b223033cd2bff3abae01c6b616800daf868f.json", "region": "us-east-1", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-us-east-1" } } }, - "135550969dc86be479785b50f9d5aae26cb7cd8b06dfac538d0a2ec138cd0273": { + "3d2522af747fc8da02b4f2bc4496653d3df949b859ad847b25a3fbc06fb24df2": { "source": { "path": "aws-cdk-eks-cluster-test.template.json", "packaging": "file" @@ -163,7 +163,7 @@ "destinations": { "current_account-us-east-1": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1", - "objectKey": "135550969dc86be479785b50f9d5aae26cb7cd8b06dfac538d0a2ec138cd0273.json", + "objectKey": "3d2522af747fc8da02b4f2bc4496653d3df949b859ad847b25a3fbc06fb24df2.json", "region": "us-east-1", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-us-east-1" } diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/aws-cdk-eks-cluster-test.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/aws-cdk-eks-cluster-test.template.json index c9c8b8f055c29..651be5f73a751 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/aws-cdk-eks-cluster-test.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/aws-cdk-eks-cluster-test.template.json @@ -3406,7 +3406,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1" }, - "/5ae9306474c5c23767a5fd25baabe8b6bc0784ab276ad7318f1a2152323b253a.json" + "/8036bc5a59e7909aeeb9b09610d5b223033cd2bff3abae01c6b616800daf868f.json" ] ] }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/awscdkeksclusterDefaultTestDeployAssertFBF4B356.assets.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/awscdkeksclusterDefaultTestDeployAssertFBF4B356.assets.json index c5a73c6555dd8..1f919c65eaa58 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/awscdkeksclusterDefaultTestDeployAssertFBF4B356.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/awscdkeksclusterDefaultTestDeployAssertFBF4B356.assets.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/awscdkeksclustertestawscdkawseksKubectlProviderE05943BF.nested.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/awscdkeksclustertestawscdkawseksKubectlProviderE05943BF.nested.template.json index b758aa6d3170d..efbd392c372a2 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/awscdkeksclustertestawscdkawseksKubectlProviderE05943BF.nested.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/awscdkeksclustertestawscdkawseksKubectlProviderE05943BF.nested.template.json @@ -51,6 +51,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -125,7 +137,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1" }, - "S3Key": "e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9.zip" + "S3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/cdk.out b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/cdk.out index ae4b03c54e770..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"30.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/integ.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/integ.json index 03a31d112b00c..e8db188b6ecf8 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "testCases": { "aws-cdk-eks-cluster/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/manifest.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/manifest.json index e3236a29bd07c..04efc8ae44d15 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "artifacts": { "aws-cdk-eks-cluster-test.assets": { "type": "cdk:asset-manifest", @@ -17,7 +17,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-us-east-1", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-us-east-1", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1/135550969dc86be479785b50f9d5aae26cb7cd8b06dfac538d0a2ec138cd0273.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1/3d2522af747fc8da02b4f2bc4496653d3df949b859ad847b25a3fbc06fb24df2.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/tree.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/tree.json index a7f52f35694fd..ce3ff96298b44 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/tree.json @@ -798,7 +798,7 @@ }, "constructInfo": { "fqn": "@aws-cdk/lambda-layer-kubectl-v24.KubectlV24Layer", - "version": "2.0.85" + "version": "2.0.100" } }, "Cluster": { @@ -1197,7 +1197,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } }, "KubectlReadyBarrier": { @@ -5557,7 +5557,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } } }, @@ -5632,7 +5632,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } }, "@aws-cdk--aws-eks.KubectlProvider": { @@ -5709,6 +5709,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -5841,7 +5853,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1" }, - "s3Key": "e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9.zip" + "s3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "role": { "Fn::GetAtt": [ @@ -6259,7 +6271,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1" }, - "/5ae9306474c5c23767a5fd25baabe8b6bc0784ab276ad7318f1a2152323b253a.json" + "/8036bc5a59e7909aeeb9b09610d5b223033cd2bff3abae01c6b616800daf868f.json" ] ] }, @@ -6302,7 +6314,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } }, "SsmParameterValue:--aws--service--eks--optimized-ami--1.24--amazon-linux-2--recommended--image_id:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter": { @@ -6606,7 +6618,7 @@ "path": "aws-cdk-eks-cluster/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } }, "DeployAssert": { @@ -6652,7 +6664,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } } }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js new file mode 100644 index 0000000000000..c9dc1b8d2c19a --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js @@ -0,0 +1,273 @@ +"use strict"; +/* eslint-disable no-console */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ClusterResourceHandler = void 0; +const common_1 = require("./common"); +const MAX_CLUSTER_NAME_LEN = 100; +class ClusterResourceHandler extends common_1.ResourceHandler { + constructor(eks, event) { + super(eks, event); + this.newProps = parseProps(this.event.ResourceProperties); + this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; + } + get clusterName() { + if (!this.physicalResourceId) { + throw new Error('Cannot determine cluster name without physical resource ID'); + } + return this.physicalResourceId; + } + // ------ + // CREATE + // ------ + async onCreate() { + console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); + if (!this.newProps.roleArn) { + throw new Error('"roleArn" is required'); + } + const clusterName = this.newProps.name || this.generateClusterName(); + const resp = await this.eks.createCluster({ + ...this.newProps, + name: clusterName, + }); + if (!resp.cluster) { + throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); + } + return { + PhysicalResourceId: resp.cluster.name, + }; + } + async isCreateComplete() { + return this.isActive(); + } + // ------ + // DELETE + // ------ + async onDelete() { + console.log(`onDelete: deleting cluster ${this.clusterName}`); + try { + await this.eks.deleteCluster({ name: this.clusterName }); + } + catch (e) { + if (e.code !== 'ResourceNotFoundException') { + throw e; + } + else { + console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); + } + } + return { + PhysicalResourceId: this.clusterName, + }; + } + async isDeleteComplete() { + console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); + try { + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); + } + catch (e) { + if (e.code === 'ResourceNotFoundException') { + console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); + return { IsComplete: true }; + } + console.log('describeCluster error:', e); + throw e; + } + return { + IsComplete: false, + }; + } + // ------ + // UPDATE + // ------ + async onUpdate() { + const updates = analyzeUpdate(this.oldProps, this.newProps); + console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); + // updates to encryption config is not supported + if (updates.updateEncryption) { + throw new Error('Cannot update cluster encryption configuration'); + } + // if there is an update that requires replacement, go ahead and just create + // a new cluster with the new config. The old cluster will automatically be + // deleted by cloudformation upon success. + if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { + // if we are replacing this cluster and the cluster has an explicit + // physical name, the creation of the new cluster will fail with "there is + // already a cluster with that name". this is a common behavior for + // CloudFormation resources that support specifying a physical name. + if (this.oldProps.name === this.newProps.name && this.oldProps.name) { + throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); + } + return this.onCreate(); + } + // if a version update is required, issue the version update + if (updates.updateVersion) { + if (!this.newProps.version) { + throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); + } + return this.updateClusterVersion(this.newProps.version); + } + if (updates.updateLogging && updates.updateAccess) { + throw new Error('Cannot update logging and access at the same time'); + } + if (updates.updateLogging || updates.updateAccess) { + const config = { + name: this.clusterName, + }; + if (updates.updateLogging) { + config.logging = this.newProps.logging; + } + ; + if (updates.updateAccess) { + // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: + // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) + // will fail, therefore we take only the access fields explicitly + config.resourcesVpcConfig = { + endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, + endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, + publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, + }; + } + const updateResponse = await this.eks.updateClusterConfig(config); + return { EksUpdateId: updateResponse.update?.id }; + } + // no updates + return; + } + async isUpdateComplete() { + console.log('isUpdateComplete'); + // if this is an EKS update, we will monitor the update event itself + if (this.event.EksUpdateId) { + const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); + if (!complete) { + return { IsComplete: false }; + } + // fall through: if the update is done, we simply delegate to isActive() + // in order to extract attributes and state from the cluster itself, which + // is supposed to be in an ACTIVE state after the update is complete. + } + return this.isActive(); + } + async updateClusterVersion(newVersion) { + console.log(`updating cluster version to ${newVersion}`); + // update-cluster-version will fail if we try to update to the same version, + // so skip in this case. + const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; + if (cluster?.version === newVersion) { + console.log(`cluster already at version ${cluster.version}, skipping version update`); + return; + } + const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); + return { EksUpdateId: updateResponse.update?.id }; + } + async isActive() { + console.log('waiting for cluster to become ACTIVE'); + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); + const cluster = resp.cluster; + // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are + // not complete. note that the custom resource provider framework forbids + // returning attributes (Data) if isComplete is false. + if (cluster?.status === 'FAILED') { + // not very informative, unfortunately the response doesn't contain any error + // information :\ + throw new Error('Cluster is in a FAILED status'); + } + else if (cluster?.status !== 'ACTIVE') { + return { + IsComplete: false, + }; + } + else { + return { + IsComplete: true, + Data: { + Name: cluster.name, + Endpoint: cluster.endpoint, + Arn: cluster.arn, + // IMPORTANT: CFN expects that attributes will *always* have values, + // so return an empty string in case the value is not defined. + // Otherwise, CFN will throw with `Vendor response doesn't contain + // XXXX key`. + CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', + ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', + OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', + OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', + // We can safely return the first item from encryption configuration array, because it has a limit of 1 item + // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig + EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', + }, + }; + } + } + async isEksUpdateComplete(eksUpdateId) { + this.log({ isEksUpdateComplete: eksUpdateId }); + const describeUpdateResponse = await this.eks.describeUpdate({ + name: this.clusterName, + updateId: eksUpdateId, + }); + this.log({ describeUpdateResponse }); + if (!describeUpdateResponse.update) { + throw new Error(`unable to describe update with id "${eksUpdateId}"`); + } + switch (describeUpdateResponse.update.status) { + case 'InProgress': + return false; + case 'Successful': + return true; + case 'Failed': + case 'Cancelled': + throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); + default: + throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); + } + } + generateClusterName() { + const suffix = this.requestId.replace(/-/g, ''); // 32 chars + const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; + const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); + return `${prefix}-${suffix}`; + } +} +exports.ClusterResourceHandler = ClusterResourceHandler; +function parseProps(props) { + const parsed = props?.Config ?? {}; + // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. + // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' + if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; + } + if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; + } + if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { + parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; + } + return parsed; +} +function analyzeUpdate(oldProps, newProps) { + console.log('old props: ', JSON.stringify(oldProps)); + console.log('new props: ', JSON.stringify(newProps)); + const newVpcProps = newProps.resourcesVpcConfig || {}; + const oldVpcProps = oldProps.resourcesVpcConfig || {}; + const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); + const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); + const newEnc = newProps.encryptionConfig || {}; + const oldEnc = oldProps.encryptionConfig || {}; + return { + replaceName: newProps.name !== oldProps.name, + replaceVpc: JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), + updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || + newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || + !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), + replaceRole: newProps.roleArn !== oldProps.roleArn, + updateVersion: newProps.version !== oldProps.version, + updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), + updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), + }; +} +function setsEqual(first, second) { + return first.size === second.size && [...first].every((e) => second.has(e)); +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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LENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztRQUNuRSxhQUFhLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBa0IsRUFBRSxNQUFtQjtJQUN4RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgRWtzQ2xpZW50LCBSZXNvdXJjZUV2ZW50LCBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX05BTUVfTEVOID0gMTAwO1xuXG5leHBvcnQgY2xhc3MgQ2x1c3RlclJlc291cmNlSGFuZGxlciBleHRlbmRzIFJlc291cmNlSGFuZGxlciB7XG4gIHB1YmxpYyBnZXQgY2x1c3Rlck5hbWUoKSB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZGV0ZXJtaW5lIGNsdXN0ZXIgbmFtZSB3aXRob3V0IHBoeXNpY2FsIHJlc291cmNlIElEJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PjtcblxuICBjb25zdHJ1Y3Rvcihla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICBzdXBlcihla3MsIGV2ZW50KTtcblxuICAgIHRoaXMubmV3UHJvcHMgPSBwYXJzZVByb3BzKHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLm9sZFByb3BzID0gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnID8gcGFyc2VQcm9wcyhldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMpIDoge307XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gQ1JFQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCdvbkNyZWF0ZTogY3JlYXRpbmcgY2x1c3RlciB3aXRoIG9wdGlvbnM6JywgSlNPTi5zdHJpbmdpZnkodGhpcy5uZXdQcm9wcywgdW5kZWZpbmVkLCAyKSk7XG4gICAgaWYgKCF0aGlzLm5ld1Byb3BzLnJvbGVBcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJyb2xlQXJuXCIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyTmFtZSA9IHRoaXMubmV3UHJvcHMubmFtZSB8fCB0aGlzLmdlbmVyYXRlQ2x1c3Rlck5hbWUoKTtcblxuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmVrcy5jcmVhdGVDbHVzdGVyKHtcbiAgICAgIC4uLnRoaXMubmV3UHJvcHMsXG4gICAgICBuYW1lOiBjbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcC5jbHVzdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBjbHVzdGVyICR7Y2x1c3Rlck5hbWV9OiBDcmVhdGVDbHVzdGVyIHJldHVybmVkIHdpdGhvdXQgY2x1c3RlciBpbmZvcm1hdGlvbmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHJlc3AuY2x1c3Rlci5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIERFTEVURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25EZWxldGUoKTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgb25EZWxldGU6IGRlbGV0aW5nIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfWApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVrcy5kZWxldGVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyICR7dGhpcy5jbHVzdGVyTmFtZX0gbm90IGZvdW5kLCBpZGVtcG90ZW50bHkgc3VjY2VlZGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coYGlzRGVsZXRlQ29tcGxldGU6IHdhaXRpbmcgZm9yIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSB0byBiZSBkZWxldGVkYCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJldHVybmVkOicsIEpTT04uc3RyaW5naWZ5KHJlc3AsIHVuZGVmaW5lZCwgMikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICBjb25zb2xlLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgY2x1c3RlciBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0cnVlIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgZXJyb3I6JywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIFVQREFURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IGFuYWx5emVVcGRhdGUodGhpcy5vbGRQcm9wcywgdGhpcy5uZXdQcm9wcyk7XG4gICAgY29uc29sZS5sb2coJ29uVXBkYXRlOicsIEpTT04uc3RyaW5naWZ5KHsgdXBkYXRlcyB9LCB1bmRlZmluZWQsIDIpKTtcblxuICAgIC8vIHVwZGF0ZXMgdG8gZW5jcnlwdGlvbiBjb25maWcgaXMgbm90IHN1cHBvcnRlZFxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUVuY3J5cHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHVwZGF0ZSBjbHVzdGVyIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZXJlIGlzIGFuIHVwZGF0ZSB0aGF0IHJlcXVpcmVzIHJlcGxhY2VtZW50LCBnbyBhaGVhZCBhbmQganVzdCBjcmVhdGVcbiAgICAvLyBhIG5ldyBjbHVzdGVyIHdpdGggdGhlIG5ldyBjb25maWcuIFRoZSBvbGQgY2x1c3RlciB3aWxsIGF1dG9tYXRpY2FsbHkgYmVcbiAgICAvLyBkZWxldGVkIGJ5IGNsb3VkZm9ybWF0aW9uIHVwb24gc3VjY2Vzcy5cbiAgICBpZiAodXBkYXRlcy5yZXBsYWNlTmFtZSB8fCB1cGRhdGVzLnJlcGxhY2VSb2xlIHx8IHVwZGF0ZXMucmVwbGFjZVZwYykge1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgcmVwbGFjaW5nIHRoaXMgY2x1c3RlciBhbmQgdGhlIGNsdXN0ZXIgaGFzIGFuIGV4cGxpY2l0XG4gICAgICAvLyBwaHlzaWNhbCBuYW1lLCB0aGUgY3JlYXRpb24gb2YgdGhlIG5ldyBjbHVzdGVyIHdpbGwgZmFpbCB3aXRoIFwidGhlcmUgaXNcbiAgICAgIC8vIGFscmVhZHkgYSBjbHVzdGVyIHdpdGggdGhhdCBuYW1lXCIuIHRoaXMgaXMgYSBjb21tb24gYmVoYXZpb3IgZm9yXG4gICAgICAvLyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZXMgdGhhdCBzdXBwb3J0IHNwZWNpZnlpbmcgYSBwaHlzaWNhbCBuYW1lLlxuICAgICAgaWYgKHRoaXMub2xkUHJvcHMubmFtZSA9PT0gdGhpcy5uZXdQcm9wcy5uYW1lICYmIHRoaXMub2xkUHJvcHMubmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXBsYWNlIGNsdXN0ZXIgXCIke3RoaXMub2xkUHJvcHMubmFtZX1cIiBzaW5jZSBpdCBoYXMgYW4gZXhwbGljaXQgcGh5c2ljYWwgbmFtZS4gRWl0aGVyIHJlbmFtZSB0aGUgY2x1c3RlciBvciByZW1vdmUgdGhlIFwibmFtZVwiIGNvbmZpZ3VyYXRpb25gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub25DcmVhdGUoKTtcbiAgICB9XG5cbiAgICAvLyBpZiBhIHZlcnNpb24gdXBkYXRlIGlzIHJlcXVpcmVkLCBpc3N1ZSB0aGUgdmVyc2lvbiB1cGRhdGVcbiAgICBpZiAodXBkYXRlcy51cGRhdGVWZXJzaW9uKSB7XG4gICAgICBpZiAoIXRoaXMubmV3UHJvcHMudmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZW1vdmUgY2x1c3RlciB2ZXJzaW9uIGNvbmZpZ3VyYXRpb24uIEN1cnJlbnQgdmVyc2lvbiBpcyAke3RoaXMub2xkUHJvcHMudmVyc2lvbn1gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlQ2x1c3RlclZlcnNpb24odGhpcy5uZXdQcm9wcy52ZXJzaW9uKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nICYmIHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1cGRhdGUgbG9nZ2luZyBhbmQgYWNjZXNzIGF0IHRoZSBzYW1lIHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nIHx8IHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICBjb25zdCBjb25maWc6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QgPSB7XG4gICAgICAgIG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgICB9O1xuICAgICAgaWYgKHVwZGF0ZXMudXBkYXRlTG9nZ2luZykge1xuICAgICAgICBjb25maWcubG9nZ2luZyA9IHRoaXMubmV3UHJvcHMubG9nZ2luZztcbiAgICAgIH07XG4gICAgICBpZiAodXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIGNsdXN0ZXIgd2l0aCBzZWN1cml0eUdyb3VwSWRzIGFuZCBzdWJuZXRJZHMgKGFzIHNwZWNpZmllZCBpbiB0aGUgd2FybmluZyBoZXJlOlxuICAgICAgICAvLyBodHRwczovL2F3c2NsaS5hbWF6b25hd3MuY29tL3YyL2RvY3VtZW50YXRpb24vYXBpL2xhdGVzdC9yZWZlcmVuY2UvZWtzL3VwZGF0ZS1jbHVzdGVyLWNvbmZpZy5odG1sKVxuICAgICAgICAvLyB3aWxsIGZhaWwsIHRoZXJlZm9yZSB3ZSB0YWtlIG9ubHkgdGhlIGFjY2VzcyBmaWVsZHMgZXhwbGljaXRseVxuICAgICAgICBjb25maWcucmVzb3VyY2VzVnBjQ29uZmlnID0ge1xuICAgICAgICAgIGVuZHBvaW50UHJpdmF0ZUFjY2VzczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzLFxuICAgICAgICAgIGVuZHBvaW50UHVibGljQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyxcbiAgICAgICAgICBwdWJsaWNBY2Nlc3NDaWRyczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcucHVibGljQWNjZXNzQ2lkcnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgICB9XG5cbiAgICAvLyBubyB1cGRhdGVzXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc29sZS5sb2coJ2lzVXBkYXRlQ29tcGxldGUnKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYW4gRUtTIHVwZGF0ZSwgd2Ugd2lsbCBtb25pdG9yIHRoZSB1cGRhdGUgZXZlbnQgaXRzZWxmXG4gICAgaWYgKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gYXdhaXQgdGhpcy5pc0Vrc1VwZGF0ZUNvbXBsZXRlKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpO1xuICAgICAgaWYgKCFjb21wbGV0ZSkge1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiBmYWxzZSB9O1xuICAgICAgfVxuXG4gICAgICAvLyBmYWxsIHRocm91Z2g6IGlmIHRoZSB1cGRhdGUgaXMgZG9uZSwgd2Ugc2ltcGx5IGRlbGVnYXRlIHRvIGlzQWN0aXZlKClcbiAgICAgIC8vIGluIG9yZGVyIHRvIGV4dHJhY3QgYXR0cmlidXRlcyBhbmQgc3RhdGUgZnJvbSB0aGUgY2x1c3RlciBpdHNlbGYsIHdoaWNoXG4gICAgICAvLyBpcyBzdXBwb3NlZCB0byBiZSBpbiBhbiBBQ1RJVkUgc3RhdGUgYWZ0ZXIgdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbHVzdGVyVmVyc2lvbihuZXdWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgdXBkYXRpbmcgY2x1c3RlciB2ZXJzaW9uIHRvICR7bmV3VmVyc2lvbn1gKTtcblxuICAgIC8vIHVwZGF0ZS1jbHVzdGVyLXZlcnNpb24gd2lsbCBmYWlsIGlmIHdlIHRyeSB0byB1cGRhdGUgdG8gdGhlIHNhbWUgdmVyc2lvbixcbiAgICAvLyBzbyBza2lwIGluIHRoaXMgY2FzZS5cbiAgICBjb25zdCBjbHVzdGVyID0gKGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSkpLmNsdXN0ZXI7XG4gICAgaWYgKGNsdXN0ZXI/LnZlcnNpb24gPT09IG5ld1ZlcnNpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyIGFscmVhZHkgYXQgdmVyc2lvbiAke2NsdXN0ZXIudmVyc2lvbn0sIHNraXBwaW5nIHZlcnNpb24gdXBkYXRlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy51cGRhdGVDbHVzdGVyVmVyc2lvbih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsIHZlcnNpb246IG5ld1ZlcnNpb24gfSk7XG4gICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNBY3RpdmUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZygnd2FpdGluZyBmb3IgY2x1c3RlciB0byBiZWNvbWUgQUNUSVZFJyk7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciByZXN1bHQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgY29uc3QgY2x1c3RlciA9IHJlc3AuY2x1c3RlcjtcblxuICAgIC8vIGlmIGNsdXN0ZXIgaXMgdW5kZWZpbmVkIChzaG91bGRudCBoYXBwZW4pIG9yIHN0YXR1cyBpcyBub3QgQUNUSVZFLCB3ZSBhcmVcbiAgICAvLyBub3QgY29tcGxldGUuIG5vdGUgdGhhdCB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZyYW1ld29yayBmb3JiaWRzXG4gICAgLy8gcmV0dXJuaW5nIGF0dHJpYnV0ZXMgKERhdGEpIGlmIGlzQ29tcGxldGUgaXMgZmFsc2UuXG4gICAgaWYgKGNsdXN0ZXI/LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgIC8vIG5vdCB2ZXJ5IGluZm9ybWF0aXZlLCB1bmZvcnR1bmF0ZWx5IHRoZSByZXNwb25zZSBkb2Vzbid0IGNvbnRhaW4gYW55IGVycm9yXG4gICAgICAvLyBpbmZvcm1hdGlvbiA6XFxcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2x1c3RlciBpcyBpbiBhIEZBSUxFRCBzdGF0dXMnKTtcbiAgICB9IGVsc2UgaWYgKGNsdXN0ZXI/LnN0YXR1cyAhPT0gJ0FDVElWRScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIE5hbWU6IGNsdXN0ZXIubmFtZSxcbiAgICAgICAgICBFbmRwb2ludDogY2x1c3Rlci5lbmRwb2ludCxcbiAgICAgICAgICBBcm46IGNsdXN0ZXIuYXJuLFxuXG4gICAgICAgICAgLy8gSU1QT1JUQU5UOiBDRk4gZXhwZWN0cyB0aGF0IGF0dHJpYnV0ZXMgd2lsbCAqYWx3YXlzKiBoYXZlIHZhbHVlcyxcbiAgICAgICAgICAvLyBzbyByZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGluIGNhc2UgdGhlIHZhbHVlIGlzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQ0ZOIHdpbGwgdGhyb3cgd2l0aCBgVmVuZG9yIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpblxuICAgICAgICAgIC8vIFhYWFgga2V5YC5cblxuICAgICAgICAgIENlcnRpZmljYXRlQXV0aG9yaXR5RGF0YTogY2x1c3Rlci5jZXJ0aWZpY2F0ZUF1dGhvcml0eT8uZGF0YSA/PyAnJyxcbiAgICAgICAgICBDbHVzdGVyU2VjdXJpdHlHcm91cElkOiBjbHVzdGVyLnJlc291cmNlc1ZwY0NvbmZpZz8uY2x1c3RlclNlY3VyaXR5R3JvdXBJZCA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyVXJsOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXIgPz8gJycsXG4gICAgICAgICAgT3BlbklkQ29ubmVjdElzc3VlcjogY2x1c3Rlci5pZGVudGl0eT8ub2lkYz8uaXNzdWVyPy5zdWJzdHJpbmcoOCkgPz8gJycsIC8vIFN0cmlwcyBvZmYgaHR0cHM6Ly8gZnJvbSB0aGUgaXNzdWVyIHVybFxuXG4gICAgICAgICAgLy8gV2UgY2FuIHNhZmVseSByZXR1cm4gdGhlIGZpcnN0IGl0ZW0gZnJvbSBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gYXJyYXksIGJlY2F1c2UgaXQgaGFzIGEgbGltaXQgb2YgMSBpdGVtXG4gICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vrcy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDbHVzdGVyLmh0bWwjQW1hem9uRUtTLUNyZWF0ZUNsdXN0ZXItcmVxdWVzdC1lbmNyeXB0aW9uQ29uZmlnXG4gICAgICAgICAgRW5jcnlwdGlvbkNvbmZpZ0tleUFybjogY2x1c3Rlci5lbmNyeXB0aW9uQ29uZmlnPy5zaGlmdCgpPy5wcm92aWRlcj8ua2V5QXJuID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzRWtzVXBkYXRlQ29tcGxldGUoZWtzVXBkYXRlSWQ6IHN0cmluZykge1xuICAgIHRoaXMubG9nKHsgaXNFa3NVcGRhdGVDb21wbGV0ZTogZWtzVXBkYXRlSWQgfSk7XG5cbiAgICBjb25zdCBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVVcGRhdGUoe1xuICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgIHVwZGF0ZUlkOiBla3NVcGRhdGVJZCxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nKHsgZGVzY3JpYmVVcGRhdGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5hYmxlIHRvIGRlc2NyaWJlIHVwZGF0ZSB3aXRoIGlkIFwiJHtla3NVcGRhdGVJZH1cImApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzKSB7XG4gICAgICBjYXNlICdJblByb2dyZXNzJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgY2FzZSAnU3VjY2Vzc2Z1bCc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnRmFpbGVkJzpcbiAgICAgIGNhc2UgJ0NhbmNlbGxlZCc6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2x1c3RlciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiIGZhaWxlZCB3aXRoIGVycm9yczogJHtKU09OLnN0cmluZ2lmeShkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5lcnJvcnMpfWApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIHN0YXR1cyBcIiR7ZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzfVwiIGZvciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNsdXN0ZXJOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9DTFVTVEVSX05BTUVfTEVOIC0gc3VmZml4Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5sb2dpY2FsUmVzb3VyY2VJZC5zbGljZSgwLCBvZmZzZXQgPiAwID8gb2Zmc2V0IDogMCk7XG4gICAgcmV0dXJuIGAke3ByZWZpeH0tJHtzdWZmaXh9YDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3BzKHByb3BzOiBhbnkpOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0IHtcblxuICBjb25zdCBwYXJzZWQgPSBwcm9wcz8uQ29uZmlnID8/IHt9O1xuXG4gIC8vIHRoaXMgaXMgd2VpcmQgYnV0IHRoZXNlIGJvb2xlYW4gcHJvcGVydGllcyBhcmUgcGFzc2VkIGJ5IENGTiBhcyBhIHN0cmluZywgYW5kIHdlIG5lZWQgdGhlbSB0byBiZSBib29sZWFuaWMgZm9yIHRoZSBTREsuXG4gIC8vIE90aGVyd2lzZSBpdCBmYWlscyB3aXRoICdVbmV4cGVjdGVkIFBhcmFtZXRlcjogcGFyYW1zLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgaXMgZXhwZWN0ZWQgdG8gYmUgYSBib29sZWFuJ1xuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWc/LmVuZHBvaW50UHJpdmF0ZUFjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9PT0gJ3RydWUnO1xuICB9XG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQdWJsaWNBY2Nlc3MpID09PSAnc3RyaW5nJykge1xuICAgIHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQubG9nZ2luZz8uY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCkgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9IHBhcnNlZC5sb2dnaW5nLmNsdXN0ZXJMb2dnaW5nWzBdLmVuYWJsZWQgPT09ICd0cnVlJztcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQ7XG5cbn1cblxuaW50ZXJmYWNlIFVwZGF0ZU1hcCB7XG4gIHJlcGxhY2VOYW1lOiBib29sZWFuOyAvLyBuYW1lXG4gIHJlcGxhY2VWcGM6IGJvb2xlYW47IC8vIHJlc291cmNlc1ZwY0NvbmZpZy5zdWJuZXRJZHMgYW5kIHNlY3VyaXR5R3JvdXBJZHNcbiAgcmVwbGFjZVJvbGU6IGJvb2xlYW47IC8vIHJvbGVBcm5cblxuICB1cGRhdGVWZXJzaW9uOiBib29sZWFuOyAvLyB2ZXJzaW9uXG4gIHVwZGF0ZUxvZ2dpbmc6IGJvb2xlYW47IC8vIGxvZ2dpbmdcbiAgdXBkYXRlRW5jcnlwdGlvbjogYm9vbGVhbjsgLy8gZW5jcnlwdGlvbiAoY2Fubm90IGJlIHVwZGF0ZWQpXG4gIHVwZGF0ZUFjY2VzczogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBhbmQgZW5kcG9pbnRQdWJsaWNBY2Nlc3Ncbn1cblxuZnVuY3Rpb24gYW5hbHl6ZVVwZGF0ZShvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PiwgbmV3UHJvcHM6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBVcGRhdGVNYXAge1xuICBjb25zb2xlLmxvZygnb2xkIHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShvbGRQcm9wcykpO1xuICBjb25zb2xlLmxvZygnbmV3IHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShuZXdQcm9wcykpO1xuXG4gIGNvbnN0IG5ld1ZwY1Byb3BzID0gbmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRWcGNQcm9wcyA9IG9sZFByb3BzLnJlc291cmNlc1ZwY0NvbmZpZyB8fCB7fTtcblxuICBjb25zdCBvbGRQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQob2xkVnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQobmV3VnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdFbmMgPSBuZXdQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRFbmMgPSBvbGRQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgcmVwbGFjZU5hbWU6IG5ld1Byb3BzLm5hbWUgIT09IG9sZFByb3BzLm5hbWUsXG4gICAgcmVwbGFjZVZwYzpcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnN1Ym5ldElkcz8uc29ydCgpKSAhPT0gSlNPTi5zdHJpbmdpZnkob2xkVnBjUHJvcHMuc3VibmV0SWRzPy5zb3J0KCkpIHx8XG4gICAgICBKU09OLnN0cmluZ2lmeShuZXdWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpICE9PSBKU09OLnN0cmluZ2lmeShvbGRWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpLFxuICAgIHVwZGF0ZUFjY2VzczpcbiAgICAgIG5ld1ZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQcml2YXRlQWNjZXNzIHx8XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFB1YmxpY0FjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgfHxcbiAgICAgICFzZXRzRXF1YWwobmV3UHVibGljQWNjZXNzQ2lkcnMsIG9sZFB1YmxpY0FjY2Vzc0NpZHJzKSxcbiAgICByZXBsYWNlUm9sZTogbmV3UHJvcHMucm9sZUFybiAhPT0gb2xkUHJvcHMucm9sZUFybixcbiAgICB1cGRhdGVWZXJzaW9uOiBuZXdQcm9wcy52ZXJzaW9uICE9PSBvbGRQcm9wcy52ZXJzaW9uLFxuICAgIHVwZGF0ZUVuY3J5cHRpb246IEpTT04uc3RyaW5naWZ5KG5ld0VuYykgIT09IEpTT04uc3RyaW5naWZ5KG9sZEVuYyksXG4gICAgdXBkYXRlTG9nZ2luZzogSlNPTi5zdHJpbmdpZnkobmV3UHJvcHMubG9nZ2luZykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFByb3BzLmxvZ2dpbmcpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzZXRzRXF1YWwoZmlyc3Q6IFNldDxzdHJpbmc+LCBzZWNvbmQ6IFNldDxzdHJpbmc+KSB7XG4gIHJldHVybiBmaXJzdC5zaXplID09PSBzZWNvbmQuc2l6ZSAmJiBbLi4uZmlyc3RdLmV2ZXJ5KChlOiBzdHJpbmcpID0+IHNlY29uZC5oYXMoZSkpO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts new file mode 100644 index 0000000000000..4b7fdda6d1dd1 --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts @@ -0,0 +1,344 @@ +/* eslint-disable no-console */ + +// eslint-disable-next-line import/no-extraneous-dependencies +import { IsCompleteResponse, OnEventResponse } from '@aws-cdk/custom-resources/lib/provider-framework/types'; +// eslint-disable-next-line import/no-extraneous-dependencies +import * as aws from 'aws-sdk'; +import { EksClient, ResourceEvent, ResourceHandler } from './common'; + +const MAX_CLUSTER_NAME_LEN = 100; + +export class ClusterResourceHandler extends ResourceHandler { + public get clusterName() { + if (!this.physicalResourceId) { + throw new Error('Cannot determine cluster name without physical resource ID'); + } + + return this.physicalResourceId; + } + + private readonly newProps: aws.EKS.CreateClusterRequest; + private readonly oldProps: Partial; + + constructor(eks: EksClient, event: ResourceEvent) { + super(eks, event); + + this.newProps = parseProps(this.event.ResourceProperties); + this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; + } + + // ------ + // CREATE + // ------ + + protected async onCreate(): Promise { + console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); + if (!this.newProps.roleArn) { + throw new Error('"roleArn" is required'); + } + + const clusterName = this.newProps.name || this.generateClusterName(); + + const resp = await this.eks.createCluster({ + ...this.newProps, + name: clusterName, + }); + + if (!resp.cluster) { + throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); + } + + return { + PhysicalResourceId: resp.cluster.name, + }; + } + + protected async isCreateComplete() { + return this.isActive(); + } + + // ------ + // DELETE + // ------ + + protected async onDelete(): Promise { + console.log(`onDelete: deleting cluster ${this.clusterName}`); + try { + await this.eks.deleteCluster({ name: this.clusterName }); + } catch (e) { + if (e.code !== 'ResourceNotFoundException') { + throw e; + } else { + console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); + } + } + return { + PhysicalResourceId: this.clusterName, + }; + } + + protected async isDeleteComplete(): Promise { + console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); + + try { + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); + } catch (e) { + if (e.code === 'ResourceNotFoundException') { + console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); + return { IsComplete: true }; + } + + console.log('describeCluster error:', e); + throw e; + } + + return { + IsComplete: false, + }; + } + + // ------ + // UPDATE + // ------ + + protected async onUpdate() { + const updates = analyzeUpdate(this.oldProps, this.newProps); + console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); + + // updates to encryption config is not supported + if (updates.updateEncryption) { + throw new Error('Cannot update cluster encryption configuration'); + } + + // if there is an update that requires replacement, go ahead and just create + // a new cluster with the new config. The old cluster will automatically be + // deleted by cloudformation upon success. + if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { + + // if we are replacing this cluster and the cluster has an explicit + // physical name, the creation of the new cluster will fail with "there is + // already a cluster with that name". this is a common behavior for + // CloudFormation resources that support specifying a physical name. + if (this.oldProps.name === this.newProps.name && this.oldProps.name) { + throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); + } + + return this.onCreate(); + } + + // if a version update is required, issue the version update + if (updates.updateVersion) { + if (!this.newProps.version) { + throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); + } + + return this.updateClusterVersion(this.newProps.version); + } + + if (updates.updateLogging && updates.updateAccess) { + throw new Error('Cannot update logging and access at the same time'); + } + + if (updates.updateLogging || updates.updateAccess) { + const config: aws.EKS.UpdateClusterConfigRequest = { + name: this.clusterName, + }; + if (updates.updateLogging) { + config.logging = this.newProps.logging; + }; + if (updates.updateAccess) { + // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: + // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) + // will fail, therefore we take only the access fields explicitly + config.resourcesVpcConfig = { + endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, + endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, + publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, + }; + } + const updateResponse = await this.eks.updateClusterConfig(config); + + return { EksUpdateId: updateResponse.update?.id }; + } + + // no updates + return; + } + + protected async isUpdateComplete() { + console.log('isUpdateComplete'); + + // if this is an EKS update, we will monitor the update event itself + if (this.event.EksUpdateId) { + const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); + if (!complete) { + return { IsComplete: false }; + } + + // fall through: if the update is done, we simply delegate to isActive() + // in order to extract attributes and state from the cluster itself, which + // is supposed to be in an ACTIVE state after the update is complete. + } + + return this.isActive(); + } + + private async updateClusterVersion(newVersion: string) { + console.log(`updating cluster version to ${newVersion}`); + + // update-cluster-version will fail if we try to update to the same version, + // so skip in this case. + const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; + if (cluster?.version === newVersion) { + console.log(`cluster already at version ${cluster.version}, skipping version update`); + return; + } + + const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); + return { EksUpdateId: updateResponse.update?.id }; + } + + private async isActive(): Promise { + console.log('waiting for cluster to become ACTIVE'); + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); + const cluster = resp.cluster; + + // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are + // not complete. note that the custom resource provider framework forbids + // returning attributes (Data) if isComplete is false. + if (cluster?.status === 'FAILED') { + // not very informative, unfortunately the response doesn't contain any error + // information :\ + throw new Error('Cluster is in a FAILED status'); + } else if (cluster?.status !== 'ACTIVE') { + return { + IsComplete: false, + }; + } else { + return { + IsComplete: true, + Data: { + Name: cluster.name, + Endpoint: cluster.endpoint, + Arn: cluster.arn, + + // IMPORTANT: CFN expects that attributes will *always* have values, + // so return an empty string in case the value is not defined. + // Otherwise, CFN will throw with `Vendor response doesn't contain + // XXXX key`. + + CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', + ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', + OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', + OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', // Strips off https:// from the issuer url + + // We can safely return the first item from encryption configuration array, because it has a limit of 1 item + // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig + EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', + }, + }; + } + } + + private async isEksUpdateComplete(eksUpdateId: string) { + this.log({ isEksUpdateComplete: eksUpdateId }); + + const describeUpdateResponse = await this.eks.describeUpdate({ + name: this.clusterName, + updateId: eksUpdateId, + }); + + this.log({ describeUpdateResponse }); + + if (!describeUpdateResponse.update) { + throw new Error(`unable to describe update with id "${eksUpdateId}"`); + } + + switch (describeUpdateResponse.update.status) { + case 'InProgress': + return false; + case 'Successful': + return true; + case 'Failed': + case 'Cancelled': + throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); + default: + throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); + } + } + + private generateClusterName() { + const suffix = this.requestId.replace(/-/g, ''); // 32 chars + const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; + const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); + return `${prefix}-${suffix}`; + } +} + +function parseProps(props: any): aws.EKS.CreateClusterRequest { + + const parsed = props?.Config ?? {}; + + // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. + // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' + + if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; + } + + if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; + } + + if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { + parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; + } + + return parsed; + +} + +interface UpdateMap { + replaceName: boolean; // name + replaceVpc: boolean; // resourcesVpcConfig.subnetIds and securityGroupIds + replaceRole: boolean; // roleArn + + updateVersion: boolean; // version + updateLogging: boolean; // logging + updateEncryption: boolean; // encryption (cannot be updated) + updateAccess: boolean; // resourcesVpcConfig.endpointPrivateAccess and endpointPublicAccess +} + +function analyzeUpdate(oldProps: Partial, newProps: aws.EKS.CreateClusterRequest): UpdateMap { + console.log('old props: ', JSON.stringify(oldProps)); + console.log('new props: ', JSON.stringify(newProps)); + + const newVpcProps = newProps.resourcesVpcConfig || {}; + const oldVpcProps = oldProps.resourcesVpcConfig || {}; + + const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); + const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); + const newEnc = newProps.encryptionConfig || {}; + const oldEnc = oldProps.encryptionConfig || {}; + + return { + replaceName: newProps.name !== oldProps.name, + replaceVpc: + JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), + updateAccess: + newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || + newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || + !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), + replaceRole: newProps.roleArn !== oldProps.roleArn, + updateVersion: newProps.version !== oldProps.version, + updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), + updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), + }; +} + +function setsEqual(first: Set, second: Set) { + return first.size === second.size && [...first].every((e: string) => second.has(e)); +} diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.js b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.js b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.js b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.js b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.563343f1aee007876e917a1bf685464df7e56190033d5ae5b9fd14d498e9c5ee/helm/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.563343f1aee007876e917a1bf685464df7e56190033d5ae5b9fd14d498e9c5ee/helm/__init__.py deleted file mode 100644 index 1d86804bd67d8..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.563343f1aee007876e917a1bf685464df7e56190033d5ae5b9fd14d498e9c5ee/helm/__init__.py +++ /dev/null @@ -1,187 +0,0 @@ -import json -import logging -import os -import re -import subprocess -import shutil -import tempfile -import zipfile -from urllib.parse import urlparse, unquote - -logger = logging.getLogger() -logger.setLevel(logging.INFO) - -# these are coming from the kubectl layer -os.environ['PATH'] = '/opt/helm:/opt/awscli:' + os.environ['PATH'] - -outdir = os.environ.get('TEST_OUTDIR', '/tmp') -kubeconfig = os.path.join(outdir, 'kubeconfig') - -def get_chart_asset_from_url(chart_asset_url): - chart_zip = os.path.join(outdir, 'chart.zip') - shutil.rmtree(chart_zip, ignore_errors=True) - subprocess.check_call(['aws', 's3', 'cp', chart_asset_url, chart_zip]) - chart_dir = os.path.join(outdir, 'chart') - shutil.rmtree(chart_dir, ignore_errors=True) - os.mkdir(chart_dir) - with zipfile.ZipFile(chart_zip, 'r') as zip_ref: - zip_ref.extractall(chart_dir) - return chart_dir - -def helm_handler(event, context): - logger.info(json.dumps(dict(event, ResponseURL='...'))) - - request_type = event['RequestType'] - props = event['ResourceProperties'] - - # resource properties - cluster_name = props['ClusterName'] - role_arn = props['RoleArn'] - release = props['Release'] - chart = props.get('Chart', None) - chart_asset_url = props.get('ChartAssetURL', None) - version = props.get('Version', None) - wait = props.get('Wait', False) - timeout = props.get('Timeout', None) - namespace = props.get('Namespace', None) - create_namespace = props.get('CreateNamespace', None) - repository = props.get('Repository', None) - values_text = props.get('Values', None) - - # "log in" to the cluster - subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig', - '--role-arn', role_arn, - '--name', cluster_name, - '--kubeconfig', kubeconfig - ]) - - if os.path.isfile(kubeconfig): - os.chmod(kubeconfig, 0o600) - - # Write out the values to a file and include them with the install and upgrade - values_file = None - if not request_type == "Delete" and not values_text is None: - values = json.loads(values_text) - values_file = os.path.join(outdir, 'values.yaml') - with open(values_file, "w") as f: - f.write(json.dumps(values, indent=2)) - - if request_type == 'Create' or request_type == 'Update': - # Ensure chart or chart_asset_url are set - if chart == None and chart_asset_url == None: - raise RuntimeError(f'chart or chartAsset must be specified') - - if chart_asset_url != None: - assert(chart==None) - assert(repository==None) - assert(version==None) - if not chart_asset_url.startswith('s3://'): - raise RuntimeError(f'ChartAssetURL must point to as s3 location but is {chart_asset_url}') - # future work: support versions from s3 assets - chart = get_chart_asset_from_url(chart_asset_url) - - if repository is not None and repository.startswith('oci://'): - tmpdir = tempfile.TemporaryDirectory() - chart_dir = get_chart_from_oci(tmpdir.name, repository, version) - chart = chart_dir - - helm('upgrade', release, chart, repository, values_file, namespace, version, wait, timeout, create_namespace) - elif request_type == "Delete": - try: - helm('uninstall', release, namespace=namespace, timeout=timeout) - except Exception as e: - logger.info("delete error: %s" % e) - - -def get_oci_cmd(repository, version): - # Generates OCI command based on pattern. Public ECR vs Private ECR are treated differently. - cmnd = [] - private_ecr_pattern = '\d+.dkr.ecr.[a-z]+-[a-z]+-\d.amazonaws.com' - public_ecr = 'public.ecr.aws' - - registry = repository.rsplit('/', 1)[0].replace('oci://', '') - - if re.fullmatch(private_ecr_pattern, registry) is not None: - logger.info("Found AWS private repository") - region = registry.replace('.amazonaws.com', '').split('.')[-1] - cmnd = [ - f"aws ecr get-login-password --region {region} | " \ - f"helm registry login --username AWS --password-stdin {registry}; helm pull {repository} --version {version} --untar" - ] - elif registry.startswith(public_ecr): - logger.info("Found AWS public repository, will use default region as deployment") - region = os.environ.get('AWS_REGION', 'us-east-1') - - cmnd = [ - f"aws ecr-public get-login-password --region {region} | " \ - f"helm registry login --username AWS --password-stdin {public_ecr}; helm pull {repository} --version {version} --untar" - ] - else: - logger.error("OCI repository format not recognized, falling back to helm pull") - cmnd = ['helm', 'pull', repository, '--version', version, '--untar'] - - return cmnd - - -def get_chart_from_oci(tmpdir, repository = None, version = None): - - cmnd = get_oci_cmd(repository, version) - - maxAttempts = 3 - retry = maxAttempts - while retry > 0: - try: - logger.info(cmnd) - output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=tmpdir, shell=True) - logger.info(output) - - return os.path.join(tmpdir, repository.rpartition('/')[-1]) - except subprocess.CalledProcessError as exc: - output = exc.output - if b'Broken pipe' in output: - retry = retry - 1 - logger.info("Broken pipe, retries left: %s" % retry) - else: - raise Exception(output) - raise Exception(f'Operation failed after {maxAttempts} attempts: {output}') - - -def helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None): - import subprocess - - cmnd = ['helm', verb, release] - if not chart is None: - cmnd.append(chart) - if verb == 'upgrade': - cmnd.append('--install') - if create_namespace: - cmnd.append('--create-namespace') - if not repo is None: - cmnd.extend(['--repo', repo]) - if not file is None: - cmnd.extend(['--values', file]) - if not version is None: - cmnd.extend(['--version', version]) - if not namespace is None: - cmnd.extend(['--namespace', namespace]) - if wait: - cmnd.append('--wait') - if not timeout is None: - cmnd.extend(['--timeout', timeout]) - cmnd.extend(['--kubeconfig', kubeconfig]) - - maxAttempts = 3 - retry = maxAttempts - while retry > 0: - try: - output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir) - logger.info(output) - return - except subprocess.CalledProcessError as exc: - output = exc.output - if b'Broken pipe' in output: - retry = retry - 1 - logger.info("Broken pipe, retries left: %s" % retry) - else: - raise Exception(output) - raise Exception(f'Operation failed after {maxAttempts} attempts: {output}') diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip index d7cb484796289..f62fe1e5a06d6 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip index e3828a91bf834..13983109fc5f5 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.563343f1aee007876e917a1bf685464df7e56190033d5ae5b9fd14d498e9c5ee/apply/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.563343f1aee007876e917a1bf685464df7e56190033d5ae5b9fd14d498e9c5ee/apply/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.563343f1aee007876e917a1bf685464df7e56190033d5ae5b9fd14d498e9c5ee/get/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.563343f1aee007876e917a1bf685464df7e56190033d5ae5b9fd14d498e9c5ee/get/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py new file mode 100644 index 0000000000000..286976ced219a --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py @@ -0,0 +1,187 @@ +import json +import logging +import os +import re +import subprocess +import shutil +import tempfile +import zipfile + +logger = logging.getLogger() +logger.setLevel(logging.INFO) + +# these are coming from the kubectl layer +os.environ['PATH'] = '/opt/helm:/opt/awscli:' + os.environ['PATH'] + +outdir = os.environ.get('TEST_OUTDIR', '/tmp') +kubeconfig = os.path.join(outdir, 'kubeconfig') + +def get_chart_asset_from_url(chart_asset_url): + chart_zip = os.path.join(outdir, 'chart.zip') + shutil.rmtree(chart_zip, ignore_errors=True) + subprocess.check_call(['aws', 's3', 'cp', chart_asset_url, chart_zip]) + chart_dir = os.path.join(outdir, 'chart') + shutil.rmtree(chart_dir, ignore_errors=True) + os.mkdir(chart_dir) + with zipfile.ZipFile(chart_zip, 'r') as zip_ref: + zip_ref.extractall(chart_dir) + return chart_dir + +def helm_handler(event, context): + logger.info(json.dumps(dict(event, ResponseURL='...'))) + + request_type = event['RequestType'] + props = event['ResourceProperties'] + + # resource properties + cluster_name = props['ClusterName'] + role_arn = props['RoleArn'] + release = props['Release'] + chart = props.get('Chart', None) + chart_asset_url = props.get('ChartAssetURL', None) + version = props.get('Version', None) + wait = props.get('Wait', False) + timeout = props.get('Timeout', None) + namespace = props.get('Namespace', None) + create_namespace = props.get('CreateNamespace', None) + repository = props.get('Repository', None) + values_text = props.get('Values', None) + + # "log in" to the cluster + subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig', + '--role-arn', role_arn, + '--name', cluster_name, + '--kubeconfig', kubeconfig + ]) + + if os.path.isfile(kubeconfig): + os.chmod(kubeconfig, 0o600) + + # Write out the values to a file and include them with the install and upgrade + values_file = None + if not request_type == "Delete" and not values_text is None: + values = json.loads(values_text) + values_file = os.path.join(outdir, 'values.yaml') + with open(values_file, "w") as f: + f.write(json.dumps(values, indent=2)) + + if request_type == 'Create' or request_type == 'Update': + # Ensure chart or chart_asset_url are set + if chart == None and chart_asset_url == None: + raise RuntimeError(f'chart or chartAsset must be specified') + + if chart_asset_url != None: + assert(chart==None) + assert(repository==None) + assert(version==None) + if not chart_asset_url.startswith('s3://'): + raise RuntimeError(f'ChartAssetURL must point to as s3 location but is {chart_asset_url}') + # future work: support versions from s3 assets + chart = get_chart_asset_from_url(chart_asset_url) + + if repository is not None and repository.startswith('oci://'): + tmpdir = tempfile.TemporaryDirectory() + chart_dir = get_chart_from_oci(tmpdir.name, repository, version) + chart = chart_dir + + helm('upgrade', release, chart, repository, values_file, namespace, version, wait, timeout, create_namespace) + elif request_type == "Delete": + try: + helm('uninstall', release, namespace=namespace, timeout=timeout) + except Exception as e: + logger.info("delete error: %s" % e) + + +def get_oci_cmd(repository, version): + # Generates OCI command based on pattern. Public ECR vs Private ECR are treated differently. + private_ecr_pattern = 'oci://(?P\d+.dkr.ecr.(?P[a-z]+-[a-z]+-\d).amazonaws.com)*' + public_ecr_pattern = 'oci://(?Ppublic.ecr.aws)*' + + private_registry = re.match(private_ecr_pattern, repository).groupdict() + public_registry = re.match(public_ecr_pattern, repository).groupdict() + + if private_registry['registry'] is not None: + logger.info("Found AWS private repository") + cmnd = [ + f"aws ecr get-login-password --region {private_registry['region']} | " \ + f"helm registry login --username AWS --password-stdin {private_registry['registry']}; helm pull {repository} --version {version} --untar" + ] + elif public_registry['registry'] is not None: + logger.info("Found AWS public repository, will use default region as deployment") + region = os.environ.get('AWS_REGION', 'us-east-1') + + cmnd = [ + f"aws ecr-public get-login-password --region us-east-1 | " \ + f"helm registry login --username AWS --password-stdin {public_registry['registry']}; helm pull {repository} --version {version} --untar" + ] + else: + logger.error("OCI repository format not recognized, falling back to helm pull") + cmnd = ['helm', 'pull', repository, '--version', version, '--untar'] + + return cmnd + + +def get_chart_from_oci(tmpdir, repository = None, version = None): + + cmnd = get_oci_cmd(repository, version) + + maxAttempts = 3 + retry = maxAttempts + while retry > 0: + try: + logger.info(cmnd) + output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=tmpdir, shell=True) + logger.info(output) + + # effectively returns "$tmpDir/$lastPartOfOCIUrl", because this is how helm pull saves OCI artifact. + # Eg. if we have oci://9999999999.dkr.ecr.us-east-1.amazonaws.com/foo/bar/pet-service repository, helm saves artifact under $tmpDir/pet-service + return os.path.join(tmpdir, repository.rpartition('/')[-1]) + except subprocess.CalledProcessError as exc: + output = exc.output + if b'Broken pipe' in output: + retry = retry - 1 + logger.info("Broken pipe, retries left: %s" % retry) + else: + raise Exception(output) + raise Exception(f'Operation failed after {maxAttempts} attempts: {output}') + + +def helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None): + import subprocess + + cmnd = ['helm', verb, release] + if not chart is None: + cmnd.append(chart) + if verb == 'upgrade': + cmnd.append('--install') + if create_namespace: + cmnd.append('--create-namespace') + if not repo is None: + cmnd.extend(['--repo', repo]) + if not file is None: + cmnd.extend(['--values', file]) + if not version is None: + cmnd.extend(['--version', version]) + if not namespace is None: + cmnd.extend(['--namespace', namespace]) + if wait: + cmnd.append('--wait') + if not timeout is None: + cmnd.extend(['--timeout', timeout]) + cmnd.extend(['--kubeconfig', kubeconfig]) + + maxAttempts = 3 + retry = maxAttempts + while retry > 0: + try: + output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir) + logger.info(output) + return + except subprocess.CalledProcessError as exc: + output = exc.output + if b'Broken pipe' in output: + retry = retry - 1 + logger.info("Broken pipe, retries left: %s" % retry) + else: + raise Exception(output) + raise Exception(f'Operation failed after {maxAttempts} attempts: {output}') diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.563343f1aee007876e917a1bf685464df7e56190033d5ae5b9fd14d498e9c5ee/index.py b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.563343f1aee007876e917a1bf685464df7e56190033d5ae5b9fd14d498e9c5ee/index.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.563343f1aee007876e917a1bf685464df7e56190033d5ae5b9fd14d498e9c5ee/patch/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.563343f1aee007876e917a1bf685464df7e56190033d5ae5b9fd14d498e9c5ee/patch/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip index 83790ed746b07..9bf8ba72b34ab 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/aws-cdk-eks-helm-test.assets.json b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/aws-cdk-eks-helm-test.assets.json index f20e6d04df408..11e0e1b19d794 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/aws-cdk-eks-helm-test.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/aws-cdk-eks-helm-test.assets.json @@ -1,5 +1,5 @@ { - "version": "29.0.0", + "version": "30.1.0", "files": { "c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064": { "source": { @@ -27,15 +27,15 @@ } } }, - "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5": { + "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee": { "source": { - "path": "asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5", + "path": "asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip", + "objectKey": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -53,15 +53,15 @@ } } }, - "563343f1aee007876e917a1bf685464df7e56190033d5ae5b9fd14d498e9c5ee": { + "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8": { "source": { - "path": "asset.563343f1aee007876e917a1bf685464df7e56190033d5ae5b9fd14d498e9c5ee", + "path": "asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "563343f1aee007876e917a1bf685464df7e56190033d5ae5b9fd14d498e9c5ee.zip", + "objectKey": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -92,7 +92,7 @@ } } }, - "d0ed18f830c9e49d64521037c4c2d872500fd7df2bc7d2d32ff2f59446d69f54": { + "013c608e5aa3f9b7c08666064fdbc7d257f19866887e2ea155c5b189fdfd6f0f": { "source": { "path": "awscdkekshelmtestawscdkawseksClusterResourceProviderB64048CD.nested.template.json", "packaging": "file" @@ -100,12 +100,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "d0ed18f830c9e49d64521037c4c2d872500fd7df2bc7d2d32ff2f59446d69f54.json", + "objectKey": "013c608e5aa3f9b7c08666064fdbc7d257f19866887e2ea155c5b189fdfd6f0f.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "dcb6b679999203518cf8e747008ba448af7bc6502f87c2b869ca87565786b67d": { + "75cb3907a84a56903beb94d07a13f98c8f205e4c2592eca626920d0e31119d45": { "source": { "path": "awscdkekshelmtestawscdkawseksKubectlProvider207F42E4.nested.template.json", "packaging": "file" @@ -113,12 +113,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "dcb6b679999203518cf8e747008ba448af7bc6502f87c2b869ca87565786b67d.json", + "objectKey": "75cb3907a84a56903beb94d07a13f98c8f205e4c2592eca626920d0e31119d45.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "9a8f080c5f01d52249f35aadae7fa8b7400e3d8d799422e7ce845995c7914eb7": { + "60857bca8b2d47131d19f9e53e3cfc304441787c56ab3ca35883021a9924a793": { "source": { "path": "aws-cdk-eks-helm-test.template.json", "packaging": "file" @@ -126,7 +126,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "9a8f080c5f01d52249f35aadae7fa8b7400e3d8d799422e7ce845995c7914eb7.json", + "objectKey": "60857bca8b2d47131d19f9e53e3cfc304441787c56ab3ca35883021a9924a793.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/aws-cdk-eks-helm-test.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/aws-cdk-eks-helm-test.template.json index 8867747159819..faba886e3e890 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/aws-cdk-eks-helm-test.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/aws-cdk-eks-helm-test.template.json @@ -992,7 +992,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/d0ed18f830c9e49d64521037c4c2d872500fd7df2bc7d2d32ff2f59446d69f54.json" + "/013c608e5aa3f9b7c08666064fdbc7d257f19866887e2ea155c5b189fdfd6f0f.json" ] ] }, @@ -1027,7 +1027,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/dcb6b679999203518cf8e747008ba448af7bc6502f87c2b869ca87565786b67d.json" + "/75cb3907a84a56903beb94d07a13f98c8f205e4c2592eca626920d0e31119d45.json" ] ] }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/awscdkekshelmDefaultTestDeployAssert044A589A.assets.json b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/awscdkekshelmDefaultTestDeployAssert044A589A.assets.json index bf373fcb2d4ba..2993275ee1385 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/awscdkekshelmDefaultTestDeployAssert044A589A.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/awscdkekshelmDefaultTestDeployAssert044A589A.assets.json @@ -1,5 +1,5 @@ { - "version": "29.0.0", + "version": "30.1.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/awscdkekshelmtestawscdkawseksClusterResourceProviderB64048CD.nested.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/awscdkekshelmtestawscdkawseksClusterResourceProviderB64048CD.nested.template.json index 4187fe2aae9e4..cf76c0a4dc67e 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/awscdkekshelmtestawscdkawseksClusterResourceProviderB64048CD.nested.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/awscdkekshelmtestawscdkawseksClusterResourceProviderB64048CD.nested.template.json @@ -73,7 +73,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ @@ -162,7 +162,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/awscdkekshelmtestawscdkawseksKubectlProvider207F42E4.nested.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/awscdkekshelmtestawscdkawseksKubectlProvider207F42E4.nested.template.json index 0fadf56a7829b..933401166ba6a 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/awscdkekshelmtestawscdkawseksKubectlProvider207F42E4.nested.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/awscdkekshelmtestawscdkawseksKubectlProvider207F42E4.nested.template.json @@ -51,6 +51,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -133,7 +145,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "563343f1aee007876e917a1bf685464df7e56190033d5ae5b9fd14d498e9c5ee.zip" + "S3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/cdk.out b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/cdk.out index d8b441d447f8a..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"29.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/integ.json b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/integ.json index 467521ffceb4e..dc7128ee4bbc7 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "29.0.0", + "version": "30.1.0", "testCases": { "aws-cdk-eks-helm/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/manifest.json b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/manifest.json index 3fcf4ec11976d..6e2dc2a0a68c6 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "29.0.0", + "version": "30.1.0", "artifacts": { "aws-cdk-eks-helm-test.assets": { "type": "cdk:asset-manifest", @@ -17,7 +17,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/9a8f080c5f01d52249f35aadae7fa8b7400e3d8d799422e7ce845995c7914eb7.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/60857bca8b2d47131d19f9e53e3cfc304441787c56ab3ca35883021a9924a793.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/tree.json b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/tree.json index 2d82b8334a8e8..8091d68af0fde 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/tree.json @@ -755,7 +755,7 @@ }, "constructInfo": { "fqn": "@aws-cdk/lambda-layer-kubectl-v24.KubectlV24Layer", - "version": "2.0.78" + "version": "2.0.100" } }, "Cluster": { @@ -1019,7 +1019,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.209" + "version": "10.1.252" } }, "KubectlReadyBarrier": { @@ -1511,7 +1511,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -1684,7 +1684,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -2525,7 +2525,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.209" + "version": "10.1.252" } } }, @@ -2582,7 +2582,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/d0ed18f830c9e49d64521037c4c2d872500fd7df2bc7d2d32ff2f59446d69f54.json" + "/013c608e5aa3f9b7c08666064fdbc7d257f19866887e2ea155c5b189fdfd6f0f.json" ] ] }, @@ -2604,7 +2604,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.209" + "version": "10.1.252" } }, "@aws-cdk--aws-eks.KubectlProvider": { @@ -2681,6 +2681,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -2821,7 +2833,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "563343f1aee007876e917a1bf685464df7e56190033d5ae5b9fd14d498e9c5ee.zip" + "s3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "role": { "Fn::GetAtt": [ @@ -3243,7 +3255,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/dcb6b679999203518cf8e747008ba448af7bc6502f87c2b869ca87565786b67d.json" + "/75cb3907a84a56903beb94d07a13f98c8f205e4c2592eca626920d0e31119d45.json" ] ] }, @@ -3286,7 +3298,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.209" + "version": "10.1.252" } }, "ChartAsset": { @@ -3350,7 +3362,7 @@ "path": "aws-cdk-eks-helm/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.209" + "version": "10.1.252" } }, "DeployAssert": { @@ -3396,7 +3408,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.209" + "version": "10.1.252" } } }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/helm/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/helm/__init__.py deleted file mode 100644 index b9a741c8972c4..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/helm/__init__.py +++ /dev/null @@ -1,187 +0,0 @@ -import json -import logging -import os -import re -import subprocess -import shutil -import tempfile -import zipfile -from urllib.parse import urlparse, unquote - -logger = logging.getLogger() -logger.setLevel(logging.INFO) - -# these are coming from the kubectl layer -os.environ['PATH'] = '/opt/helm:/opt/awscli:' + os.environ['PATH'] - -outdir = os.environ.get('TEST_OUTDIR', '/tmp') -kubeconfig = os.path.join(outdir, 'kubeconfig') - -def get_chart_asset_from_url(chart_asset_url): - chart_zip = os.path.join(outdir, 'chart.zip') - shutil.rmtree(chart_zip, ignore_errors=True) - subprocess.check_call(['aws', 's3', 'cp', chart_asset_url, chart_zip]) - chart_dir = os.path.join(outdir, 'chart') - shutil.rmtree(chart_dir, ignore_errors=True) - os.mkdir(chart_dir) - with zipfile.ZipFile(chart_zip, 'r') as zip_ref: - zip_ref.extractall(chart_dir) - return chart_dir - -def helm_handler(event, context): - logger.info(json.dumps(dict(event, ResponseURL='...'))) - - request_type = event['RequestType'] - props = event['ResourceProperties'] - - # resource properties - cluster_name = props['ClusterName'] - role_arn = props['RoleArn'] - release = props['Release'] - chart = props.get('Chart', None) - chart_asset_url = props.get('ChartAssetURL', None) - version = props.get('Version', None) - wait = props.get('Wait', False) - timeout = props.get('Timeout', None) - namespace = props.get('Namespace', None) - create_namespace = props.get('CreateNamespace', None) - repository = props.get('Repository', None) - values_text = props.get('Values', None) - - # "log in" to the cluster - subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig', - '--role-arn', role_arn, - '--name', cluster_name, - '--kubeconfig', kubeconfig - ]) - - if os.path.isfile(kubeconfig): - os.chmod(kubeconfig, 0o600) - - # Write out the values to a file and include them with the install and upgrade - values_file = None - if not request_type == "Delete" and not values_text is None: - values = json.loads(values_text) - values_file = os.path.join(outdir, 'values.yaml') - with open(values_file, "w") as f: - f.write(json.dumps(values, indent=2)) - - if request_type == 'Create' or request_type == 'Update': - # Ensure chart or chart_asset_url are set - if chart == None and chart_asset_url == None: - raise RuntimeError(f'chart or chartAsset must be specified') - - if chart_asset_url != None: - assert(chart==None) - assert(repository==None) - assert(version==None) - if not chart_asset_url.startswith('s3://'): - raise RuntimeError(f'ChartAssetURL must point to as s3 location but is {chart_asset_url}') - # future work: support versions from s3 assets - chart = get_chart_asset_from_url(chart_asset_url) - - if repository is not None and repository.startswith('oci://'): - tmpdir = tempfile.TemporaryDirectory() - chart_dir = get_chart_from_oci(tmpdir.name, release, repository, version) - chart = chart_dir - - helm('upgrade', release, chart, repository, values_file, namespace, version, wait, timeout, create_namespace) - elif request_type == "Delete": - try: - helm('uninstall', release, namespace=namespace, timeout=timeout) - except Exception as e: - logger.info("delete error: %s" % e) - - -def get_oci_cmd(repository, version): - # Generates OCI command based on pattern. Public ECR vs Private ECR are treated differently. - cmnd = [] - private_ecr_pattern = '\d+.dkr.ecr.[a-z]+-[a-z]+-\d.amazonaws.com' - public_ecr = 'public.ecr.aws' - - registry = repository.rsplit('/', 1)[0].replace('oci://', '') - - if re.fullmatch(private_ecr_pattern, registry) is not None: - logger.info("Found AWS private repository") - region = registry.replace('.amazonaws.com', '').split('.')[-1] - cmnd = [ - f"aws ecr get-login-password --region {region} | " \ - f"helm registry login --username AWS --password-stdin {registry}; helm pull {repository} --version {version} --untar" - ] - elif registry.startswith(public_ecr): - logger.info("Found AWS public repository, will use default region as deployment") - region = os.environ.get('AWS_REGION', 'us-east-1') - - cmnd = [ - f"aws ecr-public get-login-password --region {region} | " \ - f"helm registry login --username AWS --password-stdin {public_ecr}; helm pull {repository} --version {version} --untar" - ] - else: - logger.error("OCI repository format not recognized, falling back to helm pull") - cmnd = ['helm', 'pull', repository, '--version', version, '--untar'] - - return cmnd - - -def get_chart_from_oci(tmpdir, release, repository = None, version = None): - - cmnd = get_oci_cmd(repository, version) - - maxAttempts = 3 - retry = maxAttempts - while retry > 0: - try: - logger.info(cmnd) - output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=tmpdir, shell=True) - logger.info(output) - - return os.path.join(tmpdir, release) - except subprocess.CalledProcessError as exc: - output = exc.output - if b'Broken pipe' in output: - retry = retry - 1 - logger.info("Broken pipe, retries left: %s" % retry) - else: - raise Exception(output) - raise Exception(f'Operation failed after {maxAttempts} attempts: {output}') - - -def helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None): - import subprocess - - cmnd = ['helm', verb, release] - if not chart is None: - cmnd.append(chart) - if verb == 'upgrade': - cmnd.append('--install') - if create_namespace: - cmnd.append('--create-namespace') - if not repo is None: - cmnd.extend(['--repo', repo]) - if not file is None: - cmnd.extend(['--values', file]) - if not version is None: - cmnd.extend(['--version', version]) - if not namespace is None: - cmnd.extend(['--namespace', namespace]) - if wait: - cmnd.append('--wait') - if not timeout is None: - cmnd.extend(['--timeout', timeout]) - cmnd.extend(['--kubeconfig', kubeconfig]) - - maxAttempts = 3 - retry = maxAttempts - while retry > 0: - try: - output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir) - logger.info(output) - return - except subprocess.CalledProcessError as exc: - output = exc.output - if b'Broken pipe' in output: - retry = retry - 1 - logger.info("Broken pipe, retries left: %s" % retry) - else: - raise Exception(output) - raise Exception(f'Operation failed after {maxAttempts} attempts: {output}') diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js new file mode 100644 index 0000000000000..c9dc1b8d2c19a --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js @@ -0,0 +1,273 @@ +"use strict"; +/* eslint-disable no-console */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ClusterResourceHandler = void 0; +const common_1 = require("./common"); +const MAX_CLUSTER_NAME_LEN = 100; +class ClusterResourceHandler extends common_1.ResourceHandler { + constructor(eks, event) { + super(eks, event); + this.newProps = parseProps(this.event.ResourceProperties); + this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; + } + get clusterName() { + if (!this.physicalResourceId) { + throw new Error('Cannot determine cluster name without physical resource ID'); + } + return this.physicalResourceId; + } + // ------ + // CREATE + // ------ + async onCreate() { + console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); + if (!this.newProps.roleArn) { + throw new Error('"roleArn" is required'); + } + const clusterName = this.newProps.name || this.generateClusterName(); + const resp = await this.eks.createCluster({ + ...this.newProps, + name: clusterName, + }); + if (!resp.cluster) { + throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); + } + return { + PhysicalResourceId: resp.cluster.name, + }; + } + async isCreateComplete() { + return this.isActive(); + } + // ------ + // DELETE + // ------ + async onDelete() { + console.log(`onDelete: deleting cluster ${this.clusterName}`); + try { + await this.eks.deleteCluster({ name: this.clusterName }); + } + catch (e) { + if (e.code !== 'ResourceNotFoundException') { + throw e; + } + else { + console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); + } + } + return { + PhysicalResourceId: this.clusterName, + }; + } + async isDeleteComplete() { + console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); + try { + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); + } + catch (e) { + if (e.code === 'ResourceNotFoundException') { + console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); + return { IsComplete: true }; + } + console.log('describeCluster error:', e); + throw e; + } + return { + IsComplete: false, + }; + } + // ------ + // UPDATE + // ------ + async onUpdate() { + const updates = analyzeUpdate(this.oldProps, this.newProps); + console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); + // updates to encryption config is not supported + if (updates.updateEncryption) { + throw new Error('Cannot update cluster encryption configuration'); + } + // if there is an update that requires replacement, go ahead and just create + // a new cluster with the new config. The old cluster will automatically be + // deleted by cloudformation upon success. + if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { + // if we are replacing this cluster and the cluster has an explicit + // physical name, the creation of the new cluster will fail with "there is + // already a cluster with that name". this is a common behavior for + // CloudFormation resources that support specifying a physical name. + if (this.oldProps.name === this.newProps.name && this.oldProps.name) { + throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); + } + return this.onCreate(); + } + // if a version update is required, issue the version update + if (updates.updateVersion) { + if (!this.newProps.version) { + throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); + } + return this.updateClusterVersion(this.newProps.version); + } + if (updates.updateLogging && updates.updateAccess) { + throw new Error('Cannot update logging and access at the same time'); + } + if (updates.updateLogging || updates.updateAccess) { + const config = { + name: this.clusterName, + }; + if (updates.updateLogging) { + config.logging = this.newProps.logging; + } + ; + if (updates.updateAccess) { + // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: + // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) + // will fail, therefore we take only the access fields explicitly + config.resourcesVpcConfig = { + endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, + endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, + publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, + }; + } + const updateResponse = await this.eks.updateClusterConfig(config); + return { EksUpdateId: updateResponse.update?.id }; + } + // no updates + return; + } + async isUpdateComplete() { + console.log('isUpdateComplete'); + // if this is an EKS update, we will monitor the update event itself + if (this.event.EksUpdateId) { + const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); + if (!complete) { + return { IsComplete: false }; + } + // fall through: if the update is done, we simply delegate to isActive() + // in order to extract attributes and state from the cluster itself, which + // is supposed to be in an ACTIVE state after the update is complete. + } + return this.isActive(); + } + async updateClusterVersion(newVersion) { + console.log(`updating cluster version to ${newVersion}`); + // update-cluster-version will fail if we try to update to the same version, + // so skip in this case. + const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; + if (cluster?.version === newVersion) { + console.log(`cluster already at version ${cluster.version}, skipping version update`); + return; + } + const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); + return { EksUpdateId: updateResponse.update?.id }; + } + async isActive() { + console.log('waiting for cluster to become ACTIVE'); + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); + const cluster = resp.cluster; + // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are + // not complete. note that the custom resource provider framework forbids + // returning attributes (Data) if isComplete is false. + if (cluster?.status === 'FAILED') { + // not very informative, unfortunately the response doesn't contain any error + // information :\ + throw new Error('Cluster is in a FAILED status'); + } + else if (cluster?.status !== 'ACTIVE') { + return { + IsComplete: false, + }; + } + else { + return { + IsComplete: true, + Data: { + Name: cluster.name, + Endpoint: cluster.endpoint, + Arn: cluster.arn, + // IMPORTANT: CFN expects that attributes will *always* have values, + // so return an empty string in case the value is not defined. + // Otherwise, CFN will throw with `Vendor response doesn't contain + // XXXX key`. + CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', + ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', + OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', + OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', + // We can safely return the first item from encryption configuration array, because it has a limit of 1 item + // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig + EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', + }, + }; + } + } + async isEksUpdateComplete(eksUpdateId) { + this.log({ isEksUpdateComplete: eksUpdateId }); + const describeUpdateResponse = await this.eks.describeUpdate({ + name: this.clusterName, + updateId: eksUpdateId, + }); + this.log({ describeUpdateResponse }); + if (!describeUpdateResponse.update) { + throw new Error(`unable to describe update with id "${eksUpdateId}"`); + } + switch (describeUpdateResponse.update.status) { + case 'InProgress': + return false; + case 'Successful': + return true; + case 'Failed': + case 'Cancelled': + throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); + default: + throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); + } + } + generateClusterName() { + const suffix = this.requestId.replace(/-/g, ''); // 32 chars + const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; + const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); + return `${prefix}-${suffix}`; + } +} +exports.ClusterResourceHandler = ClusterResourceHandler; +function parseProps(props) { + const parsed = props?.Config ?? {}; + // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. + // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' + if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; + } + if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; + } + if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { + parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; + } + return parsed; +} +function analyzeUpdate(oldProps, newProps) { + console.log('old props: ', JSON.stringify(oldProps)); + console.log('new props: ', JSON.stringify(newProps)); + const newVpcProps = newProps.resourcesVpcConfig || {}; + const oldVpcProps = oldProps.resourcesVpcConfig || {}; + const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); + const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); + const newEnc = newProps.encryptionConfig || {}; + const oldEnc = oldProps.encryptionConfig || {}; + return { + replaceName: newProps.name !== oldProps.name, + replaceVpc: JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), + updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || + newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || + !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), + replaceRole: newProps.roleArn !== oldProps.roleArn, + updateVersion: newProps.version !== oldProps.version, + updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), + updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), + }; +} +function setsEqual(first, second) { + return first.size === second.size && [...first].every((e) => second.has(e)); +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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LENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztRQUNuRSxhQUFhLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBa0IsRUFBRSxNQUFtQjtJQUN4RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgRWtzQ2xpZW50LCBSZXNvdXJjZUV2ZW50LCBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX05BTUVfTEVOID0gMTAwO1xuXG5leHBvcnQgY2xhc3MgQ2x1c3RlclJlc291cmNlSGFuZGxlciBleHRlbmRzIFJlc291cmNlSGFuZGxlciB7XG4gIHB1YmxpYyBnZXQgY2x1c3Rlck5hbWUoKSB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZGV0ZXJtaW5lIGNsdXN0ZXIgbmFtZSB3aXRob3V0IHBoeXNpY2FsIHJlc291cmNlIElEJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PjtcblxuICBjb25zdHJ1Y3Rvcihla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICBzdXBlcihla3MsIGV2ZW50KTtcblxuICAgIHRoaXMubmV3UHJvcHMgPSBwYXJzZVByb3BzKHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLm9sZFByb3BzID0gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnID8gcGFyc2VQcm9wcyhldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMpIDoge307XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gQ1JFQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCdvbkNyZWF0ZTogY3JlYXRpbmcgY2x1c3RlciB3aXRoIG9wdGlvbnM6JywgSlNPTi5zdHJpbmdpZnkodGhpcy5uZXdQcm9wcywgdW5kZWZpbmVkLCAyKSk7XG4gICAgaWYgKCF0aGlzLm5ld1Byb3BzLnJvbGVBcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJyb2xlQXJuXCIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyTmFtZSA9IHRoaXMubmV3UHJvcHMubmFtZSB8fCB0aGlzLmdlbmVyYXRlQ2x1c3Rlck5hbWUoKTtcblxuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmVrcy5jcmVhdGVDbHVzdGVyKHtcbiAgICAgIC4uLnRoaXMubmV3UHJvcHMsXG4gICAgICBuYW1lOiBjbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcC5jbHVzdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBjbHVzdGVyICR7Y2x1c3Rlck5hbWV9OiBDcmVhdGVDbHVzdGVyIHJldHVybmVkIHdpdGhvdXQgY2x1c3RlciBpbmZvcm1hdGlvbmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHJlc3AuY2x1c3Rlci5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIERFTEVURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25EZWxldGUoKTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgb25EZWxldGU6IGRlbGV0aW5nIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfWApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVrcy5kZWxldGVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyICR7dGhpcy5jbHVzdGVyTmFtZX0gbm90IGZvdW5kLCBpZGVtcG90ZW50bHkgc3VjY2VlZGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coYGlzRGVsZXRlQ29tcGxldGU6IHdhaXRpbmcgZm9yIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSB0byBiZSBkZWxldGVkYCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJldHVybmVkOicsIEpTT04uc3RyaW5naWZ5KHJlc3AsIHVuZGVmaW5lZCwgMikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICBjb25zb2xlLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgY2x1c3RlciBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0cnVlIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgZXJyb3I6JywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIFVQREFURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IGFuYWx5emVVcGRhdGUodGhpcy5vbGRQcm9wcywgdGhpcy5uZXdQcm9wcyk7XG4gICAgY29uc29sZS5sb2coJ29uVXBkYXRlOicsIEpTT04uc3RyaW5naWZ5KHsgdXBkYXRlcyB9LCB1bmRlZmluZWQsIDIpKTtcblxuICAgIC8vIHVwZGF0ZXMgdG8gZW5jcnlwdGlvbiBjb25maWcgaXMgbm90IHN1cHBvcnRlZFxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUVuY3J5cHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHVwZGF0ZSBjbHVzdGVyIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZXJlIGlzIGFuIHVwZGF0ZSB0aGF0IHJlcXVpcmVzIHJlcGxhY2VtZW50LCBnbyBhaGVhZCBhbmQganVzdCBjcmVhdGVcbiAgICAvLyBhIG5ldyBjbHVzdGVyIHdpdGggdGhlIG5ldyBjb25maWcuIFRoZSBvbGQgY2x1c3RlciB3aWxsIGF1dG9tYXRpY2FsbHkgYmVcbiAgICAvLyBkZWxldGVkIGJ5IGNsb3VkZm9ybWF0aW9uIHVwb24gc3VjY2Vzcy5cbiAgICBpZiAodXBkYXRlcy5yZXBsYWNlTmFtZSB8fCB1cGRhdGVzLnJlcGxhY2VSb2xlIHx8IHVwZGF0ZXMucmVwbGFjZVZwYykge1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgcmVwbGFjaW5nIHRoaXMgY2x1c3RlciBhbmQgdGhlIGNsdXN0ZXIgaGFzIGFuIGV4cGxpY2l0XG4gICAgICAvLyBwaHlzaWNhbCBuYW1lLCB0aGUgY3JlYXRpb24gb2YgdGhlIG5ldyBjbHVzdGVyIHdpbGwgZmFpbCB3aXRoIFwidGhlcmUgaXNcbiAgICAgIC8vIGFscmVhZHkgYSBjbHVzdGVyIHdpdGggdGhhdCBuYW1lXCIuIHRoaXMgaXMgYSBjb21tb24gYmVoYXZpb3IgZm9yXG4gICAgICAvLyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZXMgdGhhdCBzdXBwb3J0IHNwZWNpZnlpbmcgYSBwaHlzaWNhbCBuYW1lLlxuICAgICAgaWYgKHRoaXMub2xkUHJvcHMubmFtZSA9PT0gdGhpcy5uZXdQcm9wcy5uYW1lICYmIHRoaXMub2xkUHJvcHMubmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXBsYWNlIGNsdXN0ZXIgXCIke3RoaXMub2xkUHJvcHMubmFtZX1cIiBzaW5jZSBpdCBoYXMgYW4gZXhwbGljaXQgcGh5c2ljYWwgbmFtZS4gRWl0aGVyIHJlbmFtZSB0aGUgY2x1c3RlciBvciByZW1vdmUgdGhlIFwibmFtZVwiIGNvbmZpZ3VyYXRpb25gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub25DcmVhdGUoKTtcbiAgICB9XG5cbiAgICAvLyBpZiBhIHZlcnNpb24gdXBkYXRlIGlzIHJlcXVpcmVkLCBpc3N1ZSB0aGUgdmVyc2lvbiB1cGRhdGVcbiAgICBpZiAodXBkYXRlcy51cGRhdGVWZXJzaW9uKSB7XG4gICAgICBpZiAoIXRoaXMubmV3UHJvcHMudmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZW1vdmUgY2x1c3RlciB2ZXJzaW9uIGNvbmZpZ3VyYXRpb24uIEN1cnJlbnQgdmVyc2lvbiBpcyAke3RoaXMub2xkUHJvcHMudmVyc2lvbn1gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlQ2x1c3RlclZlcnNpb24odGhpcy5uZXdQcm9wcy52ZXJzaW9uKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nICYmIHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1cGRhdGUgbG9nZ2luZyBhbmQgYWNjZXNzIGF0IHRoZSBzYW1lIHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nIHx8IHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICBjb25zdCBjb25maWc6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QgPSB7XG4gICAgICAgIG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgICB9O1xuICAgICAgaWYgKHVwZGF0ZXMudXBkYXRlTG9nZ2luZykge1xuICAgICAgICBjb25maWcubG9nZ2luZyA9IHRoaXMubmV3UHJvcHMubG9nZ2luZztcbiAgICAgIH07XG4gICAgICBpZiAodXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIGNsdXN0ZXIgd2l0aCBzZWN1cml0eUdyb3VwSWRzIGFuZCBzdWJuZXRJZHMgKGFzIHNwZWNpZmllZCBpbiB0aGUgd2FybmluZyBoZXJlOlxuICAgICAgICAvLyBodHRwczovL2F3c2NsaS5hbWF6b25hd3MuY29tL3YyL2RvY3VtZW50YXRpb24vYXBpL2xhdGVzdC9yZWZlcmVuY2UvZWtzL3VwZGF0ZS1jbHVzdGVyLWNvbmZpZy5odG1sKVxuICAgICAgICAvLyB3aWxsIGZhaWwsIHRoZXJlZm9yZSB3ZSB0YWtlIG9ubHkgdGhlIGFjY2VzcyBmaWVsZHMgZXhwbGljaXRseVxuICAgICAgICBjb25maWcucmVzb3VyY2VzVnBjQ29uZmlnID0ge1xuICAgICAgICAgIGVuZHBvaW50UHJpdmF0ZUFjY2VzczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzLFxuICAgICAgICAgIGVuZHBvaW50UHVibGljQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyxcbiAgICAgICAgICBwdWJsaWNBY2Nlc3NDaWRyczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcucHVibGljQWNjZXNzQ2lkcnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgICB9XG5cbiAgICAvLyBubyB1cGRhdGVzXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc29sZS5sb2coJ2lzVXBkYXRlQ29tcGxldGUnKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYW4gRUtTIHVwZGF0ZSwgd2Ugd2lsbCBtb25pdG9yIHRoZSB1cGRhdGUgZXZlbnQgaXRzZWxmXG4gICAgaWYgKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gYXdhaXQgdGhpcy5pc0Vrc1VwZGF0ZUNvbXBsZXRlKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpO1xuICAgICAgaWYgKCFjb21wbGV0ZSkge1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiBmYWxzZSB9O1xuICAgICAgfVxuXG4gICAgICAvLyBmYWxsIHRocm91Z2g6IGlmIHRoZSB1cGRhdGUgaXMgZG9uZSwgd2Ugc2ltcGx5IGRlbGVnYXRlIHRvIGlzQWN0aXZlKClcbiAgICAgIC8vIGluIG9yZGVyIHRvIGV4dHJhY3QgYXR0cmlidXRlcyBhbmQgc3RhdGUgZnJvbSB0aGUgY2x1c3RlciBpdHNlbGYsIHdoaWNoXG4gICAgICAvLyBpcyBzdXBwb3NlZCB0byBiZSBpbiBhbiBBQ1RJVkUgc3RhdGUgYWZ0ZXIgdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbHVzdGVyVmVyc2lvbihuZXdWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgdXBkYXRpbmcgY2x1c3RlciB2ZXJzaW9uIHRvICR7bmV3VmVyc2lvbn1gKTtcblxuICAgIC8vIHVwZGF0ZS1jbHVzdGVyLXZlcnNpb24gd2lsbCBmYWlsIGlmIHdlIHRyeSB0byB1cGRhdGUgdG8gdGhlIHNhbWUgdmVyc2lvbixcbiAgICAvLyBzbyBza2lwIGluIHRoaXMgY2FzZS5cbiAgICBjb25zdCBjbHVzdGVyID0gKGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSkpLmNsdXN0ZXI7XG4gICAgaWYgKGNsdXN0ZXI/LnZlcnNpb24gPT09IG5ld1ZlcnNpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyIGFscmVhZHkgYXQgdmVyc2lvbiAke2NsdXN0ZXIudmVyc2lvbn0sIHNraXBwaW5nIHZlcnNpb24gdXBkYXRlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy51cGRhdGVDbHVzdGVyVmVyc2lvbih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsIHZlcnNpb246IG5ld1ZlcnNpb24gfSk7XG4gICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNBY3RpdmUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZygnd2FpdGluZyBmb3IgY2x1c3RlciB0byBiZWNvbWUgQUNUSVZFJyk7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciByZXN1bHQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgY29uc3QgY2x1c3RlciA9IHJlc3AuY2x1c3RlcjtcblxuICAgIC8vIGlmIGNsdXN0ZXIgaXMgdW5kZWZpbmVkIChzaG91bGRudCBoYXBwZW4pIG9yIHN0YXR1cyBpcyBub3QgQUNUSVZFLCB3ZSBhcmVcbiAgICAvLyBub3QgY29tcGxldGUuIG5vdGUgdGhhdCB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZyYW1ld29yayBmb3JiaWRzXG4gICAgLy8gcmV0dXJuaW5nIGF0dHJpYnV0ZXMgKERhdGEpIGlmIGlzQ29tcGxldGUgaXMgZmFsc2UuXG4gICAgaWYgKGNsdXN0ZXI/LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgIC8vIG5vdCB2ZXJ5IGluZm9ybWF0aXZlLCB1bmZvcnR1bmF0ZWx5IHRoZSByZXNwb25zZSBkb2Vzbid0IGNvbnRhaW4gYW55IGVycm9yXG4gICAgICAvLyBpbmZvcm1hdGlvbiA6XFxcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2x1c3RlciBpcyBpbiBhIEZBSUxFRCBzdGF0dXMnKTtcbiAgICB9IGVsc2UgaWYgKGNsdXN0ZXI/LnN0YXR1cyAhPT0gJ0FDVElWRScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIE5hbWU6IGNsdXN0ZXIubmFtZSxcbiAgICAgICAgICBFbmRwb2ludDogY2x1c3Rlci5lbmRwb2ludCxcbiAgICAgICAgICBBcm46IGNsdXN0ZXIuYXJuLFxuXG4gICAgICAgICAgLy8gSU1QT1JUQU5UOiBDRk4gZXhwZWN0cyB0aGF0IGF0dHJpYnV0ZXMgd2lsbCAqYWx3YXlzKiBoYXZlIHZhbHVlcyxcbiAgICAgICAgICAvLyBzbyByZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGluIGNhc2UgdGhlIHZhbHVlIGlzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQ0ZOIHdpbGwgdGhyb3cgd2l0aCBgVmVuZG9yIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpblxuICAgICAgICAgIC8vIFhYWFgga2V5YC5cblxuICAgICAgICAgIENlcnRpZmljYXRlQXV0aG9yaXR5RGF0YTogY2x1c3Rlci5jZXJ0aWZpY2F0ZUF1dGhvcml0eT8uZGF0YSA/PyAnJyxcbiAgICAgICAgICBDbHVzdGVyU2VjdXJpdHlHcm91cElkOiBjbHVzdGVyLnJlc291cmNlc1ZwY0NvbmZpZz8uY2x1c3RlclNlY3VyaXR5R3JvdXBJZCA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyVXJsOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXIgPz8gJycsXG4gICAgICAgICAgT3BlbklkQ29ubmVjdElzc3VlcjogY2x1c3Rlci5pZGVudGl0eT8ub2lkYz8uaXNzdWVyPy5zdWJzdHJpbmcoOCkgPz8gJycsIC8vIFN0cmlwcyBvZmYgaHR0cHM6Ly8gZnJvbSB0aGUgaXNzdWVyIHVybFxuXG4gICAgICAgICAgLy8gV2UgY2FuIHNhZmVseSByZXR1cm4gdGhlIGZpcnN0IGl0ZW0gZnJvbSBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gYXJyYXksIGJlY2F1c2UgaXQgaGFzIGEgbGltaXQgb2YgMSBpdGVtXG4gICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vrcy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDbHVzdGVyLmh0bWwjQW1hem9uRUtTLUNyZWF0ZUNsdXN0ZXItcmVxdWVzdC1lbmNyeXB0aW9uQ29uZmlnXG4gICAgICAgICAgRW5jcnlwdGlvbkNvbmZpZ0tleUFybjogY2x1c3Rlci5lbmNyeXB0aW9uQ29uZmlnPy5zaGlmdCgpPy5wcm92aWRlcj8ua2V5QXJuID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzRWtzVXBkYXRlQ29tcGxldGUoZWtzVXBkYXRlSWQ6IHN0cmluZykge1xuICAgIHRoaXMubG9nKHsgaXNFa3NVcGRhdGVDb21wbGV0ZTogZWtzVXBkYXRlSWQgfSk7XG5cbiAgICBjb25zdCBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVVcGRhdGUoe1xuICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgIHVwZGF0ZUlkOiBla3NVcGRhdGVJZCxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nKHsgZGVzY3JpYmVVcGRhdGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5hYmxlIHRvIGRlc2NyaWJlIHVwZGF0ZSB3aXRoIGlkIFwiJHtla3NVcGRhdGVJZH1cImApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzKSB7XG4gICAgICBjYXNlICdJblByb2dyZXNzJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgY2FzZSAnU3VjY2Vzc2Z1bCc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnRmFpbGVkJzpcbiAgICAgIGNhc2UgJ0NhbmNlbGxlZCc6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2x1c3RlciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiIGZhaWxlZCB3aXRoIGVycm9yczogJHtKU09OLnN0cmluZ2lmeShkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5lcnJvcnMpfWApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIHN0YXR1cyBcIiR7ZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzfVwiIGZvciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNsdXN0ZXJOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9DTFVTVEVSX05BTUVfTEVOIC0gc3VmZml4Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5sb2dpY2FsUmVzb3VyY2VJZC5zbGljZSgwLCBvZmZzZXQgPiAwID8gb2Zmc2V0IDogMCk7XG4gICAgcmV0dXJuIGAke3ByZWZpeH0tJHtzdWZmaXh9YDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3BzKHByb3BzOiBhbnkpOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0IHtcblxuICBjb25zdCBwYXJzZWQgPSBwcm9wcz8uQ29uZmlnID8/IHt9O1xuXG4gIC8vIHRoaXMgaXMgd2VpcmQgYnV0IHRoZXNlIGJvb2xlYW4gcHJvcGVydGllcyBhcmUgcGFzc2VkIGJ5IENGTiBhcyBhIHN0cmluZywgYW5kIHdlIG5lZWQgdGhlbSB0byBiZSBib29sZWFuaWMgZm9yIHRoZSBTREsuXG4gIC8vIE90aGVyd2lzZSBpdCBmYWlscyB3aXRoICdVbmV4cGVjdGVkIFBhcmFtZXRlcjogcGFyYW1zLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgaXMgZXhwZWN0ZWQgdG8gYmUgYSBib29sZWFuJ1xuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWc/LmVuZHBvaW50UHJpdmF0ZUFjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9PT0gJ3RydWUnO1xuICB9XG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQdWJsaWNBY2Nlc3MpID09PSAnc3RyaW5nJykge1xuICAgIHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQubG9nZ2luZz8uY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCkgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9IHBhcnNlZC5sb2dnaW5nLmNsdXN0ZXJMb2dnaW5nWzBdLmVuYWJsZWQgPT09ICd0cnVlJztcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQ7XG5cbn1cblxuaW50ZXJmYWNlIFVwZGF0ZU1hcCB7XG4gIHJlcGxhY2VOYW1lOiBib29sZWFuOyAvLyBuYW1lXG4gIHJlcGxhY2VWcGM6IGJvb2xlYW47IC8vIHJlc291cmNlc1ZwY0NvbmZpZy5zdWJuZXRJZHMgYW5kIHNlY3VyaXR5R3JvdXBJZHNcbiAgcmVwbGFjZVJvbGU6IGJvb2xlYW47IC8vIHJvbGVBcm5cblxuICB1cGRhdGVWZXJzaW9uOiBib29sZWFuOyAvLyB2ZXJzaW9uXG4gIHVwZGF0ZUxvZ2dpbmc6IGJvb2xlYW47IC8vIGxvZ2dpbmdcbiAgdXBkYXRlRW5jcnlwdGlvbjogYm9vbGVhbjsgLy8gZW5jcnlwdGlvbiAoY2Fubm90IGJlIHVwZGF0ZWQpXG4gIHVwZGF0ZUFjY2VzczogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBhbmQgZW5kcG9pbnRQdWJsaWNBY2Nlc3Ncbn1cblxuZnVuY3Rpb24gYW5hbHl6ZVVwZGF0ZShvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PiwgbmV3UHJvcHM6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBVcGRhdGVNYXAge1xuICBjb25zb2xlLmxvZygnb2xkIHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShvbGRQcm9wcykpO1xuICBjb25zb2xlLmxvZygnbmV3IHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShuZXdQcm9wcykpO1xuXG4gIGNvbnN0IG5ld1ZwY1Byb3BzID0gbmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRWcGNQcm9wcyA9IG9sZFByb3BzLnJlc291cmNlc1ZwY0NvbmZpZyB8fCB7fTtcblxuICBjb25zdCBvbGRQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQob2xkVnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQobmV3VnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdFbmMgPSBuZXdQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRFbmMgPSBvbGRQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgcmVwbGFjZU5hbWU6IG5ld1Byb3BzLm5hbWUgIT09IG9sZFByb3BzLm5hbWUsXG4gICAgcmVwbGFjZVZwYzpcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnN1Ym5ldElkcz8uc29ydCgpKSAhPT0gSlNPTi5zdHJpbmdpZnkob2xkVnBjUHJvcHMuc3VibmV0SWRzPy5zb3J0KCkpIHx8XG4gICAgICBKU09OLnN0cmluZ2lmeShuZXdWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpICE9PSBKU09OLnN0cmluZ2lmeShvbGRWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpLFxuICAgIHVwZGF0ZUFjY2VzczpcbiAgICAgIG5ld1ZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQcml2YXRlQWNjZXNzIHx8XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFB1YmxpY0FjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgfHxcbiAgICAgICFzZXRzRXF1YWwobmV3UHVibGljQWNjZXNzQ2lkcnMsIG9sZFB1YmxpY0FjY2Vzc0NpZHJzKSxcbiAgICByZXBsYWNlUm9sZTogbmV3UHJvcHMucm9sZUFybiAhPT0gb2xkUHJvcHMucm9sZUFybixcbiAgICB1cGRhdGVWZXJzaW9uOiBuZXdQcm9wcy52ZXJzaW9uICE9PSBvbGRQcm9wcy52ZXJzaW9uLFxuICAgIHVwZGF0ZUVuY3J5cHRpb246IEpTT04uc3RyaW5naWZ5KG5ld0VuYykgIT09IEpTT04uc3RyaW5naWZ5KG9sZEVuYyksXG4gICAgdXBkYXRlTG9nZ2luZzogSlNPTi5zdHJpbmdpZnkobmV3UHJvcHMubG9nZ2luZykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFByb3BzLmxvZ2dpbmcpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzZXRzRXF1YWwoZmlyc3Q6IFNldDxzdHJpbmc+LCBzZWNvbmQ6IFNldDxzdHJpbmc+KSB7XG4gIHJldHVybiBmaXJzdC5zaXplID09PSBzZWNvbmQuc2l6ZSAmJiBbLi4uZmlyc3RdLmV2ZXJ5KChlOiBzdHJpbmcpID0+IHNlY29uZC5oYXMoZSkpO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts new file mode 100644 index 0000000000000..4b7fdda6d1dd1 --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts @@ -0,0 +1,344 @@ +/* eslint-disable no-console */ + +// eslint-disable-next-line import/no-extraneous-dependencies +import { IsCompleteResponse, OnEventResponse } from '@aws-cdk/custom-resources/lib/provider-framework/types'; +// eslint-disable-next-line import/no-extraneous-dependencies +import * as aws from 'aws-sdk'; +import { EksClient, ResourceEvent, ResourceHandler } from './common'; + +const MAX_CLUSTER_NAME_LEN = 100; + +export class ClusterResourceHandler extends ResourceHandler { + public get clusterName() { + if (!this.physicalResourceId) { + throw new Error('Cannot determine cluster name without physical resource ID'); + } + + return this.physicalResourceId; + } + + private readonly newProps: aws.EKS.CreateClusterRequest; + private readonly oldProps: Partial; + + constructor(eks: EksClient, event: ResourceEvent) { + super(eks, event); + + this.newProps = parseProps(this.event.ResourceProperties); + this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; + } + + // ------ + // CREATE + // ------ + + protected async onCreate(): Promise { + console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); + if (!this.newProps.roleArn) { + throw new Error('"roleArn" is required'); + } + + const clusterName = this.newProps.name || this.generateClusterName(); + + const resp = await this.eks.createCluster({ + ...this.newProps, + name: clusterName, + }); + + if (!resp.cluster) { + throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); + } + + return { + PhysicalResourceId: resp.cluster.name, + }; + } + + protected async isCreateComplete() { + return this.isActive(); + } + + // ------ + // DELETE + // ------ + + protected async onDelete(): Promise { + console.log(`onDelete: deleting cluster ${this.clusterName}`); + try { + await this.eks.deleteCluster({ name: this.clusterName }); + } catch (e) { + if (e.code !== 'ResourceNotFoundException') { + throw e; + } else { + console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); + } + } + return { + PhysicalResourceId: this.clusterName, + }; + } + + protected async isDeleteComplete(): Promise { + console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); + + try { + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); + } catch (e) { + if (e.code === 'ResourceNotFoundException') { + console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); + return { IsComplete: true }; + } + + console.log('describeCluster error:', e); + throw e; + } + + return { + IsComplete: false, + }; + } + + // ------ + // UPDATE + // ------ + + protected async onUpdate() { + const updates = analyzeUpdate(this.oldProps, this.newProps); + console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); + + // updates to encryption config is not supported + if (updates.updateEncryption) { + throw new Error('Cannot update cluster encryption configuration'); + } + + // if there is an update that requires replacement, go ahead and just create + // a new cluster with the new config. The old cluster will automatically be + // deleted by cloudformation upon success. + if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { + + // if we are replacing this cluster and the cluster has an explicit + // physical name, the creation of the new cluster will fail with "there is + // already a cluster with that name". this is a common behavior for + // CloudFormation resources that support specifying a physical name. + if (this.oldProps.name === this.newProps.name && this.oldProps.name) { + throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); + } + + return this.onCreate(); + } + + // if a version update is required, issue the version update + if (updates.updateVersion) { + if (!this.newProps.version) { + throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); + } + + return this.updateClusterVersion(this.newProps.version); + } + + if (updates.updateLogging && updates.updateAccess) { + throw new Error('Cannot update logging and access at the same time'); + } + + if (updates.updateLogging || updates.updateAccess) { + const config: aws.EKS.UpdateClusterConfigRequest = { + name: this.clusterName, + }; + if (updates.updateLogging) { + config.logging = this.newProps.logging; + }; + if (updates.updateAccess) { + // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: + // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) + // will fail, therefore we take only the access fields explicitly + config.resourcesVpcConfig = { + endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, + endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, + publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, + }; + } + const updateResponse = await this.eks.updateClusterConfig(config); + + return { EksUpdateId: updateResponse.update?.id }; + } + + // no updates + return; + } + + protected async isUpdateComplete() { + console.log('isUpdateComplete'); + + // if this is an EKS update, we will monitor the update event itself + if (this.event.EksUpdateId) { + const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); + if (!complete) { + return { IsComplete: false }; + } + + // fall through: if the update is done, we simply delegate to isActive() + // in order to extract attributes and state from the cluster itself, which + // is supposed to be in an ACTIVE state after the update is complete. + } + + return this.isActive(); + } + + private async updateClusterVersion(newVersion: string) { + console.log(`updating cluster version to ${newVersion}`); + + // update-cluster-version will fail if we try to update to the same version, + // so skip in this case. + const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; + if (cluster?.version === newVersion) { + console.log(`cluster already at version ${cluster.version}, skipping version update`); + return; + } + + const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); + return { EksUpdateId: updateResponse.update?.id }; + } + + private async isActive(): Promise { + console.log('waiting for cluster to become ACTIVE'); + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); + const cluster = resp.cluster; + + // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are + // not complete. note that the custom resource provider framework forbids + // returning attributes (Data) if isComplete is false. + if (cluster?.status === 'FAILED') { + // not very informative, unfortunately the response doesn't contain any error + // information :\ + throw new Error('Cluster is in a FAILED status'); + } else if (cluster?.status !== 'ACTIVE') { + return { + IsComplete: false, + }; + } else { + return { + IsComplete: true, + Data: { + Name: cluster.name, + Endpoint: cluster.endpoint, + Arn: cluster.arn, + + // IMPORTANT: CFN expects that attributes will *always* have values, + // so return an empty string in case the value is not defined. + // Otherwise, CFN will throw with `Vendor response doesn't contain + // XXXX key`. + + CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', + ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', + OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', + OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', // Strips off https:// from the issuer url + + // We can safely return the first item from encryption configuration array, because it has a limit of 1 item + // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig + EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', + }, + }; + } + } + + private async isEksUpdateComplete(eksUpdateId: string) { + this.log({ isEksUpdateComplete: eksUpdateId }); + + const describeUpdateResponse = await this.eks.describeUpdate({ + name: this.clusterName, + updateId: eksUpdateId, + }); + + this.log({ describeUpdateResponse }); + + if (!describeUpdateResponse.update) { + throw new Error(`unable to describe update with id "${eksUpdateId}"`); + } + + switch (describeUpdateResponse.update.status) { + case 'InProgress': + return false; + case 'Successful': + return true; + case 'Failed': + case 'Cancelled': + throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); + default: + throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); + } + } + + private generateClusterName() { + const suffix = this.requestId.replace(/-/g, ''); // 32 chars + const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; + const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); + return `${prefix}-${suffix}`; + } +} + +function parseProps(props: any): aws.EKS.CreateClusterRequest { + + const parsed = props?.Config ?? {}; + + // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. + // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' + + if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; + } + + if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; + } + + if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { + parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; + } + + return parsed; + +} + +interface UpdateMap { + replaceName: boolean; // name + replaceVpc: boolean; // resourcesVpcConfig.subnetIds and securityGroupIds + replaceRole: boolean; // roleArn + + updateVersion: boolean; // version + updateLogging: boolean; // logging + updateEncryption: boolean; // encryption (cannot be updated) + updateAccess: boolean; // resourcesVpcConfig.endpointPrivateAccess and endpointPublicAccess +} + +function analyzeUpdate(oldProps: Partial, newProps: aws.EKS.CreateClusterRequest): UpdateMap { + console.log('old props: ', JSON.stringify(oldProps)); + console.log('new props: ', JSON.stringify(newProps)); + + const newVpcProps = newProps.resourcesVpcConfig || {}; + const oldVpcProps = oldProps.resourcesVpcConfig || {}; + + const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); + const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); + const newEnc = newProps.encryptionConfig || {}; + const oldEnc = oldProps.encryptionConfig || {}; + + return { + replaceName: newProps.name !== oldProps.name, + replaceVpc: + JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), + updateAccess: + newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || + newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || + !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), + replaceRole: newProps.roleArn !== oldProps.roleArn, + updateVersion: newProps.version !== oldProps.version, + updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), + updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), + }; +} + +function setsEqual(first: Set, second: Set) { + return first.size === second.size && [...first].every((e: string) => second.has(e)); +} diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.js b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.js b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.js b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.js b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip index 593043af0139a..f62fe1e5a06d6 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js deleted file mode 100644 index 70203dcc42f3f..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js +++ /dev/null @@ -1,45 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.httpRequest = exports.invokeFunction = exports.startExecution = void 0; -/* istanbul ignore file */ -const https = require("https"); -// eslint-disable-next-line import/no-extraneous-dependencies -const AWS = require("aws-sdk"); -const FRAMEWORK_HANDLER_TIMEOUT = 900000; // 15 minutes -// In order to honor the overall maximum timeout set for the target process, -// the default 2 minutes from AWS SDK has to be overriden: -// https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html#httpOptions-property -const 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; -let lambda; -async function defaultStartExecution(req) { - if (!sfn) { - sfn = new AWS.StepFunctions(awsSdkConfig); - } - return sfn.startExecution(req).promise(); -} -async function defaultInvokeFunction(req) { - if (!lambda) { - lambda = new AWS.Lambda(awsSdkConfig); - } - return lambda.invoke(req).promise(); -} -exports.startExecution = defaultStartExecution; -exports.invokeFunction = defaultInvokeFunction; -exports.httpRequest = defaultHttpRequest; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3V0Ym91bmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJvdXRib3VuZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwwQkFBMEI7QUFDMUIsK0JBQStCO0FBQy9CLDZEQUE2RDtBQUM3RCwrQkFBK0I7QUFJL0IsTUFBTSx5QkFBeUIsR0FBRyxNQUFNLENBQUMsQ0FBQyxhQUFhO0FBRXZELDRFQUE0RTtBQUM1RSwwREFBMEQ7QUFDMUQsMkZBQTJGO0FBQzNGLE1BQU0sWUFBWSxHQUF5QjtJQUN6QyxXQUFXLEVBQUUsRUFBRSxPQUFPLEVBQUUseUJBQXlCLEVBQUU7Q0FDcEQsQ0FBQztBQUVGLEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxPQUE2QixFQUFFLFlBQW9CO0lBQ25GLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDckMsSUFBSTtZQUNGLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ2hELE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDNUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1NBQ2Y7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNYO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsSUFBSSxHQUFzQixDQUFDO0FBQzNCLElBQUksTUFBa0IsQ0FBQztBQUV2QixLQUFLLFVBQVUscUJBQXFCLENBQUMsR0FBMEM7SUFDN0UsSUFBSSxDQUFDLEdBQUcsRUFBRTtRQUNSLEdBQUcsR0FBRyxJQUFJLEdBQUcsQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUM7S0FDM0M7SUFFRCxPQUFPLEdBQUcsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7QUFDM0MsQ0FBQztBQUVELEtBQUssVUFBVSxxQkFBcUIsQ0FBQyxHQUFpQztJQUNwRSxJQUFJLENBQUMsTUFBTSxFQUFFO1FBQ1gsTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztLQUN2QztJQUVELE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztBQUN0QyxDQUFDO0FBRVUsUUFBQSxjQUFjLEdBQUcscUJBQXFCLENBQUM7QUFDdkMsUUFBQSxjQUFjLEdBQUcscUJBQXFCLENBQUM7QUFDdkMsUUFBQSxXQUFXLEdBQUcsa0JBQWtCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBpc3RhbmJ1bCBpZ25vcmUgZmlsZSAqL1xuaW1wb3J0ICogYXMgaHR0cHMgZnJvbSAnaHR0cHMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgQVdTIGZyb20gJ2F3cy1zZGsnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHR5cGUgeyBDb25maWd1cmF0aW9uT3B0aW9ucyB9IGZyb20gJ2F3cy1zZGsvbGliL2NvbmZpZy1iYXNlJztcblxuY29uc3QgRlJBTUVXT1JLX0hBTkRMRVJfVElNRU9VVCA9IDkwMDAwMDsgLy8gMTUgbWludXRlc1xuXG4vLyBJbiBvcmRlciB0byBob25vciB0aGUgb3ZlcmFsbCBtYXhpbXVtIHRpbWVvdXQgc2V0IGZvciB0aGUgdGFyZ2V0IHByb2Nlc3MsXG4vLyB0aGUgZGVmYXVsdCAyIG1pbnV0ZXMgZnJvbSBBV1MgU0RLIGhhcyB0byBiZSBvdmVycmlkZW46XG4vLyBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTSmF2YVNjcmlwdFNESy9sYXRlc3QvQVdTL0NvbmZpZy5odG1sI2h0dHBPcHRpb25zLXByb3BlcnR5XG5jb25zdCBhd3NTZGtDb25maWc6IENvbmZpZ3VyYXRpb25PcHRpb25zID0ge1xuICBodHRwT3B0aW9uczogeyB0aW1lb3V0OiBGUkFNRVdPUktfSEFORExFUl9USU1FT1VUIH0sXG59O1xuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0SHR0cFJlcXVlc3Qob3B0aW9uczogaHR0cHMuUmVxdWVzdE9wdGlvbnMsIHJlc3BvbnNlQm9keTogc3RyaW5nKSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlcXVlc3QgPSBodHRwcy5yZXF1ZXN0KG9wdGlvbnMsIHJlc29sdmUpO1xuICAgICAgcmVxdWVzdC5vbignZXJyb3InLCByZWplY3QpO1xuICAgICAgcmVxdWVzdC53cml0ZShyZXNwb25zZUJvZHkpO1xuICAgICAgcmVxdWVzdC5lbmQoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZWplY3QoZSk7XG4gICAgfVxuICB9KTtcbn1cblxubGV0IHNmbjogQVdTLlN0ZXBGdW5jdGlvbnM7XG5sZXQgbGFtYmRhOiBBV1MuTGFtYmRhO1xuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0U3RhcnRFeGVjdXRpb24ocmVxOiBBV1MuU3RlcEZ1bmN0aW9ucy5TdGFydEV4ZWN1dGlvbklucHV0KTogUHJvbWlzZTxBV1MuU3RlcEZ1bmN0aW9ucy5TdGFydEV4ZWN1dGlvbk91dHB1dD4ge1xuICBpZiAoIXNmbikge1xuICAgIHNmbiA9IG5ldyBBV1MuU3RlcEZ1bmN0aW9ucyhhd3NTZGtDb25maWcpO1xuICB9XG5cbiAgcmV0dXJuIHNmbi5zdGFydEV4ZWN1dGlvbihyZXEpLnByb21pc2UoKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdEludm9rZUZ1bmN0aW9uKHJlcTogQVdTLkxhbWJkYS5JbnZvY2F0aW9uUmVxdWVzdCk6IFByb21pc2U8QVdTLkxhbWJkYS5JbnZvY2F0aW9uUmVzcG9uc2U+IHtcbiAgaWYgKCFsYW1iZGEpIHtcbiAgICBsYW1iZGEgPSBuZXcgQVdTLkxhbWJkYShhd3NTZGtDb25maWcpO1xuICB9XG5cbiAgcmV0dXJuIGxhbWJkYS5pbnZva2UocmVxKS5wcm9taXNlKCk7XG59XG5cbmV4cG9ydCBsZXQgc3RhcnRFeGVjdXRpb24gPSBkZWZhdWx0U3RhcnRFeGVjdXRpb247XG5leHBvcnQgbGV0IGludm9rZUZ1bmN0aW9uID0gZGVmYXVsdEludm9rZUZ1bmN0aW9uO1xuZXhwb3J0IGxldCBodHRwUmVxdWVzdCA9IGRlZmF1bHRIdHRwUmVxdWVzdDtcbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.js b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.js deleted file mode 100644 index 6efe7fd22e321..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.js +++ /dev/null @@ -1,267 +0,0 @@ -"use strict"; -/* eslint-disable no-console */ -Object.defineProperty(exports, "__esModule", { value: true }); -exports.ClusterResourceHandler = void 0; -const common_1 = require("./common"); -const MAX_CLUSTER_NAME_LEN = 100; -class ClusterResourceHandler extends common_1.ResourceHandler { - constructor(eks, event) { - super(eks, event); - this.newProps = parseProps(this.event.ResourceProperties); - this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; - } - get clusterName() { - if (!this.physicalResourceId) { - throw new Error('Cannot determine cluster name without physical resource ID'); - } - return this.physicalResourceId; - } - // ------ - // CREATE - // ------ - async onCreate() { - console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); - if (!this.newProps.roleArn) { - throw new Error('"roleArn" is required'); - } - const clusterName = this.newProps.name || this.generateClusterName(); - const resp = await this.eks.createCluster({ - ...this.newProps, - name: clusterName, - }); - if (!resp.cluster) { - throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); - } - return { - PhysicalResourceId: resp.cluster.name, - }; - } - async isCreateComplete() { - return this.isActive(); - } - // ------ - // DELETE - // ------ - async onDelete() { - console.log(`onDelete: deleting cluster ${this.clusterName}`); - try { - await this.eks.deleteCluster({ name: this.clusterName }); - } - catch (e) { - if (e.code !== 'ResourceNotFoundException') { - throw e; - } - else { - console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); - } - } - return { - PhysicalResourceId: this.clusterName, - }; - } - async isDeleteComplete() { - console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); - try { - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); - } - catch (e) { - if (e.code === 'ResourceNotFoundException') { - console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); - return { IsComplete: true }; - } - console.log('describeCluster error:', e); - throw e; - } - return { - IsComplete: false, - }; - } - // ------ - // UPDATE - // ------ - async onUpdate() { - const updates = analyzeUpdate(this.oldProps, this.newProps); - console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); - // updates to encryption config is not supported - if (updates.updateEncryption) { - throw new Error('Cannot update cluster encryption configuration'); - } - // if there is an update that requires replacement, go ahead and just create - // a new cluster with the new config. The old cluster will automatically be - // deleted by cloudformation upon success. - if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { - // if we are replacing this cluster and the cluster has an explicit - // physical name, the creation of the new cluster will fail with "there is - // already a cluster with that name". this is a common behavior for - // CloudFormation resources that support specifying a physical name. - if (this.oldProps.name === this.newProps.name && this.oldProps.name) { - throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); - } - return this.onCreate(); - } - // if a version update is required, issue the version update - if (updates.updateVersion) { - if (!this.newProps.version) { - throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); - } - return this.updateClusterVersion(this.newProps.version); - } - if (updates.updateLogging || updates.updateAccess) { - const config = { - name: this.clusterName, - logging: this.newProps.logging, - }; - if (updates.updateAccess) { - // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: - // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) - // will fail, therefore we take only the access fields explicitly - config.resourcesVpcConfig = { - endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, - endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, - publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, - }; - } - const updateResponse = await this.eks.updateClusterConfig(config); - return { EksUpdateId: updateResponse.update?.id }; - } - // no updates - return; - } - async isUpdateComplete() { - console.log('isUpdateComplete'); - // if this is an EKS update, we will monitor the update event itself - if (this.event.EksUpdateId) { - const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); - if (!complete) { - return { IsComplete: false }; - } - // fall through: if the update is done, we simply delegate to isActive() - // in order to extract attributes and state from the cluster itself, which - // is supposed to be in an ACTIVE state after the update is complete. - } - return this.isActive(); - } - async updateClusterVersion(newVersion) { - console.log(`updating cluster version to ${newVersion}`); - // update-cluster-version will fail if we try to update to the same version, - // so skip in this case. - const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; - if (cluster?.version === newVersion) { - console.log(`cluster already at version ${cluster.version}, skipping version update`); - return; - } - const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); - return { EksUpdateId: updateResponse.update?.id }; - } - async isActive() { - console.log('waiting for cluster to become ACTIVE'); - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); - const cluster = resp.cluster; - // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are - // not complete. note that the custom resource provider framework forbids - // returning attributes (Data) if isComplete is false. - if (cluster?.status === 'FAILED') { - // not very informative, unfortunately the response doesn't contain any error - // information :\ - throw new Error('Cluster is in a FAILED status'); - } - else if (cluster?.status !== 'ACTIVE') { - return { - IsComplete: false, - }; - } - else { - return { - IsComplete: true, - Data: { - Name: cluster.name, - Endpoint: cluster.endpoint, - Arn: cluster.arn, - // IMPORTANT: CFN expects that attributes will *always* have values, - // so return an empty string in case the value is not defined. - // Otherwise, CFN will throw with `Vendor response doesn't contain - // XXXX key`. - CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', - ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', - OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', - OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', - // We can safely return the first item from encryption configuration array, because it has a limit of 1 item - // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig - EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', - }, - }; - } - } - async isEksUpdateComplete(eksUpdateId) { - this.log({ isEksUpdateComplete: eksUpdateId }); - const describeUpdateResponse = await this.eks.describeUpdate({ - name: this.clusterName, - updateId: eksUpdateId, - }); - this.log({ describeUpdateResponse }); - if (!describeUpdateResponse.update) { - throw new Error(`unable to describe update with id "${eksUpdateId}"`); - } - switch (describeUpdateResponse.update.status) { - case 'InProgress': - return false; - case 'Successful': - return true; - case 'Failed': - case 'Cancelled': - throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); - default: - throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); - } - } - generateClusterName() { - const suffix = this.requestId.replace(/-/g, ''); // 32 chars - const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; - const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); - return `${prefix}-${suffix}`; - } -} -exports.ClusterResourceHandler = ClusterResourceHandler; -function parseProps(props) { - const parsed = props?.Config ?? {}; - // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. - // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' - if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; - } - if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; - } - if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { - parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; - } - return parsed; -} -function analyzeUpdate(oldProps, newProps) { - console.log('old props: ', JSON.stringify(oldProps)); - console.log('new props: ', JSON.stringify(newProps)); - const newVpcProps = newProps.resourcesVpcConfig || {}; - const oldVpcProps = oldProps.resourcesVpcConfig || {}; - const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); - const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); - const newEnc = newProps.encryptionConfig || {}; - const oldEnc = oldProps.encryptionConfig || {}; - return { - replaceName: newProps.name !== oldProps.name, - replaceVpc: JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), - updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || - newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || - !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), - replaceRole: newProps.roleArn !== oldProps.roleArn, - updateVersion: newProps.version !== oldProps.version, - updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), - updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), - }; -} -function setsEqual(first, second) { - return first.size === second.size || [...first].every((e) => second.has(e)); -} -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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LElBQUksS0FBSyxNQUFNLENBQUMsSUFBSSxJQUFJLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFTLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUN0RixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgbm8tY29uc29sZSAqL1xuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzXG5pbXBvcnQgeyBJc0NvbXBsZXRlUmVzcG9uc2UsIE9uRXZlbnRSZXNwb25zZSB9IGZyb20gJ0Bhd3MtY2RrL2N1c3RvbS1yZXNvdXJjZXMvbGliL3Byb3ZpZGVyLWZyYW1ld29yay90eXBlcyc7XG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzXG5pbXBvcnQgKiBhcyBhd3MgZnJvbSAnYXdzLXNkayc7XG5pbXBvcnQgeyBFa3NDbGllbnQsIFJlc291cmNlRXZlbnQsIFJlc291cmNlSGFuZGxlciB9IGZyb20gJy4vY29tbW9uJztcblxuY29uc3QgTUFYX0NMVVNURVJfTkFNRV9MRU4gPSAxMDA7XG5cbmV4cG9ydCBjbGFzcyBDbHVzdGVyUmVzb3VyY2VIYW5kbGVyIGV4dGVuZHMgUmVzb3VyY2VIYW5kbGVyIHtcbiAgcHVibGljIGdldCBjbHVzdGVyTmFtZSgpIHtcbiAgICBpZiAoIXRoaXMucGh5c2ljYWxSZXNvdXJjZUlkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBkZXRlcm1pbmUgY2x1c3RlciBuYW1lIHdpdGhvdXQgcGh5c2ljYWwgcmVzb3VyY2UgSUQnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5waHlzaWNhbFJlc291cmNlSWQ7XG4gIH1cblxuICBwcml2YXRlIHJlYWRvbmx5IG5ld1Byb3BzOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0O1xuICBwcml2YXRlIHJlYWRvbmx5IG9sZFByb3BzOiBQYXJ0aWFsPGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3Q+O1xuXG4gIGNvbnN0cnVjdG9yKGVrczogRWtzQ2xpZW50LCBldmVudDogUmVzb3VyY2VFdmVudCkge1xuICAgIHN1cGVyKGVrcywgZXZlbnQpO1xuXG4gICAgdGhpcy5uZXdQcm9wcyA9IHBhcnNlUHJvcHModGhpcy5ldmVudC5SZXNvdXJjZVByb3BlcnRpZXMpO1xuICAgIHRoaXMub2xkUHJvcHMgPSBldmVudC5SZXF1ZXN0VHlwZSA9PT0gJ1VwZGF0ZScgPyBwYXJzZVByb3BzKGV2ZW50Lk9sZFJlc291cmNlUHJvcGVydGllcykgOiB7fTtcbiAgfVxuXG4gIC8vIC0tLS0tLVxuICAvLyBDUkVBVEVcbiAgLy8gLS0tLS0tXG5cbiAgcHJvdGVjdGVkIGFzeW5jIG9uQ3JlYXRlKCk6IFByb21pc2U8T25FdmVudFJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coJ29uQ3JlYXRlOiBjcmVhdGluZyBjbHVzdGVyIHdpdGggb3B0aW9uczonLCBKU09OLnN0cmluZ2lmeSh0aGlzLm5ld1Byb3BzLCB1bmRlZmluZWQsIDIpKTtcbiAgICBpZiAoIXRoaXMubmV3UHJvcHMucm9sZUFybikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdcInJvbGVBcm5cIiBpcyByZXF1aXJlZCcpO1xuICAgIH1cblxuICAgIGNvbnN0IGNsdXN0ZXJOYW1lID0gdGhpcy5uZXdQcm9wcy5uYW1lIHx8IHRoaXMuZ2VuZXJhdGVDbHVzdGVyTmFtZSgpO1xuXG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmNyZWF0ZUNsdXN0ZXIoe1xuICAgICAgLi4udGhpcy5uZXdQcm9wcyxcbiAgICAgIG5hbWU6IGNsdXN0ZXJOYW1lLFxuICAgIH0pO1xuXG4gICAgaWYgKCFyZXNwLmNsdXN0ZXIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3Igd2hlbiB0cnlpbmcgdG8gY3JlYXRlIGNsdXN0ZXIgJHtjbHVzdGVyTmFtZX06IENyZWF0ZUNsdXN0ZXIgcmV0dXJuZWQgd2l0aG91dCBjbHVzdGVyIGluZm9ybWF0aW9uYCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogcmVzcC5jbHVzdGVyLm5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0NyZWF0ZUNvbXBsZXRlKCkge1xuICAgIHJldHVybiB0aGlzLmlzQWN0aXZlKCk7XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gREVMRVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkRlbGV0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKGBvbkRlbGV0ZTogZGVsZXRpbmcgY2x1c3RlciAke3RoaXMuY2x1c3Rlck5hbWV9YCk7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuZWtzLmRlbGV0ZUNsdXN0ZXIoeyBuYW1lOiB0aGlzLmNsdXN0ZXJOYW1lIH0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgIT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc29sZS5sb2coYGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSBub3QgZm91bmQsIGlkZW1wb3RlbnRseSBzdWNjZWVkZWRgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICB9O1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzRGVsZXRlQ29tcGxldGUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgaXNEZWxldGVDb21wbGV0ZTogd2FpdGluZyBmb3IgY2x1c3RlciAke3RoaXMuY2x1c3Rlck5hbWV9IHRvIGJlIGRlbGV0ZWRgKTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXNwID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgcmV0dXJuZWQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKGUuY29kZSA9PT0gJ1Jlc291cmNlTm90Rm91bmRFeGNlcHRpb24nKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdyZWNlaXZlZCBSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uLCB0aGlzIG1lYW5zIHRoZSBjbHVzdGVyIGhhcyBiZWVuIGRlbGV0ZWQgKG9yIG5ldmVyIGV4aXN0ZWQpJyk7XG4gICAgICAgIHJldHVybiB7IElzQ29tcGxldGU6IHRydWUgfTtcbiAgICAgIH1cblxuICAgICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciBlcnJvcjonLCBlKTtcbiAgICAgIHRocm93IGU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgIH07XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gVVBEQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvblVwZGF0ZSgpIHtcbiAgICBjb25zdCB1cGRhdGVzID0gYW5hbHl6ZVVwZGF0ZSh0aGlzLm9sZFByb3BzLCB0aGlzLm5ld1Byb3BzKTtcbiAgICBjb25zb2xlLmxvZygnb25VcGRhdGU6JywgSlNPTi5zdHJpbmdpZnkoeyB1cGRhdGVzIH0sIHVuZGVmaW5lZCwgMikpO1xuXG4gICAgLy8gdXBkYXRlcyB0byBlbmNyeXB0aW9uIGNvbmZpZyBpcyBub3Qgc3VwcG9ydGVkXG4gICAgaWYgKHVwZGF0ZXMudXBkYXRlRW5jcnlwdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgdXBkYXRlIGNsdXN0ZXIgZW5jcnlwdGlvbiBjb25maWd1cmF0aW9uJyk7XG4gICAgfVxuXG4gICAgLy8gaWYgdGhlcmUgaXMgYW4gdXBkYXRlIHRoYXQgcmVxdWlyZXMgcmVwbGFjZW1lbnQsIGdvIGFoZWFkIGFuZCBqdXN0IGNyZWF0ZVxuICAgIC8vIGEgbmV3IGNsdXN0ZXIgd2l0aCB0aGUgbmV3IGNvbmZpZy4gVGhlIG9sZCBjbHVzdGVyIHdpbGwgYXV0b21hdGljYWxseSBiZVxuICAgIC8vIGRlbGV0ZWQgYnkgY2xvdWRmb3JtYXRpb24gdXBvbiBzdWNjZXNzLlxuICAgIGlmICh1cGRhdGVzLnJlcGxhY2VOYW1lIHx8IHVwZGF0ZXMucmVwbGFjZVJvbGUgfHwgdXBkYXRlcy5yZXBsYWNlVnBjKSB7XG5cbiAgICAgIC8vIGlmIHdlIGFyZSByZXBsYWNpbmcgdGhpcyBjbHVzdGVyIGFuZCB0aGUgY2x1c3RlciBoYXMgYW4gZXhwbGljaXRcbiAgICAgIC8vIHBoeXNpY2FsIG5hbWUsIHRoZSBjcmVhdGlvbiBvZiB0aGUgbmV3IGNsdXN0ZXIgd2lsbCBmYWlsIHdpdGggXCJ0aGVyZSBpc1xuICAgICAgLy8gYWxyZWFkeSBhIGNsdXN0ZXIgd2l0aCB0aGF0IG5hbWVcIi4gdGhpcyBpcyBhIGNvbW1vbiBiZWhhdmlvciBmb3JcbiAgICAgIC8vIENsb3VkRm9ybWF0aW9uIHJlc291cmNlcyB0aGF0IHN1cHBvcnQgc3BlY2lmeWluZyBhIHBoeXNpY2FsIG5hbWUuXG4gICAgICBpZiAodGhpcy5vbGRQcm9wcy5uYW1lID09PSB0aGlzLm5ld1Byb3BzLm5hbWUgJiYgdGhpcy5vbGRQcm9wcy5uYW1lKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IHJlcGxhY2UgY2x1c3RlciBcIiR7dGhpcy5vbGRQcm9wcy5uYW1lfVwiIHNpbmNlIGl0IGhhcyBhbiBleHBsaWNpdCBwaHlzaWNhbCBuYW1lLiBFaXRoZXIgcmVuYW1lIHRoZSBjbHVzdGVyIG9yIHJlbW92ZSB0aGUgXCJuYW1lXCIgY29uZmlndXJhdGlvbmApO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy5vbkNyZWF0ZSgpO1xuICAgIH1cblxuICAgIC8vIGlmIGEgdmVyc2lvbiB1cGRhdGUgaXMgcmVxdWlyZWQsIGlzc3VlIHRoZSB2ZXJzaW9uIHVwZGF0ZVxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZVZlcnNpb24pIHtcbiAgICAgIGlmICghdGhpcy5uZXdQcm9wcy52ZXJzaW9uKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IHJlbW92ZSBjbHVzdGVyIHZlcnNpb24gY29uZmlndXJhdGlvbi4gQ3VycmVudCB2ZXJzaW9uIGlzICR7dGhpcy5vbGRQcm9wcy52ZXJzaW9ufWApO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy51cGRhdGVDbHVzdGVyVmVyc2lvbih0aGlzLm5ld1Byb3BzLnZlcnNpb24pO1xuICAgIH1cblxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUxvZ2dpbmcgfHwgdXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgIGNvbnN0IGNvbmZpZzogYXdzLkVLUy5VcGRhdGVDbHVzdGVyQ29uZmlnUmVxdWVzdCA9IHtcbiAgICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgICAgbG9nZ2luZzogdGhpcy5uZXdQcm9wcy5sb2dnaW5nLFxuICAgICAgfTtcbiAgICAgIGlmICh1cGRhdGVzLnVwZGF0ZUFjY2Vzcykge1xuICAgICAgICAvLyBVcGRhdGluZyB0aGUgY2x1c3RlciB3aXRoIHNlY3VyaXR5R3JvdXBJZHMgYW5kIHN1Ym5ldElkcyAoYXMgc3BlY2lmaWVkIGluIHRoZSB3YXJuaW5nIGhlcmU6XG4gICAgICAgIC8vIGh0dHBzOi8vYXdzY2xpLmFtYXpvbmF3cy5jb20vdjIvZG9jdW1lbnRhdGlvbi9hcGkvbGF0ZXN0L3JlZmVyZW5jZS9la3MvdXBkYXRlLWNsdXN0ZXItY29uZmlnLmh0bWwpXG4gICAgICAgIC8vIHdpbGwgZmFpbCwgdGhlcmVmb3JlIHdlIHRha2Ugb25seSB0aGUgYWNjZXNzIGZpZWxkcyBleHBsaWNpdGx5XG4gICAgICAgIGNvbmZpZy5yZXNvdXJjZXNWcGNDb25maWcgPSB7XG4gICAgICAgICAgZW5kcG9pbnRQcml2YXRlQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MsXG4gICAgICAgICAgZW5kcG9pbnRQdWJsaWNBY2Nlc3M6IHRoaXMubmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzLFxuICAgICAgICAgIHB1YmxpY0FjY2Vzc0NpZHJzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5wdWJsaWNBY2Nlc3NDaWRycyxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MudXBkYXRlQ2x1c3RlckNvbmZpZyhjb25maWcpO1xuXG4gICAgICByZXR1cm4geyBFa3NVcGRhdGVJZDogdXBkYXRlUmVzcG9uc2UudXBkYXRlPy5pZCB9O1xuICAgIH1cblxuICAgIC8vIG5vIHVwZGF0ZXNcbiAgICByZXR1cm47XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNVcGRhdGVDb21wbGV0ZSgpIHtcbiAgICBjb25zb2xlLmxvZygnaXNVcGRhdGVDb21wbGV0ZScpO1xuXG4gICAgLy8gaWYgdGhpcyBpcyBhbiBFS1MgdXBkYXRlLCB3ZSB3aWxsIG1vbml0b3IgdGhlIHVwZGF0ZSBldmVudCBpdHNlbGZcbiAgICBpZiAodGhpcy5ldmVudC5Fa3NVcGRhdGVJZCkge1xuICAgICAgY29uc3QgY29tcGxldGUgPSBhd2FpdCB0aGlzLmlzRWtzVXBkYXRlQ29tcGxldGUodGhpcy5ldmVudC5Fa3NVcGRhdGVJZCk7XG4gICAgICBpZiAoIWNvbXBsZXRlKSB7XG4gICAgICAgIHJldHVybiB7IElzQ29tcGxldGU6IGZhbHNlIH07XG4gICAgICB9XG5cbiAgICAgIC8vIGZhbGwgdGhyb3VnaDogaWYgdGhlIHVwZGF0ZSBpcyBkb25lLCB3ZSBzaW1wbHkgZGVsZWdhdGUgdG8gaXNBY3RpdmUoKVxuICAgICAgLy8gaW4gb3JkZXIgdG8gZXh0cmFjdCBhdHRyaWJ1dGVzIGFuZCBzdGF0ZSBmcm9tIHRoZSBjbHVzdGVyIGl0c2VsZiwgd2hpY2hcbiAgICAgIC8vIGlzIHN1cHBvc2VkIHRvIGJlIGluIGFuIEFDVElWRSBzdGF0ZSBhZnRlciB0aGUgdXBkYXRlIGlzIGNvbXBsZXRlLlxuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmlzQWN0aXZlKCk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHVwZGF0ZUNsdXN0ZXJWZXJzaW9uKG5ld1ZlcnNpb246IHN0cmluZykge1xuICAgIGNvbnNvbGUubG9nKGB1cGRhdGluZyBjbHVzdGVyIHZlcnNpb24gdG8gJHtuZXdWZXJzaW9ufWApO1xuXG4gICAgLy8gdXBkYXRlLWNsdXN0ZXItdmVyc2lvbiB3aWxsIGZhaWwgaWYgd2UgdHJ5IHRvIHVwZGF0ZSB0byB0aGUgc2FtZSB2ZXJzaW9uLFxuICAgIC8vIHNvIHNraXAgaW4gdGhpcyBjYXNlLlxuICAgIGNvbnN0IGNsdXN0ZXIgPSAoYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KSkuY2x1c3RlcjtcbiAgICBpZiAoY2x1c3Rlcj8udmVyc2lvbiA9PT0gbmV3VmVyc2lvbikge1xuICAgICAgY29uc29sZS5sb2coYGNsdXN0ZXIgYWxyZWFkeSBhdCB2ZXJzaW9uICR7Y2x1c3Rlci52ZXJzaW9ufSwgc2tpcHBpbmcgdmVyc2lvbiB1cGRhdGVgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJWZXJzaW9uKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSwgdmVyc2lvbjogbmV3VmVyc2lvbiB9KTtcbiAgICByZXR1cm4geyBFa3NVcGRhdGVJZDogdXBkYXRlUmVzcG9uc2UudXBkYXRlPy5pZCB9O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBpc0FjdGl2ZSgpOiBQcm9taXNlPElzQ29tcGxldGVSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCd3YWl0aW5nIGZvciBjbHVzdGVyIHRvIGJlY29tZSBBQ1RJVkUnKTtcbiAgICBjb25zdCByZXNwID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJlc3VsdDonLCBKU09OLnN0cmluZ2lmeShyZXNwLCB1bmRlZmluZWQsIDIpKTtcbiAgICBjb25zdCBjbHVzdGVyID0gcmVzcC5jbHVzdGVyO1xuXG4gICAgLy8gaWYgY2x1c3RlciBpcyB1bmRlZmluZWQgKHNob3VsZG50IGhhcHBlbikgb3Igc3RhdHVzIGlzIG5vdCBBQ1RJVkUsIHdlIGFyZVxuICAgIC8vIG5vdCBjb21wbGV0ZS4gbm90ZSB0aGF0IHRoZSBjdXN0b20gcmVzb3VyY2UgcHJvdmlkZXIgZnJhbWV3b3JrIGZvcmJpZHNcbiAgICAvLyByZXR1cm5pbmcgYXR0cmlidXRlcyAoRGF0YSkgaWYgaXNDb21wbGV0ZSBpcyBmYWxzZS5cbiAgICBpZiAoY2x1c3Rlcj8uc3RhdHVzID09PSAnRkFJTEVEJykge1xuICAgICAgLy8gbm90IHZlcnkgaW5mb3JtYXRpdmUsIHVuZm9ydHVuYXRlbHkgdGhlIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpbiBhbnkgZXJyb3JcbiAgICAgIC8vIGluZm9ybWF0aW9uIDpcXFxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDbHVzdGVyIGlzIGluIGEgRkFJTEVEIHN0YXR1cycpO1xuICAgIH0gZWxzZSBpZiAoY2x1c3Rlcj8uc3RhdHVzICE9PSAnQUNUSVZFJykge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogZmFsc2UsXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBJc0NvbXBsZXRlOiB0cnVlLFxuICAgICAgICBEYXRhOiB7XG4gICAgICAgICAgTmFtZTogY2x1c3Rlci5uYW1lLFxuICAgICAgICAgIEVuZHBvaW50OiBjbHVzdGVyLmVuZHBvaW50LFxuICAgICAgICAgIEFybjogY2x1c3Rlci5hcm4sXG5cbiAgICAgICAgICAvLyBJTVBPUlRBTlQ6IENGTiBleHBlY3RzIHRoYXQgYXR0cmlidXRlcyB3aWxsICphbHdheXMqIGhhdmUgdmFsdWVzLFxuICAgICAgICAgIC8vIHNvIHJldHVybiBhbiBlbXB0eSBzdHJpbmcgaW4gY2FzZSB0aGUgdmFsdWUgaXMgbm90IGRlZmluZWQuXG4gICAgICAgICAgLy8gT3RoZXJ3aXNlLCBDRk4gd2lsbCB0aHJvdyB3aXRoIGBWZW5kb3IgcmVzcG9uc2UgZG9lc24ndCBjb250YWluXG4gICAgICAgICAgLy8gWFhYWCBrZXlgLlxuXG4gICAgICAgICAgQ2VydGlmaWNhdGVBdXRob3JpdHlEYXRhOiBjbHVzdGVyLmNlcnRpZmljYXRlQXV0aG9yaXR5Py5kYXRhID8/ICcnLFxuICAgICAgICAgIENsdXN0ZXJTZWN1cml0eUdyb3VwSWQ6IGNsdXN0ZXIucmVzb3VyY2VzVnBjQ29uZmlnPy5jbHVzdGVyU2VjdXJpdHlHcm91cElkID8/ICcnLFxuICAgICAgICAgIE9wZW5JZENvbm5lY3RJc3N1ZXJVcmw6IGNsdXN0ZXIuaWRlbnRpdHk/Lm9pZGM/Lmlzc3VlciA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXI/LnN1YnN0cmluZyg4KSA/PyAnJywgLy8gU3RyaXBzIG9mZiBodHRwczovLyBmcm9tIHRoZSBpc3N1ZXIgdXJsXG5cbiAgICAgICAgICAvLyBXZSBjYW4gc2FmZWx5IHJldHVybiB0aGUgZmlyc3QgaXRlbSBmcm9tIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbiBhcnJheSwgYmVjYXVzZSBpdCBoYXMgYSBsaW1pdCBvZiAxIGl0ZW1cbiAgICAgICAgICAvLyBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vZWtzL2xhdGVzdC9BUElSZWZlcmVuY2UvQVBJX0NyZWF0ZUNsdXN0ZXIuaHRtbCNBbWF6b25FS1MtQ3JlYXRlQ2x1c3Rlci1yZXF1ZXN0LWVuY3J5cHRpb25Db25maWdcbiAgICAgICAgICBFbmNyeXB0aW9uQ29uZmlnS2V5QXJuOiBjbHVzdGVyLmVuY3J5cHRpb25Db25maWc/LnNoaWZ0KCk/LnByb3ZpZGVyPy5rZXlBcm4gPz8gJycsXG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNFa3NVcGRhdGVDb21wbGV0ZShla3NVcGRhdGVJZDogc3RyaW5nKSB7XG4gICAgdGhpcy5sb2coeyBpc0Vrc1VwZGF0ZUNvbXBsZXRlOiBla3NVcGRhdGVJZCB9KTtcblxuICAgIGNvbnN0IGRlc2NyaWJlVXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy5kZXNjcmliZVVwZGF0ZSh7XG4gICAgICBuYW1lOiB0aGlzLmNsdXN0ZXJOYW1lLFxuICAgICAgdXBkYXRlSWQ6IGVrc1VwZGF0ZUlkLFxuICAgIH0pO1xuXG4gICAgdGhpcy5sb2coeyBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlIH0pO1xuXG4gICAgaWYgKCFkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmFibGUgdG8gZGVzY3JpYmUgdXBkYXRlIHdpdGggaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuXG4gICAgc3dpdGNoIChkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5zdGF0dXMpIHtcbiAgICAgIGNhc2UgJ0luUHJvZ3Jlc3MnOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBjYXNlICdTdWNjZXNzZnVsJzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlICdGYWlsZWQnOlxuICAgICAgY2FzZSAnQ2FuY2VsbGVkJzpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBjbHVzdGVyIHVwZGF0ZSBpZCBcIiR7ZWtzVXBkYXRlSWR9XCIgZmFpbGVkIHdpdGggZXJyb3JzOiAke0pTT04uc3RyaW5naWZ5KGRlc2NyaWJlVXBkYXRlUmVzcG9uc2UudXBkYXRlLmVycm9ycyl9YCk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHVua25vd24gc3RhdHVzIFwiJHtkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5zdGF0dXN9XCIgZm9yIHVwZGF0ZSBpZCBcIiR7ZWtzVXBkYXRlSWR9XCJgKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGdlbmVyYXRlQ2x1c3Rlck5hbWUoKSB7XG4gICAgY29uc3Qgc3VmZml4ID0gdGhpcy5yZXF1ZXN0SWQucmVwbGFjZSgvLS9nLCAnJyk7IC8vIDMyIGNoYXJzXG4gICAgY29uc3Qgb2Zmc2V0ID0gTUFYX0NMVVNURVJfTkFNRV9MRU4gLSBzdWZmaXgubGVuZ3RoIC0gMTtcbiAgICBjb25zdCBwcmVmaXggPSB0aGlzLmxvZ2ljYWxSZXNvdXJjZUlkLnNsaWNlKDAsIG9mZnNldCA+IDAgPyBvZmZzZXQgOiAwKTtcbiAgICByZXR1cm4gYCR7cHJlZml4fS0ke3N1ZmZpeH1gO1xuICB9XG59XG5cbmZ1bmN0aW9uIHBhcnNlUHJvcHMocHJvcHM6IGFueSk6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3Qge1xuXG4gIGNvbnN0IHBhcnNlZCA9IHByb3BzPy5Db25maWcgPz8ge307XG5cbiAgLy8gdGhpcyBpcyB3ZWlyZCBidXQgdGhlc2UgYm9vbGVhbiBwcm9wZXJ0aWVzIGFyZSBwYXNzZWQgYnkgQ0ZOIGFzIGEgc3RyaW5nLCBhbmQgd2UgbmVlZCB0aGVtIHRvIGJlIGJvb2xlYW5pYyBmb3IgdGhlIFNESy5cbiAgLy8gT3RoZXJ3aXNlIGl0IGZhaWxzIHdpdGggJ1VuZXhwZWN0ZWQgUGFyYW1ldGVyOiBwYXJhbXMucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBpcyBleHBlY3RlZCB0byBiZSBhIGJvb2xlYW4nXG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQcml2YXRlQWNjZXNzKSA9PT0gJ3N0cmluZycpIHtcbiAgICBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9IHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnPy5lbmRwb2ludFB1YmxpY0FjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyA9IHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPT09ICd0cnVlJztcbiAgfVxuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5sb2dnaW5nPy5jbHVzdGVyTG9nZ2luZ1swXS5lbmFibGVkKSA9PT0gJ3N0cmluZycpIHtcbiAgICBwYXJzZWQubG9nZ2luZy5jbHVzdGVyTG9nZ2luZ1swXS5lbmFibGVkID0gcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9PT0gJ3RydWUnO1xuICB9XG5cbiAgcmV0dXJuIHBhcnNlZDtcblxufVxuXG5pbnRlcmZhY2UgVXBkYXRlTWFwIHtcbiAgcmVwbGFjZU5hbWU6IGJvb2xlYW47IC8vIG5hbWVcbiAgcmVwbGFjZVZwYzogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLnN1Ym5ldElkcyBhbmQgc2VjdXJpdHlHcm91cElkc1xuICByZXBsYWNlUm9sZTogYm9vbGVhbjsgLy8gcm9sZUFyblxuXG4gIHVwZGF0ZVZlcnNpb246IGJvb2xlYW47IC8vIHZlcnNpb25cbiAgdXBkYXRlTG9nZ2luZzogYm9vbGVhbjsgLy8gbG9nZ2luZ1xuICB1cGRhdGVFbmNyeXB0aW9uOiBib29sZWFuOyAvLyBlbmNyeXB0aW9uIChjYW5ub3QgYmUgdXBkYXRlZClcbiAgdXBkYXRlQWNjZXNzOiBib29sZWFuOyAvLyByZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzIGFuZCBlbmRwb2ludFB1YmxpY0FjY2Vzc1xufVxuXG5mdW5jdGlvbiBhbmFseXplVXBkYXRlKG9sZFByb3BzOiBQYXJ0aWFsPGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3Q+LCBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdCk6IFVwZGF0ZU1hcCB7XG4gIGNvbnNvbGUubG9nKCdvbGQgcHJvcHM6ICcsIEpTT04uc3RyaW5naWZ5KG9sZFByb3BzKSk7XG4gIGNvbnNvbGUubG9nKCduZXcgcHJvcHM6ICcsIEpTT04uc3RyaW5naWZ5KG5ld1Byb3BzKSk7XG5cbiAgY29uc3QgbmV3VnBjUHJvcHMgPSBuZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcgfHwge307XG4gIGNvbnN0IG9sZFZwY1Byb3BzID0gb2xkUHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuXG4gIGNvbnN0IG9sZFB1YmxpY0FjY2Vzc0NpZHJzID0gbmV3IFNldChvbGRWcGNQcm9wcy5wdWJsaWNBY2Nlc3NDaWRycyA/PyBbXSk7XG4gIGNvbnN0IG5ld1B1YmxpY0FjY2Vzc0NpZHJzID0gbmV3IFNldChuZXdWcGNQcm9wcy5wdWJsaWNBY2Nlc3NDaWRycyA/PyBbXSk7XG4gIGNvbnN0IG5ld0VuYyA9IG5ld1Byb3BzLmVuY3J5cHRpb25Db25maWcgfHwge307XG4gIGNvbnN0IG9sZEVuYyA9IG9sZFByb3BzLmVuY3J5cHRpb25Db25maWcgfHwge307XG5cbiAgcmV0dXJuIHtcbiAgICByZXBsYWNlTmFtZTogbmV3UHJvcHMubmFtZSAhPT0gb2xkUHJvcHMubmFtZSxcbiAgICByZXBsYWNlVnBjOlxuICAgICAgSlNPTi5zdHJpbmdpZnkobmV3VnBjUHJvcHMuc3VibmV0SWRzKSAhPT0gSlNPTi5zdHJpbmdpZnkob2xkVnBjUHJvcHMuc3VibmV0SWRzKSB8fFxuICAgICAgSlNPTi5zdHJpbmdpZnkobmV3VnBjUHJvcHMuc2VjdXJpdHlHcm91cElkcykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFZwY1Byb3BzLnNlY3VyaXR5R3JvdXBJZHMpLFxuICAgIHVwZGF0ZUFjY2VzczpcbiAgICAgIG5ld1ZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQcml2YXRlQWNjZXNzIHx8XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFB1YmxpY0FjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgfHxcbiAgICAgICFzZXRzRXF1YWwobmV3UHVibGljQWNjZXNzQ2lkcnMsIG9sZFB1YmxpY0FjY2Vzc0NpZHJzKSxcbiAgICByZXBsYWNlUm9sZTogbmV3UHJvcHMucm9sZUFybiAhPT0gb2xkUHJvcHMucm9sZUFybixcbiAgICB1cGRhdGVWZXJzaW9uOiBuZXdQcm9wcy52ZXJzaW9uICE9PSBvbGRQcm9wcy52ZXJzaW9uLFxuICAgIHVwZGF0ZUVuY3J5cHRpb246IEpTT04uc3RyaW5naWZ5KG5ld0VuYykgIT09IEpTT04uc3RyaW5naWZ5KG9sZEVuYyksXG4gICAgdXBkYXRlTG9nZ2luZzogSlNPTi5zdHJpbmdpZnkobmV3UHJvcHMubG9nZ2luZykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFByb3BzLmxvZ2dpbmcpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzZXRzRXF1YWwoZmlyc3Q6IFNldDxzdHJpbmc+LCBzZWNvbmQ6IFNldDxzdHJpbmc+KSB7XG4gIHJldHVybiBmaXJzdC5zaXplID09PSBzZWNvbmQuc2l6ZSB8fCBbLi4uZmlyc3RdLmV2ZXJ5KChlOiBzdHJpbmcpID0+IHNlY29uZC5oYXMoZSkpO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.ts deleted file mode 100644 index 0177a7e21b695..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.ts +++ /dev/null @@ -1,338 +0,0 @@ -/* eslint-disable no-console */ - -// eslint-disable-next-line import/no-extraneous-dependencies -import { IsCompleteResponse, OnEventResponse } from '@aws-cdk/custom-resources/lib/provider-framework/types'; -// eslint-disable-next-line import/no-extraneous-dependencies -import * as aws from 'aws-sdk'; -import { EksClient, ResourceEvent, ResourceHandler } from './common'; - -const MAX_CLUSTER_NAME_LEN = 100; - -export class ClusterResourceHandler extends ResourceHandler { - public get clusterName() { - if (!this.physicalResourceId) { - throw new Error('Cannot determine cluster name without physical resource ID'); - } - - return this.physicalResourceId; - } - - private readonly newProps: aws.EKS.CreateClusterRequest; - private readonly oldProps: Partial; - - constructor(eks: EksClient, event: ResourceEvent) { - super(eks, event); - - this.newProps = parseProps(this.event.ResourceProperties); - this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; - } - - // ------ - // CREATE - // ------ - - protected async onCreate(): Promise { - console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); - if (!this.newProps.roleArn) { - throw new Error('"roleArn" is required'); - } - - const clusterName = this.newProps.name || this.generateClusterName(); - - const resp = await this.eks.createCluster({ - ...this.newProps, - name: clusterName, - }); - - if (!resp.cluster) { - throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); - } - - return { - PhysicalResourceId: resp.cluster.name, - }; - } - - protected async isCreateComplete() { - return this.isActive(); - } - - // ------ - // DELETE - // ------ - - protected async onDelete(): Promise { - console.log(`onDelete: deleting cluster ${this.clusterName}`); - try { - await this.eks.deleteCluster({ name: this.clusterName }); - } catch (e) { - if (e.code !== 'ResourceNotFoundException') { - throw e; - } else { - console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); - } - } - return { - PhysicalResourceId: this.clusterName, - }; - } - - protected async isDeleteComplete(): Promise { - console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); - - try { - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); - } catch (e) { - if (e.code === 'ResourceNotFoundException') { - console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); - return { IsComplete: true }; - } - - console.log('describeCluster error:', e); - throw e; - } - - return { - IsComplete: false, - }; - } - - // ------ - // UPDATE - // ------ - - protected async onUpdate() { - const updates = analyzeUpdate(this.oldProps, this.newProps); - console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); - - // updates to encryption config is not supported - if (updates.updateEncryption) { - throw new Error('Cannot update cluster encryption configuration'); - } - - // if there is an update that requires replacement, go ahead and just create - // a new cluster with the new config. The old cluster will automatically be - // deleted by cloudformation upon success. - if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { - - // if we are replacing this cluster and the cluster has an explicit - // physical name, the creation of the new cluster will fail with "there is - // already a cluster with that name". this is a common behavior for - // CloudFormation resources that support specifying a physical name. - if (this.oldProps.name === this.newProps.name && this.oldProps.name) { - throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); - } - - return this.onCreate(); - } - - // if a version update is required, issue the version update - if (updates.updateVersion) { - if (!this.newProps.version) { - throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); - } - - return this.updateClusterVersion(this.newProps.version); - } - - if (updates.updateLogging || updates.updateAccess) { - const config: aws.EKS.UpdateClusterConfigRequest = { - name: this.clusterName, - logging: this.newProps.logging, - }; - if (updates.updateAccess) { - // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: - // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) - // will fail, therefore we take only the access fields explicitly - config.resourcesVpcConfig = { - endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, - endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, - publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, - }; - } - const updateResponse = await this.eks.updateClusterConfig(config); - - return { EksUpdateId: updateResponse.update?.id }; - } - - // no updates - return; - } - - protected async isUpdateComplete() { - console.log('isUpdateComplete'); - - // if this is an EKS update, we will monitor the update event itself - if (this.event.EksUpdateId) { - const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); - if (!complete) { - return { IsComplete: false }; - } - - // fall through: if the update is done, we simply delegate to isActive() - // in order to extract attributes and state from the cluster itself, which - // is supposed to be in an ACTIVE state after the update is complete. - } - - return this.isActive(); - } - - private async updateClusterVersion(newVersion: string) { - console.log(`updating cluster version to ${newVersion}`); - - // update-cluster-version will fail if we try to update to the same version, - // so skip in this case. - const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; - if (cluster?.version === newVersion) { - console.log(`cluster already at version ${cluster.version}, skipping version update`); - return; - } - - const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); - return { EksUpdateId: updateResponse.update?.id }; - } - - private async isActive(): Promise { - console.log('waiting for cluster to become ACTIVE'); - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); - const cluster = resp.cluster; - - // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are - // not complete. note that the custom resource provider framework forbids - // returning attributes (Data) if isComplete is false. - if (cluster?.status === 'FAILED') { - // not very informative, unfortunately the response doesn't contain any error - // information :\ - throw new Error('Cluster is in a FAILED status'); - } else if (cluster?.status !== 'ACTIVE') { - return { - IsComplete: false, - }; - } else { - return { - IsComplete: true, - Data: { - Name: cluster.name, - Endpoint: cluster.endpoint, - Arn: cluster.arn, - - // IMPORTANT: CFN expects that attributes will *always* have values, - // so return an empty string in case the value is not defined. - // Otherwise, CFN will throw with `Vendor response doesn't contain - // XXXX key`. - - CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', - ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', - OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', - OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', // Strips off https:// from the issuer url - - // We can safely return the first item from encryption configuration array, because it has a limit of 1 item - // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig - EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', - }, - }; - } - } - - private async isEksUpdateComplete(eksUpdateId: string) { - this.log({ isEksUpdateComplete: eksUpdateId }); - - const describeUpdateResponse = await this.eks.describeUpdate({ - name: this.clusterName, - updateId: eksUpdateId, - }); - - this.log({ describeUpdateResponse }); - - if (!describeUpdateResponse.update) { - throw new Error(`unable to describe update with id "${eksUpdateId}"`); - } - - switch (describeUpdateResponse.update.status) { - case 'InProgress': - return false; - case 'Successful': - return true; - case 'Failed': - case 'Cancelled': - throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); - default: - throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); - } - } - - private generateClusterName() { - const suffix = this.requestId.replace(/-/g, ''); // 32 chars - const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; - const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); - return `${prefix}-${suffix}`; - } -} - -function parseProps(props: any): aws.EKS.CreateClusterRequest { - - const parsed = props?.Config ?? {}; - - // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. - // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' - - if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; - } - - if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; - } - - if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { - parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; - } - - return parsed; - -} - -interface UpdateMap { - replaceName: boolean; // name - replaceVpc: boolean; // resourcesVpcConfig.subnetIds and securityGroupIds - replaceRole: boolean; // roleArn - - updateVersion: boolean; // version - updateLogging: boolean; // logging - updateEncryption: boolean; // encryption (cannot be updated) - updateAccess: boolean; // resourcesVpcConfig.endpointPrivateAccess and endpointPublicAccess -} - -function analyzeUpdate(oldProps: Partial, newProps: aws.EKS.CreateClusterRequest): UpdateMap { - console.log('old props: ', JSON.stringify(oldProps)); - console.log('new props: ', JSON.stringify(newProps)); - - const newVpcProps = newProps.resourcesVpcConfig || {}; - const oldVpcProps = oldProps.resourcesVpcConfig || {}; - - const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); - const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); - const newEnc = newProps.encryptionConfig || {}; - const oldEnc = oldProps.encryptionConfig || {}; - - return { - replaceName: newProps.name !== oldProps.name, - replaceVpc: - JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), - updateAccess: - newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || - newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || - !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), - replaceRole: newProps.roleArn !== oldProps.roleArn, - updateVersion: newProps.version !== oldProps.version, - updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), - updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), - }; -} - -function setsEqual(first: Set, second: Set) { - return first.size === second.size || [...first].every((e: string) => second.has(e)); -} diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/cfn-response.js b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/cfn-response.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/cfn-response.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/cfn-response.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/consts.js b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/consts.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/consts.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/consts.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/framework.js b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/framework.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/framework.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/framework.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/outbound.js b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/outbound.js new file mode 100644 index 0000000000000..cc0667d42f0e8 --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/outbound.js @@ -0,0 +1,69 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.httpRequest = exports.invokeFunction = exports.startExecution = void 0; +/* istanbul ignore file */ +const https = require("https"); +// eslint-disable-next-line import/no-extraneous-dependencies +const AWS = require("aws-sdk"); +const FRAMEWORK_HANDLER_TIMEOUT = 900000; // 15 minutes +// In order to honor the overall maximum timeout set for the target process, +// the default 2 minutes from AWS SDK has to be overriden: +// https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html#httpOptions-property +const 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; +let lambda; +async function defaultStartExecution(req) { + if (!sfn) { + sfn = new AWS.StepFunctions(awsSdkConfig); + } + return sfn.startExecution(req).promise(); +} +async function defaultInvokeFunction(req) { + if (!lambda) { + lambda = new AWS.Lambda(awsSdkConfig); + } + try { + /** + * Try an initial invoke. + * + * When you try to invoke a function that is inactive, the invocation fails and Lambda sets + * the function to pending state until the function resources are recreated. + * If Lambda fails to recreate the resources, the function is set to the inactive state. + * + * We're using invoke first because `waitFor` doesn't trigger an inactive function to do anything, + * it just runs `getFunction` and checks the state. + */ + return await lambda.invoke(req).promise(); + } + catch (error) { + /** + * The status of the Lambda function is checked every second for up to 300 seconds. + * Exits the loop on 'Active' state and throws an error on 'Inactive' or 'Failed'. + * + * And now we wait. + */ + await lambda.waitFor('functionActiveV2', { + FunctionName: req.FunctionName, + }).promise(); + return await lambda.invoke(req).promise(); + } +} +exports.startExecution = defaultStartExecution; +exports.invokeFunction = defaultInvokeFunction; +exports.httpRequest = defaultHttpRequest; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3V0Ym91bmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJvdXRib3VuZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwwQkFBMEI7QUFDMUIsK0JBQStCO0FBQy9CLDZEQUE2RDtBQUM3RCwrQkFBK0I7QUFJL0IsTUFBTSx5QkFBeUIsR0FBRyxNQUFNLENBQUMsQ0FBQyxhQUFhO0FBRXZELDRFQUE0RTtBQUM1RSwwREFBMEQ7QUFDMUQsMkZBQTJGO0FBQzNGLE1BQU0sWUFBWSxHQUF5QjtJQUN6QyxXQUFXLEVBQUUsRUFBRSxPQUFPLEVBQUUseUJBQXlCLEVBQUU7Q0FDcEQsQ0FBQztBQUVGLEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxPQUE2QixFQUFFLFlBQW9CO0lBQ25GLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDckMsSUFBSTtZQUNGLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ2hELE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDNUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1NBQ2Y7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNYO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsSUFBSSxHQUFzQixDQUFDO0FBQzNCLElBQUksTUFBa0IsQ0FBQztBQUV2QixLQUFLLFVBQVUscUJBQXFCLENBQUMsR0FBMEM7SUFDN0UsSUFBSSxDQUFDLEdBQUcsRUFBRTtRQUNSLEdBQUcsR0FBRyxJQUFJLEdBQUcsQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUM7S0FDM0M7SUFFRCxPQUFPLEdBQUcsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7QUFDM0MsQ0FBQztBQUVELEtBQUssVUFBVSxxQkFBcUIsQ0FBQyxHQUFpQztJQUNwRSxJQUFJLENBQUMsTUFBTSxFQUFFO1FBQ1gsTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztLQUN2QztJQUVELElBQUk7UUFDRjs7Ozs7Ozs7O1dBU0c7UUFDSCxPQUFPLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztLQUMzQztJQUFDLE9BQU8sS0FBSyxFQUFFO1FBRWQ7Ozs7O1dBS0c7UUFDSCxNQUFNLE1BQU0sQ0FBQyxPQUFPLENBQUMsa0JBQWtCLEVBQUU7WUFDdkMsWUFBWSxFQUFFLEdBQUcsQ0FBQyxZQUFZO1NBQy9CLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNiLE9BQU8sTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDO0tBQzNDO0FBQ0gsQ0FBQztBQUVVLFFBQUEsY0FBYyxHQUFHLHFCQUFxQixDQUFDO0FBQ3ZDLFFBQUEsY0FBYyxHQUFHLHFCQUFxQixDQUFDO0FBQ3ZDLFFBQUEsV0FBVyxHQUFHLGtCQUFrQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogaXN0YW5idWwgaWdub3JlIGZpbGUgKi9cbmltcG9ydCAqIGFzIGh0dHBzIGZyb20gJ2h0dHBzJztcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcbmltcG9ydCAqIGFzIEFXUyBmcm9tICdhd3Mtc2RrJztcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcbmltcG9ydCB0eXBlIHsgQ29uZmlndXJhdGlvbk9wdGlvbnMgfSBmcm9tICdhd3Mtc2RrL2xpYi9jb25maWctYmFzZSc7XG5cbmNvbnN0IEZSQU1FV09SS19IQU5ETEVSX1RJTUVPVVQgPSA5MDAwMDA7IC8vIDE1IG1pbnV0ZXNcblxuLy8gSW4gb3JkZXIgdG8gaG9ub3IgdGhlIG92ZXJhbGwgbWF4aW11bSB0aW1lb3V0IHNldCBmb3IgdGhlIHRhcmdldCBwcm9jZXNzLFxuLy8gdGhlIGRlZmF1bHQgMiBtaW51dGVzIGZyb20gQVdTIFNESyBoYXMgdG8gYmUgb3ZlcnJpZGVuOlxuLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0phdmFTY3JpcHRTREsvbGF0ZXN0L0FXUy9Db25maWcuaHRtbCNodHRwT3B0aW9ucy1wcm9wZXJ0eVxuY29uc3QgYXdzU2RrQ29uZmlnOiBDb25maWd1cmF0aW9uT3B0aW9ucyA9IHtcbiAgaHR0cE9wdGlvbnM6IHsgdGltZW91dDogRlJBTUVXT1JLX0hBTkRMRVJfVElNRU9VVCB9LFxufTtcblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdEh0dHBSZXF1ZXN0KG9wdGlvbnM6IGh0dHBzLlJlcXVlc3RPcHRpb25zLCByZXNwb25zZUJvZHk6IHN0cmluZykge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gaHR0cHMucmVxdWVzdChvcHRpb25zLCByZXNvbHZlKTtcbiAgICAgIHJlcXVlc3Qub24oJ2Vycm9yJywgcmVqZWN0KTtcbiAgICAgIHJlcXVlc3Qud3JpdGUocmVzcG9uc2VCb2R5KTtcbiAgICAgIHJlcXVlc3QuZW5kKCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmVqZWN0KGUpO1xuICAgIH1cbiAgfSk7XG59XG5cbmxldCBzZm46IEFXUy5TdGVwRnVuY3Rpb25zO1xubGV0IGxhbWJkYTogQVdTLkxhbWJkYTtcblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdFN0YXJ0RXhlY3V0aW9uKHJlcTogQVdTLlN0ZXBGdW5jdGlvbnMuU3RhcnRFeGVjdXRpb25JbnB1dCk6IFByb21pc2U8QVdTLlN0ZXBGdW5jdGlvbnMuU3RhcnRFeGVjdXRpb25PdXRwdXQ+IHtcbiAgaWYgKCFzZm4pIHtcbiAgICBzZm4gPSBuZXcgQVdTLlN0ZXBGdW5jdGlvbnMoYXdzU2RrQ29uZmlnKTtcbiAgfVxuXG4gIHJldHVybiBzZm4uc3RhcnRFeGVjdXRpb24ocmVxKS5wcm9taXNlKCk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGRlZmF1bHRJbnZva2VGdW5jdGlvbihyZXE6IEFXUy5MYW1iZGEuSW52b2NhdGlvblJlcXVlc3QpOiBQcm9taXNlPEFXUy5MYW1iZGEuSW52b2NhdGlvblJlc3BvbnNlPiB7XG4gIGlmICghbGFtYmRhKSB7XG4gICAgbGFtYmRhID0gbmV3IEFXUy5MYW1iZGEoYXdzU2RrQ29uZmlnKTtcbiAgfVxuXG4gIHRyeSB7XG4gICAgLyoqXG4gICAgICogVHJ5IGFuIGluaXRpYWwgaW52b2tlLlxuICAgICAqXG4gICAgICogV2hlbiB5b3UgdHJ5IHRvIGludm9rZSBhIGZ1bmN0aW9uIHRoYXQgaXMgaW5hY3RpdmUsIHRoZSBpbnZvY2F0aW9uIGZhaWxzIGFuZCBMYW1iZGEgc2V0c1xuICAgICAqIHRoZSBmdW5jdGlvbiB0byBwZW5kaW5nIHN0YXRlIHVudGlsIHRoZSBmdW5jdGlvbiByZXNvdXJjZXMgYXJlIHJlY3JlYXRlZC5cbiAgICAgKiBJZiBMYW1iZGEgZmFpbHMgdG8gcmVjcmVhdGUgdGhlIHJlc291cmNlcywgdGhlIGZ1bmN0aW9uIGlzIHNldCB0byB0aGUgaW5hY3RpdmUgc3RhdGUuXG4gICAgICpcbiAgICAgKiBXZSdyZSB1c2luZyBpbnZva2UgZmlyc3QgYmVjYXVzZSBgd2FpdEZvcmAgZG9lc24ndCB0cmlnZ2VyIGFuIGluYWN0aXZlIGZ1bmN0aW9uIHRvIGRvIGFueXRoaW5nLFxuICAgICAqIGl0IGp1c3QgcnVucyBgZ2V0RnVuY3Rpb25gIGFuZCBjaGVja3MgdGhlIHN0YXRlLlxuICAgICAqL1xuICAgIHJldHVybiBhd2FpdCBsYW1iZGEuaW52b2tlKHJlcSkucHJvbWlzZSgpO1xuICB9IGNhdGNoIChlcnJvcikge1xuXG4gICAgLyoqXG4gICAgICogVGhlIHN0YXR1cyBvZiB0aGUgTGFtYmRhIGZ1bmN0aW9uIGlzIGNoZWNrZWQgZXZlcnkgc2Vjb25kIGZvciB1cCB0byAzMDAgc2Vjb25kcy5cbiAgICAgKiBFeGl0cyB0aGUgbG9vcCBvbiAnQWN0aXZlJyBzdGF0ZSBhbmQgdGhyb3dzIGFuIGVycm9yIG9uICdJbmFjdGl2ZScgb3IgJ0ZhaWxlZCcuXG4gICAgICpcbiAgICAgKiBBbmQgbm93IHdlIHdhaXQuXG4gICAgICovXG4gICAgYXdhaXQgbGFtYmRhLndhaXRGb3IoJ2Z1bmN0aW9uQWN0aXZlVjInLCB7XG4gICAgICBGdW5jdGlvbk5hbWU6IHJlcS5GdW5jdGlvbk5hbWUsXG4gICAgfSkucHJvbWlzZSgpO1xuICAgIHJldHVybiBhd2FpdCBsYW1iZGEuaW52b2tlKHJlcSkucHJvbWlzZSgpO1xuICB9XG59XG5cbmV4cG9ydCBsZXQgc3RhcnRFeGVjdXRpb24gPSBkZWZhdWx0U3RhcnRFeGVjdXRpb247XG5leHBvcnQgbGV0IGludm9rZUZ1bmN0aW9uID0gZGVmYXVsdEludm9rZUZ1bmN0aW9uO1xuZXhwb3J0IGxldCBodHRwUmVxdWVzdCA9IGRlZmF1bHRIdHRwUmVxdWVzdDtcbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/util.js b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/util.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/util.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/util.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip index b64a5034e3b6c..13983109fc5f5 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/apply/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/apply/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/get/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/get/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py new file mode 100644 index 0000000000000..286976ced219a --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py @@ -0,0 +1,187 @@ +import json +import logging +import os +import re +import subprocess +import shutil +import tempfile +import zipfile + +logger = logging.getLogger() +logger.setLevel(logging.INFO) + +# these are coming from the kubectl layer +os.environ['PATH'] = '/opt/helm:/opt/awscli:' + os.environ['PATH'] + +outdir = os.environ.get('TEST_OUTDIR', '/tmp') +kubeconfig = os.path.join(outdir, 'kubeconfig') + +def get_chart_asset_from_url(chart_asset_url): + chart_zip = os.path.join(outdir, 'chart.zip') + shutil.rmtree(chart_zip, ignore_errors=True) + subprocess.check_call(['aws', 's3', 'cp', chart_asset_url, chart_zip]) + chart_dir = os.path.join(outdir, 'chart') + shutil.rmtree(chart_dir, ignore_errors=True) + os.mkdir(chart_dir) + with zipfile.ZipFile(chart_zip, 'r') as zip_ref: + zip_ref.extractall(chart_dir) + return chart_dir + +def helm_handler(event, context): + logger.info(json.dumps(dict(event, ResponseURL='...'))) + + request_type = event['RequestType'] + props = event['ResourceProperties'] + + # resource properties + cluster_name = props['ClusterName'] + role_arn = props['RoleArn'] + release = props['Release'] + chart = props.get('Chart', None) + chart_asset_url = props.get('ChartAssetURL', None) + version = props.get('Version', None) + wait = props.get('Wait', False) + timeout = props.get('Timeout', None) + namespace = props.get('Namespace', None) + create_namespace = props.get('CreateNamespace', None) + repository = props.get('Repository', None) + values_text = props.get('Values', None) + + # "log in" to the cluster + subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig', + '--role-arn', role_arn, + '--name', cluster_name, + '--kubeconfig', kubeconfig + ]) + + if os.path.isfile(kubeconfig): + os.chmod(kubeconfig, 0o600) + + # Write out the values to a file and include them with the install and upgrade + values_file = None + if not request_type == "Delete" and not values_text is None: + values = json.loads(values_text) + values_file = os.path.join(outdir, 'values.yaml') + with open(values_file, "w") as f: + f.write(json.dumps(values, indent=2)) + + if request_type == 'Create' or request_type == 'Update': + # Ensure chart or chart_asset_url are set + if chart == None and chart_asset_url == None: + raise RuntimeError(f'chart or chartAsset must be specified') + + if chart_asset_url != None: + assert(chart==None) + assert(repository==None) + assert(version==None) + if not chart_asset_url.startswith('s3://'): + raise RuntimeError(f'ChartAssetURL must point to as s3 location but is {chart_asset_url}') + # future work: support versions from s3 assets + chart = get_chart_asset_from_url(chart_asset_url) + + if repository is not None and repository.startswith('oci://'): + tmpdir = tempfile.TemporaryDirectory() + chart_dir = get_chart_from_oci(tmpdir.name, repository, version) + chart = chart_dir + + helm('upgrade', release, chart, repository, values_file, namespace, version, wait, timeout, create_namespace) + elif request_type == "Delete": + try: + helm('uninstall', release, namespace=namespace, timeout=timeout) + except Exception as e: + logger.info("delete error: %s" % e) + + +def get_oci_cmd(repository, version): + # Generates OCI command based on pattern. Public ECR vs Private ECR are treated differently. + private_ecr_pattern = 'oci://(?P\d+.dkr.ecr.(?P[a-z]+-[a-z]+-\d).amazonaws.com)*' + public_ecr_pattern = 'oci://(?Ppublic.ecr.aws)*' + + private_registry = re.match(private_ecr_pattern, repository).groupdict() + public_registry = re.match(public_ecr_pattern, repository).groupdict() + + if private_registry['registry'] is not None: + logger.info("Found AWS private repository") + cmnd = [ + f"aws ecr get-login-password --region {private_registry['region']} | " \ + f"helm registry login --username AWS --password-stdin {private_registry['registry']}; helm pull {repository} --version {version} --untar" + ] + elif public_registry['registry'] is not None: + logger.info("Found AWS public repository, will use default region as deployment") + region = os.environ.get('AWS_REGION', 'us-east-1') + + cmnd = [ + f"aws ecr-public get-login-password --region us-east-1 | " \ + f"helm registry login --username AWS --password-stdin {public_registry['registry']}; helm pull {repository} --version {version} --untar" + ] + else: + logger.error("OCI repository format not recognized, falling back to helm pull") + cmnd = ['helm', 'pull', repository, '--version', version, '--untar'] + + return cmnd + + +def get_chart_from_oci(tmpdir, repository = None, version = None): + + cmnd = get_oci_cmd(repository, version) + + maxAttempts = 3 + retry = maxAttempts + while retry > 0: + try: + logger.info(cmnd) + output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=tmpdir, shell=True) + logger.info(output) + + # effectively returns "$tmpDir/$lastPartOfOCIUrl", because this is how helm pull saves OCI artifact. + # Eg. if we have oci://9999999999.dkr.ecr.us-east-1.amazonaws.com/foo/bar/pet-service repository, helm saves artifact under $tmpDir/pet-service + return os.path.join(tmpdir, repository.rpartition('/')[-1]) + except subprocess.CalledProcessError as exc: + output = exc.output + if b'Broken pipe' in output: + retry = retry - 1 + logger.info("Broken pipe, retries left: %s" % retry) + else: + raise Exception(output) + raise Exception(f'Operation failed after {maxAttempts} attempts: {output}') + + +def helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None): + import subprocess + + cmnd = ['helm', verb, release] + if not chart is None: + cmnd.append(chart) + if verb == 'upgrade': + cmnd.append('--install') + if create_namespace: + cmnd.append('--create-namespace') + if not repo is None: + cmnd.extend(['--repo', repo]) + if not file is None: + cmnd.extend(['--values', file]) + if not version is None: + cmnd.extend(['--version', version]) + if not namespace is None: + cmnd.extend(['--namespace', namespace]) + if wait: + cmnd.append('--wait') + if not timeout is None: + cmnd.extend(['--timeout', timeout]) + cmnd.extend(['--kubeconfig', kubeconfig]) + + maxAttempts = 3 + retry = maxAttempts + while retry > 0: + try: + output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir) + logger.info(output) + return + except subprocess.CalledProcessError as exc: + output = exc.output + if b'Broken pipe' in output: + retry = retry - 1 + logger.info("Broken pipe, retries left: %s" % retry) + else: + raise Exception(output) + raise Exception(f'Operation failed after {maxAttempts} attempts: {output}') diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/index.py b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/index.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/patch/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/patch/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip index a0efa36e0518a..9bf8ba72b34ab 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/aws-cdk-eks-cluster-inference-test.assets.json b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/aws-cdk-eks-cluster-inference-test.assets.json index b7ee69e29a954..75ac985d5ddf4 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/aws-cdk-eks-cluster-inference-test.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/aws-cdk-eks-cluster-inference-test.assets.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "files": { "c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064": { "source": { @@ -27,41 +27,41 @@ } } }, - "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517": { + "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee": { "source": { - "path": "asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517", + "path": "asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip", + "objectKey": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037": { + "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585": { "source": { - "path": "asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037", + "path": "asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip", + "objectKey": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33": { + "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8": { "source": { - "path": "asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33", + "path": "asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33.zip", + "objectKey": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -105,7 +105,7 @@ } } }, - "160c5063e51e97adff360ac4e9bf20abf8cc478d5aaf57a42f93b48f6a2b4845": { + "de84c9c4d1f67fa4adb8cb3b1e0aa899ce4113c4059d117e6fcd0fc2605e55a7": { "source": { "path": "awscdkeksclusterinferencetestawscdkawseksClusterResourceProviderFE14F3C4.nested.template.json", "packaging": "file" @@ -113,12 +113,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "160c5063e51e97adff360ac4e9bf20abf8cc478d5aaf57a42f93b48f6a2b4845.json", + "objectKey": "de84c9c4d1f67fa4adb8cb3b1e0aa899ce4113c4059d117e6fcd0fc2605e55a7.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "bbe941dd0ff744fff9cc3c2f087e08a3259311e76c228f7197c0a3bf7edc550f": { + "20f7730358961f0e97cf67aa93015ece8a2943b516dcd91b95b20e14b01ead36": { "source": { "path": "awscdkeksclusterinferencetestawscdkawseksKubectlProviderB4348345.nested.template.json", "packaging": "file" @@ -126,12 +126,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "bbe941dd0ff744fff9cc3c2f087e08a3259311e76c228f7197c0a3bf7edc550f.json", + "objectKey": "20f7730358961f0e97cf67aa93015ece8a2943b516dcd91b95b20e14b01ead36.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "131e26ab8ac8c0fbd4ab469fe6480d8b75772cc44d08a78150d6ada479b1e1fe": { + "2aea21fa82e8bde5c28e5a01f0449e50a6e440d6a9ecf94c8376af3ab7e40ac7": { "source": { "path": "aws-cdk-eks-cluster-inference-test.template.json", "packaging": "file" @@ -139,7 +139,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "131e26ab8ac8c0fbd4ab469fe6480d8b75772cc44d08a78150d6ada479b1e1fe.json", + "objectKey": "2aea21fa82e8bde5c28e5a01f0449e50a6e440d6a9ecf94c8376af3ab7e40ac7.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/aws-cdk-eks-cluster-inference-test.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/aws-cdk-eks-cluster-inference-test.template.json index 0262458e19fe8..1ec240045c027 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/aws-cdk-eks-cluster-inference-test.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/aws-cdk-eks-cluster-inference-test.template.json @@ -1298,7 +1298,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/160c5063e51e97adff360ac4e9bf20abf8cc478d5aaf57a42f93b48f6a2b4845.json" + "/de84c9c4d1f67fa4adb8cb3b1e0aa899ce4113c4059d117e6fcd0fc2605e55a7.json" ] ] }, @@ -1333,7 +1333,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/bbe941dd0ff744fff9cc3c2f087e08a3259311e76c228f7197c0a3bf7edc550f.json" + "/20f7730358961f0e97cf67aa93015ece8a2943b516dcd91b95b20e14b01ead36.json" ] ] }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/awscdkeksclusterinferencetestawscdkawseksClusterResourceProviderFE14F3C4.nested.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/awscdkeksclusterinferencetestawscdkawseksClusterResourceProviderFE14F3C4.nested.template.json index 56eece9571236..7e029d4327e6b 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/awscdkeksclusterinferencetestawscdkawseksClusterResourceProviderFE14F3C4.nested.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/awscdkeksclusterinferencetestawscdkawseksClusterResourceProviderFE14F3C4.nested.template.json @@ -73,7 +73,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ @@ -162,7 +162,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ @@ -297,7 +297,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ @@ -434,7 +434,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ @@ -568,7 +568,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/awscdkeksclusterinferencetestawscdkawseksKubectlProviderB4348345.nested.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/awscdkeksclusterinferencetestawscdkawseksKubectlProviderB4348345.nested.template.json index bacefdbe9de0d..de3653653c8b0 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/awscdkeksclusterinferencetestawscdkawseksKubectlProviderB4348345.nested.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/awscdkeksclusterinferencetestawscdkawseksKubectlProviderB4348345.nested.template.json @@ -51,6 +51,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -92,7 +104,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33.zip" + "S3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "Role": { "Fn::GetAtt": [ @@ -238,7 +250,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/awscdkeksclusterinterenceDefaultTestDeployAssert715EC778.assets.json b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/awscdkeksclusterinterenceDefaultTestDeployAssert715EC778.assets.json index a58558fc71f25..30e706a4b7d8e 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/awscdkeksclusterinterenceDefaultTestDeployAssert715EC778.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/awscdkeksclusterinterenceDefaultTestDeployAssert715EC778.assets.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/cdk.out b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/cdk.out index 8ecc185e9dbee..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"21.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/integ.json b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/integ.json index 5f391b6d8d18e..b31cbc02e9241 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "testCases": { "aws-cdk-eks-cluster-interence/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/manifest.json b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/manifest.json index 60c9855e3a5b2..a106a296b0a16 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "artifacts": { "aws-cdk-eks-cluster-inference-test.assets": { "type": "cdk:asset-manifest", @@ -17,7 +17,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/131e26ab8ac8c0fbd4ab469fe6480d8b75772cc44d08a78150d6ada479b1e1fe.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/2aea21fa82e8bde5c28e5a01f0449e50a6e440d6a9ecf94c8376af3ab7e40ac7.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -162,10 +162,7 @@ "/aws-cdk-eks-cluster-inference-test/KubectlLayer/Resource": [ { "type": "aws:cdk:logicalId", - "data": "KubectlLayer600207B5", - "trace": [ - "!!DESTRUCTIVE_CHANGES: WILL_REPLACE" - ] + "data": "KubectlLayer600207B5" } ], "/aws-cdk-eks-cluster-inference-test/Cluster/Role/Resource": [ @@ -259,26 +256,6 @@ } ], "/aws-cdk-eks-cluster-inference-test/Cluster/InferenceInstances/InstanceSecurityGroup": [ - { - "type": "aws:cdk:warning", - "data": "Ignoring Egress rule since 'allowAllOutbound' is set to true; To add customized rules, set allowAllOutbound=false on the SecurityGroup" - }, - { - "type": "aws:cdk:warning", - "data": "Ignoring Egress rule since 'allowAllOutbound' is set to true; To add customized rules, set allowAllOutbound=false on the SecurityGroup" - }, - { - "type": "aws:cdk:warning", - "data": "Ignoring Egress rule since 'allowAllOutbound' is set to true; To add customized rules, set allowAllOutbound=false on the SecurityGroup" - }, - { - "type": "aws:cdk:warning", - "data": "Ignoring Egress rule since 'allowAllOutbound' is set to true; To add customized rules, set allowAllOutbound=false on the SecurityGroup" - }, - { - "type": "aws:cdk:warning", - "data": "Ignoring Egress rule since 'allowAllOutbound' is set to true; To add customized rules, set allowAllOutbound=false on the SecurityGroup" - }, { "type": "aws:cdk:warning", "data": "Ignoring Egress rule since 'allowAllOutbound' is set to true; To add customized rules, set allowAllOutbound=false on the SecurityGroup" @@ -335,10 +312,7 @@ "/aws-cdk-eks-cluster-inference-test/Cluster/InferenceInstances/LaunchConfig": [ { "type": "aws:cdk:logicalId", - "data": "ClusterInferenceInstancesLaunchConfig03BF48FE", - "trace": [ - "!!DESTRUCTIVE_CHANGES: WILL_REPLACE" - ] + "data": "ClusterInferenceInstancesLaunchConfig03BF48FE" } ], "/aws-cdk-eks-cluster-inference-test/Cluster/InferenceInstances/ASG": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/tree.json b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/tree.json index 2fe38766058b2..772bf54948b21 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/tree.json @@ -697,7 +697,7 @@ }, "constructInfo": { "fqn": "@aws-cdk/lambda-layer-kubectl-v24.KubectlV24Layer", - "version": "2.0.27" + "version": "2.0.100" } }, "Cluster": { @@ -990,7 +990,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "KubectlReadyBarrier": { @@ -1968,7 +1968,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -2141,7 +2141,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -2364,7 +2364,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -2585,7 +2585,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -2803,7 +2803,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -2982,7 +2982,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } } }, @@ -3039,7 +3039,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/160c5063e51e97adff360ac4e9bf20abf8cc478d5aaf57a42f93b48f6a2b4845.json" + "/de84c9c4d1f67fa4adb8cb3b1e0aa899ce4113c4059d117e6fcd0fc2605e55a7.json" ] ] }, @@ -3061,7 +3061,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "@aws-cdk--aws-eks.KubectlProvider": { @@ -3138,6 +3138,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -3237,7 +3249,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33.zip" + "s3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "role": { "Fn::GetAtt": [ @@ -3515,7 +3527,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -3659,7 +3671,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/bbe941dd0ff744fff9cc3c2f087e08a3259311e76c228f7197c0a3bf7edc550f.json" + "/20f7730358961f0e97cf67aa93015ece8a2943b516dcd91b95b20e14b01ead36.json" ] ] }, @@ -3702,7 +3714,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "awscdkeksclusterinferencetestClusterEBBBA1AC-AlbController": { @@ -4184,7 +4196,7 @@ "path": "aws-cdk-eks-cluster-interence/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "DeployAssert": { @@ -4230,7 +4242,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } } }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.56b85a7bb756e34ab12549549eb40d34151db41531599e8f2be6c04e8ae66057/__entrypoint__.js b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.2df5a59d801a1efa337d7f2787d401cc48d736faa94d1f42eccad2d88f3ce2e3/__entrypoint__.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.56b85a7bb756e34ab12549549eb40d34151db41531599e8f2be6c04e8ae66057/__entrypoint__.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.2df5a59d801a1efa337d7f2787d401cc48d736faa94d1f42eccad2d88f3ce2e3/__entrypoint__.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.56b85a7bb756e34ab12549549eb40d34151db41531599e8f2be6c04e8ae66057/diff.js b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.2df5a59d801a1efa337d7f2787d401cc48d736faa94d1f42eccad2d88f3ce2e3/diff.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.56b85a7bb756e34ab12549549eb40d34151db41531599e8f2be6c04e8ae66057/diff.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.2df5a59d801a1efa337d7f2787d401cc48d736faa94d1f42eccad2d88f3ce2e3/diff.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.56b85a7bb756e34ab12549549eb40d34151db41531599e8f2be6c04e8ae66057/external.js b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.2df5a59d801a1efa337d7f2787d401cc48d736faa94d1f42eccad2d88f3ce2e3/external.js similarity index 58% rename from packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.56b85a7bb756e34ab12549549eb40d34151db41531599e8f2be6c04e8ae66057/external.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.2df5a59d801a1efa337d7f2787d401cc48d736faa94d1f42eccad2d88f3ce2e3/external.js index acdacae4e8175..1edead6dd3913 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.56b85a7bb756e34ab12549549eb40d34151db41531599e8f2be6c04e8ae66057/external.js +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.2df5a59d801a1efa337d7f2787d401cc48d736faa94d1f42eccad2d88f3ce2e3/external.js @@ -91,4 +91,4 @@ exports.external = { addClientIDToOpenIDConnectProvider: (req) => iam().addClientIDToOpenIDConnectProvider(req).promise(), removeClientIDFromOpenIDConnectProvider: (req) => iam().removeClientIDFromOpenIDConnectProvider(req).promise(), }; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXh0ZXJuYWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJleHRlcm5hbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFFQSwyQkFBMkI7QUFDM0IsMkJBQTJCO0FBQzNCLDZEQUE2RDtBQUM3RCwrQkFBK0I7QUFFL0IsSUFBSSxNQUFlLENBQUM7QUFFcEIsU0FBUyxHQUFHO0lBQ1YsSUFBSSxDQUFDLE1BQU0sRUFBRTtRQUFFLE1BQU0sR0FBRyxJQUFJLEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQztLQUFFO0lBQ3hDLE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUM7QUFFRCxTQUFTLGFBQWEsQ0FBQyxHQUFXLEVBQUUsR0FBRyxJQUFXO0lBQ2hELHNDQUFzQztJQUN0QyxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDO0FBQzVCLENBQUM7QUFFRDs7R0FFRztBQUNILEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxTQUFpQjtJQUVqRCxPQUFPLElBQUksT0FBTyxDQUFTLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFO1FBQ3BDLE1BQU0sSUFBSSxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDbEMsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztRQUV2RCxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRTtZQUNkLE9BQU8sRUFBRSxDQUFDLElBQUksS0FBSyxDQUFDLDRDQUE0QyxTQUFTLEVBQUUsQ0FBQyxDQUFDLENBQUM7U0FDL0U7UUFFRCxnQkFBUSxDQUFDLEdBQUcsQ0FBQywrQ0FBK0MsU0FBUyxFQUFFLENBQUMsQ0FBQztRQUV6RSxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksRUFB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R0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxHQUFHLFdBQVcsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxHQUFHLGlCQUFpQixDQUFDLENBQUM7SUFFOUYsT0FBTyxRQUFRLENBQUM7QUFDbEIsQ0FBQztBQUVELHlDQUF5QztBQUN6Qyw0QkFBNEI7QUFDZixRQUFBLFFBQVEsR0FBRztJQUN0QixrQkFBa0I7SUFDbEIsR0FBRyxFQUFFLGFBQWE7SUFDbEIsMkJBQTJCLEVBQUUsQ0FBQyxHQUErQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQywyQkFBMkIsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUU7SUFDbEksMkJBQTJCLEVBQUUsQ0FBQyxHQUErQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQywyQkFBMkIsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUU7SUFDbEkscUNBQXFDLEVBQUUsQ0FBQyxHQUF5RCxFQUFFLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxxQ0FBcUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUU7SUFDaEssa0NBQWtDLEVBQUUsQ0FBQyxHQUFzRCxFQUFFLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxrQ0FBa0MsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUU7SUFDdkosdUNBQXVDLEVBQUUsQ0FBQyxHQUEyRCxFQUFFLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyx1Q0FBdUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUU7Q0FDdkssQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGlzdGFuYnVsIGlnbm9yZSBmaWxlICovXG5pbXBvcnQgeyBYNTA5Q2VydGlmaWNhdGUgfSBmcm9tICdub2RlOmNyeXB0byc7XG5pbXBvcnQgKiBhcyB0bHMgZnJvbSAndGxzJztcbmltcG9ydCAqIGFzIHVybCBmcm9tICd1cmwnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuXG5sZXQgY2xpZW50OiBhd3MuSUFNO1xuXG5mdW5jdGlvbiBpYW0oKSB7XG4gIGlmICghY2xpZW50KSB7IGNsaWVudCA9IG5ldyBhd3MuSUFNKCk7IH1cbiAgcmV0dXJuIGNsaWVudDtcbn1cblxuZnVuY3Rpb24gZGVmYXVsdExvZ2dlcihmbXQ6IHN0cmluZywgLi4uYXJnczogYW55W10pIHtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgY29uc29sZS5sb2coZm10LCAuLi5hcmdzKTtcbn1cblxuLyoqXG4gKiBEb3dubG9hZHMgdGhlIENBIHRodW1icHJpbnQgZnJvbSB0aGUgaXNzdWVyIFVSTFxuICovXG5hc3luYyBmdW5jdGlvbiBkb3dubG9hZFRodW1icHJpbnQoaXNzdWVyVXJsOiBzdHJpbmcpIHtcblxuICByZXR1cm4gbmV3IFByb21pc2U8c3RyaW5nPigob2ssIGtvKSA9PiB7XG4gICAgY29uc3QgcHVybCA9IHVybC5wYXJzZShpc3N1ZXJVcmwpO1xuICAgIGNvbnN0IHBvcnQgPSBwdXJsLnBvcnQgPyBwYXJzZUludChwdXJsLnBvcnQsIDEwKSA6IDQ0MztcblxuICAgIGlmICghcHVybC5ob3N0KSB7XG4gICAgICByZXR1cm4ga28obmV3IEVycm9yKGB1bmFibGUgdG8gZGV0ZXJtaW5lIGhvc3QgZnJvbSBpc3N1ZXIgdXJsICR7aXNzdWVyVXJsfWApKTtcbiAgICB9XG5cbiAgICBleHRlcm5hbC5sb2coYEZldGNoaW5nIHg1MDkgY2VydGlmaWNhdGUgY2hhaW4gZnJvbSBpc3N1ZXIgJHtpc3N1ZXJVcmx9YCk7XG5cbiAgICBjb25zdCBzb2NrZXQgPSB0bHMuY29ubmVjdChwb3J0LCBwdXJsLmhvc3QsIHsgcmVqZWN0VW5hdXRob3JpemVkOiBmYWxzZSwgc2VydmVybmFtZTogcHVybC5ob3N0IH0pO1xuICAgIHNvY2tldC5vbmNlKCdlcnJvcicsIGtvKTtcblxuICAgIHNvY2tldC5vbmNlKCdzZWN1cmVDb25uZWN0JywgKCkgPT4ge1xuICAgICAgbGV0IGNlcnQgPSBzb2NrZXQuZ2V0UGVlclg1MDlDZXJ0aWZpY2F0ZSgpO1xuICAgICAgaWYgKCFjZXJ0KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5hYmxlIHRvIHJldHJpZXZlIFg1MDkgY2VydGlmaWNhdGUgZnJvbSBob3N0ICR7cHVybC5ob3N0fWApO1xuICAgICAgfVxuICAgICAgd2hpbGUgKGNlcnQuaXNzdWVyQ2VydGlmaWNhdGUpIHtcbiAgICAgICAgcHJpbnRDZXJ0aWZpY2F0ZShjZXJ0KTtcbiAgICAgICAgY2VydCA9IGNlcnQuaXNzdWVyQ2VydGlmaWNhdGU7XG4gICAgICB9XG4gICAgICBjb25zdCB2YWxpZFRvID0gbmV3IERhdGUoY2VydC52YWxpZFRvKTtcbiAgICAgIGNvbnN0IGNlcnRpZmljYXRlVmFsaWRpdHkgPSBnZXRDZXJ0aWZpY2F0ZVZhbGlkaXR5KHZhbGlkVG8pO1xuXG4gICAgICBpZiAoY2VydGlmaWNhdGVWYWxpZGl0eSA8IDApIHtcbiAgICAgICAgcmV0dXJuIGtvKG5ldyBFcnJvcihgVGhlIGNlcnRpZmljYXRlIGhhcyBhbHJlYWR5IGV4cGlyZWQgb246ICR7dmFsaWRUby50b1VUQ1N0cmluZygpfWApKTtcbiAgICAgIH1cblxuICAgICAgLy8gV2FybmluZyB1c2VyIGlmIGNlcnRpZmljYXRlIHZhbGlkaXR5IGlzIGV4cGlyaW5nIHdpdGhpbiA2IG1vbnRoc1xuICAgICAgaWYgKGNlcnRpZmljYXRlVmFsaWRpdHkgPCAxODApIHtcbiAgICAgICAgLyogZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGUgKi9cbiAgICAgICAgY29uc29sZS53YXJuKGBUaGUgcm9vdCBjZXJ0aWZpY2F0ZSBvYnRhaW5lZCB3b3VsZCBleHBpcmUgaW4gJHtjZXJ0aWZpY2F0ZVZhbGlkaXR5fSBkYXlzIWApO1xuICAgICAgfVxuXG4gICAgICBzb2NrZXQuZW5kKCk7XG5cbiAgICAgIGNvbnN0IHRodW1icHJpbnQgPSBleHRyYWN0VGh1bWJwcmludChjZXJ0KTtcbiAgICAgIGV4dGVybmFsLmxvZyhgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IHRodW1icHJpbnQgZm9yICR7aXNzdWVyVXJsfSBpcyAke3RodW1icHJpbnR9YCk7XG5cbiAgICAgIG9rKHRodW1icHJpbnQpO1xuICAgIH0pO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gZXh0cmFjdFRodW1icHJpbnQoY2VydDogWDUwOUNlcnRpZmljYXRlKSB7XG4gIHJldHVybiBjZXJ0LmZpbmdlcnByaW50LnNwbGl0KCc6Jykuam9pbignJyk7XG59XG5cbmZ1bmN0aW9uIHByaW50Q2VydGlmaWNhdGUoY2VydDogWDUwOUNlcnRpZmljYXRlKSB7XG4gIGV4dGVybmFsLmxvZygnLS0tLS0tLS0tLS0tLUJFR0lOIENFUlQtLS0tLS0tLS0tLS0tLS0tJyk7XG4gIGV4dGVybmFsLmxvZyhgVGh1bWJwcmludDogJHtleHRyYWN0VGh1bWJwcmludChjZXJ0KX1gKTtcbiAgZXh0ZXJuYWwubG9nKGBWYWxpZCBUbzogJHtjZXJ0LnZhbGlkVG99YCk7XG4gIGlmIChjZXJ0Lmlzc3VlckNlcnRpZmljYXRlKSB7XG4gICAgZXh0ZXJuYWwubG9nKGBJc3N1ZXIgVGh1bWJwcmludDogJHtleHRyYWN0VGh1bWJwcmludChjZXJ0Lmlzc3VlckNlcnRpZmljYXRlKX1gKTtcbiAgfVxuICBleHRlcm5hbC5sb2coYElzc3VlcjogJHtjZXJ0Lmlzc3Vlcn1gKTtcbiAgZXh0ZXJuYWwubG9nKGBTdWJqZWN0OiAke2NlcnQuc3ViamVjdH1gKTtcbiAgZXh0ZXJuYWwubG9nKCctLS0tLS0tLS0tLS0tRU5EIENFUlQtLS0tLS0tLS0tLS0tLS0tLS0nKTtcbn1cblxuLyoqXG4gKiBUbyBnZXQgdGhlIHZhbGlkaXR5IHRpbWVsaW5lIGZvciB0aGUgY2VydGlmaWNhdGVcbiAqIEBwYXJhbSBjZXJ0RGF0ZSBUaGUgdmFsaWQgdG8gZGF0ZSBmb3IgdGhlIGNlcnRpZmljYXRlXG4gKiBAcmV0dXJucyBUaGUgbnVtYmVyIG9mIGRheXMgdGhlIGNlcnRpZmljYXRlIGlzIHZhbGlkIHdydCBjdXJyZW50IGRhdGVcbiAqL1xuZnVuY3Rpb24gZ2V0Q2VydGlmaWNhdGVWYWxpZGl0eShjZXJ0RGF0ZTogRGF0ZSk6IE51bWJlciB7XG4gIGNvbnN0IG1pbGxpc2Vjb25kc0luRGF5ID0gMjQgKiA2MCAqIDYwICogMTAwMDtcbiAgY29uc3QgY3VycmVudERhdGUgPSBuZXcgRGF0ZSgpO1xuXG4gIGNvbnN0IHZhbGlkaXR5ID0gTWF0aC5yb3VuZCgoY2VydERhdGUuZ2V0VGltZSgpIC0gY3VycmVudERhdGUuZ2V0VGltZSgpKSAvIG1pbGxpc2Vjb25kc0luRGF5KTtcblxuICByZXR1cm4gdmFsaWRpdHk7XG59XG5cbi8vIGFsbG93cyB1bml0IHRlc3QgdG8gcmVwbGFjZSB3aXRoIG1vY2tzXG4vKiBlc2xpbnQtZGlzYWJsZSBtYXgtbGVuICovXG5leHBvcnQgY29uc3QgZXh0ZXJuYWwgPSB7XG4gIGRvd25sb2FkVGh1bWJwcmludCxcbiAgbG9nOiBkZWZhdWx0TG9nZ2VyLFxuICBjcmVhdGVPcGVuSURDb25uZWN0UHJvdmlkZXI6IChyZXE6IGF3cy5JQU0uQ3JlYXRlT3BlbklEQ29ubmVjdFByb3ZpZGVyUmVxdWVzdCkgPT4gaWFtKCkuY3JlYXRlT3BlbklEQ29ubmVjdFByb3ZpZGVyKHJlcSkucHJvbWlzZSgpLFxuICBkZWxldGVPcGVuSURDb25uZWN0UHJvdmlkZXI6IChyZXE6IGF3cy5JQU0uRGVsZXRlT3BlbklEQ29ubmVjdFByb3ZpZGVyUmVxdWVzdCkgPT4gaWFtKCkuZGVsZXRlT3BlbklEQ29ubmVjdFByb3ZpZGVyKHJlcSkucHJvbWlzZSgpLFxuICB1cGRhdGVPcGVuSURDb25uZWN0UHJvdmlkZXJUaHVtYnByaW50OiAocmVxOiBhd3MuSUFNLlVwZGF0ZU9wZW5JRENvbm5lY3RQcm92aWRlclRodW1icHJpbnRSZXF1ZXN0KSA9PiBpYW0oKS51cGRhdGVPcGVuSURDb25uZWN0UHJvdmlkZXJUaHVtYnByaW50KHJlcSkucHJvbWlzZSgpLFxuICBhZGRDbGllbnRJRFRvT3BlbklEQ29ubmVjdFByb3ZpZGVyOiAocmVxOiBhd3MuSUFNLkFkZENsaWVudElEVG9PcGVuSURDb25uZWN0UHJvdmlkZXJSZXF1ZXN0KSA9PiBpYW0oKS5hZGRDbGllbnRJRFRvT3BlbklEQ29ubmVjdFByb3ZpZGVyKHJlcSkucHJvbWlzZSgpLFxuICByZW1vdmVDbGllbnRJREZyb21PcGVuSURDb25uZWN0UHJvdmlkZXI6IChyZXE6IGF3cy5JQU0uUmVtb3ZlQ2xpZW50SURGcm9tT3BlbklEQ29ubmVjdFByb3ZpZGVyUmVxdWVzdCkgPT4gaWFtKCkucmVtb3ZlQ2xpZW50SURGcm9tT3BlbklEQ29ubmVjdFByb3ZpZGVyKHJlcSkucHJvbWlzZSgpLFxufTsiXX0= \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXh0ZXJuYWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJleHRlcm5hbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFTQSwyQkFBMkI7QUFDM0IsMkJBQTJCO0FBQzNCLDZEQUE2RDtBQUM3RCwrQkFBK0I7QUFFL0IsSUFBSSxNQUFlLENBQUM7QUFFcEIsU0FBUyxHQUFHO0lBQ1YsSUFBSSxDQUFDLE1BQU0sRUFBRTtRQUFFLE1BQU0sR0FBRyxJQUFJLEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQztLQUFFO0lBQ3hDLE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUM7QUFFRCxTQUFTLGFBQWEsQ0FBQyxHQUFXLEVBQUUsR0FBRyxJQUFXO0lBQ2hELHNDQUFzQztJQUN0QyxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDO0FBQzVCLENBQUM7QUFFRDs7R0FFRztBQUNILEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxTQUFpQjtJQUVqRCxPQUFPLElBQUksT0FBTyxDQUFTLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFO1FBQ3BDLE1BQU0sSUFBSSxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDbEMsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztRQUV2RCxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRTtZQUNkLE9BQU8sRUFBRSxDQUFDLElBQUksS0FBSyxDQUFDLDRDQUE0QyxTQUFTLEVBQUUsQ0FBQyxDQUFDLENBQUM7U0FDL0U7UUFFRCxnQkFBUSxDQUFDLEdBQUcsQ0FBQywrQ0FBK0MsU0FBUyxFQUFFLENBQUMsQ0FBQztRQUV6RSxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksRUFB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R0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxHQUFHLFdBQVcsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxHQUFHLGlCQUFpQixDQUFDLENBQUM7SUFFOUYsT0FBTyxRQUFRLENBQUM7QUFDbEIsQ0FBQztBQUVELHlDQUF5QztBQUN6Qyw0QkFBNEI7QUFDZixRQUFBLFFBQVEsR0FBRztJQUN0QixrQkFBa0I7SUFDbEIsR0FBRyxFQUFFLGFBQWE7SUFDbEIsMkJBQTJCLEVBQUUsQ0FBQyxHQUErQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQywyQkFBMkIsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUU7SUFDbEksMkJBQTJCLEVBQUUsQ0FBQyxHQUErQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQywyQkFBMkIsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUU7SUFDbEkscUNBQXFDLEVBQUUsQ0FBQyxHQUF5RCxFQUFFLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxxQ0FBcUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUU7SUFDaEssa0NBQWtDLEVBQUUsQ0FBQyxHQUFzRCxFQUFFLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxrQ0FBa0MsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUU7SUFDdkosdUNBQXVDLEVBQUUsQ0FBQyxHQUEyRCxFQUFFLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyx1Q0FBdUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUU7Q0FDdkssQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGlzdGFuYnVsIGlnbm9yZSBmaWxlICovXG4vLyB0aGUgWDUwOSBjZXJ0aWZpY2F0ZSBBUEkgaXMgYXZhaWxhYmxlIG9ubHkgaW4gbm9kZTE2LlxuLy8gc2luY2Ugd2UgY29tcGlsZSB0aGUgcmVwbyBhZ2FpbnN0IG5vZGUgMTQsIHR5cGVjaGVja2luZyBpdCB3aWxsIGZhaWwuXG4vLyBpdHMgY3VycmVudGx5IHRvbyBjb21wbGV4IHRvIGNvbmZpZ3VyZSBub2RlMTYgb25seSBvbiB0aGlzXG4vLyBmaWxlIChqc2lpIGRvZXNuJ3Qgc3VwcG9ydCBjdXN0b20gdHNjb25maWcpXG4vLyBzbyB3ZSBkaXNhYmxlIHR5cGVjaGVja2luZy4gZG9uJ3Qgd29ycnksIHdlIGhhdmUgc3VmZmljaWVudCBpbnRlZyB0ZXN0cyB0aGF0XG4vLyB2YWxpZGF0ZSB0aGlzIGNvZGUgZG9lc24ndCBicmVhay5cbi8vIEB0cy1ub2NoZWNrXG5pbXBvcnQgeyBYNTA5Q2VydGlmaWNhdGUgfSBmcm9tICdub2RlOmNyeXB0byc7XG5pbXBvcnQgKiBhcyB0bHMgZnJvbSAndGxzJztcbmltcG9ydCAqIGFzIHVybCBmcm9tICd1cmwnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuXG5sZXQgY2xpZW50OiBhd3MuSUFNO1xuXG5mdW5jdGlvbiBpYW0oKSB7XG4gIGlmICghY2xpZW50KSB7IGNsaWVudCA9IG5ldyBhd3MuSUFNKCk7IH1cbiAgcmV0dXJuIGNsaWVudDtcbn1cblxuZnVuY3Rpb24gZGVmYXVsdExvZ2dlcihmbXQ6IHN0cmluZywgLi4uYXJnczogYW55W10pIHtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgY29uc29sZS5sb2coZm10LCAuLi5hcmdzKTtcbn1cblxuLyoqXG4gKiBEb3dubG9hZHMgdGhlIENBIHRodW1icHJpbnQgZnJvbSB0aGUgaXNzdWVyIFVSTFxuICovXG5hc3luYyBmdW5jdGlvbiBkb3dubG9hZFRodW1icHJpbnQoaXNzdWVyVXJsOiBzdHJpbmcpIHtcblxuICByZXR1cm4gbmV3IFByb21pc2U8c3RyaW5nPigob2ssIGtvKSA9PiB7XG4gICAgY29uc3QgcHVybCA9IHVybC5wYXJzZShpc3N1ZXJVcmwpO1xuICAgIGNvbnN0IHBvcnQgPSBwdXJsLnBvcnQgPyBwYXJzZUludChwdXJsLnBvcnQsIDEwKSA6IDQ0MztcblxuICAgIGlmICghcHVybC5ob3N0KSB7XG4gICAgICByZXR1cm4ga28obmV3IEVycm9yKGB1bmFibGUgdG8gZGV0ZXJtaW5lIGhvc3QgZnJvbSBpc3N1ZXIgdXJsICR7aXNzdWVyVXJsfWApKTtcbiAgICB9XG5cbiAgICBleHRlcm5hbC5sb2coYEZldGNoaW5nIHg1MDkgY2VydGlmaWNhdGUgY2hhaW4gZnJvbSBpc3N1ZXIgJHtpc3N1ZXJVcmx9YCk7XG5cbiAgICBjb25zdCBzb2NrZXQgPSB0bHMuY29ubmVjdChwb3J0LCBwdXJsLmhvc3QsIHsgcmVqZWN0VW5hdXRob3JpemVkOiBmYWxzZSwgc2VydmVybmFtZTogcHVybC5ob3N0IH0pO1xuICAgIHNvY2tldC5vbmNlKCdlcnJvcicsIGtvKTtcblxuICAgIHNvY2tldC5vbmNlKCdzZWN1cmVDb25uZWN0JywgKCkgPT4ge1xuICAgICAgbGV0IGNlcnQgPSBzb2NrZXQuZ2V0UGVlclg1MDlDZXJ0aWZpY2F0ZSgpO1xuICAgICAgaWYgKCFjZXJ0KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5hYmxlIHRvIHJldHJpZXZlIFg1MDkgY2VydGlmaWNhdGUgZnJvbSBob3N0ICR7cHVybC5ob3N0fWApO1xuICAgICAgfVxuICAgICAgd2hpbGUgKGNlcnQuaXNzdWVyQ2VydGlmaWNhdGUpIHtcbiAgICAgICAgcHJpbnRDZXJ0aWZpY2F0ZShjZXJ0KTtcbiAgICAgICAgY2VydCA9IGNlcnQuaXNzdWVyQ2VydGlmaWNhdGU7XG4gICAgICB9XG4gICAgICBjb25zdCB2YWxpZFRvID0gbmV3IERhdGUoY2VydC52YWxpZFRvKTtcbiAgICAgIGNvbnN0IGNlcnRpZmljYXRlVmFsaWRpdHkgPSBnZXRDZXJ0aWZpY2F0ZVZhbGlkaXR5KHZhbGlkVG8pO1xuXG4gICAgICBpZiAoY2VydGlmaWNhdGVWYWxpZGl0eSA8IDApIHtcbiAgICAgICAgcmV0dXJuIGtvKG5ldyBFcnJvcihgVGhlIGNlcnRpZmljYXRlIGhhcyBhbHJlYWR5IGV4cGlyZWQgb246ICR7dmFsaWRUby50b1VUQ1N0cmluZygpfWApKTtcbiAgICAgIH1cblxuICAgICAgLy8gV2FybmluZyB1c2VyIGlmIGNlcnRpZmljYXRlIHZhbGlkaXR5IGlzIGV4cGlyaW5nIHdpdGhpbiA2IG1vbnRoc1xuICAgICAgaWYgKGNlcnRpZmljYXRlVmFsaWRpdHkgPCAxODApIHtcbiAgICAgICAgLyogZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGUgKi9cbiAgICAgICAgY29uc29sZS53YXJuKGBUaGUgcm9vdCBjZXJ0aWZpY2F0ZSBvYnRhaW5lZCB3b3VsZCBleHBpcmUgaW4gJHtjZXJ0aWZpY2F0ZVZhbGlkaXR5fSBkYXlzIWApO1xuICAgICAgfVxuXG4gICAgICBzb2NrZXQuZW5kKCk7XG5cbiAgICAgIGNvbnN0IHRodW1icHJpbnQgPSBleHRyYWN0VGh1bWJwcmludChjZXJ0KTtcbiAgICAgIGV4dGVybmFsLmxvZyhgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IHRodW1icHJpbnQgZm9yICR7aXNzdWVyVXJsfSBpcyAke3RodW1icHJpbnR9YCk7XG5cbiAgICAgIG9rKHRodW1icHJpbnQpO1xuICAgIH0pO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gZXh0cmFjdFRodW1icHJpbnQoY2VydDogWDUwOUNlcnRpZmljYXRlKSB7XG4gIHJldHVybiBjZXJ0LmZpbmdlcnByaW50LnNwbGl0KCc6Jykuam9pbignJyk7XG59XG5cbmZ1bmN0aW9uIHByaW50Q2VydGlmaWNhdGUoY2VydDogWDUwOUNlcnRpZmljYXRlKSB7XG4gIGV4dGVybmFsLmxvZygnLS0tLS0tLS0tLS0tLUJFR0lOIENFUlQtLS0tLS0tLS0tLS0tLS0tJyk7XG4gIGV4dGVybmFsLmxvZyhgVGh1bWJwcmludDogJHtleHRyYWN0VGh1bWJwcmludChjZXJ0KX1gKTtcbiAgZXh0ZXJuYWwubG9nKGBWYWxpZCBUbzogJHtjZXJ0LnZhbGlkVG99YCk7XG4gIGlmIChjZXJ0Lmlzc3VlckNlcnRpZmljYXRlKSB7XG4gICAgZXh0ZXJuYWwubG9nKGBJc3N1ZXIgVGh1bWJwcmludDogJHtleHRyYWN0VGh1bWJwcmludChjZXJ0Lmlzc3VlckNlcnRpZmljYXRlKX1gKTtcbiAgfVxuICBleHRlcm5hbC5sb2coYElzc3VlcjogJHtjZXJ0Lmlzc3Vlcn1gKTtcbiAgZXh0ZXJuYWwubG9nKGBTdWJqZWN0OiAke2NlcnQuc3ViamVjdH1gKTtcbiAgZXh0ZXJuYWwubG9nKCctLS0tLS0tLS0tLS0tRU5EIENFUlQtLS0tLS0tLS0tLS0tLS0tLS0nKTtcbn1cblxuLyoqXG4gKiBUbyBnZXQgdGhlIHZhbGlkaXR5IHRpbWVsaW5lIGZvciB0aGUgY2VydGlmaWNhdGVcbiAqIEBwYXJhbSBjZXJ0RGF0ZSBUaGUgdmFsaWQgdG8gZGF0ZSBmb3IgdGhlIGNlcnRpZmljYXRlXG4gKiBAcmV0dXJucyBUaGUgbnVtYmVyIG9mIGRheXMgdGhlIGNlcnRpZmljYXRlIGlzIHZhbGlkIHdydCBjdXJyZW50IGRhdGVcbiAqL1xuZnVuY3Rpb24gZ2V0Q2VydGlmaWNhdGVWYWxpZGl0eShjZXJ0RGF0ZTogRGF0ZSk6IE51bWJlciB7XG4gIGNvbnN0IG1pbGxpc2Vjb25kc0luRGF5ID0gMjQgKiA2MCAqIDYwICogMTAwMDtcbiAgY29uc3QgY3VycmVudERhdGUgPSBuZXcgRGF0ZSgpO1xuXG4gIGNvbnN0IHZhbGlkaXR5ID0gTWF0aC5yb3VuZCgoY2VydERhdGUuZ2V0VGltZSgpIC0gY3VycmVudERhdGUuZ2V0VGltZSgpKSAvIG1pbGxpc2Vjb25kc0luRGF5KTtcblxuICByZXR1cm4gdmFsaWRpdHk7XG59XG5cbi8vIGFsbG93cyB1bml0IHRlc3QgdG8gcmVwbGFjZSB3aXRoIG1vY2tzXG4vKiBlc2xpbnQtZGlzYWJsZSBtYXgtbGVuICovXG5leHBvcnQgY29uc3QgZXh0ZXJuYWwgPSB7XG4gIGRvd25sb2FkVGh1bWJwcmludCxcbiAgbG9nOiBkZWZhdWx0TG9nZ2VyLFxuICBjcmVhdGVPcGVuSURDb25uZWN0UHJvdmlkZXI6IChyZXE6IGF3cy5JQU0uQ3JlYXRlT3BlbklEQ29ubmVjdFByb3ZpZGVyUmVxdWVzdCkgPT4gaWFtKCkuY3JlYXRlT3BlbklEQ29ubmVjdFByb3ZpZGVyKHJlcSkucHJvbWlzZSgpLFxuICBkZWxldGVPcGVuSURDb25uZWN0UHJvdmlkZXI6IChyZXE6IGF3cy5JQU0uRGVsZXRlT3BlbklEQ29ubmVjdFByb3ZpZGVyUmVxdWVzdCkgPT4gaWFtKCkuZGVsZXRlT3BlbklEQ29ubmVjdFByb3ZpZGVyKHJlcSkucHJvbWlzZSgpLFxuICB1cGRhdGVPcGVuSURDb25uZWN0UHJvdmlkZXJUaHVtYnByaW50OiAocmVxOiBhd3MuSUFNLlVwZGF0ZU9wZW5JRENvbm5lY3RQcm92aWRlclRodW1icHJpbnRSZXF1ZXN0KSA9PiBpYW0oKS51cGRhdGVPcGVuSURDb25uZWN0UHJvdmlkZXJUaHVtYnByaW50KHJlcSkucHJvbWlzZSgpLFxuICBhZGRDbGllbnRJRFRvT3BlbklEQ29ubmVjdFByb3ZpZGVyOiAocmVxOiBhd3MuSUFNLkFkZENsaWVudElEVG9PcGVuSURDb25uZWN0UHJvdmlkZXJSZXF1ZXN0KSA9PiBpYW0oKS5hZGRDbGllbnRJRFRvT3BlbklEQ29ubmVjdFByb3ZpZGVyKHJlcSkucHJvbWlzZSgpLFxuICByZW1vdmVDbGllbnRJREZyb21PcGVuSURDb25uZWN0UHJvdmlkZXI6IChyZXE6IGF3cy5JQU0uUmVtb3ZlQ2xpZW50SURGcm9tT3BlbklEQ29ubmVjdFByb3ZpZGVyUmVxdWVzdCkgPT4gaWFtKCkucmVtb3ZlQ2xpZW50SURGcm9tT3BlbklEQ29ubmVjdFByb3ZpZGVyKHJlcSkucHJvbWlzZSgpLFxufTsiXX0= \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.56b85a7bb756e34ab12549549eb40d34151db41531599e8f2be6c04e8ae66057/index.js b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.2df5a59d801a1efa337d7f2787d401cc48d736faa94d1f42eccad2d88f3ce2e3/index.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.56b85a7bb756e34ab12549549eb40d34151db41531599e8f2be6c04e8ae66057/index.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.2df5a59d801a1efa337d7f2787d401cc48d736faa94d1f42eccad2d88f3ce2e3/index.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/aws-eks-oidc-provider-test.assets.json b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/aws-eks-oidc-provider-test.assets.json index 59e0b92f1c992..ecf4e6c5b6949 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/aws-eks-oidc-provider-test.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/aws-eks-oidc-provider-test.assets.json @@ -1,20 +1,20 @@ { - "version": "21.0.0", + "version": "30.1.0", "files": { - "56b85a7bb756e34ab12549549eb40d34151db41531599e8f2be6c04e8ae66057": { + "2df5a59d801a1efa337d7f2787d401cc48d736faa94d1f42eccad2d88f3ce2e3": { "source": { - "path": "asset.56b85a7bb756e34ab12549549eb40d34151db41531599e8f2be6c04e8ae66057", + "path": "asset.2df5a59d801a1efa337d7f2787d401cc48d736faa94d1f42eccad2d88f3ce2e3", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "56b85a7bb756e34ab12549549eb40d34151db41531599e8f2be6c04e8ae66057.zip", + "objectKey": "2df5a59d801a1efa337d7f2787d401cc48d736faa94d1f42eccad2d88f3ce2e3.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "4e955be736aaca99ba72477fbbb5552c4f27f3b34b7a3879f2654a831127f045": { + "9c63eb07e389af82f82f1347328d2ed0c1e975c2f142d2be2d55e48d9603ed41": { "source": { "path": "aws-eks-oidc-provider-test.template.json", "packaging": "file" @@ -22,7 +22,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "4e955be736aaca99ba72477fbbb5552c4f27f3b34b7a3879f2654a831127f045.json", + "objectKey": "9c63eb07e389af82f82f1347328d2ed0c1e975c2f142d2be2d55e48d9603ed41.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/aws-eks-oidc-provider-test.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/aws-eks-oidc-provider-test.template.json index c6e27521470aa..7d51bc35d777e 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/aws-eks-oidc-provider-test.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/aws-eks-oidc-provider-test.template.json @@ -24,7 +24,7 @@ ] ] }, - "CodeHash": "56b85a7bb756e34ab12549549eb40d34151db41531599e8f2be6c04e8ae66057" + "CodeHash": "2df5a59d801a1efa337d7f2787d401cc48d736faa94d1f42eccad2d88f3ce2e3" }, "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" @@ -79,7 +79,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "56b85a7bb756e34ab12549549eb40d34151db41531599e8f2be6c04e8ae66057.zip" + "S3Key": "2df5a59d801a1efa337d7f2787d401cc48d736faa94d1f42eccad2d88f3ce2e3.zip" }, "Timeout": 900, "MemorySize": 128, diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/awscdkeksoidcproviderDefaultTestDeployAssert0BFFC9B9.assets.json b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/awscdkeksoidcproviderDefaultTestDeployAssert0BFFC9B9.assets.json index 76c8b566c39da..8b83396d2c274 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/awscdkeksoidcproviderDefaultTestDeployAssert0BFFC9B9.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/awscdkeksoidcproviderDefaultTestDeployAssert0BFFC9B9.assets.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/cdk.out b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/cdk.out index 8ecc185e9dbee..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"21.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/integ.json b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/integ.json index 5ddd0b2dca668..4c5a77e0f9dbe 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "testCases": { "aws-cdk-eks-oidc-provider/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/manifest.json b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/manifest.json index 9330792a2acec..4cb1d3eb3636d 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "artifacts": { "aws-eks-oidc-provider-test.assets": { "type": "cdk:asset-manifest", @@ -17,7 +17,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/4e955be736aaca99ba72477fbbb5552c4f27f3b34b7a3879f2654a831127f045.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/9c63eb07e389af82f82f1347328d2ed0c1e975c2f142d2be2d55e48d9603ed41.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/tree.json b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/tree.json index 25fc52ed0d758..65509938458bb 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/tree.json @@ -105,7 +105,7 @@ "path": "aws-cdk-eks-oidc-provider/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.140" + "version": "10.1.252" } }, "DeployAssert": { @@ -151,7 +151,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.140" + "version": "10.1.252" } } }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js new file mode 100644 index 0000000000000..c9dc1b8d2c19a --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js @@ -0,0 +1,273 @@ +"use strict"; +/* eslint-disable no-console */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ClusterResourceHandler = void 0; +const common_1 = require("./common"); +const MAX_CLUSTER_NAME_LEN = 100; +class ClusterResourceHandler extends common_1.ResourceHandler { + constructor(eks, event) { + super(eks, event); + this.newProps = parseProps(this.event.ResourceProperties); + this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; + } + get clusterName() { + if (!this.physicalResourceId) { + throw new Error('Cannot determine cluster name without physical resource ID'); + } + return this.physicalResourceId; + } + // ------ + // CREATE + // ------ + async onCreate() { + console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); + if (!this.newProps.roleArn) { + throw new Error('"roleArn" is required'); + } + const clusterName = this.newProps.name || this.generateClusterName(); + const resp = await this.eks.createCluster({ + ...this.newProps, + name: clusterName, + }); + if (!resp.cluster) { + throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); + } + return { + PhysicalResourceId: resp.cluster.name, + }; + } + async isCreateComplete() { + return this.isActive(); + } + // ------ + // DELETE + // ------ + async onDelete() { + console.log(`onDelete: deleting cluster ${this.clusterName}`); + try { + await this.eks.deleteCluster({ name: this.clusterName }); + } + catch (e) { + if (e.code !== 'ResourceNotFoundException') { + throw e; + } + else { + console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); + } + } + return { + PhysicalResourceId: this.clusterName, + }; + } + async isDeleteComplete() { + console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); + try { + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); + } + catch (e) { + if (e.code === 'ResourceNotFoundException') { + console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); + return { IsComplete: true }; + } + console.log('describeCluster error:', e); + throw e; + } + return { + IsComplete: false, + }; + } + // ------ + // UPDATE + // ------ + async onUpdate() { + const updates = analyzeUpdate(this.oldProps, this.newProps); + console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); + // updates to encryption config is not supported + if (updates.updateEncryption) { + throw new Error('Cannot update cluster encryption configuration'); + } + // if there is an update that requires replacement, go ahead and just create + // a new cluster with the new config. The old cluster will automatically be + // deleted by cloudformation upon success. + if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { + // if we are replacing this cluster and the cluster has an explicit + // physical name, the creation of the new cluster will fail with "there is + // already a cluster with that name". this is a common behavior for + // CloudFormation resources that support specifying a physical name. + if (this.oldProps.name === this.newProps.name && this.oldProps.name) { + throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); + } + return this.onCreate(); + } + // if a version update is required, issue the version update + if (updates.updateVersion) { + if (!this.newProps.version) { + throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); + } + return this.updateClusterVersion(this.newProps.version); + } + if (updates.updateLogging && updates.updateAccess) { + throw new Error('Cannot update logging and access at the same time'); + } + if (updates.updateLogging || updates.updateAccess) { + const config = { + name: this.clusterName, + }; + if (updates.updateLogging) { + config.logging = this.newProps.logging; + } + ; + if (updates.updateAccess) { + // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: + // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) + // will fail, therefore we take only the access fields explicitly + config.resourcesVpcConfig = { + endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, + endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, + publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, + }; + } + const updateResponse = await this.eks.updateClusterConfig(config); + return { EksUpdateId: updateResponse.update?.id }; + } + // no updates + return; + } + async isUpdateComplete() { + console.log('isUpdateComplete'); + // if this is an EKS update, we will monitor the update event itself + if (this.event.EksUpdateId) { + const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); + if (!complete) { + return { IsComplete: false }; + } + // fall through: if the update is done, we simply delegate to isActive() + // in order to extract attributes and state from the cluster itself, which + // is supposed to be in an ACTIVE state after the update is complete. + } + return this.isActive(); + } + async updateClusterVersion(newVersion) { + console.log(`updating cluster version to ${newVersion}`); + // update-cluster-version will fail if we try to update to the same version, + // so skip in this case. + const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; + if (cluster?.version === newVersion) { + console.log(`cluster already at version ${cluster.version}, skipping version update`); + return; + } + const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); + return { EksUpdateId: updateResponse.update?.id }; + } + async isActive() { + console.log('waiting for cluster to become ACTIVE'); + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); + const cluster = resp.cluster; + // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are + // not complete. note that the custom resource provider framework forbids + // returning attributes (Data) if isComplete is false. + if (cluster?.status === 'FAILED') { + // not very informative, unfortunately the response doesn't contain any error + // information :\ + throw new Error('Cluster is in a FAILED status'); + } + else if (cluster?.status !== 'ACTIVE') { + return { + IsComplete: false, + }; + } + else { + return { + IsComplete: true, + Data: { + Name: cluster.name, + Endpoint: cluster.endpoint, + Arn: cluster.arn, + // IMPORTANT: CFN expects that attributes will *always* have values, + // so return an empty string in case the value is not defined. + // Otherwise, CFN will throw with `Vendor response doesn't contain + // XXXX key`. + CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', + ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', + OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', + OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', + // We can safely return the first item from encryption configuration array, because it has a limit of 1 item + // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig + EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', + }, + }; + } + } + async isEksUpdateComplete(eksUpdateId) { + this.log({ isEksUpdateComplete: eksUpdateId }); + const describeUpdateResponse = await this.eks.describeUpdate({ + name: this.clusterName, + updateId: eksUpdateId, + }); + this.log({ describeUpdateResponse }); + if (!describeUpdateResponse.update) { + throw new Error(`unable to describe update with id "${eksUpdateId}"`); + } + switch (describeUpdateResponse.update.status) { + case 'InProgress': + return false; + case 'Successful': + return true; + case 'Failed': + case 'Cancelled': + throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); + default: + throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); + } + } + generateClusterName() { + const suffix = this.requestId.replace(/-/g, ''); // 32 chars + const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; + const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); + return `${prefix}-${suffix}`; + } +} +exports.ClusterResourceHandler = ClusterResourceHandler; +function parseProps(props) { + const parsed = props?.Config ?? {}; + // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. + // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' + if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; + } + if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; + } + if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { + parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; + } + return parsed; +} +function analyzeUpdate(oldProps, newProps) { + console.log('old props: ', JSON.stringify(oldProps)); + console.log('new props: ', JSON.stringify(newProps)); + const newVpcProps = newProps.resourcesVpcConfig || {}; + const oldVpcProps = oldProps.resourcesVpcConfig || {}; + const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); + const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); + const newEnc = newProps.encryptionConfig || {}; + const oldEnc = oldProps.encryptionConfig || {}; + return { + replaceName: newProps.name !== oldProps.name, + replaceVpc: JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), + updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || + newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || + !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), + replaceRole: newProps.roleArn !== oldProps.roleArn, + updateVersion: newProps.version !== oldProps.version, + updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), + updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), + }; +} +function setsEqual(first, second) { + return first.size === second.size && [...first].every((e) => second.has(e)); +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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LENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztRQUNuRSxhQUFhLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBa0IsRUFBRSxNQUFtQjtJQUN4RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgRWtzQ2xpZW50LCBSZXNvdXJjZUV2ZW50LCBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX05BTUVfTEVOID0gMTAwO1xuXG5leHBvcnQgY2xhc3MgQ2x1c3RlclJlc291cmNlSGFuZGxlciBleHRlbmRzIFJlc291cmNlSGFuZGxlciB7XG4gIHB1YmxpYyBnZXQgY2x1c3Rlck5hbWUoKSB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZGV0ZXJtaW5lIGNsdXN0ZXIgbmFtZSB3aXRob3V0IHBoeXNpY2FsIHJlc291cmNlIElEJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PjtcblxuICBjb25zdHJ1Y3Rvcihla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICBzdXBlcihla3MsIGV2ZW50KTtcblxuICAgIHRoaXMubmV3UHJvcHMgPSBwYXJzZVByb3BzKHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLm9sZFByb3BzID0gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnID8gcGFyc2VQcm9wcyhldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMpIDoge307XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gQ1JFQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCdvbkNyZWF0ZTogY3JlYXRpbmcgY2x1c3RlciB3aXRoIG9wdGlvbnM6JywgSlNPTi5zdHJpbmdpZnkodGhpcy5uZXdQcm9wcywgdW5kZWZpbmVkLCAyKSk7XG4gICAgaWYgKCF0aGlzLm5ld1Byb3BzLnJvbGVBcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJyb2xlQXJuXCIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyTmFtZSA9IHRoaXMubmV3UHJvcHMubmFtZSB8fCB0aGlzLmdlbmVyYXRlQ2x1c3Rlck5hbWUoKTtcblxuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmVrcy5jcmVhdGVDbHVzdGVyKHtcbiAgICAgIC4uLnRoaXMubmV3UHJvcHMsXG4gICAgICBuYW1lOiBjbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcC5jbHVzdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBjbHVzdGVyICR7Y2x1c3Rlck5hbWV9OiBDcmVhdGVDbHVzdGVyIHJldHVybmVkIHdpdGhvdXQgY2x1c3RlciBpbmZvcm1hdGlvbmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHJlc3AuY2x1c3Rlci5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIERFTEVURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25EZWxldGUoKTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgb25EZWxldGU6IGRlbGV0aW5nIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfWApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVrcy5kZWxldGVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyICR7dGhpcy5jbHVzdGVyTmFtZX0gbm90IGZvdW5kLCBpZGVtcG90ZW50bHkgc3VjY2VlZGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coYGlzRGVsZXRlQ29tcGxldGU6IHdhaXRpbmcgZm9yIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSB0byBiZSBkZWxldGVkYCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJldHVybmVkOicsIEpTT04uc3RyaW5naWZ5KHJlc3AsIHVuZGVmaW5lZCwgMikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICBjb25zb2xlLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgY2x1c3RlciBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0cnVlIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgZXJyb3I6JywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIFVQREFURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IGFuYWx5emVVcGRhdGUodGhpcy5vbGRQcm9wcywgdGhpcy5uZXdQcm9wcyk7XG4gICAgY29uc29sZS5sb2coJ29uVXBkYXRlOicsIEpTT04uc3RyaW5naWZ5KHsgdXBkYXRlcyB9LCB1bmRlZmluZWQsIDIpKTtcblxuICAgIC8vIHVwZGF0ZXMgdG8gZW5jcnlwdGlvbiBjb25maWcgaXMgbm90IHN1cHBvcnRlZFxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUVuY3J5cHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHVwZGF0ZSBjbHVzdGVyIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZXJlIGlzIGFuIHVwZGF0ZSB0aGF0IHJlcXVpcmVzIHJlcGxhY2VtZW50LCBnbyBhaGVhZCBhbmQganVzdCBjcmVhdGVcbiAgICAvLyBhIG5ldyBjbHVzdGVyIHdpdGggdGhlIG5ldyBjb25maWcuIFRoZSBvbGQgY2x1c3RlciB3aWxsIGF1dG9tYXRpY2FsbHkgYmVcbiAgICAvLyBkZWxldGVkIGJ5IGNsb3VkZm9ybWF0aW9uIHVwb24gc3VjY2Vzcy5cbiAgICBpZiAodXBkYXRlcy5yZXBsYWNlTmFtZSB8fCB1cGRhdGVzLnJlcGxhY2VSb2xlIHx8IHVwZGF0ZXMucmVwbGFjZVZwYykge1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgcmVwbGFjaW5nIHRoaXMgY2x1c3RlciBhbmQgdGhlIGNsdXN0ZXIgaGFzIGFuIGV4cGxpY2l0XG4gICAgICAvLyBwaHlzaWNhbCBuYW1lLCB0aGUgY3JlYXRpb24gb2YgdGhlIG5ldyBjbHVzdGVyIHdpbGwgZmFpbCB3aXRoIFwidGhlcmUgaXNcbiAgICAgIC8vIGFscmVhZHkgYSBjbHVzdGVyIHdpdGggdGhhdCBuYW1lXCIuIHRoaXMgaXMgYSBjb21tb24gYmVoYXZpb3IgZm9yXG4gICAgICAvLyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZXMgdGhhdCBzdXBwb3J0IHNwZWNpZnlpbmcgYSBwaHlzaWNhbCBuYW1lLlxuICAgICAgaWYgKHRoaXMub2xkUHJvcHMubmFtZSA9PT0gdGhpcy5uZXdQcm9wcy5uYW1lICYmIHRoaXMub2xkUHJvcHMubmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXBsYWNlIGNsdXN0ZXIgXCIke3RoaXMub2xkUHJvcHMubmFtZX1cIiBzaW5jZSBpdCBoYXMgYW4gZXhwbGljaXQgcGh5c2ljYWwgbmFtZS4gRWl0aGVyIHJlbmFtZSB0aGUgY2x1c3RlciBvciByZW1vdmUgdGhlIFwibmFtZVwiIGNvbmZpZ3VyYXRpb25gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub25DcmVhdGUoKTtcbiAgICB9XG5cbiAgICAvLyBpZiBhIHZlcnNpb24gdXBkYXRlIGlzIHJlcXVpcmVkLCBpc3N1ZSB0aGUgdmVyc2lvbiB1cGRhdGVcbiAgICBpZiAodXBkYXRlcy51cGRhdGVWZXJzaW9uKSB7XG4gICAgICBpZiAoIXRoaXMubmV3UHJvcHMudmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZW1vdmUgY2x1c3RlciB2ZXJzaW9uIGNvbmZpZ3VyYXRpb24uIEN1cnJlbnQgdmVyc2lvbiBpcyAke3RoaXMub2xkUHJvcHMudmVyc2lvbn1gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlQ2x1c3RlclZlcnNpb24odGhpcy5uZXdQcm9wcy52ZXJzaW9uKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nICYmIHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1cGRhdGUgbG9nZ2luZyBhbmQgYWNjZXNzIGF0IHRoZSBzYW1lIHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nIHx8IHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICBjb25zdCBjb25maWc6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QgPSB7XG4gICAgICAgIG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgICB9O1xuICAgICAgaWYgKHVwZGF0ZXMudXBkYXRlTG9nZ2luZykge1xuICAgICAgICBjb25maWcubG9nZ2luZyA9IHRoaXMubmV3UHJvcHMubG9nZ2luZztcbiAgICAgIH07XG4gICAgICBpZiAodXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIGNsdXN0ZXIgd2l0aCBzZWN1cml0eUdyb3VwSWRzIGFuZCBzdWJuZXRJZHMgKGFzIHNwZWNpZmllZCBpbiB0aGUgd2FybmluZyBoZXJlOlxuICAgICAgICAvLyBodHRwczovL2F3c2NsaS5hbWF6b25hd3MuY29tL3YyL2RvY3VtZW50YXRpb24vYXBpL2xhdGVzdC9yZWZlcmVuY2UvZWtzL3VwZGF0ZS1jbHVzdGVyLWNvbmZpZy5odG1sKVxuICAgICAgICAvLyB3aWxsIGZhaWwsIHRoZXJlZm9yZSB3ZSB0YWtlIG9ubHkgdGhlIGFjY2VzcyBmaWVsZHMgZXhwbGljaXRseVxuICAgICAgICBjb25maWcucmVzb3VyY2VzVnBjQ29uZmlnID0ge1xuICAgICAgICAgIGVuZHBvaW50UHJpdmF0ZUFjY2VzczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzLFxuICAgICAgICAgIGVuZHBvaW50UHVibGljQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyxcbiAgICAgICAgICBwdWJsaWNBY2Nlc3NDaWRyczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcucHVibGljQWNjZXNzQ2lkcnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgICB9XG5cbiAgICAvLyBubyB1cGRhdGVzXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc29sZS5sb2coJ2lzVXBkYXRlQ29tcGxldGUnKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYW4gRUtTIHVwZGF0ZSwgd2Ugd2lsbCBtb25pdG9yIHRoZSB1cGRhdGUgZXZlbnQgaXRzZWxmXG4gICAgaWYgKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gYXdhaXQgdGhpcy5pc0Vrc1VwZGF0ZUNvbXBsZXRlKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpO1xuICAgICAgaWYgKCFjb21wbGV0ZSkge1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiBmYWxzZSB9O1xuICAgICAgfVxuXG4gICAgICAvLyBmYWxsIHRocm91Z2g6IGlmIHRoZSB1cGRhdGUgaXMgZG9uZSwgd2Ugc2ltcGx5IGRlbGVnYXRlIHRvIGlzQWN0aXZlKClcbiAgICAgIC8vIGluIG9yZGVyIHRvIGV4dHJhY3QgYXR0cmlidXRlcyBhbmQgc3RhdGUgZnJvbSB0aGUgY2x1c3RlciBpdHNlbGYsIHdoaWNoXG4gICAgICAvLyBpcyBzdXBwb3NlZCB0byBiZSBpbiBhbiBBQ1RJVkUgc3RhdGUgYWZ0ZXIgdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbHVzdGVyVmVyc2lvbihuZXdWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgdXBkYXRpbmcgY2x1c3RlciB2ZXJzaW9uIHRvICR7bmV3VmVyc2lvbn1gKTtcblxuICAgIC8vIHVwZGF0ZS1jbHVzdGVyLXZlcnNpb24gd2lsbCBmYWlsIGlmIHdlIHRyeSB0byB1cGRhdGUgdG8gdGhlIHNhbWUgdmVyc2lvbixcbiAgICAvLyBzbyBza2lwIGluIHRoaXMgY2FzZS5cbiAgICBjb25zdCBjbHVzdGVyID0gKGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSkpLmNsdXN0ZXI7XG4gICAgaWYgKGNsdXN0ZXI/LnZlcnNpb24gPT09IG5ld1ZlcnNpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyIGFscmVhZHkgYXQgdmVyc2lvbiAke2NsdXN0ZXIudmVyc2lvbn0sIHNraXBwaW5nIHZlcnNpb24gdXBkYXRlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy51cGRhdGVDbHVzdGVyVmVyc2lvbih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsIHZlcnNpb246IG5ld1ZlcnNpb24gfSk7XG4gICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNBY3RpdmUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZygnd2FpdGluZyBmb3IgY2x1c3RlciB0byBiZWNvbWUgQUNUSVZFJyk7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciByZXN1bHQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgY29uc3QgY2x1c3RlciA9IHJlc3AuY2x1c3RlcjtcblxuICAgIC8vIGlmIGNsdXN0ZXIgaXMgdW5kZWZpbmVkIChzaG91bGRudCBoYXBwZW4pIG9yIHN0YXR1cyBpcyBub3QgQUNUSVZFLCB3ZSBhcmVcbiAgICAvLyBub3QgY29tcGxldGUuIG5vdGUgdGhhdCB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZyYW1ld29yayBmb3JiaWRzXG4gICAgLy8gcmV0dXJuaW5nIGF0dHJpYnV0ZXMgKERhdGEpIGlmIGlzQ29tcGxldGUgaXMgZmFsc2UuXG4gICAgaWYgKGNsdXN0ZXI/LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgIC8vIG5vdCB2ZXJ5IGluZm9ybWF0aXZlLCB1bmZvcnR1bmF0ZWx5IHRoZSByZXNwb25zZSBkb2Vzbid0IGNvbnRhaW4gYW55IGVycm9yXG4gICAgICAvLyBpbmZvcm1hdGlvbiA6XFxcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2x1c3RlciBpcyBpbiBhIEZBSUxFRCBzdGF0dXMnKTtcbiAgICB9IGVsc2UgaWYgKGNsdXN0ZXI/LnN0YXR1cyAhPT0gJ0FDVElWRScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIE5hbWU6IGNsdXN0ZXIubmFtZSxcbiAgICAgICAgICBFbmRwb2ludDogY2x1c3Rlci5lbmRwb2ludCxcbiAgICAgICAgICBBcm46IGNsdXN0ZXIuYXJuLFxuXG4gICAgICAgICAgLy8gSU1QT1JUQU5UOiBDRk4gZXhwZWN0cyB0aGF0IGF0dHJpYnV0ZXMgd2lsbCAqYWx3YXlzKiBoYXZlIHZhbHVlcyxcbiAgICAgICAgICAvLyBzbyByZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGluIGNhc2UgdGhlIHZhbHVlIGlzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQ0ZOIHdpbGwgdGhyb3cgd2l0aCBgVmVuZG9yIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpblxuICAgICAgICAgIC8vIFhYWFgga2V5YC5cblxuICAgICAgICAgIENlcnRpZmljYXRlQXV0aG9yaXR5RGF0YTogY2x1c3Rlci5jZXJ0aWZpY2F0ZUF1dGhvcml0eT8uZGF0YSA/PyAnJyxcbiAgICAgICAgICBDbHVzdGVyU2VjdXJpdHlHcm91cElkOiBjbHVzdGVyLnJlc291cmNlc1ZwY0NvbmZpZz8uY2x1c3RlclNlY3VyaXR5R3JvdXBJZCA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyVXJsOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXIgPz8gJycsXG4gICAgICAgICAgT3BlbklkQ29ubmVjdElzc3VlcjogY2x1c3Rlci5pZGVudGl0eT8ub2lkYz8uaXNzdWVyPy5zdWJzdHJpbmcoOCkgPz8gJycsIC8vIFN0cmlwcyBvZmYgaHR0cHM6Ly8gZnJvbSB0aGUgaXNzdWVyIHVybFxuXG4gICAgICAgICAgLy8gV2UgY2FuIHNhZmVseSByZXR1cm4gdGhlIGZpcnN0IGl0ZW0gZnJvbSBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gYXJyYXksIGJlY2F1c2UgaXQgaGFzIGEgbGltaXQgb2YgMSBpdGVtXG4gICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vrcy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDbHVzdGVyLmh0bWwjQW1hem9uRUtTLUNyZWF0ZUNsdXN0ZXItcmVxdWVzdC1lbmNyeXB0aW9uQ29uZmlnXG4gICAgICAgICAgRW5jcnlwdGlvbkNvbmZpZ0tleUFybjogY2x1c3Rlci5lbmNyeXB0aW9uQ29uZmlnPy5zaGlmdCgpPy5wcm92aWRlcj8ua2V5QXJuID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzRWtzVXBkYXRlQ29tcGxldGUoZWtzVXBkYXRlSWQ6IHN0cmluZykge1xuICAgIHRoaXMubG9nKHsgaXNFa3NVcGRhdGVDb21wbGV0ZTogZWtzVXBkYXRlSWQgfSk7XG5cbiAgICBjb25zdCBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVVcGRhdGUoe1xuICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgIHVwZGF0ZUlkOiBla3NVcGRhdGVJZCxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nKHsgZGVzY3JpYmVVcGRhdGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5hYmxlIHRvIGRlc2NyaWJlIHVwZGF0ZSB3aXRoIGlkIFwiJHtla3NVcGRhdGVJZH1cImApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzKSB7XG4gICAgICBjYXNlICdJblByb2dyZXNzJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgY2FzZSAnU3VjY2Vzc2Z1bCc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnRmFpbGVkJzpcbiAgICAgIGNhc2UgJ0NhbmNlbGxlZCc6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2x1c3RlciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiIGZhaWxlZCB3aXRoIGVycm9yczogJHtKU09OLnN0cmluZ2lmeShkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5lcnJvcnMpfWApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIHN0YXR1cyBcIiR7ZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzfVwiIGZvciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNsdXN0ZXJOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9DTFVTVEVSX05BTUVfTEVOIC0gc3VmZml4Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5sb2dpY2FsUmVzb3VyY2VJZC5zbGljZSgwLCBvZmZzZXQgPiAwID8gb2Zmc2V0IDogMCk7XG4gICAgcmV0dXJuIGAke3ByZWZpeH0tJHtzdWZmaXh9YDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3BzKHByb3BzOiBhbnkpOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0IHtcblxuICBjb25zdCBwYXJzZWQgPSBwcm9wcz8uQ29uZmlnID8/IHt9O1xuXG4gIC8vIHRoaXMgaXMgd2VpcmQgYnV0IHRoZXNlIGJvb2xlYW4gcHJvcGVydGllcyBhcmUgcGFzc2VkIGJ5IENGTiBhcyBhIHN0cmluZywgYW5kIHdlIG5lZWQgdGhlbSB0byBiZSBib29sZWFuaWMgZm9yIHRoZSBTREsuXG4gIC8vIE90aGVyd2lzZSBpdCBmYWlscyB3aXRoICdVbmV4cGVjdGVkIFBhcmFtZXRlcjogcGFyYW1zLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgaXMgZXhwZWN0ZWQgdG8gYmUgYSBib29sZWFuJ1xuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWc/LmVuZHBvaW50UHJpdmF0ZUFjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9PT0gJ3RydWUnO1xuICB9XG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQdWJsaWNBY2Nlc3MpID09PSAnc3RyaW5nJykge1xuICAgIHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQubG9nZ2luZz8uY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCkgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9IHBhcnNlZC5sb2dnaW5nLmNsdXN0ZXJMb2dnaW5nWzBdLmVuYWJsZWQgPT09ICd0cnVlJztcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQ7XG5cbn1cblxuaW50ZXJmYWNlIFVwZGF0ZU1hcCB7XG4gIHJlcGxhY2VOYW1lOiBib29sZWFuOyAvLyBuYW1lXG4gIHJlcGxhY2VWcGM6IGJvb2xlYW47IC8vIHJlc291cmNlc1ZwY0NvbmZpZy5zdWJuZXRJZHMgYW5kIHNlY3VyaXR5R3JvdXBJZHNcbiAgcmVwbGFjZVJvbGU6IGJvb2xlYW47IC8vIHJvbGVBcm5cblxuICB1cGRhdGVWZXJzaW9uOiBib29sZWFuOyAvLyB2ZXJzaW9uXG4gIHVwZGF0ZUxvZ2dpbmc6IGJvb2xlYW47IC8vIGxvZ2dpbmdcbiAgdXBkYXRlRW5jcnlwdGlvbjogYm9vbGVhbjsgLy8gZW5jcnlwdGlvbiAoY2Fubm90IGJlIHVwZGF0ZWQpXG4gIHVwZGF0ZUFjY2VzczogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBhbmQgZW5kcG9pbnRQdWJsaWNBY2Nlc3Ncbn1cblxuZnVuY3Rpb24gYW5hbHl6ZVVwZGF0ZShvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PiwgbmV3UHJvcHM6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBVcGRhdGVNYXAge1xuICBjb25zb2xlLmxvZygnb2xkIHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShvbGRQcm9wcykpO1xuICBjb25zb2xlLmxvZygnbmV3IHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShuZXdQcm9wcykpO1xuXG4gIGNvbnN0IG5ld1ZwY1Byb3BzID0gbmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRWcGNQcm9wcyA9IG9sZFByb3BzLnJlc291cmNlc1ZwY0NvbmZpZyB8fCB7fTtcblxuICBjb25zdCBvbGRQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQob2xkVnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQobmV3VnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdFbmMgPSBuZXdQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRFbmMgPSBvbGRQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgcmVwbGFjZU5hbWU6IG5ld1Byb3BzLm5hbWUgIT09IG9sZFByb3BzLm5hbWUsXG4gICAgcmVwbGFjZVZwYzpcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnN1Ym5ldElkcz8uc29ydCgpKSAhPT0gSlNPTi5zdHJpbmdpZnkob2xkVnBjUHJvcHMuc3VibmV0SWRzPy5zb3J0KCkpIHx8XG4gICAgICBKU09OLnN0cmluZ2lmeShuZXdWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpICE9PSBKU09OLnN0cmluZ2lmeShvbGRWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpLFxuICAgIHVwZGF0ZUFjY2VzczpcbiAgICAgIG5ld1ZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQcml2YXRlQWNjZXNzIHx8XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFB1YmxpY0FjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgfHxcbiAgICAgICFzZXRzRXF1YWwobmV3UHVibGljQWNjZXNzQ2lkcnMsIG9sZFB1YmxpY0FjY2Vzc0NpZHJzKSxcbiAgICByZXBsYWNlUm9sZTogbmV3UHJvcHMucm9sZUFybiAhPT0gb2xkUHJvcHMucm9sZUFybixcbiAgICB1cGRhdGVWZXJzaW9uOiBuZXdQcm9wcy52ZXJzaW9uICE9PSBvbGRQcm9wcy52ZXJzaW9uLFxuICAgIHVwZGF0ZUVuY3J5cHRpb246IEpTT04uc3RyaW5naWZ5KG5ld0VuYykgIT09IEpTT04uc3RyaW5naWZ5KG9sZEVuYyksXG4gICAgdXBkYXRlTG9nZ2luZzogSlNPTi5zdHJpbmdpZnkobmV3UHJvcHMubG9nZ2luZykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFByb3BzLmxvZ2dpbmcpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzZXRzRXF1YWwoZmlyc3Q6IFNldDxzdHJpbmc+LCBzZWNvbmQ6IFNldDxzdHJpbmc+KSB7XG4gIHJldHVybiBmaXJzdC5zaXplID09PSBzZWNvbmQuc2l6ZSAmJiBbLi4uZmlyc3RdLmV2ZXJ5KChlOiBzdHJpbmcpID0+IHNlY29uZC5oYXMoZSkpO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts new file mode 100644 index 0000000000000..4b7fdda6d1dd1 --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts @@ -0,0 +1,344 @@ +/* eslint-disable no-console */ + +// eslint-disable-next-line import/no-extraneous-dependencies +import { IsCompleteResponse, OnEventResponse } from '@aws-cdk/custom-resources/lib/provider-framework/types'; +// eslint-disable-next-line import/no-extraneous-dependencies +import * as aws from 'aws-sdk'; +import { EksClient, ResourceEvent, ResourceHandler } from './common'; + +const MAX_CLUSTER_NAME_LEN = 100; + +export class ClusterResourceHandler extends ResourceHandler { + public get clusterName() { + if (!this.physicalResourceId) { + throw new Error('Cannot determine cluster name without physical resource ID'); + } + + return this.physicalResourceId; + } + + private readonly newProps: aws.EKS.CreateClusterRequest; + private readonly oldProps: Partial; + + constructor(eks: EksClient, event: ResourceEvent) { + super(eks, event); + + this.newProps = parseProps(this.event.ResourceProperties); + this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; + } + + // ------ + // CREATE + // ------ + + protected async onCreate(): Promise { + console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); + if (!this.newProps.roleArn) { + throw new Error('"roleArn" is required'); + } + + const clusterName = this.newProps.name || this.generateClusterName(); + + const resp = await this.eks.createCluster({ + ...this.newProps, + name: clusterName, + }); + + if (!resp.cluster) { + throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); + } + + return { + PhysicalResourceId: resp.cluster.name, + }; + } + + protected async isCreateComplete() { + return this.isActive(); + } + + // ------ + // DELETE + // ------ + + protected async onDelete(): Promise { + console.log(`onDelete: deleting cluster ${this.clusterName}`); + try { + await this.eks.deleteCluster({ name: this.clusterName }); + } catch (e) { + if (e.code !== 'ResourceNotFoundException') { + throw e; + } else { + console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); + } + } + return { + PhysicalResourceId: this.clusterName, + }; + } + + protected async isDeleteComplete(): Promise { + console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); + + try { + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); + } catch (e) { + if (e.code === 'ResourceNotFoundException') { + console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); + return { IsComplete: true }; + } + + console.log('describeCluster error:', e); + throw e; + } + + return { + IsComplete: false, + }; + } + + // ------ + // UPDATE + // ------ + + protected async onUpdate() { + const updates = analyzeUpdate(this.oldProps, this.newProps); + console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); + + // updates to encryption config is not supported + if (updates.updateEncryption) { + throw new Error('Cannot update cluster encryption configuration'); + } + + // if there is an update that requires replacement, go ahead and just create + // a new cluster with the new config. The old cluster will automatically be + // deleted by cloudformation upon success. + if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { + + // if we are replacing this cluster and the cluster has an explicit + // physical name, the creation of the new cluster will fail with "there is + // already a cluster with that name". this is a common behavior for + // CloudFormation resources that support specifying a physical name. + if (this.oldProps.name === this.newProps.name && this.oldProps.name) { + throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); + } + + return this.onCreate(); + } + + // if a version update is required, issue the version update + if (updates.updateVersion) { + if (!this.newProps.version) { + throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); + } + + return this.updateClusterVersion(this.newProps.version); + } + + if (updates.updateLogging && updates.updateAccess) { + throw new Error('Cannot update logging and access at the same time'); + } + + if (updates.updateLogging || updates.updateAccess) { + const config: aws.EKS.UpdateClusterConfigRequest = { + name: this.clusterName, + }; + if (updates.updateLogging) { + config.logging = this.newProps.logging; + }; + if (updates.updateAccess) { + // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: + // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) + // will fail, therefore we take only the access fields explicitly + config.resourcesVpcConfig = { + endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, + endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, + publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, + }; + } + const updateResponse = await this.eks.updateClusterConfig(config); + + return { EksUpdateId: updateResponse.update?.id }; + } + + // no updates + return; + } + + protected async isUpdateComplete() { + console.log('isUpdateComplete'); + + // if this is an EKS update, we will monitor the update event itself + if (this.event.EksUpdateId) { + const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); + if (!complete) { + return { IsComplete: false }; + } + + // fall through: if the update is done, we simply delegate to isActive() + // in order to extract attributes and state from the cluster itself, which + // is supposed to be in an ACTIVE state after the update is complete. + } + + return this.isActive(); + } + + private async updateClusterVersion(newVersion: string) { + console.log(`updating cluster version to ${newVersion}`); + + // update-cluster-version will fail if we try to update to the same version, + // so skip in this case. + const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; + if (cluster?.version === newVersion) { + console.log(`cluster already at version ${cluster.version}, skipping version update`); + return; + } + + const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); + return { EksUpdateId: updateResponse.update?.id }; + } + + private async isActive(): Promise { + console.log('waiting for cluster to become ACTIVE'); + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); + const cluster = resp.cluster; + + // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are + // not complete. note that the custom resource provider framework forbids + // returning attributes (Data) if isComplete is false. + if (cluster?.status === 'FAILED') { + // not very informative, unfortunately the response doesn't contain any error + // information :\ + throw new Error('Cluster is in a FAILED status'); + } else if (cluster?.status !== 'ACTIVE') { + return { + IsComplete: false, + }; + } else { + return { + IsComplete: true, + Data: { + Name: cluster.name, + Endpoint: cluster.endpoint, + Arn: cluster.arn, + + // IMPORTANT: CFN expects that attributes will *always* have values, + // so return an empty string in case the value is not defined. + // Otherwise, CFN will throw with `Vendor response doesn't contain + // XXXX key`. + + CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', + ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', + OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', + OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', // Strips off https:// from the issuer url + + // We can safely return the first item from encryption configuration array, because it has a limit of 1 item + // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig + EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', + }, + }; + } + } + + private async isEksUpdateComplete(eksUpdateId: string) { + this.log({ isEksUpdateComplete: eksUpdateId }); + + const describeUpdateResponse = await this.eks.describeUpdate({ + name: this.clusterName, + updateId: eksUpdateId, + }); + + this.log({ describeUpdateResponse }); + + if (!describeUpdateResponse.update) { + throw new Error(`unable to describe update with id "${eksUpdateId}"`); + } + + switch (describeUpdateResponse.update.status) { + case 'InProgress': + return false; + case 'Successful': + return true; + case 'Failed': + case 'Cancelled': + throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); + default: + throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); + } + } + + private generateClusterName() { + const suffix = this.requestId.replace(/-/g, ''); // 32 chars + const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; + const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); + return `${prefix}-${suffix}`; + } +} + +function parseProps(props: any): aws.EKS.CreateClusterRequest { + + const parsed = props?.Config ?? {}; + + // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. + // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' + + if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; + } + + if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; + } + + if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { + parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; + } + + return parsed; + +} + +interface UpdateMap { + replaceName: boolean; // name + replaceVpc: boolean; // resourcesVpcConfig.subnetIds and securityGroupIds + replaceRole: boolean; // roleArn + + updateVersion: boolean; // version + updateLogging: boolean; // logging + updateEncryption: boolean; // encryption (cannot be updated) + updateAccess: boolean; // resourcesVpcConfig.endpointPrivateAccess and endpointPublicAccess +} + +function analyzeUpdate(oldProps: Partial, newProps: aws.EKS.CreateClusterRequest): UpdateMap { + console.log('old props: ', JSON.stringify(oldProps)); + console.log('new props: ', JSON.stringify(newProps)); + + const newVpcProps = newProps.resourcesVpcConfig || {}; + const oldVpcProps = oldProps.resourcesVpcConfig || {}; + + const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); + const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); + const newEnc = newProps.encryptionConfig || {}; + const oldEnc = oldProps.encryptionConfig || {}; + + return { + replaceName: newProps.name !== oldProps.name, + replaceVpc: + JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), + updateAccess: + newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || + newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || + !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), + replaceRole: newProps.roleArn !== oldProps.roleArn, + updateVersion: newProps.version !== oldProps.version, + updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), + updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), + }; +} + +function setsEqual(first: Set, second: Set) { + return first.size === second.size && [...first].every((e: string) => second.has(e)); +} diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.js b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.js b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.js b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.js b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/apply/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/apply/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/get/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/get/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py new file mode 100644 index 0000000000000..286976ced219a --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py @@ -0,0 +1,187 @@ +import json +import logging +import os +import re +import subprocess +import shutil +import tempfile +import zipfile + +logger = logging.getLogger() +logger.setLevel(logging.INFO) + +# these are coming from the kubectl layer +os.environ['PATH'] = '/opt/helm:/opt/awscli:' + os.environ['PATH'] + +outdir = os.environ.get('TEST_OUTDIR', '/tmp') +kubeconfig = os.path.join(outdir, 'kubeconfig') + +def get_chart_asset_from_url(chart_asset_url): + chart_zip = os.path.join(outdir, 'chart.zip') + shutil.rmtree(chart_zip, ignore_errors=True) + subprocess.check_call(['aws', 's3', 'cp', chart_asset_url, chart_zip]) + chart_dir = os.path.join(outdir, 'chart') + shutil.rmtree(chart_dir, ignore_errors=True) + os.mkdir(chart_dir) + with zipfile.ZipFile(chart_zip, 'r') as zip_ref: + zip_ref.extractall(chart_dir) + return chart_dir + +def helm_handler(event, context): + logger.info(json.dumps(dict(event, ResponseURL='...'))) + + request_type = event['RequestType'] + props = event['ResourceProperties'] + + # resource properties + cluster_name = props['ClusterName'] + role_arn = props['RoleArn'] + release = props['Release'] + chart = props.get('Chart', None) + chart_asset_url = props.get('ChartAssetURL', None) + version = props.get('Version', None) + wait = props.get('Wait', False) + timeout = props.get('Timeout', None) + namespace = props.get('Namespace', None) + create_namespace = props.get('CreateNamespace', None) + repository = props.get('Repository', None) + values_text = props.get('Values', None) + + # "log in" to the cluster + subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig', + '--role-arn', role_arn, + '--name', cluster_name, + '--kubeconfig', kubeconfig + ]) + + if os.path.isfile(kubeconfig): + os.chmod(kubeconfig, 0o600) + + # Write out the values to a file and include them with the install and upgrade + values_file = None + if not request_type == "Delete" and not values_text is None: + values = json.loads(values_text) + values_file = os.path.join(outdir, 'values.yaml') + with open(values_file, "w") as f: + f.write(json.dumps(values, indent=2)) + + if request_type == 'Create' or request_type == 'Update': + # Ensure chart or chart_asset_url are set + if chart == None and chart_asset_url == None: + raise RuntimeError(f'chart or chartAsset must be specified') + + if chart_asset_url != None: + assert(chart==None) + assert(repository==None) + assert(version==None) + if not chart_asset_url.startswith('s3://'): + raise RuntimeError(f'ChartAssetURL must point to as s3 location but is {chart_asset_url}') + # future work: support versions from s3 assets + chart = get_chart_asset_from_url(chart_asset_url) + + if repository is not None and repository.startswith('oci://'): + tmpdir = tempfile.TemporaryDirectory() + chart_dir = get_chart_from_oci(tmpdir.name, repository, version) + chart = chart_dir + + helm('upgrade', release, chart, repository, values_file, namespace, version, wait, timeout, create_namespace) + elif request_type == "Delete": + try: + helm('uninstall', release, namespace=namespace, timeout=timeout) + except Exception as e: + logger.info("delete error: %s" % e) + + +def get_oci_cmd(repository, version): + # Generates OCI command based on pattern. Public ECR vs Private ECR are treated differently. + private_ecr_pattern = 'oci://(?P\d+.dkr.ecr.(?P[a-z]+-[a-z]+-\d).amazonaws.com)*' + public_ecr_pattern = 'oci://(?Ppublic.ecr.aws)*' + + private_registry = re.match(private_ecr_pattern, repository).groupdict() + public_registry = re.match(public_ecr_pattern, repository).groupdict() + + if private_registry['registry'] is not None: + logger.info("Found AWS private repository") + cmnd = [ + f"aws ecr get-login-password --region {private_registry['region']} | " \ + f"helm registry login --username AWS --password-stdin {private_registry['registry']}; helm pull {repository} --version {version} --untar" + ] + elif public_registry['registry'] is not None: + logger.info("Found AWS public repository, will use default region as deployment") + region = os.environ.get('AWS_REGION', 'us-east-1') + + cmnd = [ + f"aws ecr-public get-login-password --region us-east-1 | " \ + f"helm registry login --username AWS --password-stdin {public_registry['registry']}; helm pull {repository} --version {version} --untar" + ] + else: + logger.error("OCI repository format not recognized, falling back to helm pull") + cmnd = ['helm', 'pull', repository, '--version', version, '--untar'] + + return cmnd + + +def get_chart_from_oci(tmpdir, repository = None, version = None): + + cmnd = get_oci_cmd(repository, version) + + maxAttempts = 3 + retry = maxAttempts + while retry > 0: + try: + logger.info(cmnd) + output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=tmpdir, shell=True) + logger.info(output) + + # effectively returns "$tmpDir/$lastPartOfOCIUrl", because this is how helm pull saves OCI artifact. + # Eg. if we have oci://9999999999.dkr.ecr.us-east-1.amazonaws.com/foo/bar/pet-service repository, helm saves artifact under $tmpDir/pet-service + return os.path.join(tmpdir, repository.rpartition('/')[-1]) + except subprocess.CalledProcessError as exc: + output = exc.output + if b'Broken pipe' in output: + retry = retry - 1 + logger.info("Broken pipe, retries left: %s" % retry) + else: + raise Exception(output) + raise Exception(f'Operation failed after {maxAttempts} attempts: {output}') + + +def helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None): + import subprocess + + cmnd = ['helm', verb, release] + if not chart is None: + cmnd.append(chart) + if verb == 'upgrade': + cmnd.append('--install') + if create_namespace: + cmnd.append('--create-namespace') + if not repo is None: + cmnd.extend(['--repo', repo]) + if not file is None: + cmnd.extend(['--values', file]) + if not version is None: + cmnd.extend(['--version', version]) + if not namespace is None: + cmnd.extend(['--namespace', namespace]) + if wait: + cmnd.append('--wait') + if not timeout is None: + cmnd.extend(['--timeout', timeout]) + cmnd.extend(['--kubeconfig', kubeconfig]) + + maxAttempts = 3 + retry = maxAttempts + while retry > 0: + try: + output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir) + logger.info(output) + return + except subprocess.CalledProcessError as exc: + output = exc.output + if b'Broken pipe' in output: + retry = retry - 1 + logger.info("Broken pipe, retries left: %s" % retry) + else: + raise Exception(output) + raise Exception(f'Operation failed after {maxAttempts} attempts: {output}') diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/index.py b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/index.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/patch/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/patch/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/aws-eks-service-account-sdk-calls-test.assets.json b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/aws-eks-service-account-sdk-calls-test.assets.json index fd01a578d678a..be236d4d2296a 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/aws-eks-service-account-sdk-calls-test.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/aws-eks-service-account-sdk-calls-test.assets.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "files": { "ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1": { "source": { @@ -14,15 +14,15 @@ } } }, - "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5": { + "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee": { "source": { - "path": "asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5", + "path": "asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip", + "objectKey": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -40,15 +40,15 @@ } } }, - "e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9": { + "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8": { "source": { - "path": "asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9", + "path": "asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9.zip", + "objectKey": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -118,7 +118,7 @@ } } }, - "4422b5163ce3c03b7df4cc3c0f3ab30647ac2ac54fad5e3e1cb022b6d377a583": { + "5a9c925516063e7d602e462f9d785c5c8918c64f4f3d1fda0b413dfb1dd87364": { "source": { "path": "awseksserviceaccountsdkcallstestawscdkawseksClusterResourceProvider7862DD6A.nested.template.json", "packaging": "file" @@ -126,12 +126,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "4422b5163ce3c03b7df4cc3c0f3ab30647ac2ac54fad5e3e1cb022b6d377a583.json", + "objectKey": "5a9c925516063e7d602e462f9d785c5c8918c64f4f3d1fda0b413dfb1dd87364.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "56a93a19ca9db980b01dbf3dbea01632e423c2529b92baa1cbd4c650df41b83a": { + "2add9700d3e45c3801eaf35070c27d935901edd64bf8e1bd2ddbdde470263bdb": { "source": { "path": "awseksserviceaccountsdkcallstestawscdkawseksKubectlProvider62B779F7.nested.template.json", "packaging": "file" @@ -139,12 +139,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "56a93a19ca9db980b01dbf3dbea01632e423c2529b92baa1cbd4c650df41b83a.json", + "objectKey": "2add9700d3e45c3801eaf35070c27d935901edd64bf8e1bd2ddbdde470263bdb.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "3ba669b8cbb8100db0bc3a91c65b4b388c7b96bfe1a594706161a256fc9500f9": { + "70966cef1197eaa250138ee97adb33cc0a849cfd8074fb47480dd7db4bcc4f4d": { "source": { "path": "aws-eks-service-account-sdk-calls-test.template.json", "packaging": "file" @@ -152,7 +152,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "3ba669b8cbb8100db0bc3a91c65b4b388c7b96bfe1a594706161a256fc9500f9.json", + "objectKey": "70966cef1197eaa250138ee97adb33cc0a849cfd8074fb47480dd7db4bcc4f4d.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/aws-eks-service-account-sdk-calls-test.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/aws-eks-service-account-sdk-calls-test.template.json index 8dc1162cddda2..c21ba972188e5 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/aws-eks-service-account-sdk-calls-test.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/aws-eks-service-account-sdk-calls-test.template.json @@ -1096,7 +1096,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/4422b5163ce3c03b7df4cc3c0f3ab30647ac2ac54fad5e3e1cb022b6d377a583.json" + "/5a9c925516063e7d602e462f9d785c5c8918c64f4f3d1fda0b413dfb1dd87364.json" ] ] }, @@ -1131,7 +1131,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/56a93a19ca9db980b01dbf3dbea01632e423c2529b92baa1cbd4c650df41b83a.json" + "/2add9700d3e45c3801eaf35070c27d935901edd64bf8e1bd2ddbdde470263bdb.json" ] ] }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/awscdkeksserviceaccountsdkcallDefaultTestDeployAssertC5196707.assets.json b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/awscdkeksserviceaccountsdkcallDefaultTestDeployAssertC5196707.assets.json index 1c0686d9de199..52b8d483d98d1 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/awscdkeksserviceaccountsdkcallDefaultTestDeployAssertC5196707.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/awscdkeksserviceaccountsdkcallDefaultTestDeployAssertC5196707.assets.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/awseksserviceaccountsdkcallstestawscdkawseksClusterResourceProvider7862DD6A.nested.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/awseksserviceaccountsdkcallstestawscdkawseksClusterResourceProvider7862DD6A.nested.template.json index ef7ce8b1f8fa2..876e30e0f99ff 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/awseksserviceaccountsdkcallstestawscdkawseksClusterResourceProvider7862DD6A.nested.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/awseksserviceaccountsdkcallstestawscdkawseksClusterResourceProvider7862DD6A.nested.template.json @@ -73,7 +73,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ @@ -162,7 +162,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/awseksserviceaccountsdkcallstestawscdkawseksKubectlProvider62B779F7.nested.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/awseksserviceaccountsdkcallstestawscdkawseksKubectlProvider62B779F7.nested.template.json index cd0e765e57a11..2c5bcceca8f1e 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/awseksserviceaccountsdkcallstestawscdkawseksKubectlProvider62B779F7.nested.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/awseksserviceaccountsdkcallstestawscdkawseksKubectlProvider62B779F7.nested.template.json @@ -51,6 +51,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -92,7 +104,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9.zip" + "S3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/cdk.out b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/cdk.out index ae4b03c54e770..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"30.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/integ.json b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/integ.json index 7568669a378e9..c51334d485b28 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "testCases": { "aws-cdk-eks-service-account-sdk-call/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/manifest.json b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/manifest.json index 4737b9e88162e..39ef825a5901b 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "artifacts": { "aws-eks-service-account-sdk-calls-test.assets": { "type": "cdk:asset-manifest", @@ -17,7 +17,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/3ba669b8cbb8100db0bc3a91c65b4b388c7b96bfe1a594706161a256fc9500f9.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/70966cef1197eaa250138ee97adb33cc0a849cfd8074fb47480dd7db4bcc4f4d.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/tree.json b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/tree.json index 211767771b8a2..7082a77fa70aa 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/tree.json @@ -1624,7 +1624,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -1797,7 +1797,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -2695,7 +2695,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/4422b5163ce3c03b7df4cc3c0f3ab30647ac2ac54fad5e3e1cb022b6d377a583.json" + "/5a9c925516063e7d602e462f9d785c5c8918c64f4f3d1fda0b413dfb1dd87364.json" ] ] }, @@ -2794,6 +2794,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -2893,7 +2905,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9.zip" + "s3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "role": { "Fn::GetAtt": [ @@ -3363,7 +3375,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/56a93a19ca9db980b01dbf3dbea01632e423c2529b92baa1cbd4c650df41b83a.json" + "/2add9700d3e45c3801eaf35070c27d935901edd64bf8e1bd2ddbdde470263bdb.json" ] ] }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/helm/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/helm/__init__.py deleted file mode 100644 index b9a741c8972c4..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/helm/__init__.py +++ /dev/null @@ -1,187 +0,0 @@ -import json -import logging -import os -import re -import subprocess -import shutil -import tempfile -import zipfile -from urllib.parse import urlparse, unquote - -logger = logging.getLogger() -logger.setLevel(logging.INFO) - -# these are coming from the kubectl layer -os.environ['PATH'] = '/opt/helm:/opt/awscli:' + os.environ['PATH'] - -outdir = os.environ.get('TEST_OUTDIR', '/tmp') -kubeconfig = os.path.join(outdir, 'kubeconfig') - -def get_chart_asset_from_url(chart_asset_url): - chart_zip = os.path.join(outdir, 'chart.zip') - shutil.rmtree(chart_zip, ignore_errors=True) - subprocess.check_call(['aws', 's3', 'cp', chart_asset_url, chart_zip]) - chart_dir = os.path.join(outdir, 'chart') - shutil.rmtree(chart_dir, ignore_errors=True) - os.mkdir(chart_dir) - with zipfile.ZipFile(chart_zip, 'r') as zip_ref: - zip_ref.extractall(chart_dir) - return chart_dir - -def helm_handler(event, context): - logger.info(json.dumps(dict(event, ResponseURL='...'))) - - request_type = event['RequestType'] - props = event['ResourceProperties'] - - # resource properties - cluster_name = props['ClusterName'] - role_arn = props['RoleArn'] - release = props['Release'] - chart = props.get('Chart', None) - chart_asset_url = props.get('ChartAssetURL', None) - version = props.get('Version', None) - wait = props.get('Wait', False) - timeout = props.get('Timeout', None) - namespace = props.get('Namespace', None) - create_namespace = props.get('CreateNamespace', None) - repository = props.get('Repository', None) - values_text = props.get('Values', None) - - # "log in" to the cluster - subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig', - '--role-arn', role_arn, - '--name', cluster_name, - '--kubeconfig', kubeconfig - ]) - - if os.path.isfile(kubeconfig): - os.chmod(kubeconfig, 0o600) - - # Write out the values to a file and include them with the install and upgrade - values_file = None - if not request_type == "Delete" and not values_text is None: - values = json.loads(values_text) - values_file = os.path.join(outdir, 'values.yaml') - with open(values_file, "w") as f: - f.write(json.dumps(values, indent=2)) - - if request_type == 'Create' or request_type == 'Update': - # Ensure chart or chart_asset_url are set - if chart == None and chart_asset_url == None: - raise RuntimeError(f'chart or chartAsset must be specified') - - if chart_asset_url != None: - assert(chart==None) - assert(repository==None) - assert(version==None) - if not chart_asset_url.startswith('s3://'): - raise RuntimeError(f'ChartAssetURL must point to as s3 location but is {chart_asset_url}') - # future work: support versions from s3 assets - chart = get_chart_asset_from_url(chart_asset_url) - - if repository is not None and repository.startswith('oci://'): - tmpdir = tempfile.TemporaryDirectory() - chart_dir = get_chart_from_oci(tmpdir.name, release, repository, version) - chart = chart_dir - - helm('upgrade', release, chart, repository, values_file, namespace, version, wait, timeout, create_namespace) - elif request_type == "Delete": - try: - helm('uninstall', release, namespace=namespace, timeout=timeout) - except Exception as e: - logger.info("delete error: %s" % e) - - -def get_oci_cmd(repository, version): - # Generates OCI command based on pattern. Public ECR vs Private ECR are treated differently. - cmnd = [] - private_ecr_pattern = '\d+.dkr.ecr.[a-z]+-[a-z]+-\d.amazonaws.com' - public_ecr = 'public.ecr.aws' - - registry = repository.rsplit('/', 1)[0].replace('oci://', '') - - if re.fullmatch(private_ecr_pattern, registry) is not None: - logger.info("Found AWS private repository") - region = registry.replace('.amazonaws.com', '').split('.')[-1] - cmnd = [ - f"aws ecr get-login-password --region {region} | " \ - f"helm registry login --username AWS --password-stdin {registry}; helm pull {repository} --version {version} --untar" - ] - elif registry.startswith(public_ecr): - logger.info("Found AWS public repository, will use default region as deployment") - region = os.environ.get('AWS_REGION', 'us-east-1') - - cmnd = [ - f"aws ecr-public get-login-password --region {region} | " \ - f"helm registry login --username AWS --password-stdin {public_ecr}; helm pull {repository} --version {version} --untar" - ] - else: - logger.error("OCI repository format not recognized, falling back to helm pull") - cmnd = ['helm', 'pull', repository, '--version', version, '--untar'] - - return cmnd - - -def get_chart_from_oci(tmpdir, release, repository = None, version = None): - - cmnd = get_oci_cmd(repository, version) - - maxAttempts = 3 - retry = maxAttempts - while retry > 0: - try: - logger.info(cmnd) - output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=tmpdir, shell=True) - logger.info(output) - - return os.path.join(tmpdir, release) - except subprocess.CalledProcessError as exc: - output = exc.output - if b'Broken pipe' in output: - retry = retry - 1 - logger.info("Broken pipe, retries left: %s" % retry) - else: - raise Exception(output) - raise Exception(f'Operation failed after {maxAttempts} attempts: {output}') - - -def helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None): - import subprocess - - cmnd = ['helm', verb, release] - if not chart is None: - cmnd.append(chart) - if verb == 'upgrade': - cmnd.append('--install') - if create_namespace: - cmnd.append('--create-namespace') - if not repo is None: - cmnd.extend(['--repo', repo]) - if not file is None: - cmnd.extend(['--values', file]) - if not version is None: - cmnd.extend(['--version', version]) - if not namespace is None: - cmnd.extend(['--namespace', namespace]) - if wait: - cmnd.append('--wait') - if not timeout is None: - cmnd.extend(['--timeout', timeout]) - cmnd.extend(['--kubeconfig', kubeconfig]) - - maxAttempts = 3 - retry = maxAttempts - while retry > 0: - try: - output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir) - logger.info(output) - return - except subprocess.CalledProcessError as exc: - output = exc.output - if b'Broken pipe' in output: - retry = retry - 1 - logger.info("Broken pipe, retries left: %s" % retry) - else: - raise Exception(output) - raise Exception(f'Operation failed after {maxAttempts} attempts: {output}') diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.d.ts b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js new file mode 100644 index 0000000000000..c9dc1b8d2c19a --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js @@ -0,0 +1,273 @@ +"use strict"; +/* eslint-disable no-console */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ClusterResourceHandler = void 0; +const common_1 = require("./common"); +const MAX_CLUSTER_NAME_LEN = 100; +class ClusterResourceHandler extends common_1.ResourceHandler { + constructor(eks, event) { + super(eks, event); + this.newProps = parseProps(this.event.ResourceProperties); + this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; + } + get clusterName() { + if (!this.physicalResourceId) { + throw new Error('Cannot determine cluster name without physical resource ID'); + } + return this.physicalResourceId; + } + // ------ + // CREATE + // ------ + async onCreate() { + console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); + if (!this.newProps.roleArn) { + throw new Error('"roleArn" is required'); + } + const clusterName = this.newProps.name || this.generateClusterName(); + const resp = await this.eks.createCluster({ + ...this.newProps, + name: clusterName, + }); + if (!resp.cluster) { + throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); + } + return { + PhysicalResourceId: resp.cluster.name, + }; + } + async isCreateComplete() { + return this.isActive(); + } + // ------ + // DELETE + // ------ + async onDelete() { + console.log(`onDelete: deleting cluster ${this.clusterName}`); + try { + await this.eks.deleteCluster({ name: this.clusterName }); + } + catch (e) { + if (e.code !== 'ResourceNotFoundException') { + throw e; + } + else { + console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); + } + } + return { + PhysicalResourceId: this.clusterName, + }; + } + async isDeleteComplete() { + console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); + try { + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); + } + catch (e) { + if (e.code === 'ResourceNotFoundException') { + console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); + return { IsComplete: true }; + } + console.log('describeCluster error:', e); + throw e; + } + return { + IsComplete: false, + }; + } + // ------ + // UPDATE + // ------ + async onUpdate() { + const updates = analyzeUpdate(this.oldProps, this.newProps); + console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); + // updates to encryption config is not supported + if (updates.updateEncryption) { + throw new Error('Cannot update cluster encryption configuration'); + } + // if there is an update that requires replacement, go ahead and just create + // a new cluster with the new config. The old cluster will automatically be + // deleted by cloudformation upon success. + if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { + // if we are replacing this cluster and the cluster has an explicit + // physical name, the creation of the new cluster will fail with "there is + // already a cluster with that name". this is a common behavior for + // CloudFormation resources that support specifying a physical name. + if (this.oldProps.name === this.newProps.name && this.oldProps.name) { + throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); + } + return this.onCreate(); + } + // if a version update is required, issue the version update + if (updates.updateVersion) { + if (!this.newProps.version) { + throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); + } + return this.updateClusterVersion(this.newProps.version); + } + if (updates.updateLogging && updates.updateAccess) { + throw new Error('Cannot update logging and access at the same time'); + } + if (updates.updateLogging || updates.updateAccess) { + const config = { + name: this.clusterName, + }; + if (updates.updateLogging) { + config.logging = this.newProps.logging; + } + ; + if (updates.updateAccess) { + // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: + // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) + // will fail, therefore we take only the access fields explicitly + config.resourcesVpcConfig = { + endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, + endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, + publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, + }; + } + const updateResponse = await this.eks.updateClusterConfig(config); + return { EksUpdateId: updateResponse.update?.id }; + } + // no updates + return; + } + async isUpdateComplete() { + console.log('isUpdateComplete'); + // if this is an EKS update, we will monitor the update event itself + if (this.event.EksUpdateId) { + const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); + if (!complete) { + return { IsComplete: false }; + } + // fall through: if the update is done, we simply delegate to isActive() + // in order to extract attributes and state from the cluster itself, which + // is supposed to be in an ACTIVE state after the update is complete. + } + return this.isActive(); + } + async updateClusterVersion(newVersion) { + console.log(`updating cluster version to ${newVersion}`); + // update-cluster-version will fail if we try to update to the same version, + // so skip in this case. + const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; + if (cluster?.version === newVersion) { + console.log(`cluster already at version ${cluster.version}, skipping version update`); + return; + } + const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); + return { EksUpdateId: updateResponse.update?.id }; + } + async isActive() { + console.log('waiting for cluster to become ACTIVE'); + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); + const cluster = resp.cluster; + // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are + // not complete. note that the custom resource provider framework forbids + // returning attributes (Data) if isComplete is false. + if (cluster?.status === 'FAILED') { + // not very informative, unfortunately the response doesn't contain any error + // information :\ + throw new Error('Cluster is in a FAILED status'); + } + else if (cluster?.status !== 'ACTIVE') { + return { + IsComplete: false, + }; + } + else { + return { + IsComplete: true, + Data: { + Name: cluster.name, + Endpoint: cluster.endpoint, + Arn: cluster.arn, + // IMPORTANT: CFN expects that attributes will *always* have values, + // so return an empty string in case the value is not defined. + // Otherwise, CFN will throw with `Vendor response doesn't contain + // XXXX key`. + CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', + ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', + OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', + OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', + // We can safely return the first item from encryption configuration array, because it has a limit of 1 item + // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig + EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', + }, + }; + } + } + async isEksUpdateComplete(eksUpdateId) { + this.log({ isEksUpdateComplete: eksUpdateId }); + const describeUpdateResponse = await this.eks.describeUpdate({ + name: this.clusterName, + updateId: eksUpdateId, + }); + this.log({ describeUpdateResponse }); + if (!describeUpdateResponse.update) { + throw new Error(`unable to describe update with id "${eksUpdateId}"`); + } + switch (describeUpdateResponse.update.status) { + case 'InProgress': + return false; + case 'Successful': + return true; + case 'Failed': + case 'Cancelled': + throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); + default: + throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); + } + } + generateClusterName() { + const suffix = this.requestId.replace(/-/g, ''); // 32 chars + const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; + const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); + return `${prefix}-${suffix}`; + } +} +exports.ClusterResourceHandler = ClusterResourceHandler; +function parseProps(props) { + const parsed = props?.Config ?? {}; + // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. + // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' + if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; + } + if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; + } + if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { + parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; + } + return parsed; +} +function analyzeUpdate(oldProps, newProps) { + console.log('old props: ', JSON.stringify(oldProps)); + console.log('new props: ', JSON.stringify(newProps)); + const newVpcProps = newProps.resourcesVpcConfig || {}; + const oldVpcProps = oldProps.resourcesVpcConfig || {}; + const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); + const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); + const newEnc = newProps.encryptionConfig || {}; + const oldEnc = oldProps.encryptionConfig || {}; + return { + replaceName: newProps.name !== oldProps.name, + replaceVpc: JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), + updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || + newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || + !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), + replaceRole: newProps.roleArn !== oldProps.roleArn, + updateVersion: newProps.version !== oldProps.version, + updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), + updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), + }; +} +function setsEqual(first, second) { + return first.size === second.size && [...first].every((e) => second.has(e)); +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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LENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztRQUNuRSxhQUFhLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBa0IsRUFBRSxNQUFtQjtJQUN4RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgRWtzQ2xpZW50LCBSZXNvdXJjZUV2ZW50LCBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX05BTUVfTEVOID0gMTAwO1xuXG5leHBvcnQgY2xhc3MgQ2x1c3RlclJlc291cmNlSGFuZGxlciBleHRlbmRzIFJlc291cmNlSGFuZGxlciB7XG4gIHB1YmxpYyBnZXQgY2x1c3Rlck5hbWUoKSB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZGV0ZXJtaW5lIGNsdXN0ZXIgbmFtZSB3aXRob3V0IHBoeXNpY2FsIHJlc291cmNlIElEJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PjtcblxuICBjb25zdHJ1Y3Rvcihla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICBzdXBlcihla3MsIGV2ZW50KTtcblxuICAgIHRoaXMubmV3UHJvcHMgPSBwYXJzZVByb3BzKHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLm9sZFByb3BzID0gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnID8gcGFyc2VQcm9wcyhldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMpIDoge307XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gQ1JFQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCdvbkNyZWF0ZTogY3JlYXRpbmcgY2x1c3RlciB3aXRoIG9wdGlvbnM6JywgSlNPTi5zdHJpbmdpZnkodGhpcy5uZXdQcm9wcywgdW5kZWZpbmVkLCAyKSk7XG4gICAgaWYgKCF0aGlzLm5ld1Byb3BzLnJvbGVBcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJyb2xlQXJuXCIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyTmFtZSA9IHRoaXMubmV3UHJvcHMubmFtZSB8fCB0aGlzLmdlbmVyYXRlQ2x1c3Rlck5hbWUoKTtcblxuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmVrcy5jcmVhdGVDbHVzdGVyKHtcbiAgICAgIC4uLnRoaXMubmV3UHJvcHMsXG4gICAgICBuYW1lOiBjbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcC5jbHVzdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBjbHVzdGVyICR7Y2x1c3Rlck5hbWV9OiBDcmVhdGVDbHVzdGVyIHJldHVybmVkIHdpdGhvdXQgY2x1c3RlciBpbmZvcm1hdGlvbmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHJlc3AuY2x1c3Rlci5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIERFTEVURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25EZWxldGUoKTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgb25EZWxldGU6IGRlbGV0aW5nIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfWApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVrcy5kZWxldGVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyICR7dGhpcy5jbHVzdGVyTmFtZX0gbm90IGZvdW5kLCBpZGVtcG90ZW50bHkgc3VjY2VlZGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coYGlzRGVsZXRlQ29tcGxldGU6IHdhaXRpbmcgZm9yIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSB0byBiZSBkZWxldGVkYCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJldHVybmVkOicsIEpTT04uc3RyaW5naWZ5KHJlc3AsIHVuZGVmaW5lZCwgMikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICBjb25zb2xlLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgY2x1c3RlciBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0cnVlIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgZXJyb3I6JywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIFVQREFURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IGFuYWx5emVVcGRhdGUodGhpcy5vbGRQcm9wcywgdGhpcy5uZXdQcm9wcyk7XG4gICAgY29uc29sZS5sb2coJ29uVXBkYXRlOicsIEpTT04uc3RyaW5naWZ5KHsgdXBkYXRlcyB9LCB1bmRlZmluZWQsIDIpKTtcblxuICAgIC8vIHVwZGF0ZXMgdG8gZW5jcnlwdGlvbiBjb25maWcgaXMgbm90IHN1cHBvcnRlZFxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUVuY3J5cHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHVwZGF0ZSBjbHVzdGVyIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZXJlIGlzIGFuIHVwZGF0ZSB0aGF0IHJlcXVpcmVzIHJlcGxhY2VtZW50LCBnbyBhaGVhZCBhbmQganVzdCBjcmVhdGVcbiAgICAvLyBhIG5ldyBjbHVzdGVyIHdpdGggdGhlIG5ldyBjb25maWcuIFRoZSBvbGQgY2x1c3RlciB3aWxsIGF1dG9tYXRpY2FsbHkgYmVcbiAgICAvLyBkZWxldGVkIGJ5IGNsb3VkZm9ybWF0aW9uIHVwb24gc3VjY2Vzcy5cbiAgICBpZiAodXBkYXRlcy5yZXBsYWNlTmFtZSB8fCB1cGRhdGVzLnJlcGxhY2VSb2xlIHx8IHVwZGF0ZXMucmVwbGFjZVZwYykge1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgcmVwbGFjaW5nIHRoaXMgY2x1c3RlciBhbmQgdGhlIGNsdXN0ZXIgaGFzIGFuIGV4cGxpY2l0XG4gICAgICAvLyBwaHlzaWNhbCBuYW1lLCB0aGUgY3JlYXRpb24gb2YgdGhlIG5ldyBjbHVzdGVyIHdpbGwgZmFpbCB3aXRoIFwidGhlcmUgaXNcbiAgICAgIC8vIGFscmVhZHkgYSBjbHVzdGVyIHdpdGggdGhhdCBuYW1lXCIuIHRoaXMgaXMgYSBjb21tb24gYmVoYXZpb3IgZm9yXG4gICAgICAvLyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZXMgdGhhdCBzdXBwb3J0IHNwZWNpZnlpbmcgYSBwaHlzaWNhbCBuYW1lLlxuICAgICAgaWYgKHRoaXMub2xkUHJvcHMubmFtZSA9PT0gdGhpcy5uZXdQcm9wcy5uYW1lICYmIHRoaXMub2xkUHJvcHMubmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXBsYWNlIGNsdXN0ZXIgXCIke3RoaXMub2xkUHJvcHMubmFtZX1cIiBzaW5jZSBpdCBoYXMgYW4gZXhwbGljaXQgcGh5c2ljYWwgbmFtZS4gRWl0aGVyIHJlbmFtZSB0aGUgY2x1c3RlciBvciByZW1vdmUgdGhlIFwibmFtZVwiIGNvbmZpZ3VyYXRpb25gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub25DcmVhdGUoKTtcbiAgICB9XG5cbiAgICAvLyBpZiBhIHZlcnNpb24gdXBkYXRlIGlzIHJlcXVpcmVkLCBpc3N1ZSB0aGUgdmVyc2lvbiB1cGRhdGVcbiAgICBpZiAodXBkYXRlcy51cGRhdGVWZXJzaW9uKSB7XG4gICAgICBpZiAoIXRoaXMubmV3UHJvcHMudmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZW1vdmUgY2x1c3RlciB2ZXJzaW9uIGNvbmZpZ3VyYXRpb24uIEN1cnJlbnQgdmVyc2lvbiBpcyAke3RoaXMub2xkUHJvcHMudmVyc2lvbn1gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlQ2x1c3RlclZlcnNpb24odGhpcy5uZXdQcm9wcy52ZXJzaW9uKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nICYmIHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1cGRhdGUgbG9nZ2luZyBhbmQgYWNjZXNzIGF0IHRoZSBzYW1lIHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nIHx8IHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICBjb25zdCBjb25maWc6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QgPSB7XG4gICAgICAgIG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgICB9O1xuICAgICAgaWYgKHVwZGF0ZXMudXBkYXRlTG9nZ2luZykge1xuICAgICAgICBjb25maWcubG9nZ2luZyA9IHRoaXMubmV3UHJvcHMubG9nZ2luZztcbiAgICAgIH07XG4gICAgICBpZiAodXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIGNsdXN0ZXIgd2l0aCBzZWN1cml0eUdyb3VwSWRzIGFuZCBzdWJuZXRJZHMgKGFzIHNwZWNpZmllZCBpbiB0aGUgd2FybmluZyBoZXJlOlxuICAgICAgICAvLyBodHRwczovL2F3c2NsaS5hbWF6b25hd3MuY29tL3YyL2RvY3VtZW50YXRpb24vYXBpL2xhdGVzdC9yZWZlcmVuY2UvZWtzL3VwZGF0ZS1jbHVzdGVyLWNvbmZpZy5odG1sKVxuICAgICAgICAvLyB3aWxsIGZhaWwsIHRoZXJlZm9yZSB3ZSB0YWtlIG9ubHkgdGhlIGFjY2VzcyBmaWVsZHMgZXhwbGljaXRseVxuICAgICAgICBjb25maWcucmVzb3VyY2VzVnBjQ29uZmlnID0ge1xuICAgICAgICAgIGVuZHBvaW50UHJpdmF0ZUFjY2VzczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzLFxuICAgICAgICAgIGVuZHBvaW50UHVibGljQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyxcbiAgICAgICAgICBwdWJsaWNBY2Nlc3NDaWRyczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcucHVibGljQWNjZXNzQ2lkcnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgICB9XG5cbiAgICAvLyBubyB1cGRhdGVzXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc29sZS5sb2coJ2lzVXBkYXRlQ29tcGxldGUnKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYW4gRUtTIHVwZGF0ZSwgd2Ugd2lsbCBtb25pdG9yIHRoZSB1cGRhdGUgZXZlbnQgaXRzZWxmXG4gICAgaWYgKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gYXdhaXQgdGhpcy5pc0Vrc1VwZGF0ZUNvbXBsZXRlKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpO1xuICAgICAgaWYgKCFjb21wbGV0ZSkge1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiBmYWxzZSB9O1xuICAgICAgfVxuXG4gICAgICAvLyBmYWxsIHRocm91Z2g6IGlmIHRoZSB1cGRhdGUgaXMgZG9uZSwgd2Ugc2ltcGx5IGRlbGVnYXRlIHRvIGlzQWN0aXZlKClcbiAgICAgIC8vIGluIG9yZGVyIHRvIGV4dHJhY3QgYXR0cmlidXRlcyBhbmQgc3RhdGUgZnJvbSB0aGUgY2x1c3RlciBpdHNlbGYsIHdoaWNoXG4gICAgICAvLyBpcyBzdXBwb3NlZCB0byBiZSBpbiBhbiBBQ1RJVkUgc3RhdGUgYWZ0ZXIgdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbHVzdGVyVmVyc2lvbihuZXdWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgdXBkYXRpbmcgY2x1c3RlciB2ZXJzaW9uIHRvICR7bmV3VmVyc2lvbn1gKTtcblxuICAgIC8vIHVwZGF0ZS1jbHVzdGVyLXZlcnNpb24gd2lsbCBmYWlsIGlmIHdlIHRyeSB0byB1cGRhdGUgdG8gdGhlIHNhbWUgdmVyc2lvbixcbiAgICAvLyBzbyBza2lwIGluIHRoaXMgY2FzZS5cbiAgICBjb25zdCBjbHVzdGVyID0gKGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSkpLmNsdXN0ZXI7XG4gICAgaWYgKGNsdXN0ZXI/LnZlcnNpb24gPT09IG5ld1ZlcnNpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyIGFscmVhZHkgYXQgdmVyc2lvbiAke2NsdXN0ZXIudmVyc2lvbn0sIHNraXBwaW5nIHZlcnNpb24gdXBkYXRlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy51cGRhdGVDbHVzdGVyVmVyc2lvbih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsIHZlcnNpb246IG5ld1ZlcnNpb24gfSk7XG4gICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNBY3RpdmUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZygnd2FpdGluZyBmb3IgY2x1c3RlciB0byBiZWNvbWUgQUNUSVZFJyk7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciByZXN1bHQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgY29uc3QgY2x1c3RlciA9IHJlc3AuY2x1c3RlcjtcblxuICAgIC8vIGlmIGNsdXN0ZXIgaXMgdW5kZWZpbmVkIChzaG91bGRudCBoYXBwZW4pIG9yIHN0YXR1cyBpcyBub3QgQUNUSVZFLCB3ZSBhcmVcbiAgICAvLyBub3QgY29tcGxldGUuIG5vdGUgdGhhdCB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZyYW1ld29yayBmb3JiaWRzXG4gICAgLy8gcmV0dXJuaW5nIGF0dHJpYnV0ZXMgKERhdGEpIGlmIGlzQ29tcGxldGUgaXMgZmFsc2UuXG4gICAgaWYgKGNsdXN0ZXI/LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgIC8vIG5vdCB2ZXJ5IGluZm9ybWF0aXZlLCB1bmZvcnR1bmF0ZWx5IHRoZSByZXNwb25zZSBkb2Vzbid0IGNvbnRhaW4gYW55IGVycm9yXG4gICAgICAvLyBpbmZvcm1hdGlvbiA6XFxcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2x1c3RlciBpcyBpbiBhIEZBSUxFRCBzdGF0dXMnKTtcbiAgICB9IGVsc2UgaWYgKGNsdXN0ZXI/LnN0YXR1cyAhPT0gJ0FDVElWRScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIE5hbWU6IGNsdXN0ZXIubmFtZSxcbiAgICAgICAgICBFbmRwb2ludDogY2x1c3Rlci5lbmRwb2ludCxcbiAgICAgICAgICBBcm46IGNsdXN0ZXIuYXJuLFxuXG4gICAgICAgICAgLy8gSU1QT1JUQU5UOiBDRk4gZXhwZWN0cyB0aGF0IGF0dHJpYnV0ZXMgd2lsbCAqYWx3YXlzKiBoYXZlIHZhbHVlcyxcbiAgICAgICAgICAvLyBzbyByZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGluIGNhc2UgdGhlIHZhbHVlIGlzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQ0ZOIHdpbGwgdGhyb3cgd2l0aCBgVmVuZG9yIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpblxuICAgICAgICAgIC8vIFhYWFgga2V5YC5cblxuICAgICAgICAgIENlcnRpZmljYXRlQXV0aG9yaXR5RGF0YTogY2x1c3Rlci5jZXJ0aWZpY2F0ZUF1dGhvcml0eT8uZGF0YSA/PyAnJyxcbiAgICAgICAgICBDbHVzdGVyU2VjdXJpdHlHcm91cElkOiBjbHVzdGVyLnJlc291cmNlc1ZwY0NvbmZpZz8uY2x1c3RlclNlY3VyaXR5R3JvdXBJZCA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyVXJsOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXIgPz8gJycsXG4gICAgICAgICAgT3BlbklkQ29ubmVjdElzc3VlcjogY2x1c3Rlci5pZGVudGl0eT8ub2lkYz8uaXNzdWVyPy5zdWJzdHJpbmcoOCkgPz8gJycsIC8vIFN0cmlwcyBvZmYgaHR0cHM6Ly8gZnJvbSB0aGUgaXNzdWVyIHVybFxuXG4gICAgICAgICAgLy8gV2UgY2FuIHNhZmVseSByZXR1cm4gdGhlIGZpcnN0IGl0ZW0gZnJvbSBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gYXJyYXksIGJlY2F1c2UgaXQgaGFzIGEgbGltaXQgb2YgMSBpdGVtXG4gICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vrcy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDbHVzdGVyLmh0bWwjQW1hem9uRUtTLUNyZWF0ZUNsdXN0ZXItcmVxdWVzdC1lbmNyeXB0aW9uQ29uZmlnXG4gICAgICAgICAgRW5jcnlwdGlvbkNvbmZpZ0tleUFybjogY2x1c3Rlci5lbmNyeXB0aW9uQ29uZmlnPy5zaGlmdCgpPy5wcm92aWRlcj8ua2V5QXJuID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzRWtzVXBkYXRlQ29tcGxldGUoZWtzVXBkYXRlSWQ6IHN0cmluZykge1xuICAgIHRoaXMubG9nKHsgaXNFa3NVcGRhdGVDb21wbGV0ZTogZWtzVXBkYXRlSWQgfSk7XG5cbiAgICBjb25zdCBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVVcGRhdGUoe1xuICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgIHVwZGF0ZUlkOiBla3NVcGRhdGVJZCxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nKHsgZGVzY3JpYmVVcGRhdGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5hYmxlIHRvIGRlc2NyaWJlIHVwZGF0ZSB3aXRoIGlkIFwiJHtla3NVcGRhdGVJZH1cImApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzKSB7XG4gICAgICBjYXNlICdJblByb2dyZXNzJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgY2FzZSAnU3VjY2Vzc2Z1bCc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnRmFpbGVkJzpcbiAgICAgIGNhc2UgJ0NhbmNlbGxlZCc6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2x1c3RlciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiIGZhaWxlZCB3aXRoIGVycm9yczogJHtKU09OLnN0cmluZ2lmeShkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5lcnJvcnMpfWApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIHN0YXR1cyBcIiR7ZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzfVwiIGZvciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNsdXN0ZXJOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9DTFVTVEVSX05BTUVfTEVOIC0gc3VmZml4Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5sb2dpY2FsUmVzb3VyY2VJZC5zbGljZSgwLCBvZmZzZXQgPiAwID8gb2Zmc2V0IDogMCk7XG4gICAgcmV0dXJuIGAke3ByZWZpeH0tJHtzdWZmaXh9YDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3BzKHByb3BzOiBhbnkpOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0IHtcblxuICBjb25zdCBwYXJzZWQgPSBwcm9wcz8uQ29uZmlnID8/IHt9O1xuXG4gIC8vIHRoaXMgaXMgd2VpcmQgYnV0IHRoZXNlIGJvb2xlYW4gcHJvcGVydGllcyBhcmUgcGFzc2VkIGJ5IENGTiBhcyBhIHN0cmluZywgYW5kIHdlIG5lZWQgdGhlbSB0byBiZSBib29sZWFuaWMgZm9yIHRoZSBTREsuXG4gIC8vIE90aGVyd2lzZSBpdCBmYWlscyB3aXRoICdVbmV4cGVjdGVkIFBhcmFtZXRlcjogcGFyYW1zLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgaXMgZXhwZWN0ZWQgdG8gYmUgYSBib29sZWFuJ1xuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWc/LmVuZHBvaW50UHJpdmF0ZUFjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9PT0gJ3RydWUnO1xuICB9XG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQdWJsaWNBY2Nlc3MpID09PSAnc3RyaW5nJykge1xuICAgIHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQubG9nZ2luZz8uY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCkgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9IHBhcnNlZC5sb2dnaW5nLmNsdXN0ZXJMb2dnaW5nWzBdLmVuYWJsZWQgPT09ICd0cnVlJztcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQ7XG5cbn1cblxuaW50ZXJmYWNlIFVwZGF0ZU1hcCB7XG4gIHJlcGxhY2VOYW1lOiBib29sZWFuOyAvLyBuYW1lXG4gIHJlcGxhY2VWcGM6IGJvb2xlYW47IC8vIHJlc291cmNlc1ZwY0NvbmZpZy5zdWJuZXRJZHMgYW5kIHNlY3VyaXR5R3JvdXBJZHNcbiAgcmVwbGFjZVJvbGU6IGJvb2xlYW47IC8vIHJvbGVBcm5cblxuICB1cGRhdGVWZXJzaW9uOiBib29sZWFuOyAvLyB2ZXJzaW9uXG4gIHVwZGF0ZUxvZ2dpbmc6IGJvb2xlYW47IC8vIGxvZ2dpbmdcbiAgdXBkYXRlRW5jcnlwdGlvbjogYm9vbGVhbjsgLy8gZW5jcnlwdGlvbiAoY2Fubm90IGJlIHVwZGF0ZWQpXG4gIHVwZGF0ZUFjY2VzczogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBhbmQgZW5kcG9pbnRQdWJsaWNBY2Nlc3Ncbn1cblxuZnVuY3Rpb24gYW5hbHl6ZVVwZGF0ZShvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PiwgbmV3UHJvcHM6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBVcGRhdGVNYXAge1xuICBjb25zb2xlLmxvZygnb2xkIHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShvbGRQcm9wcykpO1xuICBjb25zb2xlLmxvZygnbmV3IHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShuZXdQcm9wcykpO1xuXG4gIGNvbnN0IG5ld1ZwY1Byb3BzID0gbmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRWcGNQcm9wcyA9IG9sZFByb3BzLnJlc291cmNlc1ZwY0NvbmZpZyB8fCB7fTtcblxuICBjb25zdCBvbGRQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQob2xkVnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQobmV3VnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdFbmMgPSBuZXdQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRFbmMgPSBvbGRQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgcmVwbGFjZU5hbWU6IG5ld1Byb3BzLm5hbWUgIT09IG9sZFByb3BzLm5hbWUsXG4gICAgcmVwbGFjZVZwYzpcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnN1Ym5ldElkcz8uc29ydCgpKSAhPT0gSlNPTi5zdHJpbmdpZnkob2xkVnBjUHJvcHMuc3VibmV0SWRzPy5zb3J0KCkpIHx8XG4gICAgICBKU09OLnN0cmluZ2lmeShuZXdWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpICE9PSBKU09OLnN0cmluZ2lmeShvbGRWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpLFxuICAgIHVwZGF0ZUFjY2VzczpcbiAgICAgIG5ld1ZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQcml2YXRlQWNjZXNzIHx8XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFB1YmxpY0FjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgfHxcbiAgICAgICFzZXRzRXF1YWwobmV3UHVibGljQWNjZXNzQ2lkcnMsIG9sZFB1YmxpY0FjY2Vzc0NpZHJzKSxcbiAgICByZXBsYWNlUm9sZTogbmV3UHJvcHMucm9sZUFybiAhPT0gb2xkUHJvcHMucm9sZUFybixcbiAgICB1cGRhdGVWZXJzaW9uOiBuZXdQcm9wcy52ZXJzaW9uICE9PSBvbGRQcm9wcy52ZXJzaW9uLFxuICAgIHVwZGF0ZUVuY3J5cHRpb246IEpTT04uc3RyaW5naWZ5KG5ld0VuYykgIT09IEpTT04uc3RyaW5naWZ5KG9sZEVuYyksXG4gICAgdXBkYXRlTG9nZ2luZzogSlNPTi5zdHJpbmdpZnkobmV3UHJvcHMubG9nZ2luZykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFByb3BzLmxvZ2dpbmcpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzZXRzRXF1YWwoZmlyc3Q6IFNldDxzdHJpbmc+LCBzZWNvbmQ6IFNldDxzdHJpbmc+KSB7XG4gIHJldHVybiBmaXJzdC5zaXplID09PSBzZWNvbmQuc2l6ZSAmJiBbLi4uZmlyc3RdLmV2ZXJ5KChlOiBzdHJpbmcpID0+IHNlY29uZC5oYXMoZSkpO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts new file mode 100644 index 0000000000000..4b7fdda6d1dd1 --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts @@ -0,0 +1,344 @@ +/* eslint-disable no-console */ + +// eslint-disable-next-line import/no-extraneous-dependencies +import { IsCompleteResponse, OnEventResponse } from '@aws-cdk/custom-resources/lib/provider-framework/types'; +// eslint-disable-next-line import/no-extraneous-dependencies +import * as aws from 'aws-sdk'; +import { EksClient, ResourceEvent, ResourceHandler } from './common'; + +const MAX_CLUSTER_NAME_LEN = 100; + +export class ClusterResourceHandler extends ResourceHandler { + public get clusterName() { + if (!this.physicalResourceId) { + throw new Error('Cannot determine cluster name without physical resource ID'); + } + + return this.physicalResourceId; + } + + private readonly newProps: aws.EKS.CreateClusterRequest; + private readonly oldProps: Partial; + + constructor(eks: EksClient, event: ResourceEvent) { + super(eks, event); + + this.newProps = parseProps(this.event.ResourceProperties); + this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; + } + + // ------ + // CREATE + // ------ + + protected async onCreate(): Promise { + console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); + if (!this.newProps.roleArn) { + throw new Error('"roleArn" is required'); + } + + const clusterName = this.newProps.name || this.generateClusterName(); + + const resp = await this.eks.createCluster({ + ...this.newProps, + name: clusterName, + }); + + if (!resp.cluster) { + throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); + } + + return { + PhysicalResourceId: resp.cluster.name, + }; + } + + protected async isCreateComplete() { + return this.isActive(); + } + + // ------ + // DELETE + // ------ + + protected async onDelete(): Promise { + console.log(`onDelete: deleting cluster ${this.clusterName}`); + try { + await this.eks.deleteCluster({ name: this.clusterName }); + } catch (e) { + if (e.code !== 'ResourceNotFoundException') { + throw e; + } else { + console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); + } + } + return { + PhysicalResourceId: this.clusterName, + }; + } + + protected async isDeleteComplete(): Promise { + console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); + + try { + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); + } catch (e) { + if (e.code === 'ResourceNotFoundException') { + console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); + return { IsComplete: true }; + } + + console.log('describeCluster error:', e); + throw e; + } + + return { + IsComplete: false, + }; + } + + // ------ + // UPDATE + // ------ + + protected async onUpdate() { + const updates = analyzeUpdate(this.oldProps, this.newProps); + console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); + + // updates to encryption config is not supported + if (updates.updateEncryption) { + throw new Error('Cannot update cluster encryption configuration'); + } + + // if there is an update that requires replacement, go ahead and just create + // a new cluster with the new config. The old cluster will automatically be + // deleted by cloudformation upon success. + if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { + + // if we are replacing this cluster and the cluster has an explicit + // physical name, the creation of the new cluster will fail with "there is + // already a cluster with that name". this is a common behavior for + // CloudFormation resources that support specifying a physical name. + if (this.oldProps.name === this.newProps.name && this.oldProps.name) { + throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); + } + + return this.onCreate(); + } + + // if a version update is required, issue the version update + if (updates.updateVersion) { + if (!this.newProps.version) { + throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); + } + + return this.updateClusterVersion(this.newProps.version); + } + + if (updates.updateLogging && updates.updateAccess) { + throw new Error('Cannot update logging and access at the same time'); + } + + if (updates.updateLogging || updates.updateAccess) { + const config: aws.EKS.UpdateClusterConfigRequest = { + name: this.clusterName, + }; + if (updates.updateLogging) { + config.logging = this.newProps.logging; + }; + if (updates.updateAccess) { + // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: + // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) + // will fail, therefore we take only the access fields explicitly + config.resourcesVpcConfig = { + endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, + endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, + publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, + }; + } + const updateResponse = await this.eks.updateClusterConfig(config); + + return { EksUpdateId: updateResponse.update?.id }; + } + + // no updates + return; + } + + protected async isUpdateComplete() { + console.log('isUpdateComplete'); + + // if this is an EKS update, we will monitor the update event itself + if (this.event.EksUpdateId) { + const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); + if (!complete) { + return { IsComplete: false }; + } + + // fall through: if the update is done, we simply delegate to isActive() + // in order to extract attributes and state from the cluster itself, which + // is supposed to be in an ACTIVE state after the update is complete. + } + + return this.isActive(); + } + + private async updateClusterVersion(newVersion: string) { + console.log(`updating cluster version to ${newVersion}`); + + // update-cluster-version will fail if we try to update to the same version, + // so skip in this case. + const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; + if (cluster?.version === newVersion) { + console.log(`cluster already at version ${cluster.version}, skipping version update`); + return; + } + + const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); + return { EksUpdateId: updateResponse.update?.id }; + } + + private async isActive(): Promise { + console.log('waiting for cluster to become ACTIVE'); + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); + const cluster = resp.cluster; + + // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are + // not complete. note that the custom resource provider framework forbids + // returning attributes (Data) if isComplete is false. + if (cluster?.status === 'FAILED') { + // not very informative, unfortunately the response doesn't contain any error + // information :\ + throw new Error('Cluster is in a FAILED status'); + } else if (cluster?.status !== 'ACTIVE') { + return { + IsComplete: false, + }; + } else { + return { + IsComplete: true, + Data: { + Name: cluster.name, + Endpoint: cluster.endpoint, + Arn: cluster.arn, + + // IMPORTANT: CFN expects that attributes will *always* have values, + // so return an empty string in case the value is not defined. + // Otherwise, CFN will throw with `Vendor response doesn't contain + // XXXX key`. + + CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', + ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', + OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', + OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', // Strips off https:// from the issuer url + + // We can safely return the first item from encryption configuration array, because it has a limit of 1 item + // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig + EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', + }, + }; + } + } + + private async isEksUpdateComplete(eksUpdateId: string) { + this.log({ isEksUpdateComplete: eksUpdateId }); + + const describeUpdateResponse = await this.eks.describeUpdate({ + name: this.clusterName, + updateId: eksUpdateId, + }); + + this.log({ describeUpdateResponse }); + + if (!describeUpdateResponse.update) { + throw new Error(`unable to describe update with id "${eksUpdateId}"`); + } + + switch (describeUpdateResponse.update.status) { + case 'InProgress': + return false; + case 'Successful': + return true; + case 'Failed': + case 'Cancelled': + throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); + default: + throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); + } + } + + private generateClusterName() { + const suffix = this.requestId.replace(/-/g, ''); // 32 chars + const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; + const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); + return `${prefix}-${suffix}`; + } +} + +function parseProps(props: any): aws.EKS.CreateClusterRequest { + + const parsed = props?.Config ?? {}; + + // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. + // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' + + if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; + } + + if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; + } + + if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { + parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; + } + + return parsed; + +} + +interface UpdateMap { + replaceName: boolean; // name + replaceVpc: boolean; // resourcesVpcConfig.subnetIds and securityGroupIds + replaceRole: boolean; // roleArn + + updateVersion: boolean; // version + updateLogging: boolean; // logging + updateEncryption: boolean; // encryption (cannot be updated) + updateAccess: boolean; // resourcesVpcConfig.endpointPrivateAccess and endpointPublicAccess +} + +function analyzeUpdate(oldProps: Partial, newProps: aws.EKS.CreateClusterRequest): UpdateMap { + console.log('old props: ', JSON.stringify(oldProps)); + console.log('new props: ', JSON.stringify(newProps)); + + const newVpcProps = newProps.resourcesVpcConfig || {}; + const oldVpcProps = oldProps.resourcesVpcConfig || {}; + + const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); + const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); + const newEnc = newProps.encryptionConfig || {}; + const oldEnc = oldProps.encryptionConfig || {}; + + return { + replaceName: newProps.name !== oldProps.name, + replaceVpc: + JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), + updateAccess: + newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || + newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || + !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), + replaceRole: newProps.roleArn !== oldProps.roleArn, + updateVersion: newProps.version !== oldProps.version, + updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), + updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), + }; +} + +function setsEqual(first: Set, second: Set) { + return first.size === second.size && [...first].every((e: string) => second.has(e)); +} diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.d.ts b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.js b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.js rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.ts b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.ts rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.d.ts b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.js b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.js rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.ts b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.ts rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.d.ts b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.js b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.js rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.ts b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.ts rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.d.ts b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.js b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.js rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.ts b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.ts rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip index 593043af0139a..f62fe1e5a06d6 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip and b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js deleted file mode 100644 index 70203dcc42f3f..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js +++ /dev/null @@ -1,45 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.httpRequest = exports.invokeFunction = exports.startExecution = void 0; -/* istanbul ignore file */ -const https = require("https"); -// eslint-disable-next-line import/no-extraneous-dependencies -const AWS = require("aws-sdk"); -const FRAMEWORK_HANDLER_TIMEOUT = 900000; // 15 minutes -// In order to honor the overall maximum timeout set for the target process, -// the default 2 minutes from AWS SDK has to be overriden: -// https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html#httpOptions-property -const 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; -let lambda; -async function defaultStartExecution(req) { - if (!sfn) { - sfn = new AWS.StepFunctions(awsSdkConfig); - } - return sfn.startExecution(req).promise(); -} -async function defaultInvokeFunction(req) { - if (!lambda) { - lambda = new AWS.Lambda(awsSdkConfig); - } - return lambda.invoke(req).promise(); -} -exports.startExecution = defaultStartExecution; -exports.invokeFunction = defaultInvokeFunction; -exports.httpRequest = defaultHttpRequest; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3V0Ym91bmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJvdXRib3VuZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwwQkFBMEI7QUFDMUIsK0JBQStCO0FBQy9CLDZEQUE2RDtBQUM3RCwrQkFBK0I7QUFJL0IsTUFBTSx5QkFBeUIsR0FBRyxNQUFNLENBQUMsQ0FBQyxhQUFhO0FBRXZELDRFQUE0RTtBQUM1RSwwREFBMEQ7QUFDMUQsMkZBQTJGO0FBQzNGLE1BQU0sWUFBWSxHQUF5QjtJQUN6QyxXQUFXLEVBQUUsRUFBRSxPQUFPLEVBQUUseUJBQXlCLEVBQUU7Q0FDcEQsQ0FBQztBQUVGLEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxPQUE2QixFQUFFLFlBQW9CO0lBQ25GLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDckMsSUFBSTtZQUNGLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ2hELE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDNUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1NBQ2Y7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNYO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsSUFBSSxHQUFzQixDQUFDO0FBQzNCLElBQUksTUFBa0IsQ0FBQztBQUV2QixLQUFLLFVBQVUscUJBQXFCLENBQUMsR0FBMEM7SUFDN0UsSUFBSSxDQUFDLEdBQUcsRUFBRTtRQUNSLEdBQUcsR0FBRyxJQUFJLEdBQUcsQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUM7S0FDM0M7SUFFRCxPQUFPLEdBQUcsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7QUFDM0MsQ0FBQztBQUVELEtBQUssVUFBVSxxQkFBcUIsQ0FBQyxHQUFpQztJQUNwRSxJQUFJLENBQUMsTUFBTSxFQUFFO1FBQ1gsTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztLQUN2QztJQUVELE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztBQUN0QyxDQUFDO0FBRVUsUUFBQSxjQUFjLEdBQUcscUJBQXFCLENBQUM7QUFDdkMsUUFBQSxjQUFjLEdBQUcscUJBQXFCLENBQUM7QUFDdkMsUUFBQSxXQUFXLEdBQUcsa0JBQWtCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBpc3RhbmJ1bCBpZ25vcmUgZmlsZSAqL1xuaW1wb3J0ICogYXMgaHR0cHMgZnJvbSAnaHR0cHMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgQVdTIGZyb20gJ2F3cy1zZGsnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHR5cGUgeyBDb25maWd1cmF0aW9uT3B0aW9ucyB9IGZyb20gJ2F3cy1zZGsvbGliL2NvbmZpZy1iYXNlJztcblxuY29uc3QgRlJBTUVXT1JLX0hBTkRMRVJfVElNRU9VVCA9IDkwMDAwMDsgLy8gMTUgbWludXRlc1xuXG4vLyBJbiBvcmRlciB0byBob25vciB0aGUgb3ZlcmFsbCBtYXhpbXVtIHRpbWVvdXQgc2V0IGZvciB0aGUgdGFyZ2V0IHByb2Nlc3MsXG4vLyB0aGUgZGVmYXVsdCAyIG1pbnV0ZXMgZnJvbSBBV1MgU0RLIGhhcyB0byBiZSBvdmVycmlkZW46XG4vLyBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTSmF2YVNjcmlwdFNESy9sYXRlc3QvQVdTL0NvbmZpZy5odG1sI2h0dHBPcHRpb25zLXByb3BlcnR5XG5jb25zdCBhd3NTZGtDb25maWc6IENvbmZpZ3VyYXRpb25PcHRpb25zID0ge1xuICBodHRwT3B0aW9uczogeyB0aW1lb3V0OiBGUkFNRVdPUktfSEFORExFUl9USU1FT1VUIH0sXG59O1xuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0SHR0cFJlcXVlc3Qob3B0aW9uczogaHR0cHMuUmVxdWVzdE9wdGlvbnMsIHJlc3BvbnNlQm9keTogc3RyaW5nKSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlcXVlc3QgPSBodHRwcy5yZXF1ZXN0KG9wdGlvbnMsIHJlc29sdmUpO1xuICAgICAgcmVxdWVzdC5vbignZXJyb3InLCByZWplY3QpO1xuICAgICAgcmVxdWVzdC53cml0ZShyZXNwb25zZUJvZHkpO1xuICAgICAgcmVxdWVzdC5lbmQoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZWplY3QoZSk7XG4gICAgfVxuICB9KTtcbn1cblxubGV0IHNmbjogQVdTLlN0ZXBGdW5jdGlvbnM7XG5sZXQgbGFtYmRhOiBBV1MuTGFtYmRhO1xuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0U3RhcnRFeGVjdXRpb24ocmVxOiBBV1MuU3RlcEZ1bmN0aW9ucy5TdGFydEV4ZWN1dGlvbklucHV0KTogUHJvbWlzZTxBV1MuU3RlcEZ1bmN0aW9ucy5TdGFydEV4ZWN1dGlvbk91dHB1dD4ge1xuICBpZiAoIXNmbikge1xuICAgIHNmbiA9IG5ldyBBV1MuU3RlcEZ1bmN0aW9ucyhhd3NTZGtDb25maWcpO1xuICB9XG5cbiAgcmV0dXJuIHNmbi5zdGFydEV4ZWN1dGlvbihyZXEpLnByb21pc2UoKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdEludm9rZUZ1bmN0aW9uKHJlcTogQVdTLkxhbWJkYS5JbnZvY2F0aW9uUmVxdWVzdCk6IFByb21pc2U8QVdTLkxhbWJkYS5JbnZvY2F0aW9uUmVzcG9uc2U+IHtcbiAgaWYgKCFsYW1iZGEpIHtcbiAgICBsYW1iZGEgPSBuZXcgQVdTLkxhbWJkYShhd3NTZGtDb25maWcpO1xuICB9XG5cbiAgcmV0dXJuIGxhbWJkYS5pbnZva2UocmVxKS5wcm9taXNlKCk7XG59XG5cbmV4cG9ydCBsZXQgc3RhcnRFeGVjdXRpb24gPSBkZWZhdWx0U3RhcnRFeGVjdXRpb247XG5leHBvcnQgbGV0IGludm9rZUZ1bmN0aW9uID0gZGVmYXVsdEludm9rZUZ1bmN0aW9uO1xuZXhwb3J0IGxldCBodHRwUmVxdWVzdCA9IGRlZmF1bHRIdHRwUmVxdWVzdDtcbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.js b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.js deleted file mode 100644 index 6efe7fd22e321..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.js +++ /dev/null @@ -1,267 +0,0 @@ -"use strict"; -/* eslint-disable no-console */ -Object.defineProperty(exports, "__esModule", { value: true }); -exports.ClusterResourceHandler = void 0; -const common_1 = require("./common"); -const MAX_CLUSTER_NAME_LEN = 100; -class ClusterResourceHandler extends common_1.ResourceHandler { - constructor(eks, event) { - super(eks, event); - this.newProps = parseProps(this.event.ResourceProperties); - this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; - } - get clusterName() { - if (!this.physicalResourceId) { - throw new Error('Cannot determine cluster name without physical resource ID'); - } - return this.physicalResourceId; - } - // ------ - // CREATE - // ------ - async onCreate() { - console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); - if (!this.newProps.roleArn) { - throw new Error('"roleArn" is required'); - } - const clusterName = this.newProps.name || this.generateClusterName(); - const resp = await this.eks.createCluster({ - ...this.newProps, - name: clusterName, - }); - if (!resp.cluster) { - throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); - } - return { - PhysicalResourceId: resp.cluster.name, - }; - } - async isCreateComplete() { - return this.isActive(); - } - // ------ - // DELETE - // ------ - async onDelete() { - console.log(`onDelete: deleting cluster ${this.clusterName}`); - try { - await this.eks.deleteCluster({ name: this.clusterName }); - } - catch (e) { - if (e.code !== 'ResourceNotFoundException') { - throw e; - } - else { - console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); - } - } - return { - PhysicalResourceId: this.clusterName, - }; - } - async isDeleteComplete() { - console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); - try { - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); - } - catch (e) { - if (e.code === 'ResourceNotFoundException') { - console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); - return { IsComplete: true }; - } - console.log('describeCluster error:', e); - throw e; - } - return { - IsComplete: false, - }; - } - // ------ - // UPDATE - // ------ - async onUpdate() { - const updates = analyzeUpdate(this.oldProps, this.newProps); - console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); - // updates to encryption config is not supported - if (updates.updateEncryption) { - throw new Error('Cannot update cluster encryption configuration'); - } - // if there is an update that requires replacement, go ahead and just create - // a new cluster with the new config. The old cluster will automatically be - // deleted by cloudformation upon success. - if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { - // if we are replacing this cluster and the cluster has an explicit - // physical name, the creation of the new cluster will fail with "there is - // already a cluster with that name". this is a common behavior for - // CloudFormation resources that support specifying a physical name. - if (this.oldProps.name === this.newProps.name && this.oldProps.name) { - throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); - } - return this.onCreate(); - } - // if a version update is required, issue the version update - if (updates.updateVersion) { - if (!this.newProps.version) { - throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); - } - return this.updateClusterVersion(this.newProps.version); - } - if (updates.updateLogging || updates.updateAccess) { - const config = { - name: this.clusterName, - logging: this.newProps.logging, - }; - if (updates.updateAccess) { - // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: - // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) - // will fail, therefore we take only the access fields explicitly - config.resourcesVpcConfig = { - endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, - endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, - publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, - }; - } - const updateResponse = await this.eks.updateClusterConfig(config); - return { EksUpdateId: updateResponse.update?.id }; - } - // no updates - return; - } - async isUpdateComplete() { - console.log('isUpdateComplete'); - // if this is an EKS update, we will monitor the update event itself - if (this.event.EksUpdateId) { - const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); - if (!complete) { - return { IsComplete: false }; - } - // fall through: if the update is done, we simply delegate to isActive() - // in order to extract attributes and state from the cluster itself, which - // is supposed to be in an ACTIVE state after the update is complete. - } - return this.isActive(); - } - async updateClusterVersion(newVersion) { - console.log(`updating cluster version to ${newVersion}`); - // update-cluster-version will fail if we try to update to the same version, - // so skip in this case. - const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; - if (cluster?.version === newVersion) { - console.log(`cluster already at version ${cluster.version}, skipping version update`); - return; - } - const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); - return { EksUpdateId: updateResponse.update?.id }; - } - async isActive() { - console.log('waiting for cluster to become ACTIVE'); - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); - const cluster = resp.cluster; - // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are - // not complete. note that the custom resource provider framework forbids - // returning attributes (Data) if isComplete is false. - if (cluster?.status === 'FAILED') { - // not very informative, unfortunately the response doesn't contain any error - // information :\ - throw new Error('Cluster is in a FAILED status'); - } - else if (cluster?.status !== 'ACTIVE') { - return { - IsComplete: false, - }; - } - else { - return { - IsComplete: true, - Data: { - Name: cluster.name, - Endpoint: cluster.endpoint, - Arn: cluster.arn, - // IMPORTANT: CFN expects that attributes will *always* have values, - // so return an empty string in case the value is not defined. - // Otherwise, CFN will throw with `Vendor response doesn't contain - // XXXX key`. - CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', - ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', - OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', - OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', - // We can safely return the first item from encryption configuration array, because it has a limit of 1 item - // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig - EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', - }, - }; - } - } - async isEksUpdateComplete(eksUpdateId) { - this.log({ isEksUpdateComplete: eksUpdateId }); - const describeUpdateResponse = await this.eks.describeUpdate({ - name: this.clusterName, - updateId: eksUpdateId, - }); - this.log({ describeUpdateResponse }); - if (!describeUpdateResponse.update) { - throw new Error(`unable to describe update with id "${eksUpdateId}"`); - } - switch (describeUpdateResponse.update.status) { - case 'InProgress': - return false; - case 'Successful': - return true; - case 'Failed': - case 'Cancelled': - throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); - default: - throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); - } - } - generateClusterName() { - const suffix = this.requestId.replace(/-/g, ''); // 32 chars - const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; - const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); - return `${prefix}-${suffix}`; - } -} -exports.ClusterResourceHandler = ClusterResourceHandler; -function parseProps(props) { - const parsed = props?.Config ?? {}; - // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. - // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' - if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; - } - if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; - } - if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { - parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; - } - return parsed; -} -function analyzeUpdate(oldProps, newProps) { - console.log('old props: ', JSON.stringify(oldProps)); - console.log('new props: ', JSON.stringify(newProps)); - const newVpcProps = newProps.resourcesVpcConfig || {}; - const oldVpcProps = oldProps.resourcesVpcConfig || {}; - const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); - const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); - const newEnc = newProps.encryptionConfig || {}; - const oldEnc = oldProps.encryptionConfig || {}; - return { - replaceName: newProps.name !== oldProps.name, - replaceVpc: JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), - updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || - newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || - !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), - replaceRole: newProps.roleArn !== oldProps.roleArn, - updateVersion: newProps.version !== oldProps.version, - updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), - updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), - }; -} -function setsEqual(first, second) { - return first.size === second.size || [...first].every((e) => second.has(e)); -} -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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LElBQUksS0FBSyxNQUFNLENBQUMsSUFBSSxJQUFJLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFTLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUN0RixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgbm8tY29uc29sZSAqL1xuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzXG5pbXBvcnQgeyBJc0NvbXBsZXRlUmVzcG9uc2UsIE9uRXZlbnRSZXNwb25zZSB9IGZyb20gJ0Bhd3MtY2RrL2N1c3RvbS1yZXNvdXJjZXMvbGliL3Byb3ZpZGVyLWZyYW1ld29yay90eXBlcyc7XG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzXG5pbXBvcnQgKiBhcyBhd3MgZnJvbSAnYXdzLXNkayc7XG5pbXBvcnQgeyBFa3NDbGllbnQsIFJlc291cmNlRXZlbnQsIFJlc291cmNlSGFuZGxlciB9IGZyb20gJy4vY29tbW9uJztcblxuY29uc3QgTUFYX0NMVVNURVJfTkFNRV9MRU4gPSAxMDA7XG5cbmV4cG9ydCBjbGFzcyBDbHVzdGVyUmVzb3VyY2VIYW5kbGVyIGV4dGVuZHMgUmVzb3VyY2VIYW5kbGVyIHtcbiAgcHVibGljIGdldCBjbHVzdGVyTmFtZSgpIHtcbiAgICBpZiAoIXRoaXMucGh5c2ljYWxSZXNvdXJjZUlkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBkZXRlcm1pbmUgY2x1c3RlciBuYW1lIHdpdGhvdXQgcGh5c2ljYWwgcmVzb3VyY2UgSUQnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5waHlzaWNhbFJlc291cmNlSWQ7XG4gIH1cblxuICBwcml2YXRlIHJlYWRvbmx5IG5ld1Byb3BzOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0O1xuICBwcml2YXRlIHJlYWRvbmx5IG9sZFByb3BzOiBQYXJ0aWFsPGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3Q+O1xuXG4gIGNvbnN0cnVjdG9yKGVrczogRWtzQ2xpZW50LCBldmVudDogUmVzb3VyY2VFdmVudCkge1xuICAgIHN1cGVyKGVrcywgZXZlbnQpO1xuXG4gICAgdGhpcy5uZXdQcm9wcyA9IHBhcnNlUHJvcHModGhpcy5ldmVudC5SZXNvdXJjZVByb3BlcnRpZXMpO1xuICAgIHRoaXMub2xkUHJvcHMgPSBldmVudC5SZXF1ZXN0VHlwZSA9PT0gJ1VwZGF0ZScgPyBwYXJzZVByb3BzKGV2ZW50Lk9sZFJlc291cmNlUHJvcGVydGllcykgOiB7fTtcbiAgfVxuXG4gIC8vIC0tLS0tLVxuICAvLyBDUkVBVEVcbiAgLy8gLS0tLS0tXG5cbiAgcHJvdGVjdGVkIGFzeW5jIG9uQ3JlYXRlKCk6IFByb21pc2U8T25FdmVudFJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coJ29uQ3JlYXRlOiBjcmVhdGluZyBjbHVzdGVyIHdpdGggb3B0aW9uczonLCBKU09OLnN0cmluZ2lmeSh0aGlzLm5ld1Byb3BzLCB1bmRlZmluZWQsIDIpKTtcbiAgICBpZiAoIXRoaXMubmV3UHJvcHMucm9sZUFybikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdcInJvbGVBcm5cIiBpcyByZXF1aXJlZCcpO1xuICAgIH1cblxuICAgIGNvbnN0IGNsdXN0ZXJOYW1lID0gdGhpcy5uZXdQcm9wcy5uYW1lIHx8IHRoaXMuZ2VuZXJhdGVDbHVzdGVyTmFtZSgpO1xuXG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmNyZWF0ZUNsdXN0ZXIoe1xuICAgICAgLi4udGhpcy5uZXdQcm9wcyxcbiAgICAgIG5hbWU6IGNsdXN0ZXJOYW1lLFxuICAgIH0pO1xuXG4gICAgaWYgKCFyZXNwLmNsdXN0ZXIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3Igd2hlbiB0cnlpbmcgdG8gY3JlYXRlIGNsdXN0ZXIgJHtjbHVzdGVyTmFtZX06IENyZWF0ZUNsdXN0ZXIgcmV0dXJuZWQgd2l0aG91dCBjbHVzdGVyIGluZm9ybWF0aW9uYCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogcmVzcC5jbHVzdGVyLm5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0NyZWF0ZUNvbXBsZXRlKCkge1xuICAgIHJldHVybiB0aGlzLmlzQWN0aXZlKCk7XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gREVMRVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkRlbGV0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKGBvbkRlbGV0ZTogZGVsZXRpbmcgY2x1c3RlciAke3RoaXMuY2x1c3Rlck5hbWV9YCk7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuZWtzLmRlbGV0ZUNsdXN0ZXIoeyBuYW1lOiB0aGlzLmNsdXN0ZXJOYW1lIH0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgIT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc29sZS5sb2coYGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSBub3QgZm91bmQsIGlkZW1wb3RlbnRseSBzdWNjZWVkZWRgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICB9O1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzRGVsZXRlQ29tcGxldGUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgaXNEZWxldGVDb21wbGV0ZTogd2FpdGluZyBmb3IgY2x1c3RlciAke3RoaXMuY2x1c3Rlck5hbWV9IHRvIGJlIGRlbGV0ZWRgKTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXNwID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgcmV0dXJuZWQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKGUuY29kZSA9PT0gJ1Jlc291cmNlTm90Rm91bmRFeGNlcHRpb24nKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdyZWNlaXZlZCBSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uLCB0aGlzIG1lYW5zIHRoZSBjbHVzdGVyIGhhcyBiZWVuIGRlbGV0ZWQgKG9yIG5ldmVyIGV4aXN0ZWQpJyk7XG4gICAgICAgIHJldHVybiB7IElzQ29tcGxldGU6IHRydWUgfTtcbiAgICAgIH1cblxuICAgICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciBlcnJvcjonLCBlKTtcbiAgICAgIHRocm93IGU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgIH07XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gVVBEQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvblVwZGF0ZSgpIHtcbiAgICBjb25zdCB1cGRhdGVzID0gYW5hbHl6ZVVwZGF0ZSh0aGlzLm9sZFByb3BzLCB0aGlzLm5ld1Byb3BzKTtcbiAgICBjb25zb2xlLmxvZygnb25VcGRhdGU6JywgSlNPTi5zdHJpbmdpZnkoeyB1cGRhdGVzIH0sIHVuZGVmaW5lZCwgMikpO1xuXG4gICAgLy8gdXBkYXRlcyB0byBlbmNyeXB0aW9uIGNvbmZpZyBpcyBub3Qgc3VwcG9ydGVkXG4gICAgaWYgKHVwZGF0ZXMudXBkYXRlRW5jcnlwdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgdXBkYXRlIGNsdXN0ZXIgZW5jcnlwdGlvbiBjb25maWd1cmF0aW9uJyk7XG4gICAgfVxuXG4gICAgLy8gaWYgdGhlcmUgaXMgYW4gdXBkYXRlIHRoYXQgcmVxdWlyZXMgcmVwbGFjZW1lbnQsIGdvIGFoZWFkIGFuZCBqdXN0IGNyZWF0ZVxuICAgIC8vIGEgbmV3IGNsdXN0ZXIgd2l0aCB0aGUgbmV3IGNvbmZpZy4gVGhlIG9sZCBjbHVzdGVyIHdpbGwgYXV0b21hdGljYWxseSBiZVxuICAgIC8vIGRlbGV0ZWQgYnkgY2xvdWRmb3JtYXRpb24gdXBvbiBzdWNjZXNzLlxuICAgIGlmICh1cGRhdGVzLnJlcGxhY2VOYW1lIHx8IHVwZGF0ZXMucmVwbGFjZVJvbGUgfHwgdXBkYXRlcy5yZXBsYWNlVnBjKSB7XG5cbiAgICAgIC8vIGlmIHdlIGFyZSByZXBsYWNpbmcgdGhpcyBjbHVzdGVyIGFuZCB0aGUgY2x1c3RlciBoYXMgYW4gZXhwbGljaXRcbiAgICAgIC8vIHBoeXNpY2FsIG5hbWUsIHRoZSBjcmVhdGlvbiBvZiB0aGUgbmV3IGNsdXN0ZXIgd2lsbCBmYWlsIHdpdGggXCJ0aGVyZSBpc1xuICAgICAgLy8gYWxyZWFkeSBhIGNsdXN0ZXIgd2l0aCB0aGF0IG5hbWVcIi4gdGhpcyBpcyBhIGNvbW1vbiBiZWhhdmlvciBmb3JcbiAgICAgIC8vIENsb3VkRm9ybWF0aW9uIHJlc291cmNlcyB0aGF0IHN1cHBvcnQgc3BlY2lmeWluZyBhIHBoeXNpY2FsIG5hbWUuXG4gICAgICBpZiAodGhpcy5vbGRQcm9wcy5uYW1lID09PSB0aGlzLm5ld1Byb3BzLm5hbWUgJiYgdGhpcy5vbGRQcm9wcy5uYW1lKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IHJlcGxhY2UgY2x1c3RlciBcIiR7dGhpcy5vbGRQcm9wcy5uYW1lfVwiIHNpbmNlIGl0IGhhcyBhbiBleHBsaWNpdCBwaHlzaWNhbCBuYW1lLiBFaXRoZXIgcmVuYW1lIHRoZSBjbHVzdGVyIG9yIHJlbW92ZSB0aGUgXCJuYW1lXCIgY29uZmlndXJhdGlvbmApO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy5vbkNyZWF0ZSgpO1xuICAgIH1cblxuICAgIC8vIGlmIGEgdmVyc2lvbiB1cGRhdGUgaXMgcmVxdWlyZWQsIGlzc3VlIHRoZSB2ZXJzaW9uIHVwZGF0ZVxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZVZlcnNpb24pIHtcbiAgICAgIGlmICghdGhpcy5uZXdQcm9wcy52ZXJzaW9uKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IHJlbW92ZSBjbHVzdGVyIHZlcnNpb24gY29uZmlndXJhdGlvbi4gQ3VycmVudCB2ZXJzaW9uIGlzICR7dGhpcy5vbGRQcm9wcy52ZXJzaW9ufWApO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy51cGRhdGVDbHVzdGVyVmVyc2lvbih0aGlzLm5ld1Byb3BzLnZlcnNpb24pO1xuICAgIH1cblxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUxvZ2dpbmcgfHwgdXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgIGNvbnN0IGNvbmZpZzogYXdzLkVLUy5VcGRhdGVDbHVzdGVyQ29uZmlnUmVxdWVzdCA9IHtcbiAgICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgICAgbG9nZ2luZzogdGhpcy5uZXdQcm9wcy5sb2dnaW5nLFxuICAgICAgfTtcbiAgICAgIGlmICh1cGRhdGVzLnVwZGF0ZUFjY2Vzcykge1xuICAgICAgICAvLyBVcGRhdGluZyB0aGUgY2x1c3RlciB3aXRoIHNlY3VyaXR5R3JvdXBJZHMgYW5kIHN1Ym5ldElkcyAoYXMgc3BlY2lmaWVkIGluIHRoZSB3YXJuaW5nIGhlcmU6XG4gICAgICAgIC8vIGh0dHBzOi8vYXdzY2xpLmFtYXpvbmF3cy5jb20vdjIvZG9jdW1lbnRhdGlvbi9hcGkvbGF0ZXN0L3JlZmVyZW5jZS9la3MvdXBkYXRlLWNsdXN0ZXItY29uZmlnLmh0bWwpXG4gICAgICAgIC8vIHdpbGwgZmFpbCwgdGhlcmVmb3JlIHdlIHRha2Ugb25seSB0aGUgYWNjZXNzIGZpZWxkcyBleHBsaWNpdGx5XG4gICAgICAgIGNvbmZpZy5yZXNvdXJjZXNWcGNDb25maWcgPSB7XG4gICAgICAgICAgZW5kcG9pbnRQcml2YXRlQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MsXG4gICAgICAgICAgZW5kcG9pbnRQdWJsaWNBY2Nlc3M6IHRoaXMubmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzLFxuICAgICAgICAgIHB1YmxpY0FjY2Vzc0NpZHJzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5wdWJsaWNBY2Nlc3NDaWRycyxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MudXBkYXRlQ2x1c3RlckNvbmZpZyhjb25maWcpO1xuXG4gICAgICByZXR1cm4geyBFa3NVcGRhdGVJZDogdXBkYXRlUmVzcG9uc2UudXBkYXRlPy5pZCB9O1xuICAgIH1cblxuICAgIC8vIG5vIHVwZGF0ZXNcbiAgICByZXR1cm47XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNVcGRhdGVDb21wbGV0ZSgpIHtcbiAgICBjb25zb2xlLmxvZygnaXNVcGRhdGVDb21wbGV0ZScpO1xuXG4gICAgLy8gaWYgdGhpcyBpcyBhbiBFS1MgdXBkYXRlLCB3ZSB3aWxsIG1vbml0b3IgdGhlIHVwZGF0ZSBldmVudCBpdHNlbGZcbiAgICBpZiAodGhpcy5ldmVudC5Fa3NVcGRhdGVJZCkge1xuICAgICAgY29uc3QgY29tcGxldGUgPSBhd2FpdCB0aGlzLmlzRWtzVXBkYXRlQ29tcGxldGUodGhpcy5ldmVudC5Fa3NVcGRhdGVJZCk7XG4gICAgICBpZiAoIWNvbXBsZXRlKSB7XG4gICAgICAgIHJldHVybiB7IElzQ29tcGxldGU6IGZhbHNlIH07XG4gICAgICB9XG5cbiAgICAgIC8vIGZhbGwgdGhyb3VnaDogaWYgdGhlIHVwZGF0ZSBpcyBkb25lLCB3ZSBzaW1wbHkgZGVsZWdhdGUgdG8gaXNBY3RpdmUoKVxuICAgICAgLy8gaW4gb3JkZXIgdG8gZXh0cmFjdCBhdHRyaWJ1dGVzIGFuZCBzdGF0ZSBmcm9tIHRoZSBjbHVzdGVyIGl0c2VsZiwgd2hpY2hcbiAgICAgIC8vIGlzIHN1cHBvc2VkIHRvIGJlIGluIGFuIEFDVElWRSBzdGF0ZSBhZnRlciB0aGUgdXBkYXRlIGlzIGNvbXBsZXRlLlxuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmlzQWN0aXZlKCk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHVwZGF0ZUNsdXN0ZXJWZXJzaW9uKG5ld1ZlcnNpb246IHN0cmluZykge1xuICAgIGNvbnNvbGUubG9nKGB1cGRhdGluZyBjbHVzdGVyIHZlcnNpb24gdG8gJHtuZXdWZXJzaW9ufWApO1xuXG4gICAgLy8gdXBkYXRlLWNsdXN0ZXItdmVyc2lvbiB3aWxsIGZhaWwgaWYgd2UgdHJ5IHRvIHVwZGF0ZSB0byB0aGUgc2FtZSB2ZXJzaW9uLFxuICAgIC8vIHNvIHNraXAgaW4gdGhpcyBjYXNlLlxuICAgIGNvbnN0IGNsdXN0ZXIgPSAoYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KSkuY2x1c3RlcjtcbiAgICBpZiAoY2x1c3Rlcj8udmVyc2lvbiA9PT0gbmV3VmVyc2lvbikge1xuICAgICAgY29uc29sZS5sb2coYGNsdXN0ZXIgYWxyZWFkeSBhdCB2ZXJzaW9uICR7Y2x1c3Rlci52ZXJzaW9ufSwgc2tpcHBpbmcgdmVyc2lvbiB1cGRhdGVgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJWZXJzaW9uKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSwgdmVyc2lvbjogbmV3VmVyc2lvbiB9KTtcbiAgICByZXR1cm4geyBFa3NVcGRhdGVJZDogdXBkYXRlUmVzcG9uc2UudXBkYXRlPy5pZCB9O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBpc0FjdGl2ZSgpOiBQcm9taXNlPElzQ29tcGxldGVSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCd3YWl0aW5nIGZvciBjbHVzdGVyIHRvIGJlY29tZSBBQ1RJVkUnKTtcbiAgICBjb25zdCByZXNwID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJlc3VsdDonLCBKU09OLnN0cmluZ2lmeShyZXNwLCB1bmRlZmluZWQsIDIpKTtcbiAgICBjb25zdCBjbHVzdGVyID0gcmVzcC5jbHVzdGVyO1xuXG4gICAgLy8gaWYgY2x1c3RlciBpcyB1bmRlZmluZWQgKHNob3VsZG50IGhhcHBlbikgb3Igc3RhdHVzIGlzIG5vdCBBQ1RJVkUsIHdlIGFyZVxuICAgIC8vIG5vdCBjb21wbGV0ZS4gbm90ZSB0aGF0IHRoZSBjdXN0b20gcmVzb3VyY2UgcHJvdmlkZXIgZnJhbWV3b3JrIGZvcmJpZHNcbiAgICAvLyByZXR1cm5pbmcgYXR0cmlidXRlcyAoRGF0YSkgaWYgaXNDb21wbGV0ZSBpcyBmYWxzZS5cbiAgICBpZiAoY2x1c3Rlcj8uc3RhdHVzID09PSAnRkFJTEVEJykge1xuICAgICAgLy8gbm90IHZlcnkgaW5mb3JtYXRpdmUsIHVuZm9ydHVuYXRlbHkgdGhlIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpbiBhbnkgZXJyb3JcbiAgICAgIC8vIGluZm9ybWF0aW9uIDpcXFxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDbHVzdGVyIGlzIGluIGEgRkFJTEVEIHN0YXR1cycpO1xuICAgIH0gZWxzZSBpZiAoY2x1c3Rlcj8uc3RhdHVzICE9PSAnQUNUSVZFJykge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogZmFsc2UsXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBJc0NvbXBsZXRlOiB0cnVlLFxuICAgICAgICBEYXRhOiB7XG4gICAgICAgICAgTmFtZTogY2x1c3Rlci5uYW1lLFxuICAgICAgICAgIEVuZHBvaW50OiBjbHVzdGVyLmVuZHBvaW50LFxuICAgICAgICAgIEFybjogY2x1c3Rlci5hcm4sXG5cbiAgICAgICAgICAvLyBJTVBPUlRBTlQ6IENGTiBleHBlY3RzIHRoYXQgYXR0cmlidXRlcyB3aWxsICphbHdheXMqIGhhdmUgdmFsdWVzLFxuICAgICAgICAgIC8vIHNvIHJldHVybiBhbiBlbXB0eSBzdHJpbmcgaW4gY2FzZSB0aGUgdmFsdWUgaXMgbm90IGRlZmluZWQuXG4gICAgICAgICAgLy8gT3RoZXJ3aXNlLCBDRk4gd2lsbCB0aHJvdyB3aXRoIGBWZW5kb3IgcmVzcG9uc2UgZG9lc24ndCBjb250YWluXG4gICAgICAgICAgLy8gWFhYWCBrZXlgLlxuXG4gICAgICAgICAgQ2VydGlmaWNhdGVBdXRob3JpdHlEYXRhOiBjbHVzdGVyLmNlcnRpZmljYXRlQXV0aG9yaXR5Py5kYXRhID8/ICcnLFxuICAgICAgICAgIENsdXN0ZXJTZWN1cml0eUdyb3VwSWQ6IGNsdXN0ZXIucmVzb3VyY2VzVnBjQ29uZmlnPy5jbHVzdGVyU2VjdXJpdHlHcm91cElkID8/ICcnLFxuICAgICAgICAgIE9wZW5JZENvbm5lY3RJc3N1ZXJVcmw6IGNsdXN0ZXIuaWRlbnRpdHk/Lm9pZGM/Lmlzc3VlciA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXI/LnN1YnN0cmluZyg4KSA/PyAnJywgLy8gU3RyaXBzIG9mZiBodHRwczovLyBmcm9tIHRoZSBpc3N1ZXIgdXJsXG5cbiAgICAgICAgICAvLyBXZSBjYW4gc2FmZWx5IHJldHVybiB0aGUgZmlyc3QgaXRlbSBmcm9tIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbiBhcnJheSwgYmVjYXVzZSBpdCBoYXMgYSBsaW1pdCBvZiAxIGl0ZW1cbiAgICAgICAgICAvLyBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vZWtzL2xhdGVzdC9BUElSZWZlcmVuY2UvQVBJX0NyZWF0ZUNsdXN0ZXIuaHRtbCNBbWF6b25FS1MtQ3JlYXRlQ2x1c3Rlci1yZXF1ZXN0LWVuY3J5cHRpb25Db25maWdcbiAgICAgICAgICBFbmNyeXB0aW9uQ29uZmlnS2V5QXJuOiBjbHVzdGVyLmVuY3J5cHRpb25Db25maWc/LnNoaWZ0KCk/LnByb3ZpZGVyPy5rZXlBcm4gPz8gJycsXG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNFa3NVcGRhdGVDb21wbGV0ZShla3NVcGRhdGVJZDogc3RyaW5nKSB7XG4gICAgdGhpcy5sb2coeyBpc0Vrc1VwZGF0ZUNvbXBsZXRlOiBla3NVcGRhdGVJZCB9KTtcblxuICAgIGNvbnN0IGRlc2NyaWJlVXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy5kZXNjcmliZVVwZGF0ZSh7XG4gICAgICBuYW1lOiB0aGlzLmNsdXN0ZXJOYW1lLFxuICAgICAgdXBkYXRlSWQ6IGVrc1VwZGF0ZUlkLFxuICAgIH0pO1xuXG4gICAgdGhpcy5sb2coeyBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlIH0pO1xuXG4gICAgaWYgKCFkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmFibGUgdG8gZGVzY3JpYmUgdXBkYXRlIHdpdGggaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuXG4gICAgc3dpdGNoIChkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5zdGF0dXMpIHtcbiAgICAgIGNhc2UgJ0luUHJvZ3Jlc3MnOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBjYXNlICdTdWNjZXNzZnVsJzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlICdGYWlsZWQnOlxuICAgICAgY2FzZSAnQ2FuY2VsbGVkJzpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBjbHVzdGVyIHVwZGF0ZSBpZCBcIiR7ZWtzVXBkYXRlSWR9XCIgZmFpbGVkIHdpdGggZXJyb3JzOiAke0pTT04uc3RyaW5naWZ5KGRlc2NyaWJlVXBkYXRlUmVzcG9uc2UudXBkYXRlLmVycm9ycyl9YCk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHVua25vd24gc3RhdHVzIFwiJHtkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5zdGF0dXN9XCIgZm9yIHVwZGF0ZSBpZCBcIiR7ZWtzVXBkYXRlSWR9XCJgKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGdlbmVyYXRlQ2x1c3Rlck5hbWUoKSB7XG4gICAgY29uc3Qgc3VmZml4ID0gdGhpcy5yZXF1ZXN0SWQucmVwbGFjZSgvLS9nLCAnJyk7IC8vIDMyIGNoYXJzXG4gICAgY29uc3Qgb2Zmc2V0ID0gTUFYX0NMVVNURVJfTkFNRV9MRU4gLSBzdWZmaXgubGVuZ3RoIC0gMTtcbiAgICBjb25zdCBwcmVmaXggPSB0aGlzLmxvZ2ljYWxSZXNvdXJjZUlkLnNsaWNlKDAsIG9mZnNldCA+IDAgPyBvZmZzZXQgOiAwKTtcbiAgICByZXR1cm4gYCR7cHJlZml4fS0ke3N1ZmZpeH1gO1xuICB9XG59XG5cbmZ1bmN0aW9uIHBhcnNlUHJvcHMocHJvcHM6IGFueSk6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3Qge1xuXG4gIGNvbnN0IHBhcnNlZCA9IHByb3BzPy5Db25maWcgPz8ge307XG5cbiAgLy8gdGhpcyBpcyB3ZWlyZCBidXQgdGhlc2UgYm9vbGVhbiBwcm9wZXJ0aWVzIGFyZSBwYXNzZWQgYnkgQ0ZOIGFzIGEgc3RyaW5nLCBhbmQgd2UgbmVlZCB0aGVtIHRvIGJlIGJvb2xlYW5pYyBmb3IgdGhlIFNESy5cbiAgLy8gT3RoZXJ3aXNlIGl0IGZhaWxzIHdpdGggJ1VuZXhwZWN0ZWQgUGFyYW1ldGVyOiBwYXJhbXMucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBpcyBleHBlY3RlZCB0byBiZSBhIGJvb2xlYW4nXG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQcml2YXRlQWNjZXNzKSA9PT0gJ3N0cmluZycpIHtcbiAgICBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9IHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnPy5lbmRwb2ludFB1YmxpY0FjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyA9IHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPT09ICd0cnVlJztcbiAgfVxuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5sb2dnaW5nPy5jbHVzdGVyTG9nZ2luZ1swXS5lbmFibGVkKSA9PT0gJ3N0cmluZycpIHtcbiAgICBwYXJzZWQubG9nZ2luZy5jbHVzdGVyTG9nZ2luZ1swXS5lbmFibGVkID0gcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9PT0gJ3RydWUnO1xuICB9XG5cbiAgcmV0dXJuIHBhcnNlZDtcblxufVxuXG5pbnRlcmZhY2UgVXBkYXRlTWFwIHtcbiAgcmVwbGFjZU5hbWU6IGJvb2xlYW47IC8vIG5hbWVcbiAgcmVwbGFjZVZwYzogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLnN1Ym5ldElkcyBhbmQgc2VjdXJpdHlHcm91cElkc1xuICByZXBsYWNlUm9sZTogYm9vbGVhbjsgLy8gcm9sZUFyblxuXG4gIHVwZGF0ZVZlcnNpb246IGJvb2xlYW47IC8vIHZlcnNpb25cbiAgdXBkYXRlTG9nZ2luZzogYm9vbGVhbjsgLy8gbG9nZ2luZ1xuICB1cGRhdGVFbmNyeXB0aW9uOiBib29sZWFuOyAvLyBlbmNyeXB0aW9uIChjYW5ub3QgYmUgdXBkYXRlZClcbiAgdXBkYXRlQWNjZXNzOiBib29sZWFuOyAvLyByZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzIGFuZCBlbmRwb2ludFB1YmxpY0FjY2Vzc1xufVxuXG5mdW5jdGlvbiBhbmFseXplVXBkYXRlKG9sZFByb3BzOiBQYXJ0aWFsPGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3Q+LCBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdCk6IFVwZGF0ZU1hcCB7XG4gIGNvbnNvbGUubG9nKCdvbGQgcHJvcHM6ICcsIEpTT04uc3RyaW5naWZ5KG9sZFByb3BzKSk7XG4gIGNvbnNvbGUubG9nKCduZXcgcHJvcHM6ICcsIEpTT04uc3RyaW5naWZ5KG5ld1Byb3BzKSk7XG5cbiAgY29uc3QgbmV3VnBjUHJvcHMgPSBuZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcgfHwge307XG4gIGNvbnN0IG9sZFZwY1Byb3BzID0gb2xkUHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuXG4gIGNvbnN0IG9sZFB1YmxpY0FjY2Vzc0NpZHJzID0gbmV3IFNldChvbGRWcGNQcm9wcy5wdWJsaWNBY2Nlc3NDaWRycyA/PyBbXSk7XG4gIGNvbnN0IG5ld1B1YmxpY0FjY2Vzc0NpZHJzID0gbmV3IFNldChuZXdWcGNQcm9wcy5wdWJsaWNBY2Nlc3NDaWRycyA/PyBbXSk7XG4gIGNvbnN0IG5ld0VuYyA9IG5ld1Byb3BzLmVuY3J5cHRpb25Db25maWcgfHwge307XG4gIGNvbnN0IG9sZEVuYyA9IG9sZFByb3BzLmVuY3J5cHRpb25Db25maWcgfHwge307XG5cbiAgcmV0dXJuIHtcbiAgICByZXBsYWNlTmFtZTogbmV3UHJvcHMubmFtZSAhPT0gb2xkUHJvcHMubmFtZSxcbiAgICByZXBsYWNlVnBjOlxuICAgICAgSlNPTi5zdHJpbmdpZnkobmV3VnBjUHJvcHMuc3VibmV0SWRzKSAhPT0gSlNPTi5zdHJpbmdpZnkob2xkVnBjUHJvcHMuc3VibmV0SWRzKSB8fFxuICAgICAgSlNPTi5zdHJpbmdpZnkobmV3VnBjUHJvcHMuc2VjdXJpdHlHcm91cElkcykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFZwY1Byb3BzLnNlY3VyaXR5R3JvdXBJZHMpLFxuICAgIHVwZGF0ZUFjY2VzczpcbiAgICAgIG5ld1ZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQcml2YXRlQWNjZXNzIHx8XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFB1YmxpY0FjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgfHxcbiAgICAgICFzZXRzRXF1YWwobmV3UHVibGljQWNjZXNzQ2lkcnMsIG9sZFB1YmxpY0FjY2Vzc0NpZHJzKSxcbiAgICByZXBsYWNlUm9sZTogbmV3UHJvcHMucm9sZUFybiAhPT0gb2xkUHJvcHMucm9sZUFybixcbiAgICB1cGRhdGVWZXJzaW9uOiBuZXdQcm9wcy52ZXJzaW9uICE9PSBvbGRQcm9wcy52ZXJzaW9uLFxuICAgIHVwZGF0ZUVuY3J5cHRpb246IEpTT04uc3RyaW5naWZ5KG5ld0VuYykgIT09IEpTT04uc3RyaW5naWZ5KG9sZEVuYyksXG4gICAgdXBkYXRlTG9nZ2luZzogSlNPTi5zdHJpbmdpZnkobmV3UHJvcHMubG9nZ2luZykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFByb3BzLmxvZ2dpbmcpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzZXRzRXF1YWwoZmlyc3Q6IFNldDxzdHJpbmc+LCBzZWNvbmQ6IFNldDxzdHJpbmc+KSB7XG4gIHJldHVybiBmaXJzdC5zaXplID09PSBzZWNvbmQuc2l6ZSB8fCBbLi4uZmlyc3RdLmV2ZXJ5KChlOiBzdHJpbmcpID0+IHNlY29uZC5oYXMoZSkpO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.ts b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.ts deleted file mode 100644 index 0177a7e21b695..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.ts +++ /dev/null @@ -1,338 +0,0 @@ -/* eslint-disable no-console */ - -// eslint-disable-next-line import/no-extraneous-dependencies -import { IsCompleteResponse, OnEventResponse } from '@aws-cdk/custom-resources/lib/provider-framework/types'; -// eslint-disable-next-line import/no-extraneous-dependencies -import * as aws from 'aws-sdk'; -import { EksClient, ResourceEvent, ResourceHandler } from './common'; - -const MAX_CLUSTER_NAME_LEN = 100; - -export class ClusterResourceHandler extends ResourceHandler { - public get clusterName() { - if (!this.physicalResourceId) { - throw new Error('Cannot determine cluster name without physical resource ID'); - } - - return this.physicalResourceId; - } - - private readonly newProps: aws.EKS.CreateClusterRequest; - private readonly oldProps: Partial; - - constructor(eks: EksClient, event: ResourceEvent) { - super(eks, event); - - this.newProps = parseProps(this.event.ResourceProperties); - this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; - } - - // ------ - // CREATE - // ------ - - protected async onCreate(): Promise { - console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); - if (!this.newProps.roleArn) { - throw new Error('"roleArn" is required'); - } - - const clusterName = this.newProps.name || this.generateClusterName(); - - const resp = await this.eks.createCluster({ - ...this.newProps, - name: clusterName, - }); - - if (!resp.cluster) { - throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); - } - - return { - PhysicalResourceId: resp.cluster.name, - }; - } - - protected async isCreateComplete() { - return this.isActive(); - } - - // ------ - // DELETE - // ------ - - protected async onDelete(): Promise { - console.log(`onDelete: deleting cluster ${this.clusterName}`); - try { - await this.eks.deleteCluster({ name: this.clusterName }); - } catch (e) { - if (e.code !== 'ResourceNotFoundException') { - throw e; - } else { - console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); - } - } - return { - PhysicalResourceId: this.clusterName, - }; - } - - protected async isDeleteComplete(): Promise { - console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); - - try { - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); - } catch (e) { - if (e.code === 'ResourceNotFoundException') { - console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); - return { IsComplete: true }; - } - - console.log('describeCluster error:', e); - throw e; - } - - return { - IsComplete: false, - }; - } - - // ------ - // UPDATE - // ------ - - protected async onUpdate() { - const updates = analyzeUpdate(this.oldProps, this.newProps); - console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); - - // updates to encryption config is not supported - if (updates.updateEncryption) { - throw new Error('Cannot update cluster encryption configuration'); - } - - // if there is an update that requires replacement, go ahead and just create - // a new cluster with the new config. The old cluster will automatically be - // deleted by cloudformation upon success. - if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { - - // if we are replacing this cluster and the cluster has an explicit - // physical name, the creation of the new cluster will fail with "there is - // already a cluster with that name". this is a common behavior for - // CloudFormation resources that support specifying a physical name. - if (this.oldProps.name === this.newProps.name && this.oldProps.name) { - throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); - } - - return this.onCreate(); - } - - // if a version update is required, issue the version update - if (updates.updateVersion) { - if (!this.newProps.version) { - throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); - } - - return this.updateClusterVersion(this.newProps.version); - } - - if (updates.updateLogging || updates.updateAccess) { - const config: aws.EKS.UpdateClusterConfigRequest = { - name: this.clusterName, - logging: this.newProps.logging, - }; - if (updates.updateAccess) { - // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: - // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) - // will fail, therefore we take only the access fields explicitly - config.resourcesVpcConfig = { - endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, - endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, - publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, - }; - } - const updateResponse = await this.eks.updateClusterConfig(config); - - return { EksUpdateId: updateResponse.update?.id }; - } - - // no updates - return; - } - - protected async isUpdateComplete() { - console.log('isUpdateComplete'); - - // if this is an EKS update, we will monitor the update event itself - if (this.event.EksUpdateId) { - const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); - if (!complete) { - return { IsComplete: false }; - } - - // fall through: if the update is done, we simply delegate to isActive() - // in order to extract attributes and state from the cluster itself, which - // is supposed to be in an ACTIVE state after the update is complete. - } - - return this.isActive(); - } - - private async updateClusterVersion(newVersion: string) { - console.log(`updating cluster version to ${newVersion}`); - - // update-cluster-version will fail if we try to update to the same version, - // so skip in this case. - const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; - if (cluster?.version === newVersion) { - console.log(`cluster already at version ${cluster.version}, skipping version update`); - return; - } - - const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); - return { EksUpdateId: updateResponse.update?.id }; - } - - private async isActive(): Promise { - console.log('waiting for cluster to become ACTIVE'); - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); - const cluster = resp.cluster; - - // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are - // not complete. note that the custom resource provider framework forbids - // returning attributes (Data) if isComplete is false. - if (cluster?.status === 'FAILED') { - // not very informative, unfortunately the response doesn't contain any error - // information :\ - throw new Error('Cluster is in a FAILED status'); - } else if (cluster?.status !== 'ACTIVE') { - return { - IsComplete: false, - }; - } else { - return { - IsComplete: true, - Data: { - Name: cluster.name, - Endpoint: cluster.endpoint, - Arn: cluster.arn, - - // IMPORTANT: CFN expects that attributes will *always* have values, - // so return an empty string in case the value is not defined. - // Otherwise, CFN will throw with `Vendor response doesn't contain - // XXXX key`. - - CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', - ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', - OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', - OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', // Strips off https:// from the issuer url - - // We can safely return the first item from encryption configuration array, because it has a limit of 1 item - // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig - EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', - }, - }; - } - } - - private async isEksUpdateComplete(eksUpdateId: string) { - this.log({ isEksUpdateComplete: eksUpdateId }); - - const describeUpdateResponse = await this.eks.describeUpdate({ - name: this.clusterName, - updateId: eksUpdateId, - }); - - this.log({ describeUpdateResponse }); - - if (!describeUpdateResponse.update) { - throw new Error(`unable to describe update with id "${eksUpdateId}"`); - } - - switch (describeUpdateResponse.update.status) { - case 'InProgress': - return false; - case 'Successful': - return true; - case 'Failed': - case 'Cancelled': - throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); - default: - throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); - } - } - - private generateClusterName() { - const suffix = this.requestId.replace(/-/g, ''); // 32 chars - const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; - const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); - return `${prefix}-${suffix}`; - } -} - -function parseProps(props: any): aws.EKS.CreateClusterRequest { - - const parsed = props?.Config ?? {}; - - // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. - // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' - - if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; - } - - if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; - } - - if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { - parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; - } - - return parsed; - -} - -interface UpdateMap { - replaceName: boolean; // name - replaceVpc: boolean; // resourcesVpcConfig.subnetIds and securityGroupIds - replaceRole: boolean; // roleArn - - updateVersion: boolean; // version - updateLogging: boolean; // logging - updateEncryption: boolean; // encryption (cannot be updated) - updateAccess: boolean; // resourcesVpcConfig.endpointPrivateAccess and endpointPublicAccess -} - -function analyzeUpdate(oldProps: Partial, newProps: aws.EKS.CreateClusterRequest): UpdateMap { - console.log('old props: ', JSON.stringify(oldProps)); - console.log('new props: ', JSON.stringify(newProps)); - - const newVpcProps = newProps.resourcesVpcConfig || {}; - const oldVpcProps = oldProps.resourcesVpcConfig || {}; - - const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); - const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); - const newEnc = newProps.encryptionConfig || {}; - const oldEnc = oldProps.encryptionConfig || {}; - - return { - replaceName: newProps.name !== oldProps.name, - replaceVpc: - JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), - updateAccess: - newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || - newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || - !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), - replaceRole: newProps.roleArn !== oldProps.roleArn, - updateVersion: newProps.version !== oldProps.version, - updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), - updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), - }; -} - -function setsEqual(first: Set, second: Set) { - return first.size === second.size || [...first].every((e: string) => second.has(e)); -} diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/cfn-response.js b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/cfn-response.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/cfn-response.js rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/cfn-response.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/consts.js b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/consts.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/consts.js rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/consts.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/framework.js b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/framework.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/framework.js rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/framework.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/outbound.js b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/outbound.js new file mode 100644 index 0000000000000..cc0667d42f0e8 --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/outbound.js @@ -0,0 +1,69 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.httpRequest = exports.invokeFunction = exports.startExecution = void 0; +/* istanbul ignore file */ +const https = require("https"); +// eslint-disable-next-line import/no-extraneous-dependencies +const AWS = require("aws-sdk"); +const FRAMEWORK_HANDLER_TIMEOUT = 900000; // 15 minutes +// In order to honor the overall maximum timeout set for the target process, +// the default 2 minutes from AWS SDK has to be overriden: +// https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html#httpOptions-property +const 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; +let lambda; +async function defaultStartExecution(req) { + if (!sfn) { + sfn = new AWS.StepFunctions(awsSdkConfig); + } + return sfn.startExecution(req).promise(); +} +async function defaultInvokeFunction(req) { + if (!lambda) { + lambda = new AWS.Lambda(awsSdkConfig); + } + try { + /** + * Try an initial invoke. + * + * When you try to invoke a function that is inactive, the invocation fails and Lambda sets + * the function to pending state until the function resources are recreated. + * If Lambda fails to recreate the resources, the function is set to the inactive state. + * + * We're using invoke first because `waitFor` doesn't trigger an inactive function to do anything, + * it just runs `getFunction` and checks the state. + */ + return await lambda.invoke(req).promise(); + } + catch (error) { + /** + * The status of the Lambda function is checked every second for up to 300 seconds. + * Exits the loop on 'Active' state and throws an error on 'Inactive' or 'Failed'. + * + * And now we wait. + */ + await lambda.waitFor('functionActiveV2', { + FunctionName: req.FunctionName, + }).promise(); + return await lambda.invoke(req).promise(); + } +} +exports.startExecution = defaultStartExecution; +exports.invokeFunction = defaultInvokeFunction; +exports.httpRequest = defaultHttpRequest; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3V0Ym91bmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJvdXRib3VuZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwwQkFBMEI7QUFDMUIsK0JBQStCO0FBQy9CLDZEQUE2RDtBQUM3RCwrQkFBK0I7QUFJL0IsTUFBTSx5QkFBeUIsR0FBRyxNQUFNLENBQUMsQ0FBQyxhQUFhO0FBRXZELDRFQUE0RTtBQUM1RSwwREFBMEQ7QUFDMUQsMkZBQTJGO0FBQzNGLE1BQU0sWUFBWSxHQUF5QjtJQUN6QyxXQUFXLEVBQUUsRUFBRSxPQUFPLEVBQUUseUJBQXlCLEVBQUU7Q0FDcEQsQ0FBQztBQUVGLEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxPQUE2QixFQUFFLFlBQW9CO0lBQ25GLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDckMsSUFBSTtZQUNGLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ2hELE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDNUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1NBQ2Y7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNYO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsSUFBSSxHQUFzQixDQUFDO0FBQzNCLElBQUksTUFBa0IsQ0FBQztBQUV2QixLQUFLLFVBQVUscUJBQXFCLENBQUMsR0FBMEM7SUFDN0UsSUFBSSxDQUFDLEdBQUcsRUFBRTtRQUNSLEdBQUcsR0FBRyxJQUFJLEdBQUcsQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUM7S0FDM0M7SUFFRCxPQUFPLEdBQUcsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7QUFDM0MsQ0FBQztBQUVELEtBQUssVUFBVSxxQkFBcUIsQ0FBQyxHQUFpQztJQUNwRSxJQUFJLENBQUMsTUFBTSxFQUFFO1FBQ1gsTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztLQUN2QztJQUVELElBQUk7UUFDRjs7Ozs7Ozs7O1dBU0c7UUFDSCxPQUFPLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztLQUMzQztJQUFDLE9BQU8sS0FBSyxFQUFFO1FBRWQ7Ozs7O1dBS0c7UUFDSCxNQUFNLE1BQU0sQ0FBQyxPQUFPLENBQUMsa0JBQWtCLEVBQUU7WUFDdkMsWUFBWSxFQUFFLEdBQUcsQ0FBQyxZQUFZO1NBQy9CLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNiLE9BQU8sTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDO0tBQzNDO0FBQ0gsQ0FBQztBQUVVLFFBQUEsY0FBYyxHQUFHLHFCQUFxQixDQUFDO0FBQ3ZDLFFBQUEsY0FBYyxHQUFHLHFCQUFxQixDQUFDO0FBQ3ZDLFFBQUEsV0FBVyxHQUFHLGtCQUFrQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogaXN0YW5idWwgaWdub3JlIGZpbGUgKi9cbmltcG9ydCAqIGFzIGh0dHBzIGZyb20gJ2h0dHBzJztcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcbmltcG9ydCAqIGFzIEFXUyBmcm9tICdhd3Mtc2RrJztcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcbmltcG9ydCB0eXBlIHsgQ29uZmlndXJhdGlvbk9wdGlvbnMgfSBmcm9tICdhd3Mtc2RrL2xpYi9jb25maWctYmFzZSc7XG5cbmNvbnN0IEZSQU1FV09SS19IQU5ETEVSX1RJTUVPVVQgPSA5MDAwMDA7IC8vIDE1IG1pbnV0ZXNcblxuLy8gSW4gb3JkZXIgdG8gaG9ub3IgdGhlIG92ZXJhbGwgbWF4aW11bSB0aW1lb3V0IHNldCBmb3IgdGhlIHRhcmdldCBwcm9jZXNzLFxuLy8gdGhlIGRlZmF1bHQgMiBtaW51dGVzIGZyb20gQVdTIFNESyBoYXMgdG8gYmUgb3ZlcnJpZGVuOlxuLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0phdmFTY3JpcHRTREsvbGF0ZXN0L0FXUy9Db25maWcuaHRtbCNodHRwT3B0aW9ucy1wcm9wZXJ0eVxuY29uc3QgYXdzU2RrQ29uZmlnOiBDb25maWd1cmF0aW9uT3B0aW9ucyA9IHtcbiAgaHR0cE9wdGlvbnM6IHsgdGltZW91dDogRlJBTUVXT1JLX0hBTkRMRVJfVElNRU9VVCB9LFxufTtcblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdEh0dHBSZXF1ZXN0KG9wdGlvbnM6IGh0dHBzLlJlcXVlc3RPcHRpb25zLCByZXNwb25zZUJvZHk6IHN0cmluZykge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gaHR0cHMucmVxdWVzdChvcHRpb25zLCByZXNvbHZlKTtcbiAgICAgIHJlcXVlc3Qub24oJ2Vycm9yJywgcmVqZWN0KTtcbiAgICAgIHJlcXVlc3Qud3JpdGUocmVzcG9uc2VCb2R5KTtcbiAgICAgIHJlcXVlc3QuZW5kKCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmVqZWN0KGUpO1xuICAgIH1cbiAgfSk7XG59XG5cbmxldCBzZm46IEFXUy5TdGVwRnVuY3Rpb25zO1xubGV0IGxhbWJkYTogQVdTLkxhbWJkYTtcblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdFN0YXJ0RXhlY3V0aW9uKHJlcTogQVdTLlN0ZXBGdW5jdGlvbnMuU3RhcnRFeGVjdXRpb25JbnB1dCk6IFByb21pc2U8QVdTLlN0ZXBGdW5jdGlvbnMuU3RhcnRFeGVjdXRpb25PdXRwdXQ+IHtcbiAgaWYgKCFzZm4pIHtcbiAgICBzZm4gPSBuZXcgQVdTLlN0ZXBGdW5jdGlvbnMoYXdzU2RrQ29uZmlnKTtcbiAgfVxuXG4gIHJldHVybiBzZm4uc3RhcnRFeGVjdXRpb24ocmVxKS5wcm9taXNlKCk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGRlZmF1bHRJbnZva2VGdW5jdGlvbihyZXE6IEFXUy5MYW1iZGEuSW52b2NhdGlvblJlcXVlc3QpOiBQcm9taXNlPEFXUy5MYW1iZGEuSW52b2NhdGlvblJlc3BvbnNlPiB7XG4gIGlmICghbGFtYmRhKSB7XG4gICAgbGFtYmRhID0gbmV3IEFXUy5MYW1iZGEoYXdzU2RrQ29uZmlnKTtcbiAgfVxuXG4gIHRyeSB7XG4gICAgLyoqXG4gICAgICogVHJ5IGFuIGluaXRpYWwgaW52b2tlLlxuICAgICAqXG4gICAgICogV2hlbiB5b3UgdHJ5IHRvIGludm9rZSBhIGZ1bmN0aW9uIHRoYXQgaXMgaW5hY3RpdmUsIHRoZSBpbnZvY2F0aW9uIGZhaWxzIGFuZCBMYW1iZGEgc2V0c1xuICAgICAqIHRoZSBmdW5jdGlvbiB0byBwZW5kaW5nIHN0YXRlIHVudGlsIHRoZSBmdW5jdGlvbiByZXNvdXJjZXMgYXJlIHJlY3JlYXRlZC5cbiAgICAgKiBJZiBMYW1iZGEgZmFpbHMgdG8gcmVjcmVhdGUgdGhlIHJlc291cmNlcywgdGhlIGZ1bmN0aW9uIGlzIHNldCB0byB0aGUgaW5hY3RpdmUgc3RhdGUuXG4gICAgICpcbiAgICAgKiBXZSdyZSB1c2luZyBpbnZva2UgZmlyc3QgYmVjYXVzZSBgd2FpdEZvcmAgZG9lc24ndCB0cmlnZ2VyIGFuIGluYWN0aXZlIGZ1bmN0aW9uIHRvIGRvIGFueXRoaW5nLFxuICAgICAqIGl0IGp1c3QgcnVucyBgZ2V0RnVuY3Rpb25gIGFuZCBjaGVja3MgdGhlIHN0YXRlLlxuICAgICAqL1xuICAgIHJldHVybiBhd2FpdCBsYW1iZGEuaW52b2tlKHJlcSkucHJvbWlzZSgpO1xuICB9IGNhdGNoIChlcnJvcikge1xuXG4gICAgLyoqXG4gICAgICogVGhlIHN0YXR1cyBvZiB0aGUgTGFtYmRhIGZ1bmN0aW9uIGlzIGNoZWNrZWQgZXZlcnkgc2Vjb25kIGZvciB1cCB0byAzMDAgc2Vjb25kcy5cbiAgICAgKiBFeGl0cyB0aGUgbG9vcCBvbiAnQWN0aXZlJyBzdGF0ZSBhbmQgdGhyb3dzIGFuIGVycm9yIG9uICdJbmFjdGl2ZScgb3IgJ0ZhaWxlZCcuXG4gICAgICpcbiAgICAgKiBBbmQgbm93IHdlIHdhaXQuXG4gICAgICovXG4gICAgYXdhaXQgbGFtYmRhLndhaXRGb3IoJ2Z1bmN0aW9uQWN0aXZlVjInLCB7XG4gICAgICBGdW5jdGlvbk5hbWU6IHJlcS5GdW5jdGlvbk5hbWUsXG4gICAgfSkucHJvbWlzZSgpO1xuICAgIHJldHVybiBhd2FpdCBsYW1iZGEuaW52b2tlKHJlcSkucHJvbWlzZSgpO1xuICB9XG59XG5cbmV4cG9ydCBsZXQgc3RhcnRFeGVjdXRpb24gPSBkZWZhdWx0U3RhcnRFeGVjdXRpb247XG5leHBvcnQgbGV0IGludm9rZUZ1bmN0aW9uID0gZGVmYXVsdEludm9rZUZ1bmN0aW9uO1xuZXhwb3J0IGxldCBodHRwUmVxdWVzdCA9IGRlZmF1bHRIdHRwUmVxdWVzdDtcbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/util.js b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/util.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/util.js rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/util.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip index b64a5034e3b6c..13983109fc5f5 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip and b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/apply/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/apply/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/get/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/get/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py new file mode 100644 index 0000000000000..286976ced219a --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py @@ -0,0 +1,187 @@ +import json +import logging +import os +import re +import subprocess +import shutil +import tempfile +import zipfile + +logger = logging.getLogger() +logger.setLevel(logging.INFO) + +# these are coming from the kubectl layer +os.environ['PATH'] = '/opt/helm:/opt/awscli:' + os.environ['PATH'] + +outdir = os.environ.get('TEST_OUTDIR', '/tmp') +kubeconfig = os.path.join(outdir, 'kubeconfig') + +def get_chart_asset_from_url(chart_asset_url): + chart_zip = os.path.join(outdir, 'chart.zip') + shutil.rmtree(chart_zip, ignore_errors=True) + subprocess.check_call(['aws', 's3', 'cp', chart_asset_url, chart_zip]) + chart_dir = os.path.join(outdir, 'chart') + shutil.rmtree(chart_dir, ignore_errors=True) + os.mkdir(chart_dir) + with zipfile.ZipFile(chart_zip, 'r') as zip_ref: + zip_ref.extractall(chart_dir) + return chart_dir + +def helm_handler(event, context): + logger.info(json.dumps(dict(event, ResponseURL='...'))) + + request_type = event['RequestType'] + props = event['ResourceProperties'] + + # resource properties + cluster_name = props['ClusterName'] + role_arn = props['RoleArn'] + release = props['Release'] + chart = props.get('Chart', None) + chart_asset_url = props.get('ChartAssetURL', None) + version = props.get('Version', None) + wait = props.get('Wait', False) + timeout = props.get('Timeout', None) + namespace = props.get('Namespace', None) + create_namespace = props.get('CreateNamespace', None) + repository = props.get('Repository', None) + values_text = props.get('Values', None) + + # "log in" to the cluster + subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig', + '--role-arn', role_arn, + '--name', cluster_name, + '--kubeconfig', kubeconfig + ]) + + if os.path.isfile(kubeconfig): + os.chmod(kubeconfig, 0o600) + + # Write out the values to a file and include them with the install and upgrade + values_file = None + if not request_type == "Delete" and not values_text is None: + values = json.loads(values_text) + values_file = os.path.join(outdir, 'values.yaml') + with open(values_file, "w") as f: + f.write(json.dumps(values, indent=2)) + + if request_type == 'Create' or request_type == 'Update': + # Ensure chart or chart_asset_url are set + if chart == None and chart_asset_url == None: + raise RuntimeError(f'chart or chartAsset must be specified') + + if chart_asset_url != None: + assert(chart==None) + assert(repository==None) + assert(version==None) + if not chart_asset_url.startswith('s3://'): + raise RuntimeError(f'ChartAssetURL must point to as s3 location but is {chart_asset_url}') + # future work: support versions from s3 assets + chart = get_chart_asset_from_url(chart_asset_url) + + if repository is not None and repository.startswith('oci://'): + tmpdir = tempfile.TemporaryDirectory() + chart_dir = get_chart_from_oci(tmpdir.name, repository, version) + chart = chart_dir + + helm('upgrade', release, chart, repository, values_file, namespace, version, wait, timeout, create_namespace) + elif request_type == "Delete": + try: + helm('uninstall', release, namespace=namespace, timeout=timeout) + except Exception as e: + logger.info("delete error: %s" % e) + + +def get_oci_cmd(repository, version): + # Generates OCI command based on pattern. Public ECR vs Private ECR are treated differently. + private_ecr_pattern = 'oci://(?P\d+.dkr.ecr.(?P[a-z]+-[a-z]+-\d).amazonaws.com)*' + public_ecr_pattern = 'oci://(?Ppublic.ecr.aws)*' + + private_registry = re.match(private_ecr_pattern, repository).groupdict() + public_registry = re.match(public_ecr_pattern, repository).groupdict() + + if private_registry['registry'] is not None: + logger.info("Found AWS private repository") + cmnd = [ + f"aws ecr get-login-password --region {private_registry['region']} | " \ + f"helm registry login --username AWS --password-stdin {private_registry['registry']}; helm pull {repository} --version {version} --untar" + ] + elif public_registry['registry'] is not None: + logger.info("Found AWS public repository, will use default region as deployment") + region = os.environ.get('AWS_REGION', 'us-east-1') + + cmnd = [ + f"aws ecr-public get-login-password --region us-east-1 | " \ + f"helm registry login --username AWS --password-stdin {public_registry['registry']}; helm pull {repository} --version {version} --untar" + ] + else: + logger.error("OCI repository format not recognized, falling back to helm pull") + cmnd = ['helm', 'pull', repository, '--version', version, '--untar'] + + return cmnd + + +def get_chart_from_oci(tmpdir, repository = None, version = None): + + cmnd = get_oci_cmd(repository, version) + + maxAttempts = 3 + retry = maxAttempts + while retry > 0: + try: + logger.info(cmnd) + output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=tmpdir, shell=True) + logger.info(output) + + # effectively returns "$tmpDir/$lastPartOfOCIUrl", because this is how helm pull saves OCI artifact. + # Eg. if we have oci://9999999999.dkr.ecr.us-east-1.amazonaws.com/foo/bar/pet-service repository, helm saves artifact under $tmpDir/pet-service + return os.path.join(tmpdir, repository.rpartition('/')[-1]) + except subprocess.CalledProcessError as exc: + output = exc.output + if b'Broken pipe' in output: + retry = retry - 1 + logger.info("Broken pipe, retries left: %s" % retry) + else: + raise Exception(output) + raise Exception(f'Operation failed after {maxAttempts} attempts: {output}') + + +def helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None): + import subprocess + + cmnd = ['helm', verb, release] + if not chart is None: + cmnd.append(chart) + if verb == 'upgrade': + cmnd.append('--install') + if create_namespace: + cmnd.append('--create-namespace') + if not repo is None: + cmnd.extend(['--repo', repo]) + if not file is None: + cmnd.extend(['--values', file]) + if not version is None: + cmnd.extend(['--version', version]) + if not namespace is None: + cmnd.extend(['--namespace', namespace]) + if wait: + cmnd.append('--wait') + if not timeout is None: + cmnd.extend(['--timeout', timeout]) + cmnd.extend(['--kubeconfig', kubeconfig]) + + maxAttempts = 3 + retry = maxAttempts + while retry > 0: + try: + output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir) + logger.info(output) + return + except subprocess.CalledProcessError as exc: + output = exc.output + if b'Broken pipe' in output: + retry = retry - 1 + logger.info("Broken pipe, retries left: %s" % retry) + else: + raise Exception(output) + raise Exception(f'Operation failed after {maxAttempts} attempts: {output}') diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/index.py b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/index.py rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/patch/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/patch/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip index a0efa36e0518a..9bf8ba72b34ab 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip and b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/aws-cdk-eks-fargate-cluster-test.assets.json b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/aws-cdk-eks-fargate-cluster-test.assets.json index 93e52d0689d1e..b82f69d938a97 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/aws-cdk-eks-fargate-cluster-test.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/aws-cdk-eks-fargate-cluster-test.assets.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "files": { "c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064": { "source": { @@ -27,41 +27,41 @@ } } }, - "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517": { + "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee": { "source": { - "path": "asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517", + "path": "asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip", + "objectKey": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037": { + "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585": { "source": { - "path": "asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037", + "path": "asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip", + "objectKey": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33": { + "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8": { "source": { - "path": "asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33", + "path": "asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33.zip", + "objectKey": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -79,7 +79,7 @@ } } }, - "fc71d3f52bbfd7601c262c027d9b9a1dad423a29a0113574840703d2dec76aec": { + "4d43e74130fa986d0dccce8d2b755a1bb2195fe9bf5e8a5531ad69bbb97acaa5": { "source": { "path": "awscdkeksfargateclustertestawscdkawseksClusterResourceProviderB8887E20.nested.template.json", "packaging": "file" @@ -87,12 +87,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "fc71d3f52bbfd7601c262c027d9b9a1dad423a29a0113574840703d2dec76aec.json", + "objectKey": "4d43e74130fa986d0dccce8d2b755a1bb2195fe9bf5e8a5531ad69bbb97acaa5.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "47ef31ad4e6f7cee2b0651e66eaa0896ec32f1fbbfca379fcea6afc0723d9325": { + "eb2424de0291785175d9304f682a14024fef1cdabfc3246c96a6fcdebcc69500": { "source": { "path": "awscdkeksfargateclustertestawscdkawseksKubectlProviderB383571D.nested.template.json", "packaging": "file" @@ -100,12 +100,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "47ef31ad4e6f7cee2b0651e66eaa0896ec32f1fbbfca379fcea6afc0723d9325.json", + "objectKey": "eb2424de0291785175d9304f682a14024fef1cdabfc3246c96a6fcdebcc69500.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "9f01c63a68719a7917d90c32f619415229f7cbaca2a55ae8ff985e37f653fdc1": { + "bcf75f6fbd774fe312af7535b5f3d78609738a015df48e8cbfb4572802108f13": { "source": { "path": "aws-cdk-eks-fargate-cluster-test.template.json", "packaging": "file" @@ -113,7 +113,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "9f01c63a68719a7917d90c32f619415229f7cbaca2a55ae8ff985e37f653fdc1.json", + "objectKey": "bcf75f6fbd774fe312af7535b5f3d78609738a015df48e8cbfb4572802108f13.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/aws-cdk-eks-fargate-cluster-test.template.json b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/aws-cdk-eks-fargate-cluster-test.template.json index 0410cc141806d..0a3262e1baea9 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/aws-cdk-eks-fargate-cluster-test.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/aws-cdk-eks-fargate-cluster-test.template.json @@ -955,7 +955,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/fc71d3f52bbfd7601c262c027d9b9a1dad423a29a0113574840703d2dec76aec.json" + "/4d43e74130fa986d0dccce8d2b755a1bb2195fe9bf5e8a5531ad69bbb97acaa5.json" ] ] }, @@ -990,7 +990,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/47ef31ad4e6f7cee2b0651e66eaa0896ec32f1fbbfca379fcea6afc0723d9325.json" + "/eb2424de0291785175d9304f682a14024fef1cdabfc3246c96a6fcdebcc69500.json" ] ] }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/awscdkeksfargateclusterDefaultTestDeployAssert7DCC5E4C.assets.json b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/awscdkeksfargateclusterDefaultTestDeployAssert7DCC5E4C.assets.json index 51ebbd84cea21..430c3c299b42c 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/awscdkeksfargateclusterDefaultTestDeployAssert7DCC5E4C.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/awscdkeksfargateclusterDefaultTestDeployAssert7DCC5E4C.assets.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/awscdkeksfargateclustertestawscdkawseksClusterResourceProviderB8887E20.nested.template.json b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/awscdkeksfargateclustertestawscdkawseksClusterResourceProviderB8887E20.nested.template.json index 7342c5874547f..fe85dcb4f6e7b 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/awscdkeksfargateclustertestawscdkawseksClusterResourceProviderB8887E20.nested.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/awscdkeksfargateclustertestawscdkawseksClusterResourceProviderB8887E20.nested.template.json @@ -73,7 +73,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ @@ -162,7 +162,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ @@ -297,7 +297,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ @@ -434,7 +434,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ @@ -568,7 +568,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/awscdkeksfargateclustertestawscdkawseksKubectlProviderB383571D.nested.template.json b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/awscdkeksfargateclustertestawscdkawseksKubectlProviderB383571D.nested.template.json index 6e77724b99300..6ac42c273fb7d 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/awscdkeksfargateclustertestawscdkawseksKubectlProviderB383571D.nested.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/awscdkeksfargateclustertestawscdkawseksKubectlProviderB383571D.nested.template.json @@ -51,6 +51,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -92,7 +104,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33.zip" + "S3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "Role": { "Fn::GetAtt": [ @@ -238,7 +250,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/cdk.out b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/cdk.out index 8ecc185e9dbee..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"21.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/integ.json b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/integ.json index 18e56a84bcf2b..3e6fa6d1ded11 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "testCases": { "aws-cdk-eks-fargate-cluster/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/manifest.json b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/manifest.json index 72cdaccd7c7b6..8263237c819fe 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "artifacts": { "aws-cdk-eks-fargate-cluster-test.assets": { "type": "cdk:asset-manifest", @@ -17,7 +17,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/9f01c63a68719a7917d90c32f619415229f7cbaca2a55ae8ff985e37f653fdc1.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/bcf75f6fbd774fe312af7535b5f3d78609738a015df48e8cbfb4572802108f13.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -36,10 +36,7 @@ "/aws-cdk-eks-fargate-cluster-test/KubectlLayer/Resource": [ { "type": "aws:cdk:logicalId", - "data": "KubectlLayer600207B5", - "trace": [ - "!!DESTRUCTIVE_CHANGES: WILL_REPLACE" - ] + "data": "KubectlLayer600207B5" } ], "/aws-cdk-eks-fargate-cluster-test/FargateCluster/DefaultVpc/Resource": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/tree.json b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/tree.json index b1ce4199b8fc5..3f268f54211b2 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/tree.json @@ -62,7 +62,7 @@ }, "constructInfo": { "fqn": "@aws-cdk/lambda-layer-kubectl-v24.KubectlV24Layer", - "version": "2.0.27" + "version": "2.0.100" } }, "FargateCluster": { @@ -1025,7 +1025,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "KubectlReadyBarrier": { @@ -1473,7 +1473,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -1646,7 +1646,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -1869,7 +1869,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -2090,7 +2090,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -2308,7 +2308,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -2487,7 +2487,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } } }, @@ -2544,7 +2544,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/fc71d3f52bbfd7601c262c027d9b9a1dad423a29a0113574840703d2dec76aec.json" + "/4d43e74130fa986d0dccce8d2b755a1bb2195fe9bf5e8a5531ad69bbb97acaa5.json" ] ] }, @@ -2566,7 +2566,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "@aws-cdk--aws-eks.KubectlProvider": { @@ -2643,6 +2643,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -2742,7 +2754,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33.zip" + "s3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "role": { "Fn::GetAtt": [ @@ -3020,7 +3032,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -3164,7 +3176,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/47ef31ad4e6f7cee2b0651e66eaa0896ec32f1fbbfca379fcea6afc0723d9325.json" + "/eb2424de0291785175d9304f682a14024fef1cdabfc3246c96a6fcdebcc69500.json" ] ] }, @@ -3207,7 +3219,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "BootstrapVersion": { @@ -3245,7 +3257,7 @@ "path": "aws-cdk-eks-fargate-cluster/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "DeployAssert": { @@ -3291,7 +3303,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } } }, diff --git a/packages/@aws-cdk/aws-redshift/test/cluster-reboot.integ.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js b/packages/@aws-cdk/aws-redshift/test/cluster-reboot.integ.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js deleted file mode 100644 index 70203dcc42f3f..0000000000000 --- a/packages/@aws-cdk/aws-redshift/test/cluster-reboot.integ.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js +++ /dev/null @@ -1,45 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.httpRequest = exports.invokeFunction = exports.startExecution = void 0; -/* istanbul ignore file */ -const https = require("https"); -// eslint-disable-next-line import/no-extraneous-dependencies -const AWS = require("aws-sdk"); -const FRAMEWORK_HANDLER_TIMEOUT = 900000; // 15 minutes -// In order to honor the overall maximum timeout set for the target process, -// the default 2 minutes from AWS SDK has to be overriden: -// https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html#httpOptions-property -const 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; -let lambda; -async function defaultStartExecution(req) { - if (!sfn) { - sfn = new AWS.StepFunctions(awsSdkConfig); - } - return sfn.startExecution(req).promise(); -} -async function defaultInvokeFunction(req) { - if (!lambda) { - lambda = new AWS.Lambda(awsSdkConfig); - } - return lambda.invoke(req).promise(); -} -exports.startExecution = defaultStartExecution; -exports.invokeFunction = defaultInvokeFunction; -exports.httpRequest = defaultHttpRequest; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3V0Ym91bmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJvdXRib3VuZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwwQkFBMEI7QUFDMUIsK0JBQStCO0FBQy9CLDZEQUE2RDtBQUM3RCwrQkFBK0I7QUFJL0IsTUFBTSx5QkFBeUIsR0FBRyxNQUFNLENBQUMsQ0FBQyxhQUFhO0FBRXZELDRFQUE0RTtBQUM1RSwwREFBMEQ7QUFDMUQsMkZBQTJGO0FBQzNGLE1BQU0sWUFBWSxHQUF5QjtJQUN6QyxXQUFXLEVBQUUsRUFBRSxPQUFPLEVBQUUseUJBQXlCLEVBQUU7Q0FDcEQsQ0FBQztBQUVGLEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxPQUE2QixFQUFFLFlBQW9CO0lBQ25GLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDckMsSUFBSTtZQUNGLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ2hELE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDNUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1NBQ2Y7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNYO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsSUFBSSxHQUFzQixDQUFDO0FBQzNCLElBQUksTUFBa0IsQ0FBQztBQUV2QixLQUFLLFVBQVUscUJBQXFCLENBQUMsR0FBMEM7SUFDN0UsSUFBSSxDQUFDLEdBQUcsRUFBRTtRQUNSLEdBQUcsR0FBRyxJQUFJLEdBQUcsQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUM7S0FDM0M7SUFFRCxPQUFPLEdBQUcsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7QUFDM0MsQ0FBQztBQUVELEtBQUssVUFBVSxxQkFBcUIsQ0FBQyxHQUFpQztJQUNwRSxJQUFJLENBQUMsTUFBTSxFQUFFO1FBQ1gsTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztLQUN2QztJQUVELE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztBQUN0QyxDQUFDO0FBRVUsUUFBQSxjQUFjLEdBQUcscUJBQXFCLENBQUM7QUFDdkMsUUFBQSxjQUFjLEdBQUcscUJBQXFCLENBQUM7QUFDdkMsUUFBQSxXQUFXLEdBQUcsa0JBQWtCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBpc3RhbmJ1bCBpZ25vcmUgZmlsZSAqL1xuaW1wb3J0ICogYXMgaHR0cHMgZnJvbSAnaHR0cHMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgQVdTIGZyb20gJ2F3cy1zZGsnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHR5cGUgeyBDb25maWd1cmF0aW9uT3B0aW9ucyB9IGZyb20gJ2F3cy1zZGsvbGliL2NvbmZpZy1iYXNlJztcblxuY29uc3QgRlJBTUVXT1JLX0hBTkRMRVJfVElNRU9VVCA9IDkwMDAwMDsgLy8gMTUgbWludXRlc1xuXG4vLyBJbiBvcmRlciB0byBob25vciB0aGUgb3ZlcmFsbCBtYXhpbXVtIHRpbWVvdXQgc2V0IGZvciB0aGUgdGFyZ2V0IHByb2Nlc3MsXG4vLyB0aGUgZGVmYXVsdCAyIG1pbnV0ZXMgZnJvbSBBV1MgU0RLIGhhcyB0byBiZSBvdmVycmlkZW46XG4vLyBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTSmF2YVNjcmlwdFNESy9sYXRlc3QvQVdTL0NvbmZpZy5odG1sI2h0dHBPcHRpb25zLXByb3BlcnR5XG5jb25zdCBhd3NTZGtDb25maWc6IENvbmZpZ3VyYXRpb25PcHRpb25zID0ge1xuICBodHRwT3B0aW9uczogeyB0aW1lb3V0OiBGUkFNRVdPUktfSEFORExFUl9USU1FT1VUIH0sXG59O1xuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0SHR0cFJlcXVlc3Qob3B0aW9uczogaHR0cHMuUmVxdWVzdE9wdGlvbnMsIHJlc3BvbnNlQm9keTogc3RyaW5nKSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlcXVlc3QgPSBodHRwcy5yZXF1ZXN0KG9wdGlvbnMsIHJlc29sdmUpO1xuICAgICAgcmVxdWVzdC5vbignZXJyb3InLCByZWplY3QpO1xuICAgICAgcmVxdWVzdC53cml0ZShyZXNwb25zZUJvZHkpO1xuICAgICAgcmVxdWVzdC5lbmQoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZWplY3QoZSk7XG4gICAgfVxuICB9KTtcbn1cblxubGV0IHNmbjogQVdTLlN0ZXBGdW5jdGlvbnM7XG5sZXQgbGFtYmRhOiBBV1MuTGFtYmRhO1xuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0U3RhcnRFeGVjdXRpb24ocmVxOiBBV1MuU3RlcEZ1bmN0aW9ucy5TdGFydEV4ZWN1dGlvbklucHV0KTogUHJvbWlzZTxBV1MuU3RlcEZ1bmN0aW9ucy5TdGFydEV4ZWN1dGlvbk91dHB1dD4ge1xuICBpZiAoIXNmbikge1xuICAgIHNmbiA9IG5ldyBBV1MuU3RlcEZ1bmN0aW9ucyhhd3NTZGtDb25maWcpO1xuICB9XG5cbiAgcmV0dXJuIHNmbi5zdGFydEV4ZWN1dGlvbihyZXEpLnByb21pc2UoKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdEludm9rZUZ1bmN0aW9uKHJlcTogQVdTLkxhbWJkYS5JbnZvY2F0aW9uUmVxdWVzdCk6IFByb21pc2U8QVdTLkxhbWJkYS5JbnZvY2F0aW9uUmVzcG9uc2U+IHtcbiAgaWYgKCFsYW1iZGEpIHtcbiAgICBsYW1iZGEgPSBuZXcgQVdTLkxhbWJkYShhd3NTZGtDb25maWcpO1xuICB9XG5cbiAgcmV0dXJuIGxhbWJkYS5pbnZva2UocmVxKS5wcm9taXNlKCk7XG59XG5cbmV4cG9ydCBsZXQgc3RhcnRFeGVjdXRpb24gPSBkZWZhdWx0U3RhcnRFeGVjdXRpb247XG5leHBvcnQgbGV0IGludm9rZUZ1bmN0aW9uID0gZGVmYXVsdEludm9rZUZ1bmN0aW9uO1xuZXhwb3J0IGxldCBodHRwUmVxdWVzdCA9IGRlZmF1bHRIdHRwUmVxdWVzdDtcbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.d.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.d.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js new file mode 100644 index 0000000000000..c9dc1b8d2c19a --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js @@ -0,0 +1,273 @@ +"use strict"; +/* eslint-disable no-console */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ClusterResourceHandler = void 0; +const common_1 = require("./common"); +const MAX_CLUSTER_NAME_LEN = 100; +class ClusterResourceHandler extends common_1.ResourceHandler { + constructor(eks, event) { + super(eks, event); + this.newProps = parseProps(this.event.ResourceProperties); + this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; + } + get clusterName() { + if (!this.physicalResourceId) { + throw new Error('Cannot determine cluster name without physical resource ID'); + } + return this.physicalResourceId; + } + // ------ + // CREATE + // ------ + async onCreate() { + console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); + if (!this.newProps.roleArn) { + throw new Error('"roleArn" is required'); + } + const clusterName = this.newProps.name || this.generateClusterName(); + const resp = await this.eks.createCluster({ + ...this.newProps, + name: clusterName, + }); + if (!resp.cluster) { + throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); + } + return { + PhysicalResourceId: resp.cluster.name, + }; + } + async isCreateComplete() { + return this.isActive(); + } + // ------ + // DELETE + // ------ + async onDelete() { + console.log(`onDelete: deleting cluster ${this.clusterName}`); + try { + await this.eks.deleteCluster({ name: this.clusterName }); + } + catch (e) { + if (e.code !== 'ResourceNotFoundException') { + throw e; + } + else { + console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); + } + } + return { + PhysicalResourceId: this.clusterName, + }; + } + async isDeleteComplete() { + console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); + try { + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); + } + catch (e) { + if (e.code === 'ResourceNotFoundException') { + console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); + return { IsComplete: true }; + } + console.log('describeCluster error:', e); + throw e; + } + return { + IsComplete: false, + }; + } + // ------ + // UPDATE + // ------ + async onUpdate() { + const updates = analyzeUpdate(this.oldProps, this.newProps); + console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); + // updates to encryption config is not supported + if (updates.updateEncryption) { + throw new Error('Cannot update cluster encryption configuration'); + } + // if there is an update that requires replacement, go ahead and just create + // a new cluster with the new config. The old cluster will automatically be + // deleted by cloudformation upon success. + if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { + // if we are replacing this cluster and the cluster has an explicit + // physical name, the creation of the new cluster will fail with "there is + // already a cluster with that name". this is a common behavior for + // CloudFormation resources that support specifying a physical name. + if (this.oldProps.name === this.newProps.name && this.oldProps.name) { + throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); + } + return this.onCreate(); + } + // if a version update is required, issue the version update + if (updates.updateVersion) { + if (!this.newProps.version) { + throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); + } + return this.updateClusterVersion(this.newProps.version); + } + if (updates.updateLogging && updates.updateAccess) { + throw new Error('Cannot update logging and access at the same time'); + } + if (updates.updateLogging || updates.updateAccess) { + const config = { + name: this.clusterName, + }; + if (updates.updateLogging) { + config.logging = this.newProps.logging; + } + ; + if (updates.updateAccess) { + // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: + // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) + // will fail, therefore we take only the access fields explicitly + config.resourcesVpcConfig = { + endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, + endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, + publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, + }; + } + const updateResponse = await this.eks.updateClusterConfig(config); + return { EksUpdateId: updateResponse.update?.id }; + } + // no updates + return; + } + async isUpdateComplete() { + console.log('isUpdateComplete'); + // if this is an EKS update, we will monitor the update event itself + if (this.event.EksUpdateId) { + const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); + if (!complete) { + return { IsComplete: false }; + } + // fall through: if the update is done, we simply delegate to isActive() + // in order to extract attributes and state from the cluster itself, which + // is supposed to be in an ACTIVE state after the update is complete. + } + return this.isActive(); + } + async updateClusterVersion(newVersion) { + console.log(`updating cluster version to ${newVersion}`); + // update-cluster-version will fail if we try to update to the same version, + // so skip in this case. + const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; + if (cluster?.version === newVersion) { + console.log(`cluster already at version ${cluster.version}, skipping version update`); + return; + } + const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); + return { EksUpdateId: updateResponse.update?.id }; + } + async isActive() { + console.log('waiting for cluster to become ACTIVE'); + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); + const cluster = resp.cluster; + // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are + // not complete. note that the custom resource provider framework forbids + // returning attributes (Data) if isComplete is false. + if (cluster?.status === 'FAILED') { + // not very informative, unfortunately the response doesn't contain any error + // information :\ + throw new Error('Cluster is in a FAILED status'); + } + else if (cluster?.status !== 'ACTIVE') { + return { + IsComplete: false, + }; + } + else { + return { + IsComplete: true, + Data: { + Name: cluster.name, + Endpoint: cluster.endpoint, + Arn: cluster.arn, + // IMPORTANT: CFN expects that attributes will *always* have values, + // so return an empty string in case the value is not defined. + // Otherwise, CFN will throw with `Vendor response doesn't contain + // XXXX key`. + CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', + ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', + OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', + OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', + // We can safely return the first item from encryption configuration array, because it has a limit of 1 item + // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig + EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', + }, + }; + } + } + async isEksUpdateComplete(eksUpdateId) { + this.log({ isEksUpdateComplete: eksUpdateId }); + const describeUpdateResponse = await this.eks.describeUpdate({ + name: this.clusterName, + updateId: eksUpdateId, + }); + this.log({ describeUpdateResponse }); + if (!describeUpdateResponse.update) { + throw new Error(`unable to describe update with id "${eksUpdateId}"`); + } + switch (describeUpdateResponse.update.status) { + case 'InProgress': + return false; + case 'Successful': + return true; + case 'Failed': + case 'Cancelled': + throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); + default: + throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); + } + } + generateClusterName() { + const suffix = this.requestId.replace(/-/g, ''); // 32 chars + const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; + const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); + return `${prefix}-${suffix}`; + } +} +exports.ClusterResourceHandler = ClusterResourceHandler; +function parseProps(props) { + const parsed = props?.Config ?? {}; + // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. + // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' + if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; + } + if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; + } + if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { + parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; + } + return parsed; +} +function analyzeUpdate(oldProps, newProps) { + console.log('old props: ', JSON.stringify(oldProps)); + console.log('new props: ', JSON.stringify(newProps)); + const newVpcProps = newProps.resourcesVpcConfig || {}; + const oldVpcProps = oldProps.resourcesVpcConfig || {}; + const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); + const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); + const newEnc = newProps.encryptionConfig || {}; + const oldEnc = oldProps.encryptionConfig || {}; + return { + replaceName: newProps.name !== oldProps.name, + replaceVpc: JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), + updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || + newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || + !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), + replaceRole: newProps.roleArn !== oldProps.roleArn, + updateVersion: newProps.version !== oldProps.version, + updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), + updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), + }; +} +function setsEqual(first, second) { + return first.size === second.size && [...first].every((e) => second.has(e)); +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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LENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztRQUNuRSxhQUFhLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBa0IsRUFBRSxNQUFtQjtJQUN4RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgRWtzQ2xpZW50LCBSZXNvdXJjZUV2ZW50LCBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX05BTUVfTEVOID0gMTAwO1xuXG5leHBvcnQgY2xhc3MgQ2x1c3RlclJlc291cmNlSGFuZGxlciBleHRlbmRzIFJlc291cmNlSGFuZGxlciB7XG4gIHB1YmxpYyBnZXQgY2x1c3Rlck5hbWUoKSB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZGV0ZXJtaW5lIGNsdXN0ZXIgbmFtZSB3aXRob3V0IHBoeXNpY2FsIHJlc291cmNlIElEJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PjtcblxuICBjb25zdHJ1Y3Rvcihla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICBzdXBlcihla3MsIGV2ZW50KTtcblxuICAgIHRoaXMubmV3UHJvcHMgPSBwYXJzZVByb3BzKHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLm9sZFByb3BzID0gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnID8gcGFyc2VQcm9wcyhldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMpIDoge307XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gQ1JFQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCdvbkNyZWF0ZTogY3JlYXRpbmcgY2x1c3RlciB3aXRoIG9wdGlvbnM6JywgSlNPTi5zdHJpbmdpZnkodGhpcy5uZXdQcm9wcywgdW5kZWZpbmVkLCAyKSk7XG4gICAgaWYgKCF0aGlzLm5ld1Byb3BzLnJvbGVBcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJyb2xlQXJuXCIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyTmFtZSA9IHRoaXMubmV3UHJvcHMubmFtZSB8fCB0aGlzLmdlbmVyYXRlQ2x1c3Rlck5hbWUoKTtcblxuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmVrcy5jcmVhdGVDbHVzdGVyKHtcbiAgICAgIC4uLnRoaXMubmV3UHJvcHMsXG4gICAgICBuYW1lOiBjbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcC5jbHVzdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBjbHVzdGVyICR7Y2x1c3Rlck5hbWV9OiBDcmVhdGVDbHVzdGVyIHJldHVybmVkIHdpdGhvdXQgY2x1c3RlciBpbmZvcm1hdGlvbmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHJlc3AuY2x1c3Rlci5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIERFTEVURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25EZWxldGUoKTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgb25EZWxldGU6IGRlbGV0aW5nIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfWApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVrcy5kZWxldGVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyICR7dGhpcy5jbHVzdGVyTmFtZX0gbm90IGZvdW5kLCBpZGVtcG90ZW50bHkgc3VjY2VlZGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coYGlzRGVsZXRlQ29tcGxldGU6IHdhaXRpbmcgZm9yIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSB0byBiZSBkZWxldGVkYCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJldHVybmVkOicsIEpTT04uc3RyaW5naWZ5KHJlc3AsIHVuZGVmaW5lZCwgMikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICBjb25zb2xlLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgY2x1c3RlciBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0cnVlIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgZXJyb3I6JywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIFVQREFURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IGFuYWx5emVVcGRhdGUodGhpcy5vbGRQcm9wcywgdGhpcy5uZXdQcm9wcyk7XG4gICAgY29uc29sZS5sb2coJ29uVXBkYXRlOicsIEpTT04uc3RyaW5naWZ5KHsgdXBkYXRlcyB9LCB1bmRlZmluZWQsIDIpKTtcblxuICAgIC8vIHVwZGF0ZXMgdG8gZW5jcnlwdGlvbiBjb25maWcgaXMgbm90IHN1cHBvcnRlZFxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUVuY3J5cHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHVwZGF0ZSBjbHVzdGVyIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZXJlIGlzIGFuIHVwZGF0ZSB0aGF0IHJlcXVpcmVzIHJlcGxhY2VtZW50LCBnbyBhaGVhZCBhbmQganVzdCBjcmVhdGVcbiAgICAvLyBhIG5ldyBjbHVzdGVyIHdpdGggdGhlIG5ldyBjb25maWcuIFRoZSBvbGQgY2x1c3RlciB3aWxsIGF1dG9tYXRpY2FsbHkgYmVcbiAgICAvLyBkZWxldGVkIGJ5IGNsb3VkZm9ybWF0aW9uIHVwb24gc3VjY2Vzcy5cbiAgICBpZiAodXBkYXRlcy5yZXBsYWNlTmFtZSB8fCB1cGRhdGVzLnJlcGxhY2VSb2xlIHx8IHVwZGF0ZXMucmVwbGFjZVZwYykge1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgcmVwbGFjaW5nIHRoaXMgY2x1c3RlciBhbmQgdGhlIGNsdXN0ZXIgaGFzIGFuIGV4cGxpY2l0XG4gICAgICAvLyBwaHlzaWNhbCBuYW1lLCB0aGUgY3JlYXRpb24gb2YgdGhlIG5ldyBjbHVzdGVyIHdpbGwgZmFpbCB3aXRoIFwidGhlcmUgaXNcbiAgICAgIC8vIGFscmVhZHkgYSBjbHVzdGVyIHdpdGggdGhhdCBuYW1lXCIuIHRoaXMgaXMgYSBjb21tb24gYmVoYXZpb3IgZm9yXG4gICAgICAvLyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZXMgdGhhdCBzdXBwb3J0IHNwZWNpZnlpbmcgYSBwaHlzaWNhbCBuYW1lLlxuICAgICAgaWYgKHRoaXMub2xkUHJvcHMubmFtZSA9PT0gdGhpcy5uZXdQcm9wcy5uYW1lICYmIHRoaXMub2xkUHJvcHMubmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXBsYWNlIGNsdXN0ZXIgXCIke3RoaXMub2xkUHJvcHMubmFtZX1cIiBzaW5jZSBpdCBoYXMgYW4gZXhwbGljaXQgcGh5c2ljYWwgbmFtZS4gRWl0aGVyIHJlbmFtZSB0aGUgY2x1c3RlciBvciByZW1vdmUgdGhlIFwibmFtZVwiIGNvbmZpZ3VyYXRpb25gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub25DcmVhdGUoKTtcbiAgICB9XG5cbiAgICAvLyBpZiBhIHZlcnNpb24gdXBkYXRlIGlzIHJlcXVpcmVkLCBpc3N1ZSB0aGUgdmVyc2lvbiB1cGRhdGVcbiAgICBpZiAodXBkYXRlcy51cGRhdGVWZXJzaW9uKSB7XG4gICAgICBpZiAoIXRoaXMubmV3UHJvcHMudmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZW1vdmUgY2x1c3RlciB2ZXJzaW9uIGNvbmZpZ3VyYXRpb24uIEN1cnJlbnQgdmVyc2lvbiBpcyAke3RoaXMub2xkUHJvcHMudmVyc2lvbn1gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlQ2x1c3RlclZlcnNpb24odGhpcy5uZXdQcm9wcy52ZXJzaW9uKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nICYmIHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1cGRhdGUgbG9nZ2luZyBhbmQgYWNjZXNzIGF0IHRoZSBzYW1lIHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nIHx8IHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICBjb25zdCBjb25maWc6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QgPSB7XG4gICAgICAgIG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgICB9O1xuICAgICAgaWYgKHVwZGF0ZXMudXBkYXRlTG9nZ2luZykge1xuICAgICAgICBjb25maWcubG9nZ2luZyA9IHRoaXMubmV3UHJvcHMubG9nZ2luZztcbiAgICAgIH07XG4gICAgICBpZiAodXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIGNsdXN0ZXIgd2l0aCBzZWN1cml0eUdyb3VwSWRzIGFuZCBzdWJuZXRJZHMgKGFzIHNwZWNpZmllZCBpbiB0aGUgd2FybmluZyBoZXJlOlxuICAgICAgICAvLyBodHRwczovL2F3c2NsaS5hbWF6b25hd3MuY29tL3YyL2RvY3VtZW50YXRpb24vYXBpL2xhdGVzdC9yZWZlcmVuY2UvZWtzL3VwZGF0ZS1jbHVzdGVyLWNvbmZpZy5odG1sKVxuICAgICAgICAvLyB3aWxsIGZhaWwsIHRoZXJlZm9yZSB3ZSB0YWtlIG9ubHkgdGhlIGFjY2VzcyBmaWVsZHMgZXhwbGljaXRseVxuICAgICAgICBjb25maWcucmVzb3VyY2VzVnBjQ29uZmlnID0ge1xuICAgICAgICAgIGVuZHBvaW50UHJpdmF0ZUFjY2VzczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzLFxuICAgICAgICAgIGVuZHBvaW50UHVibGljQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyxcbiAgICAgICAgICBwdWJsaWNBY2Nlc3NDaWRyczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcucHVibGljQWNjZXNzQ2lkcnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgICB9XG5cbiAgICAvLyBubyB1cGRhdGVzXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc29sZS5sb2coJ2lzVXBkYXRlQ29tcGxldGUnKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYW4gRUtTIHVwZGF0ZSwgd2Ugd2lsbCBtb25pdG9yIHRoZSB1cGRhdGUgZXZlbnQgaXRzZWxmXG4gICAgaWYgKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gYXdhaXQgdGhpcy5pc0Vrc1VwZGF0ZUNvbXBsZXRlKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpO1xuICAgICAgaWYgKCFjb21wbGV0ZSkge1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiBmYWxzZSB9O1xuICAgICAgfVxuXG4gICAgICAvLyBmYWxsIHRocm91Z2g6IGlmIHRoZSB1cGRhdGUgaXMgZG9uZSwgd2Ugc2ltcGx5IGRlbGVnYXRlIHRvIGlzQWN0aXZlKClcbiAgICAgIC8vIGluIG9yZGVyIHRvIGV4dHJhY3QgYXR0cmlidXRlcyBhbmQgc3RhdGUgZnJvbSB0aGUgY2x1c3RlciBpdHNlbGYsIHdoaWNoXG4gICAgICAvLyBpcyBzdXBwb3NlZCB0byBiZSBpbiBhbiBBQ1RJVkUgc3RhdGUgYWZ0ZXIgdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbHVzdGVyVmVyc2lvbihuZXdWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgdXBkYXRpbmcgY2x1c3RlciB2ZXJzaW9uIHRvICR7bmV3VmVyc2lvbn1gKTtcblxuICAgIC8vIHVwZGF0ZS1jbHVzdGVyLXZlcnNpb24gd2lsbCBmYWlsIGlmIHdlIHRyeSB0byB1cGRhdGUgdG8gdGhlIHNhbWUgdmVyc2lvbixcbiAgICAvLyBzbyBza2lwIGluIHRoaXMgY2FzZS5cbiAgICBjb25zdCBjbHVzdGVyID0gKGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSkpLmNsdXN0ZXI7XG4gICAgaWYgKGNsdXN0ZXI/LnZlcnNpb24gPT09IG5ld1ZlcnNpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyIGFscmVhZHkgYXQgdmVyc2lvbiAke2NsdXN0ZXIudmVyc2lvbn0sIHNraXBwaW5nIHZlcnNpb24gdXBkYXRlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy51cGRhdGVDbHVzdGVyVmVyc2lvbih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsIHZlcnNpb246IG5ld1ZlcnNpb24gfSk7XG4gICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNBY3RpdmUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZygnd2FpdGluZyBmb3IgY2x1c3RlciB0byBiZWNvbWUgQUNUSVZFJyk7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciByZXN1bHQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgY29uc3QgY2x1c3RlciA9IHJlc3AuY2x1c3RlcjtcblxuICAgIC8vIGlmIGNsdXN0ZXIgaXMgdW5kZWZpbmVkIChzaG91bGRudCBoYXBwZW4pIG9yIHN0YXR1cyBpcyBub3QgQUNUSVZFLCB3ZSBhcmVcbiAgICAvLyBub3QgY29tcGxldGUuIG5vdGUgdGhhdCB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZyYW1ld29yayBmb3JiaWRzXG4gICAgLy8gcmV0dXJuaW5nIGF0dHJpYnV0ZXMgKERhdGEpIGlmIGlzQ29tcGxldGUgaXMgZmFsc2UuXG4gICAgaWYgKGNsdXN0ZXI/LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgIC8vIG5vdCB2ZXJ5IGluZm9ybWF0aXZlLCB1bmZvcnR1bmF0ZWx5IHRoZSByZXNwb25zZSBkb2Vzbid0IGNvbnRhaW4gYW55IGVycm9yXG4gICAgICAvLyBpbmZvcm1hdGlvbiA6XFxcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2x1c3RlciBpcyBpbiBhIEZBSUxFRCBzdGF0dXMnKTtcbiAgICB9IGVsc2UgaWYgKGNsdXN0ZXI/LnN0YXR1cyAhPT0gJ0FDVElWRScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIE5hbWU6IGNsdXN0ZXIubmFtZSxcbiAgICAgICAgICBFbmRwb2ludDogY2x1c3Rlci5lbmRwb2ludCxcbiAgICAgICAgICBBcm46IGNsdXN0ZXIuYXJuLFxuXG4gICAgICAgICAgLy8gSU1QT1JUQU5UOiBDRk4gZXhwZWN0cyB0aGF0IGF0dHJpYnV0ZXMgd2lsbCAqYWx3YXlzKiBoYXZlIHZhbHVlcyxcbiAgICAgICAgICAvLyBzbyByZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGluIGNhc2UgdGhlIHZhbHVlIGlzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQ0ZOIHdpbGwgdGhyb3cgd2l0aCBgVmVuZG9yIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpblxuICAgICAgICAgIC8vIFhYWFgga2V5YC5cblxuICAgICAgICAgIENlcnRpZmljYXRlQXV0aG9yaXR5RGF0YTogY2x1c3Rlci5jZXJ0aWZpY2F0ZUF1dGhvcml0eT8uZGF0YSA/PyAnJyxcbiAgICAgICAgICBDbHVzdGVyU2VjdXJpdHlHcm91cElkOiBjbHVzdGVyLnJlc291cmNlc1ZwY0NvbmZpZz8uY2x1c3RlclNlY3VyaXR5R3JvdXBJZCA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyVXJsOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXIgPz8gJycsXG4gICAgICAgICAgT3BlbklkQ29ubmVjdElzc3VlcjogY2x1c3Rlci5pZGVudGl0eT8ub2lkYz8uaXNzdWVyPy5zdWJzdHJpbmcoOCkgPz8gJycsIC8vIFN0cmlwcyBvZmYgaHR0cHM6Ly8gZnJvbSB0aGUgaXNzdWVyIHVybFxuXG4gICAgICAgICAgLy8gV2UgY2FuIHNhZmVseSByZXR1cm4gdGhlIGZpcnN0IGl0ZW0gZnJvbSBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gYXJyYXksIGJlY2F1c2UgaXQgaGFzIGEgbGltaXQgb2YgMSBpdGVtXG4gICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vrcy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDbHVzdGVyLmh0bWwjQW1hem9uRUtTLUNyZWF0ZUNsdXN0ZXItcmVxdWVzdC1lbmNyeXB0aW9uQ29uZmlnXG4gICAgICAgICAgRW5jcnlwdGlvbkNvbmZpZ0tleUFybjogY2x1c3Rlci5lbmNyeXB0aW9uQ29uZmlnPy5zaGlmdCgpPy5wcm92aWRlcj8ua2V5QXJuID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzRWtzVXBkYXRlQ29tcGxldGUoZWtzVXBkYXRlSWQ6IHN0cmluZykge1xuICAgIHRoaXMubG9nKHsgaXNFa3NVcGRhdGVDb21wbGV0ZTogZWtzVXBkYXRlSWQgfSk7XG5cbiAgICBjb25zdCBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVVcGRhdGUoe1xuICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgIHVwZGF0ZUlkOiBla3NVcGRhdGVJZCxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nKHsgZGVzY3JpYmVVcGRhdGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5hYmxlIHRvIGRlc2NyaWJlIHVwZGF0ZSB3aXRoIGlkIFwiJHtla3NVcGRhdGVJZH1cImApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzKSB7XG4gICAgICBjYXNlICdJblByb2dyZXNzJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgY2FzZSAnU3VjY2Vzc2Z1bCc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnRmFpbGVkJzpcbiAgICAgIGNhc2UgJ0NhbmNlbGxlZCc6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2x1c3RlciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiIGZhaWxlZCB3aXRoIGVycm9yczogJHtKU09OLnN0cmluZ2lmeShkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5lcnJvcnMpfWApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIHN0YXR1cyBcIiR7ZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzfVwiIGZvciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNsdXN0ZXJOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9DTFVTVEVSX05BTUVfTEVOIC0gc3VmZml4Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5sb2dpY2FsUmVzb3VyY2VJZC5zbGljZSgwLCBvZmZzZXQgPiAwID8gb2Zmc2V0IDogMCk7XG4gICAgcmV0dXJuIGAke3ByZWZpeH0tJHtzdWZmaXh9YDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3BzKHByb3BzOiBhbnkpOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0IHtcblxuICBjb25zdCBwYXJzZWQgPSBwcm9wcz8uQ29uZmlnID8/IHt9O1xuXG4gIC8vIHRoaXMgaXMgd2VpcmQgYnV0IHRoZXNlIGJvb2xlYW4gcHJvcGVydGllcyBhcmUgcGFzc2VkIGJ5IENGTiBhcyBhIHN0cmluZywgYW5kIHdlIG5lZWQgdGhlbSB0byBiZSBib29sZWFuaWMgZm9yIHRoZSBTREsuXG4gIC8vIE90aGVyd2lzZSBpdCBmYWlscyB3aXRoICdVbmV4cGVjdGVkIFBhcmFtZXRlcjogcGFyYW1zLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgaXMgZXhwZWN0ZWQgdG8gYmUgYSBib29sZWFuJ1xuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWc/LmVuZHBvaW50UHJpdmF0ZUFjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9PT0gJ3RydWUnO1xuICB9XG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQdWJsaWNBY2Nlc3MpID09PSAnc3RyaW5nJykge1xuICAgIHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQubG9nZ2luZz8uY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCkgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9IHBhcnNlZC5sb2dnaW5nLmNsdXN0ZXJMb2dnaW5nWzBdLmVuYWJsZWQgPT09ICd0cnVlJztcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQ7XG5cbn1cblxuaW50ZXJmYWNlIFVwZGF0ZU1hcCB7XG4gIHJlcGxhY2VOYW1lOiBib29sZWFuOyAvLyBuYW1lXG4gIHJlcGxhY2VWcGM6IGJvb2xlYW47IC8vIHJlc291cmNlc1ZwY0NvbmZpZy5zdWJuZXRJZHMgYW5kIHNlY3VyaXR5R3JvdXBJZHNcbiAgcmVwbGFjZVJvbGU6IGJvb2xlYW47IC8vIHJvbGVBcm5cblxuICB1cGRhdGVWZXJzaW9uOiBib29sZWFuOyAvLyB2ZXJzaW9uXG4gIHVwZGF0ZUxvZ2dpbmc6IGJvb2xlYW47IC8vIGxvZ2dpbmdcbiAgdXBkYXRlRW5jcnlwdGlvbjogYm9vbGVhbjsgLy8gZW5jcnlwdGlvbiAoY2Fubm90IGJlIHVwZGF0ZWQpXG4gIHVwZGF0ZUFjY2VzczogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBhbmQgZW5kcG9pbnRQdWJsaWNBY2Nlc3Ncbn1cblxuZnVuY3Rpb24gYW5hbHl6ZVVwZGF0ZShvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PiwgbmV3UHJvcHM6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBVcGRhdGVNYXAge1xuICBjb25zb2xlLmxvZygnb2xkIHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShvbGRQcm9wcykpO1xuICBjb25zb2xlLmxvZygnbmV3IHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShuZXdQcm9wcykpO1xuXG4gIGNvbnN0IG5ld1ZwY1Byb3BzID0gbmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRWcGNQcm9wcyA9IG9sZFByb3BzLnJlc291cmNlc1ZwY0NvbmZpZyB8fCB7fTtcblxuICBjb25zdCBvbGRQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQob2xkVnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQobmV3VnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdFbmMgPSBuZXdQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRFbmMgPSBvbGRQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgcmVwbGFjZU5hbWU6IG5ld1Byb3BzLm5hbWUgIT09IG9sZFByb3BzLm5hbWUsXG4gICAgcmVwbGFjZVZwYzpcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnN1Ym5ldElkcz8uc29ydCgpKSAhPT0gSlNPTi5zdHJpbmdpZnkob2xkVnBjUHJvcHMuc3VibmV0SWRzPy5zb3J0KCkpIHx8XG4gICAgICBKU09OLnN0cmluZ2lmeShuZXdWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpICE9PSBKU09OLnN0cmluZ2lmeShvbGRWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpLFxuICAgIHVwZGF0ZUFjY2VzczpcbiAgICAgIG5ld1ZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQcml2YXRlQWNjZXNzIHx8XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFB1YmxpY0FjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgfHxcbiAgICAgICFzZXRzRXF1YWwobmV3UHVibGljQWNjZXNzQ2lkcnMsIG9sZFB1YmxpY0FjY2Vzc0NpZHJzKSxcbiAgICByZXBsYWNlUm9sZTogbmV3UHJvcHMucm9sZUFybiAhPT0gb2xkUHJvcHMucm9sZUFybixcbiAgICB1cGRhdGVWZXJzaW9uOiBuZXdQcm9wcy52ZXJzaW9uICE9PSBvbGRQcm9wcy52ZXJzaW9uLFxuICAgIHVwZGF0ZUVuY3J5cHRpb246IEpTT04uc3RyaW5naWZ5KG5ld0VuYykgIT09IEpTT04uc3RyaW5naWZ5KG9sZEVuYyksXG4gICAgdXBkYXRlTG9nZ2luZzogSlNPTi5zdHJpbmdpZnkobmV3UHJvcHMubG9nZ2luZykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFByb3BzLmxvZ2dpbmcpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzZXRzRXF1YWwoZmlyc3Q6IFNldDxzdHJpbmc+LCBzZWNvbmQ6IFNldDxzdHJpbmc+KSB7XG4gIHJldHVybiBmaXJzdC5zaXplID09PSBzZWNvbmQuc2l6ZSAmJiBbLi4uZmlyc3RdLmV2ZXJ5KChlOiBzdHJpbmcpID0+IHNlY29uZC5oYXMoZSkpO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts new file mode 100644 index 0000000000000..4b7fdda6d1dd1 --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts @@ -0,0 +1,344 @@ +/* eslint-disable no-console */ + +// eslint-disable-next-line import/no-extraneous-dependencies +import { IsCompleteResponse, OnEventResponse } from '@aws-cdk/custom-resources/lib/provider-framework/types'; +// eslint-disable-next-line import/no-extraneous-dependencies +import * as aws from 'aws-sdk'; +import { EksClient, ResourceEvent, ResourceHandler } from './common'; + +const MAX_CLUSTER_NAME_LEN = 100; + +export class ClusterResourceHandler extends ResourceHandler { + public get clusterName() { + if (!this.physicalResourceId) { + throw new Error('Cannot determine cluster name without physical resource ID'); + } + + return this.physicalResourceId; + } + + private readonly newProps: aws.EKS.CreateClusterRequest; + private readonly oldProps: Partial; + + constructor(eks: EksClient, event: ResourceEvent) { + super(eks, event); + + this.newProps = parseProps(this.event.ResourceProperties); + this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; + } + + // ------ + // CREATE + // ------ + + protected async onCreate(): Promise { + console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); + if (!this.newProps.roleArn) { + throw new Error('"roleArn" is required'); + } + + const clusterName = this.newProps.name || this.generateClusterName(); + + const resp = await this.eks.createCluster({ + ...this.newProps, + name: clusterName, + }); + + if (!resp.cluster) { + throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); + } + + return { + PhysicalResourceId: resp.cluster.name, + }; + } + + protected async isCreateComplete() { + return this.isActive(); + } + + // ------ + // DELETE + // ------ + + protected async onDelete(): Promise { + console.log(`onDelete: deleting cluster ${this.clusterName}`); + try { + await this.eks.deleteCluster({ name: this.clusterName }); + } catch (e) { + if (e.code !== 'ResourceNotFoundException') { + throw e; + } else { + console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); + } + } + return { + PhysicalResourceId: this.clusterName, + }; + } + + protected async isDeleteComplete(): Promise { + console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); + + try { + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); + } catch (e) { + if (e.code === 'ResourceNotFoundException') { + console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); + return { IsComplete: true }; + } + + console.log('describeCluster error:', e); + throw e; + } + + return { + IsComplete: false, + }; + } + + // ------ + // UPDATE + // ------ + + protected async onUpdate() { + const updates = analyzeUpdate(this.oldProps, this.newProps); + console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); + + // updates to encryption config is not supported + if (updates.updateEncryption) { + throw new Error('Cannot update cluster encryption configuration'); + } + + // if there is an update that requires replacement, go ahead and just create + // a new cluster with the new config. The old cluster will automatically be + // deleted by cloudformation upon success. + if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { + + // if we are replacing this cluster and the cluster has an explicit + // physical name, the creation of the new cluster will fail with "there is + // already a cluster with that name". this is a common behavior for + // CloudFormation resources that support specifying a physical name. + if (this.oldProps.name === this.newProps.name && this.oldProps.name) { + throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); + } + + return this.onCreate(); + } + + // if a version update is required, issue the version update + if (updates.updateVersion) { + if (!this.newProps.version) { + throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); + } + + return this.updateClusterVersion(this.newProps.version); + } + + if (updates.updateLogging && updates.updateAccess) { + throw new Error('Cannot update logging and access at the same time'); + } + + if (updates.updateLogging || updates.updateAccess) { + const config: aws.EKS.UpdateClusterConfigRequest = { + name: this.clusterName, + }; + if (updates.updateLogging) { + config.logging = this.newProps.logging; + }; + if (updates.updateAccess) { + // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: + // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) + // will fail, therefore we take only the access fields explicitly + config.resourcesVpcConfig = { + endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, + endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, + publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, + }; + } + const updateResponse = await this.eks.updateClusterConfig(config); + + return { EksUpdateId: updateResponse.update?.id }; + } + + // no updates + return; + } + + protected async isUpdateComplete() { + console.log('isUpdateComplete'); + + // if this is an EKS update, we will monitor the update event itself + if (this.event.EksUpdateId) { + const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); + if (!complete) { + return { IsComplete: false }; + } + + // fall through: if the update is done, we simply delegate to isActive() + // in order to extract attributes and state from the cluster itself, which + // is supposed to be in an ACTIVE state after the update is complete. + } + + return this.isActive(); + } + + private async updateClusterVersion(newVersion: string) { + console.log(`updating cluster version to ${newVersion}`); + + // update-cluster-version will fail if we try to update to the same version, + // so skip in this case. + const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; + if (cluster?.version === newVersion) { + console.log(`cluster already at version ${cluster.version}, skipping version update`); + return; + } + + const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); + return { EksUpdateId: updateResponse.update?.id }; + } + + private async isActive(): Promise { + console.log('waiting for cluster to become ACTIVE'); + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); + const cluster = resp.cluster; + + // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are + // not complete. note that the custom resource provider framework forbids + // returning attributes (Data) if isComplete is false. + if (cluster?.status === 'FAILED') { + // not very informative, unfortunately the response doesn't contain any error + // information :\ + throw new Error('Cluster is in a FAILED status'); + } else if (cluster?.status !== 'ACTIVE') { + return { + IsComplete: false, + }; + } else { + return { + IsComplete: true, + Data: { + Name: cluster.name, + Endpoint: cluster.endpoint, + Arn: cluster.arn, + + // IMPORTANT: CFN expects that attributes will *always* have values, + // so return an empty string in case the value is not defined. + // Otherwise, CFN will throw with `Vendor response doesn't contain + // XXXX key`. + + CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', + ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', + OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', + OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', // Strips off https:// from the issuer url + + // We can safely return the first item from encryption configuration array, because it has a limit of 1 item + // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig + EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', + }, + }; + } + } + + private async isEksUpdateComplete(eksUpdateId: string) { + this.log({ isEksUpdateComplete: eksUpdateId }); + + const describeUpdateResponse = await this.eks.describeUpdate({ + name: this.clusterName, + updateId: eksUpdateId, + }); + + this.log({ describeUpdateResponse }); + + if (!describeUpdateResponse.update) { + throw new Error(`unable to describe update with id "${eksUpdateId}"`); + } + + switch (describeUpdateResponse.update.status) { + case 'InProgress': + return false; + case 'Successful': + return true; + case 'Failed': + case 'Cancelled': + throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); + default: + throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); + } + } + + private generateClusterName() { + const suffix = this.requestId.replace(/-/g, ''); // 32 chars + const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; + const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); + return `${prefix}-${suffix}`; + } +} + +function parseProps(props: any): aws.EKS.CreateClusterRequest { + + const parsed = props?.Config ?? {}; + + // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. + // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' + + if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; + } + + if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; + } + + if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { + parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; + } + + return parsed; + +} + +interface UpdateMap { + replaceName: boolean; // name + replaceVpc: boolean; // resourcesVpcConfig.subnetIds and securityGroupIds + replaceRole: boolean; // roleArn + + updateVersion: boolean; // version + updateLogging: boolean; // logging + updateEncryption: boolean; // encryption (cannot be updated) + updateAccess: boolean; // resourcesVpcConfig.endpointPrivateAccess and endpointPublicAccess +} + +function analyzeUpdate(oldProps: Partial, newProps: aws.EKS.CreateClusterRequest): UpdateMap { + console.log('old props: ', JSON.stringify(oldProps)); + console.log('new props: ', JSON.stringify(newProps)); + + const newVpcProps = newProps.resourcesVpcConfig || {}; + const oldVpcProps = oldProps.resourcesVpcConfig || {}; + + const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); + const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); + const newEnc = newProps.encryptionConfig || {}; + const oldEnc = oldProps.encryptionConfig || {}; + + return { + replaceName: newProps.name !== oldProps.name, + replaceVpc: + JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), + updateAccess: + newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || + newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || + !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), + replaceRole: newProps.roleArn !== oldProps.roleArn, + updateVersion: newProps.version !== oldProps.version, + updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), + updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), + }; +} + +function setsEqual(first: Set, second: Set) { + return first.size === second.size && [...first].every((e: string) => second.has(e)); +} diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.d.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.d.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.js b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.js rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.d.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.d.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.js b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.js rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.d.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.d.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.js b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.js rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.d.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.d.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.js b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.js rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip index 298edd40a09fc..f62fe1e5a06d6 100644 Binary files a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip and b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip differ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip index ce3ea448ac19d..13983109fc5f5 100644 Binary files a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip and b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip differ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/apply/__init__.py b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/apply/__init__.py rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/get/__init__.py b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/get/__init__.py rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py new file mode 100644 index 0000000000000..286976ced219a --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py @@ -0,0 +1,187 @@ +import json +import logging +import os +import re +import subprocess +import shutil +import tempfile +import zipfile + +logger = logging.getLogger() +logger.setLevel(logging.INFO) + +# these are coming from the kubectl layer +os.environ['PATH'] = '/opt/helm:/opt/awscli:' + os.environ['PATH'] + +outdir = os.environ.get('TEST_OUTDIR', '/tmp') +kubeconfig = os.path.join(outdir, 'kubeconfig') + +def get_chart_asset_from_url(chart_asset_url): + chart_zip = os.path.join(outdir, 'chart.zip') + shutil.rmtree(chart_zip, ignore_errors=True) + subprocess.check_call(['aws', 's3', 'cp', chart_asset_url, chart_zip]) + chart_dir = os.path.join(outdir, 'chart') + shutil.rmtree(chart_dir, ignore_errors=True) + os.mkdir(chart_dir) + with zipfile.ZipFile(chart_zip, 'r') as zip_ref: + zip_ref.extractall(chart_dir) + return chart_dir + +def helm_handler(event, context): + logger.info(json.dumps(dict(event, ResponseURL='...'))) + + request_type = event['RequestType'] + props = event['ResourceProperties'] + + # resource properties + cluster_name = props['ClusterName'] + role_arn = props['RoleArn'] + release = props['Release'] + chart = props.get('Chart', None) + chart_asset_url = props.get('ChartAssetURL', None) + version = props.get('Version', None) + wait = props.get('Wait', False) + timeout = props.get('Timeout', None) + namespace = props.get('Namespace', None) + create_namespace = props.get('CreateNamespace', None) + repository = props.get('Repository', None) + values_text = props.get('Values', None) + + # "log in" to the cluster + subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig', + '--role-arn', role_arn, + '--name', cluster_name, + '--kubeconfig', kubeconfig + ]) + + if os.path.isfile(kubeconfig): + os.chmod(kubeconfig, 0o600) + + # Write out the values to a file and include them with the install and upgrade + values_file = None + if not request_type == "Delete" and not values_text is None: + values = json.loads(values_text) + values_file = os.path.join(outdir, 'values.yaml') + with open(values_file, "w") as f: + f.write(json.dumps(values, indent=2)) + + if request_type == 'Create' or request_type == 'Update': + # Ensure chart or chart_asset_url are set + if chart == None and chart_asset_url == None: + raise RuntimeError(f'chart or chartAsset must be specified') + + if chart_asset_url != None: + assert(chart==None) + assert(repository==None) + assert(version==None) + if not chart_asset_url.startswith('s3://'): + raise RuntimeError(f'ChartAssetURL must point to as s3 location but is {chart_asset_url}') + # future work: support versions from s3 assets + chart = get_chart_asset_from_url(chart_asset_url) + + if repository is not None and repository.startswith('oci://'): + tmpdir = tempfile.TemporaryDirectory() + chart_dir = get_chart_from_oci(tmpdir.name, repository, version) + chart = chart_dir + + helm('upgrade', release, chart, repository, values_file, namespace, version, wait, timeout, create_namespace) + elif request_type == "Delete": + try: + helm('uninstall', release, namespace=namespace, timeout=timeout) + except Exception as e: + logger.info("delete error: %s" % e) + + +def get_oci_cmd(repository, version): + # Generates OCI command based on pattern. Public ECR vs Private ECR are treated differently. + private_ecr_pattern = 'oci://(?P\d+.dkr.ecr.(?P[a-z]+-[a-z]+-\d).amazonaws.com)*' + public_ecr_pattern = 'oci://(?Ppublic.ecr.aws)*' + + private_registry = re.match(private_ecr_pattern, repository).groupdict() + public_registry = re.match(public_ecr_pattern, repository).groupdict() + + if private_registry['registry'] is not None: + logger.info("Found AWS private repository") + cmnd = [ + f"aws ecr get-login-password --region {private_registry['region']} | " \ + f"helm registry login --username AWS --password-stdin {private_registry['registry']}; helm pull {repository} --version {version} --untar" + ] + elif public_registry['registry'] is not None: + logger.info("Found AWS public repository, will use default region as deployment") + region = os.environ.get('AWS_REGION', 'us-east-1') + + cmnd = [ + f"aws ecr-public get-login-password --region us-east-1 | " \ + f"helm registry login --username AWS --password-stdin {public_registry['registry']}; helm pull {repository} --version {version} --untar" + ] + else: + logger.error("OCI repository format not recognized, falling back to helm pull") + cmnd = ['helm', 'pull', repository, '--version', version, '--untar'] + + return cmnd + + +def get_chart_from_oci(tmpdir, repository = None, version = None): + + cmnd = get_oci_cmd(repository, version) + + maxAttempts = 3 + retry = maxAttempts + while retry > 0: + try: + logger.info(cmnd) + output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=tmpdir, shell=True) + logger.info(output) + + # effectively returns "$tmpDir/$lastPartOfOCIUrl", because this is how helm pull saves OCI artifact. + # Eg. if we have oci://9999999999.dkr.ecr.us-east-1.amazonaws.com/foo/bar/pet-service repository, helm saves artifact under $tmpDir/pet-service + return os.path.join(tmpdir, repository.rpartition('/')[-1]) + except subprocess.CalledProcessError as exc: + output = exc.output + if b'Broken pipe' in output: + retry = retry - 1 + logger.info("Broken pipe, retries left: %s" % retry) + else: + raise Exception(output) + raise Exception(f'Operation failed after {maxAttempts} attempts: {output}') + + +def helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None): + import subprocess + + cmnd = ['helm', verb, release] + if not chart is None: + cmnd.append(chart) + if verb == 'upgrade': + cmnd.append('--install') + if create_namespace: + cmnd.append('--create-namespace') + if not repo is None: + cmnd.extend(['--repo', repo]) + if not file is None: + cmnd.extend(['--values', file]) + if not version is None: + cmnd.extend(['--version', version]) + if not namespace is None: + cmnd.extend(['--namespace', namespace]) + if wait: + cmnd.append('--wait') + if not timeout is None: + cmnd.extend(['--timeout', timeout]) + cmnd.extend(['--kubeconfig', kubeconfig]) + + maxAttempts = 3 + retry = maxAttempts + while retry > 0: + try: + output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir) + logger.info(output) + return + except subprocess.CalledProcessError as exc: + output = exc.output + if b'Broken pipe' in output: + retry = retry - 1 + logger.info("Broken pipe, retries left: %s" % retry) + else: + raise Exception(output) + raise Exception(f'Operation failed after {maxAttempts} attempts: {output}') diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/index.py b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/index.py rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/patch/__init__.py b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/patch/__init__.py rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/aws-stepfunctions-tasks-eks-call-integ-test.assets.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/aws-stepfunctions-tasks-eks-call-integ-test.assets.json index 48c34232a2aca..11c7ad9c32e0b 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/aws-stepfunctions-tasks-eks-call-integ-test.assets.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/aws-stepfunctions-tasks-eks-call-integ-test.assets.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "files": { "ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1": { "source": { @@ -14,15 +14,15 @@ } } }, - "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5": { + "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee": { "source": { - "path": "asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5", + "path": "asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip", + "objectKey": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -40,15 +40,15 @@ } } }, - "a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd": { + "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8": { "source": { - "path": "asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd", + "path": "asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd.zip", + "objectKey": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -79,7 +79,7 @@ } } }, - "8d5969a90e2e720721ef401f4a46a8d1c61cb13e72e729538898ef747c3641ac": { + "ce676dd00b6b83bd39d97745ba4264d3db3b983f6c1862784cb9a0c8b02466e7": { "source": { "path": "awsstepfunctionstasksekscallintegtestawscdkawseksClusterResourceProvider412BC189.nested.template.json", "packaging": "file" @@ -87,12 +87,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "8d5969a90e2e720721ef401f4a46a8d1c61cb13e72e729538898ef747c3641ac.json", + "objectKey": "ce676dd00b6b83bd39d97745ba4264d3db3b983f6c1862784cb9a0c8b02466e7.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "2a398731934eca1054c33c88ad3e4128309643d200092ff00c7605e8965451cc": { + "2f6232262f61ee4d0aaf7ccee2de42f40c122cd7d534b88592e9543db954213f": { "source": { "path": "awsstepfunctionstasksekscallintegtestawscdkawseksKubectlProvider65D285A0.nested.template.json", "packaging": "file" @@ -100,12 +100,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "2a398731934eca1054c33c88ad3e4128309643d200092ff00c7605e8965451cc.json", + "objectKey": "2f6232262f61ee4d0aaf7ccee2de42f40c122cd7d534b88592e9543db954213f.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "9a5ccbde1de37acad0d352a3fc3a1b1615c04d758008522a66e1fb1c087310a5": { + "517638b14b3968f2d1b04504c73efba2af37b71a925d21253557359ea48ac5da": { "source": { "path": "aws-stepfunctions-tasks-eks-call-integ-test.template.json", "packaging": "file" @@ -113,7 +113,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "9a5ccbde1de37acad0d352a3fc3a1b1615c04d758008522a66e1fb1c087310a5.json", + "objectKey": "517638b14b3968f2d1b04504c73efba2af37b71a925d21253557359ea48ac5da.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/aws-stepfunctions-tasks-eks-call-integ-test.template.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/aws-stepfunctions-tasks-eks-call-integ-test.template.json index 45b2cdc39c34c..0c46cdd0cd81b 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/aws-stepfunctions-tasks-eks-call-integ-test.template.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/aws-stepfunctions-tasks-eks-call-integ-test.template.json @@ -996,7 +996,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/8d5969a90e2e720721ef401f4a46a8d1c61cb13e72e729538898ef747c3641ac.json" + "/ce676dd00b6b83bd39d97745ba4264d3db3b983f6c1862784cb9a0c8b02466e7.json" ] ] }, @@ -1031,7 +1031,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/2a398731934eca1054c33c88ad3e4128309643d200092ff00c7605e8965451cc.json" + "/2f6232262f61ee4d0aaf7ccee2de42f40c122cd7d534b88592e9543db954213f.json" ] ] }, diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/awsstepfunctionstasksekscallintegDefaultTestDeployAssert2DF4AD1E.assets.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/awsstepfunctionstasksekscallintegDefaultTestDeployAssert2DF4AD1E.assets.json index 3e37b187392c6..1d6357d705d4f 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/awsstepfunctionstasksekscallintegDefaultTestDeployAssert2DF4AD1E.assets.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/awsstepfunctionstasksekscallintegDefaultTestDeployAssert2DF4AD1E.assets.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/awsstepfunctionstasksekscallintegtestawscdkawseksClusterResourceProvider412BC189.nested.template.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/awsstepfunctionstasksekscallintegtestawscdkawseksClusterResourceProvider412BC189.nested.template.json index 504a30f0d65b5..c5b6a97520a15 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/awsstepfunctionstasksekscallintegtestawscdkawseksClusterResourceProvider412BC189.nested.template.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/awsstepfunctionstasksekscallintegtestawscdkawseksClusterResourceProvider412BC189.nested.template.json @@ -73,7 +73,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ @@ -162,7 +162,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/awsstepfunctionstasksekscallintegtestawscdkawseksKubectlProvider65D285A0.nested.template.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/awsstepfunctionstasksekscallintegtestawscdkawseksKubectlProvider65D285A0.nested.template.json index c48d6b8e26afb..3dd91320ca7ac 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/awsstepfunctionstasksekscallintegtestawscdkawseksKubectlProvider65D285A0.nested.template.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/awsstepfunctionstasksekscallintegtestawscdkawseksKubectlProvider65D285A0.nested.template.json @@ -51,6 +51,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -92,7 +104,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd.zip" + "S3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/cdk.out b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/cdk.out index ae4b03c54e770..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"30.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/integ.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/integ.json index b2e0b69af5538..6b97c3e72a57f 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "testCases": { "aws-stepfunctions-tasks-eks-call-integ/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/manifest.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/manifest.json index a2c620649373b..b5f90a2e3ec5a 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "artifacts": { "aws-stepfunctions-tasks-eks-call-integ-test.assets": { "type": "cdk:asset-manifest", @@ -17,7 +17,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/9a5ccbde1de37acad0d352a3fc3a1b1615c04d758008522a66e1fb1c087310a5.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/517638b14b3968f2d1b04504c73efba2af37b71a925d21253557359ea48ac5da.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/tree.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/tree.json index a80b88576947a..125ae02f335e2 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/tree.json @@ -1020,7 +1020,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } }, "KubectlReadyBarrier": { @@ -1486,7 +1486,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -1659,7 +1659,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -2500,7 +2500,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } } }, @@ -2557,7 +2557,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/8d5969a90e2e720721ef401f4a46a8d1c61cb13e72e729538898ef747c3641ac.json" + "/ce676dd00b6b83bd39d97745ba4264d3db3b983f6c1862784cb9a0c8b02466e7.json" ] ] }, @@ -2579,7 +2579,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } }, "@aws-cdk--aws-eks.KubectlProvider": { @@ -2656,6 +2656,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -2755,7 +2767,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd.zip" + "s3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "role": { "Fn::GetAtt": [ @@ -3225,7 +3237,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/2a398731934eca1054c33c88ad3e4128309643d200092ff00c7605e8965451cc.json" + "/2f6232262f61ee4d0aaf7ccee2de42f40c122cd7d534b88592e9543db954213f.json" ] ] }, @@ -3265,7 +3277,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } }, "Role": { @@ -3422,7 +3434,7 @@ "path": "aws-stepfunctions-tasks-eks-call-integ/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } }, "DeployAssert": { @@ -3468,7 +3480,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } } }, diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.d.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.d.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js new file mode 100644 index 0000000000000..c9dc1b8d2c19a --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js @@ -0,0 +1,273 @@ +"use strict"; +/* eslint-disable no-console */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ClusterResourceHandler = void 0; +const common_1 = require("./common"); +const MAX_CLUSTER_NAME_LEN = 100; +class ClusterResourceHandler extends common_1.ResourceHandler { + constructor(eks, event) { + super(eks, event); + this.newProps = parseProps(this.event.ResourceProperties); + this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; + } + get clusterName() { + if (!this.physicalResourceId) { + throw new Error('Cannot determine cluster name without physical resource ID'); + } + return this.physicalResourceId; + } + // ------ + // CREATE + // ------ + async onCreate() { + console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); + if (!this.newProps.roleArn) { + throw new Error('"roleArn" is required'); + } + const clusterName = this.newProps.name || this.generateClusterName(); + const resp = await this.eks.createCluster({ + ...this.newProps, + name: clusterName, + }); + if (!resp.cluster) { + throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); + } + return { + PhysicalResourceId: resp.cluster.name, + }; + } + async isCreateComplete() { + return this.isActive(); + } + // ------ + // DELETE + // ------ + async onDelete() { + console.log(`onDelete: deleting cluster ${this.clusterName}`); + try { + await this.eks.deleteCluster({ name: this.clusterName }); + } + catch (e) { + if (e.code !== 'ResourceNotFoundException') { + throw e; + } + else { + console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); + } + } + return { + PhysicalResourceId: this.clusterName, + }; + } + async isDeleteComplete() { + console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); + try { + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); + } + catch (e) { + if (e.code === 'ResourceNotFoundException') { + console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); + return { IsComplete: true }; + } + console.log('describeCluster error:', e); + throw e; + } + return { + IsComplete: false, + }; + } + // ------ + // UPDATE + // ------ + async onUpdate() { + const updates = analyzeUpdate(this.oldProps, this.newProps); + console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); + // updates to encryption config is not supported + if (updates.updateEncryption) { + throw new Error('Cannot update cluster encryption configuration'); + } + // if there is an update that requires replacement, go ahead and just create + // a new cluster with the new config. The old cluster will automatically be + // deleted by cloudformation upon success. + if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { + // if we are replacing this cluster and the cluster has an explicit + // physical name, the creation of the new cluster will fail with "there is + // already a cluster with that name". this is a common behavior for + // CloudFormation resources that support specifying a physical name. + if (this.oldProps.name === this.newProps.name && this.oldProps.name) { + throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); + } + return this.onCreate(); + } + // if a version update is required, issue the version update + if (updates.updateVersion) { + if (!this.newProps.version) { + throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); + } + return this.updateClusterVersion(this.newProps.version); + } + if (updates.updateLogging && updates.updateAccess) { + throw new Error('Cannot update logging and access at the same time'); + } + if (updates.updateLogging || updates.updateAccess) { + const config = { + name: this.clusterName, + }; + if (updates.updateLogging) { + config.logging = this.newProps.logging; + } + ; + if (updates.updateAccess) { + // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: + // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) + // will fail, therefore we take only the access fields explicitly + config.resourcesVpcConfig = { + endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, + endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, + publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, + }; + } + const updateResponse = await this.eks.updateClusterConfig(config); + return { EksUpdateId: updateResponse.update?.id }; + } + // no updates + return; + } + async isUpdateComplete() { + console.log('isUpdateComplete'); + // if this is an EKS update, we will monitor the update event itself + if (this.event.EksUpdateId) { + const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); + if (!complete) { + return { IsComplete: false }; + } + // fall through: if the update is done, we simply delegate to isActive() + // in order to extract attributes and state from the cluster itself, which + // is supposed to be in an ACTIVE state after the update is complete. + } + return this.isActive(); + } + async updateClusterVersion(newVersion) { + console.log(`updating cluster version to ${newVersion}`); + // update-cluster-version will fail if we try to update to the same version, + // so skip in this case. + const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; + if (cluster?.version === newVersion) { + console.log(`cluster already at version ${cluster.version}, skipping version update`); + return; + } + const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); + return { EksUpdateId: updateResponse.update?.id }; + } + async isActive() { + console.log('waiting for cluster to become ACTIVE'); + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); + const cluster = resp.cluster; + // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are + // not complete. note that the custom resource provider framework forbids + // returning attributes (Data) if isComplete is false. + if (cluster?.status === 'FAILED') { + // not very informative, unfortunately the response doesn't contain any error + // information :\ + throw new Error('Cluster is in a FAILED status'); + } + else if (cluster?.status !== 'ACTIVE') { + return { + IsComplete: false, + }; + } + else { + return { + IsComplete: true, + Data: { + Name: cluster.name, + Endpoint: cluster.endpoint, + Arn: cluster.arn, + // IMPORTANT: CFN expects that attributes will *always* have values, + // so return an empty string in case the value is not defined. + // Otherwise, CFN will throw with `Vendor response doesn't contain + // XXXX key`. + CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', + ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', + OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', + OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', + // We can safely return the first item from encryption configuration array, because it has a limit of 1 item + // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig + EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', + }, + }; + } + } + async isEksUpdateComplete(eksUpdateId) { + this.log({ isEksUpdateComplete: eksUpdateId }); + const describeUpdateResponse = await this.eks.describeUpdate({ + name: this.clusterName, + updateId: eksUpdateId, + }); + this.log({ describeUpdateResponse }); + if (!describeUpdateResponse.update) { + throw new Error(`unable to describe update with id "${eksUpdateId}"`); + } + switch (describeUpdateResponse.update.status) { + case 'InProgress': + return false; + case 'Successful': + return true; + case 'Failed': + case 'Cancelled': + throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); + default: + throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); + } + } + generateClusterName() { + const suffix = this.requestId.replace(/-/g, ''); // 32 chars + const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; + const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); + return `${prefix}-${suffix}`; + } +} +exports.ClusterResourceHandler = ClusterResourceHandler; +function parseProps(props) { + const parsed = props?.Config ?? {}; + // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. + // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' + if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; + } + if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; + } + if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { + parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; + } + return parsed; +} +function analyzeUpdate(oldProps, newProps) { + console.log('old props: ', JSON.stringify(oldProps)); + console.log('new props: ', JSON.stringify(newProps)); + const newVpcProps = newProps.resourcesVpcConfig || {}; + const oldVpcProps = oldProps.resourcesVpcConfig || {}; + const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); + const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); + const newEnc = newProps.encryptionConfig || {}; + const oldEnc = oldProps.encryptionConfig || {}; + return { + replaceName: newProps.name !== oldProps.name, + replaceVpc: JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), + updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || + newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || + !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), + replaceRole: newProps.roleArn !== oldProps.roleArn, + updateVersion: newProps.version !== oldProps.version, + updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), + updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), + }; +} +function setsEqual(first, second) { + return first.size === second.size && [...first].every((e) => second.has(e)); +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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LENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztRQUNuRSxhQUFhLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBa0IsRUFBRSxNQUFtQjtJQUN4RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgRWtzQ2xpZW50LCBSZXNvdXJjZUV2ZW50LCBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX05BTUVfTEVOID0gMTAwO1xuXG5leHBvcnQgY2xhc3MgQ2x1c3RlclJlc291cmNlSGFuZGxlciBleHRlbmRzIFJlc291cmNlSGFuZGxlciB7XG4gIHB1YmxpYyBnZXQgY2x1c3Rlck5hbWUoKSB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZGV0ZXJtaW5lIGNsdXN0ZXIgbmFtZSB3aXRob3V0IHBoeXNpY2FsIHJlc291cmNlIElEJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PjtcblxuICBjb25zdHJ1Y3Rvcihla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICBzdXBlcihla3MsIGV2ZW50KTtcblxuICAgIHRoaXMubmV3UHJvcHMgPSBwYXJzZVByb3BzKHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLm9sZFByb3BzID0gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnID8gcGFyc2VQcm9wcyhldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMpIDoge307XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gQ1JFQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCdvbkNyZWF0ZTogY3JlYXRpbmcgY2x1c3RlciB3aXRoIG9wdGlvbnM6JywgSlNPTi5zdHJpbmdpZnkodGhpcy5uZXdQcm9wcywgdW5kZWZpbmVkLCAyKSk7XG4gICAgaWYgKCF0aGlzLm5ld1Byb3BzLnJvbGVBcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJyb2xlQXJuXCIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyTmFtZSA9IHRoaXMubmV3UHJvcHMubmFtZSB8fCB0aGlzLmdlbmVyYXRlQ2x1c3Rlck5hbWUoKTtcblxuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmVrcy5jcmVhdGVDbHVzdGVyKHtcbiAgICAgIC4uLnRoaXMubmV3UHJvcHMsXG4gICAgICBuYW1lOiBjbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcC5jbHVzdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBjbHVzdGVyICR7Y2x1c3Rlck5hbWV9OiBDcmVhdGVDbHVzdGVyIHJldHVybmVkIHdpdGhvdXQgY2x1c3RlciBpbmZvcm1hdGlvbmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHJlc3AuY2x1c3Rlci5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIERFTEVURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25EZWxldGUoKTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgb25EZWxldGU6IGRlbGV0aW5nIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfWApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVrcy5kZWxldGVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyICR7dGhpcy5jbHVzdGVyTmFtZX0gbm90IGZvdW5kLCBpZGVtcG90ZW50bHkgc3VjY2VlZGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coYGlzRGVsZXRlQ29tcGxldGU6IHdhaXRpbmcgZm9yIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSB0byBiZSBkZWxldGVkYCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJldHVybmVkOicsIEpTT04uc3RyaW5naWZ5KHJlc3AsIHVuZGVmaW5lZCwgMikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICBjb25zb2xlLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgY2x1c3RlciBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0cnVlIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgZXJyb3I6JywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIFVQREFURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IGFuYWx5emVVcGRhdGUodGhpcy5vbGRQcm9wcywgdGhpcy5uZXdQcm9wcyk7XG4gICAgY29uc29sZS5sb2coJ29uVXBkYXRlOicsIEpTT04uc3RyaW5naWZ5KHsgdXBkYXRlcyB9LCB1bmRlZmluZWQsIDIpKTtcblxuICAgIC8vIHVwZGF0ZXMgdG8gZW5jcnlwdGlvbiBjb25maWcgaXMgbm90IHN1cHBvcnRlZFxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUVuY3J5cHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHVwZGF0ZSBjbHVzdGVyIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZXJlIGlzIGFuIHVwZGF0ZSB0aGF0IHJlcXVpcmVzIHJlcGxhY2VtZW50LCBnbyBhaGVhZCBhbmQganVzdCBjcmVhdGVcbiAgICAvLyBhIG5ldyBjbHVzdGVyIHdpdGggdGhlIG5ldyBjb25maWcuIFRoZSBvbGQgY2x1c3RlciB3aWxsIGF1dG9tYXRpY2FsbHkgYmVcbiAgICAvLyBkZWxldGVkIGJ5IGNsb3VkZm9ybWF0aW9uIHVwb24gc3VjY2Vzcy5cbiAgICBpZiAodXBkYXRlcy5yZXBsYWNlTmFtZSB8fCB1cGRhdGVzLnJlcGxhY2VSb2xlIHx8IHVwZGF0ZXMucmVwbGFjZVZwYykge1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgcmVwbGFjaW5nIHRoaXMgY2x1c3RlciBhbmQgdGhlIGNsdXN0ZXIgaGFzIGFuIGV4cGxpY2l0XG4gICAgICAvLyBwaHlzaWNhbCBuYW1lLCB0aGUgY3JlYXRpb24gb2YgdGhlIG5ldyBjbHVzdGVyIHdpbGwgZmFpbCB3aXRoIFwidGhlcmUgaXNcbiAgICAgIC8vIGFscmVhZHkgYSBjbHVzdGVyIHdpdGggdGhhdCBuYW1lXCIuIHRoaXMgaXMgYSBjb21tb24gYmVoYXZpb3IgZm9yXG4gICAgICAvLyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZXMgdGhhdCBzdXBwb3J0IHNwZWNpZnlpbmcgYSBwaHlzaWNhbCBuYW1lLlxuICAgICAgaWYgKHRoaXMub2xkUHJvcHMubmFtZSA9PT0gdGhpcy5uZXdQcm9wcy5uYW1lICYmIHRoaXMub2xkUHJvcHMubmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXBsYWNlIGNsdXN0ZXIgXCIke3RoaXMub2xkUHJvcHMubmFtZX1cIiBzaW5jZSBpdCBoYXMgYW4gZXhwbGljaXQgcGh5c2ljYWwgbmFtZS4gRWl0aGVyIHJlbmFtZSB0aGUgY2x1c3RlciBvciByZW1vdmUgdGhlIFwibmFtZVwiIGNvbmZpZ3VyYXRpb25gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub25DcmVhdGUoKTtcbiAgICB9XG5cbiAgICAvLyBpZiBhIHZlcnNpb24gdXBkYXRlIGlzIHJlcXVpcmVkLCBpc3N1ZSB0aGUgdmVyc2lvbiB1cGRhdGVcbiAgICBpZiAodXBkYXRlcy51cGRhdGVWZXJzaW9uKSB7XG4gICAgICBpZiAoIXRoaXMubmV3UHJvcHMudmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZW1vdmUgY2x1c3RlciB2ZXJzaW9uIGNvbmZpZ3VyYXRpb24uIEN1cnJlbnQgdmVyc2lvbiBpcyAke3RoaXMub2xkUHJvcHMudmVyc2lvbn1gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlQ2x1c3RlclZlcnNpb24odGhpcy5uZXdQcm9wcy52ZXJzaW9uKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nICYmIHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1cGRhdGUgbG9nZ2luZyBhbmQgYWNjZXNzIGF0IHRoZSBzYW1lIHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nIHx8IHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICBjb25zdCBjb25maWc6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QgPSB7XG4gICAgICAgIG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgICB9O1xuICAgICAgaWYgKHVwZGF0ZXMudXBkYXRlTG9nZ2luZykge1xuICAgICAgICBjb25maWcubG9nZ2luZyA9IHRoaXMubmV3UHJvcHMubG9nZ2luZztcbiAgICAgIH07XG4gICAgICBpZiAodXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIGNsdXN0ZXIgd2l0aCBzZWN1cml0eUdyb3VwSWRzIGFuZCBzdWJuZXRJZHMgKGFzIHNwZWNpZmllZCBpbiB0aGUgd2FybmluZyBoZXJlOlxuICAgICAgICAvLyBodHRwczovL2F3c2NsaS5hbWF6b25hd3MuY29tL3YyL2RvY3VtZW50YXRpb24vYXBpL2xhdGVzdC9yZWZlcmVuY2UvZWtzL3VwZGF0ZS1jbHVzdGVyLWNvbmZpZy5odG1sKVxuICAgICAgICAvLyB3aWxsIGZhaWwsIHRoZXJlZm9yZSB3ZSB0YWtlIG9ubHkgdGhlIGFjY2VzcyBmaWVsZHMgZXhwbGljaXRseVxuICAgICAgICBjb25maWcucmVzb3VyY2VzVnBjQ29uZmlnID0ge1xuICAgICAgICAgIGVuZHBvaW50UHJpdmF0ZUFjY2VzczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzLFxuICAgICAgICAgIGVuZHBvaW50UHVibGljQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyxcbiAgICAgICAgICBwdWJsaWNBY2Nlc3NDaWRyczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcucHVibGljQWNjZXNzQ2lkcnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgICB9XG5cbiAgICAvLyBubyB1cGRhdGVzXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc29sZS5sb2coJ2lzVXBkYXRlQ29tcGxldGUnKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYW4gRUtTIHVwZGF0ZSwgd2Ugd2lsbCBtb25pdG9yIHRoZSB1cGRhdGUgZXZlbnQgaXRzZWxmXG4gICAgaWYgKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gYXdhaXQgdGhpcy5pc0Vrc1VwZGF0ZUNvbXBsZXRlKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpO1xuICAgICAgaWYgKCFjb21wbGV0ZSkge1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiBmYWxzZSB9O1xuICAgICAgfVxuXG4gICAgICAvLyBmYWxsIHRocm91Z2g6IGlmIHRoZSB1cGRhdGUgaXMgZG9uZSwgd2Ugc2ltcGx5IGRlbGVnYXRlIHRvIGlzQWN0aXZlKClcbiAgICAgIC8vIGluIG9yZGVyIHRvIGV4dHJhY3QgYXR0cmlidXRlcyBhbmQgc3RhdGUgZnJvbSB0aGUgY2x1c3RlciBpdHNlbGYsIHdoaWNoXG4gICAgICAvLyBpcyBzdXBwb3NlZCB0byBiZSBpbiBhbiBBQ1RJVkUgc3RhdGUgYWZ0ZXIgdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbHVzdGVyVmVyc2lvbihuZXdWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgdXBkYXRpbmcgY2x1c3RlciB2ZXJzaW9uIHRvICR7bmV3VmVyc2lvbn1gKTtcblxuICAgIC8vIHVwZGF0ZS1jbHVzdGVyLXZlcnNpb24gd2lsbCBmYWlsIGlmIHdlIHRyeSB0byB1cGRhdGUgdG8gdGhlIHNhbWUgdmVyc2lvbixcbiAgICAvLyBzbyBza2lwIGluIHRoaXMgY2FzZS5cbiAgICBjb25zdCBjbHVzdGVyID0gKGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSkpLmNsdXN0ZXI7XG4gICAgaWYgKGNsdXN0ZXI/LnZlcnNpb24gPT09IG5ld1ZlcnNpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyIGFscmVhZHkgYXQgdmVyc2lvbiAke2NsdXN0ZXIudmVyc2lvbn0sIHNraXBwaW5nIHZlcnNpb24gdXBkYXRlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy51cGRhdGVDbHVzdGVyVmVyc2lvbih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsIHZlcnNpb246IG5ld1ZlcnNpb24gfSk7XG4gICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNBY3RpdmUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZygnd2FpdGluZyBmb3IgY2x1c3RlciB0byBiZWNvbWUgQUNUSVZFJyk7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciByZXN1bHQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgY29uc3QgY2x1c3RlciA9IHJlc3AuY2x1c3RlcjtcblxuICAgIC8vIGlmIGNsdXN0ZXIgaXMgdW5kZWZpbmVkIChzaG91bGRudCBoYXBwZW4pIG9yIHN0YXR1cyBpcyBub3QgQUNUSVZFLCB3ZSBhcmVcbiAgICAvLyBub3QgY29tcGxldGUuIG5vdGUgdGhhdCB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZyYW1ld29yayBmb3JiaWRzXG4gICAgLy8gcmV0dXJuaW5nIGF0dHJpYnV0ZXMgKERhdGEpIGlmIGlzQ29tcGxldGUgaXMgZmFsc2UuXG4gICAgaWYgKGNsdXN0ZXI/LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgIC8vIG5vdCB2ZXJ5IGluZm9ybWF0aXZlLCB1bmZvcnR1bmF0ZWx5IHRoZSByZXNwb25zZSBkb2Vzbid0IGNvbnRhaW4gYW55IGVycm9yXG4gICAgICAvLyBpbmZvcm1hdGlvbiA6XFxcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2x1c3RlciBpcyBpbiBhIEZBSUxFRCBzdGF0dXMnKTtcbiAgICB9IGVsc2UgaWYgKGNsdXN0ZXI/LnN0YXR1cyAhPT0gJ0FDVElWRScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIE5hbWU6IGNsdXN0ZXIubmFtZSxcbiAgICAgICAgICBFbmRwb2ludDogY2x1c3Rlci5lbmRwb2ludCxcbiAgICAgICAgICBBcm46IGNsdXN0ZXIuYXJuLFxuXG4gICAgICAgICAgLy8gSU1QT1JUQU5UOiBDRk4gZXhwZWN0cyB0aGF0IGF0dHJpYnV0ZXMgd2lsbCAqYWx3YXlzKiBoYXZlIHZhbHVlcyxcbiAgICAgICAgICAvLyBzbyByZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGluIGNhc2UgdGhlIHZhbHVlIGlzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQ0ZOIHdpbGwgdGhyb3cgd2l0aCBgVmVuZG9yIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpblxuICAgICAgICAgIC8vIFhYWFgga2V5YC5cblxuICAgICAgICAgIENlcnRpZmljYXRlQXV0aG9yaXR5RGF0YTogY2x1c3Rlci5jZXJ0aWZpY2F0ZUF1dGhvcml0eT8uZGF0YSA/PyAnJyxcbiAgICAgICAgICBDbHVzdGVyU2VjdXJpdHlHcm91cElkOiBjbHVzdGVyLnJlc291cmNlc1ZwY0NvbmZpZz8uY2x1c3RlclNlY3VyaXR5R3JvdXBJZCA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyVXJsOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXIgPz8gJycsXG4gICAgICAgICAgT3BlbklkQ29ubmVjdElzc3VlcjogY2x1c3Rlci5pZGVudGl0eT8ub2lkYz8uaXNzdWVyPy5zdWJzdHJpbmcoOCkgPz8gJycsIC8vIFN0cmlwcyBvZmYgaHR0cHM6Ly8gZnJvbSB0aGUgaXNzdWVyIHVybFxuXG4gICAgICAgICAgLy8gV2UgY2FuIHNhZmVseSByZXR1cm4gdGhlIGZpcnN0IGl0ZW0gZnJvbSBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gYXJyYXksIGJlY2F1c2UgaXQgaGFzIGEgbGltaXQgb2YgMSBpdGVtXG4gICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vrcy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDbHVzdGVyLmh0bWwjQW1hem9uRUtTLUNyZWF0ZUNsdXN0ZXItcmVxdWVzdC1lbmNyeXB0aW9uQ29uZmlnXG4gICAgICAgICAgRW5jcnlwdGlvbkNvbmZpZ0tleUFybjogY2x1c3Rlci5lbmNyeXB0aW9uQ29uZmlnPy5zaGlmdCgpPy5wcm92aWRlcj8ua2V5QXJuID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzRWtzVXBkYXRlQ29tcGxldGUoZWtzVXBkYXRlSWQ6IHN0cmluZykge1xuICAgIHRoaXMubG9nKHsgaXNFa3NVcGRhdGVDb21wbGV0ZTogZWtzVXBkYXRlSWQgfSk7XG5cbiAgICBjb25zdCBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVVcGRhdGUoe1xuICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgIHVwZGF0ZUlkOiBla3NVcGRhdGVJZCxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nKHsgZGVzY3JpYmVVcGRhdGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5hYmxlIHRvIGRlc2NyaWJlIHVwZGF0ZSB3aXRoIGlkIFwiJHtla3NVcGRhdGVJZH1cImApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzKSB7XG4gICAgICBjYXNlICdJblByb2dyZXNzJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgY2FzZSAnU3VjY2Vzc2Z1bCc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnRmFpbGVkJzpcbiAgICAgIGNhc2UgJ0NhbmNlbGxlZCc6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2x1c3RlciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiIGZhaWxlZCB3aXRoIGVycm9yczogJHtKU09OLnN0cmluZ2lmeShkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5lcnJvcnMpfWApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIHN0YXR1cyBcIiR7ZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzfVwiIGZvciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNsdXN0ZXJOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9DTFVTVEVSX05BTUVfTEVOIC0gc3VmZml4Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5sb2dpY2FsUmVzb3VyY2VJZC5zbGljZSgwLCBvZmZzZXQgPiAwID8gb2Zmc2V0IDogMCk7XG4gICAgcmV0dXJuIGAke3ByZWZpeH0tJHtzdWZmaXh9YDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3BzKHByb3BzOiBhbnkpOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0IHtcblxuICBjb25zdCBwYXJzZWQgPSBwcm9wcz8uQ29uZmlnID8/IHt9O1xuXG4gIC8vIHRoaXMgaXMgd2VpcmQgYnV0IHRoZXNlIGJvb2xlYW4gcHJvcGVydGllcyBhcmUgcGFzc2VkIGJ5IENGTiBhcyBhIHN0cmluZywgYW5kIHdlIG5lZWQgdGhlbSB0byBiZSBib29sZWFuaWMgZm9yIHRoZSBTREsuXG4gIC8vIE90aGVyd2lzZSBpdCBmYWlscyB3aXRoICdVbmV4cGVjdGVkIFBhcmFtZXRlcjogcGFyYW1zLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgaXMgZXhwZWN0ZWQgdG8gYmUgYSBib29sZWFuJ1xuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWc/LmVuZHBvaW50UHJpdmF0ZUFjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9PT0gJ3RydWUnO1xuICB9XG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQdWJsaWNBY2Nlc3MpID09PSAnc3RyaW5nJykge1xuICAgIHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQubG9nZ2luZz8uY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCkgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9IHBhcnNlZC5sb2dnaW5nLmNsdXN0ZXJMb2dnaW5nWzBdLmVuYWJsZWQgPT09ICd0cnVlJztcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQ7XG5cbn1cblxuaW50ZXJmYWNlIFVwZGF0ZU1hcCB7XG4gIHJlcGxhY2VOYW1lOiBib29sZWFuOyAvLyBuYW1lXG4gIHJlcGxhY2VWcGM6IGJvb2xlYW47IC8vIHJlc291cmNlc1ZwY0NvbmZpZy5zdWJuZXRJZHMgYW5kIHNlY3VyaXR5R3JvdXBJZHNcbiAgcmVwbGFjZVJvbGU6IGJvb2xlYW47IC8vIHJvbGVBcm5cblxuICB1cGRhdGVWZXJzaW9uOiBib29sZWFuOyAvLyB2ZXJzaW9uXG4gIHVwZGF0ZUxvZ2dpbmc6IGJvb2xlYW47IC8vIGxvZ2dpbmdcbiAgdXBkYXRlRW5jcnlwdGlvbjogYm9vbGVhbjsgLy8gZW5jcnlwdGlvbiAoY2Fubm90IGJlIHVwZGF0ZWQpXG4gIHVwZGF0ZUFjY2VzczogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBhbmQgZW5kcG9pbnRQdWJsaWNBY2Nlc3Ncbn1cblxuZnVuY3Rpb24gYW5hbHl6ZVVwZGF0ZShvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PiwgbmV3UHJvcHM6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBVcGRhdGVNYXAge1xuICBjb25zb2xlLmxvZygnb2xkIHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShvbGRQcm9wcykpO1xuICBjb25zb2xlLmxvZygnbmV3IHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShuZXdQcm9wcykpO1xuXG4gIGNvbnN0IG5ld1ZwY1Byb3BzID0gbmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRWcGNQcm9wcyA9IG9sZFByb3BzLnJlc291cmNlc1ZwY0NvbmZpZyB8fCB7fTtcblxuICBjb25zdCBvbGRQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQob2xkVnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQobmV3VnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdFbmMgPSBuZXdQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRFbmMgPSBvbGRQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgcmVwbGFjZU5hbWU6IG5ld1Byb3BzLm5hbWUgIT09IG9sZFByb3BzLm5hbWUsXG4gICAgcmVwbGFjZVZwYzpcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnN1Ym5ldElkcz8uc29ydCgpKSAhPT0gSlNPTi5zdHJpbmdpZnkob2xkVnBjUHJvcHMuc3VibmV0SWRzPy5zb3J0KCkpIHx8XG4gICAgICBKU09OLnN0cmluZ2lmeShuZXdWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpICE9PSBKU09OLnN0cmluZ2lmeShvbGRWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpLFxuICAgIHVwZGF0ZUFjY2VzczpcbiAgICAgIG5ld1ZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQcml2YXRlQWNjZXNzIHx8XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFB1YmxpY0FjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgfHxcbiAgICAgICFzZXRzRXF1YWwobmV3UHVibGljQWNjZXNzQ2lkcnMsIG9sZFB1YmxpY0FjY2Vzc0NpZHJzKSxcbiAgICByZXBsYWNlUm9sZTogbmV3UHJvcHMucm9sZUFybiAhPT0gb2xkUHJvcHMucm9sZUFybixcbiAgICB1cGRhdGVWZXJzaW9uOiBuZXdQcm9wcy52ZXJzaW9uICE9PSBvbGRQcm9wcy52ZXJzaW9uLFxuICAgIHVwZGF0ZUVuY3J5cHRpb246IEpTT04uc3RyaW5naWZ5KG5ld0VuYykgIT09IEpTT04uc3RyaW5naWZ5KG9sZEVuYyksXG4gICAgdXBkYXRlTG9nZ2luZzogSlNPTi5zdHJpbmdpZnkobmV3UHJvcHMubG9nZ2luZykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFByb3BzLmxvZ2dpbmcpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzZXRzRXF1YWwoZmlyc3Q6IFNldDxzdHJpbmc+LCBzZWNvbmQ6IFNldDxzdHJpbmc+KSB7XG4gIHJldHVybiBmaXJzdC5zaXplID09PSBzZWNvbmQuc2l6ZSAmJiBbLi4uZmlyc3RdLmV2ZXJ5KChlOiBzdHJpbmcpID0+IHNlY29uZC5oYXMoZSkpO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts new file mode 100644 index 0000000000000..4b7fdda6d1dd1 --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts @@ -0,0 +1,344 @@ +/* eslint-disable no-console */ + +// eslint-disable-next-line import/no-extraneous-dependencies +import { IsCompleteResponse, OnEventResponse } from '@aws-cdk/custom-resources/lib/provider-framework/types'; +// eslint-disable-next-line import/no-extraneous-dependencies +import * as aws from 'aws-sdk'; +import { EksClient, ResourceEvent, ResourceHandler } from './common'; + +const MAX_CLUSTER_NAME_LEN = 100; + +export class ClusterResourceHandler extends ResourceHandler { + public get clusterName() { + if (!this.physicalResourceId) { + throw new Error('Cannot determine cluster name without physical resource ID'); + } + + return this.physicalResourceId; + } + + private readonly newProps: aws.EKS.CreateClusterRequest; + private readonly oldProps: Partial; + + constructor(eks: EksClient, event: ResourceEvent) { + super(eks, event); + + this.newProps = parseProps(this.event.ResourceProperties); + this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; + } + + // ------ + // CREATE + // ------ + + protected async onCreate(): Promise { + console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); + if (!this.newProps.roleArn) { + throw new Error('"roleArn" is required'); + } + + const clusterName = this.newProps.name || this.generateClusterName(); + + const resp = await this.eks.createCluster({ + ...this.newProps, + name: clusterName, + }); + + if (!resp.cluster) { + throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); + } + + return { + PhysicalResourceId: resp.cluster.name, + }; + } + + protected async isCreateComplete() { + return this.isActive(); + } + + // ------ + // DELETE + // ------ + + protected async onDelete(): Promise { + console.log(`onDelete: deleting cluster ${this.clusterName}`); + try { + await this.eks.deleteCluster({ name: this.clusterName }); + } catch (e) { + if (e.code !== 'ResourceNotFoundException') { + throw e; + } else { + console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); + } + } + return { + PhysicalResourceId: this.clusterName, + }; + } + + protected async isDeleteComplete(): Promise { + console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); + + try { + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); + } catch (e) { + if (e.code === 'ResourceNotFoundException') { + console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); + return { IsComplete: true }; + } + + console.log('describeCluster error:', e); + throw e; + } + + return { + IsComplete: false, + }; + } + + // ------ + // UPDATE + // ------ + + protected async onUpdate() { + const updates = analyzeUpdate(this.oldProps, this.newProps); + console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); + + // updates to encryption config is not supported + if (updates.updateEncryption) { + throw new Error('Cannot update cluster encryption configuration'); + } + + // if there is an update that requires replacement, go ahead and just create + // a new cluster with the new config. The old cluster will automatically be + // deleted by cloudformation upon success. + if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { + + // if we are replacing this cluster and the cluster has an explicit + // physical name, the creation of the new cluster will fail with "there is + // already a cluster with that name". this is a common behavior for + // CloudFormation resources that support specifying a physical name. + if (this.oldProps.name === this.newProps.name && this.oldProps.name) { + throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); + } + + return this.onCreate(); + } + + // if a version update is required, issue the version update + if (updates.updateVersion) { + if (!this.newProps.version) { + throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); + } + + return this.updateClusterVersion(this.newProps.version); + } + + if (updates.updateLogging && updates.updateAccess) { + throw new Error('Cannot update logging and access at the same time'); + } + + if (updates.updateLogging || updates.updateAccess) { + const config: aws.EKS.UpdateClusterConfigRequest = { + name: this.clusterName, + }; + if (updates.updateLogging) { + config.logging = this.newProps.logging; + }; + if (updates.updateAccess) { + // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: + // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) + // will fail, therefore we take only the access fields explicitly + config.resourcesVpcConfig = { + endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, + endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, + publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, + }; + } + const updateResponse = await this.eks.updateClusterConfig(config); + + return { EksUpdateId: updateResponse.update?.id }; + } + + // no updates + return; + } + + protected async isUpdateComplete() { + console.log('isUpdateComplete'); + + // if this is an EKS update, we will monitor the update event itself + if (this.event.EksUpdateId) { + const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); + if (!complete) { + return { IsComplete: false }; + } + + // fall through: if the update is done, we simply delegate to isActive() + // in order to extract attributes and state from the cluster itself, which + // is supposed to be in an ACTIVE state after the update is complete. + } + + return this.isActive(); + } + + private async updateClusterVersion(newVersion: string) { + console.log(`updating cluster version to ${newVersion}`); + + // update-cluster-version will fail if we try to update to the same version, + // so skip in this case. + const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; + if (cluster?.version === newVersion) { + console.log(`cluster already at version ${cluster.version}, skipping version update`); + return; + } + + const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); + return { EksUpdateId: updateResponse.update?.id }; + } + + private async isActive(): Promise { + console.log('waiting for cluster to become ACTIVE'); + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); + const cluster = resp.cluster; + + // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are + // not complete. note that the custom resource provider framework forbids + // returning attributes (Data) if isComplete is false. + if (cluster?.status === 'FAILED') { + // not very informative, unfortunately the response doesn't contain any error + // information :\ + throw new Error('Cluster is in a FAILED status'); + } else if (cluster?.status !== 'ACTIVE') { + return { + IsComplete: false, + }; + } else { + return { + IsComplete: true, + Data: { + Name: cluster.name, + Endpoint: cluster.endpoint, + Arn: cluster.arn, + + // IMPORTANT: CFN expects that attributes will *always* have values, + // so return an empty string in case the value is not defined. + // Otherwise, CFN will throw with `Vendor response doesn't contain + // XXXX key`. + + CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', + ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', + OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', + OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', // Strips off https:// from the issuer url + + // We can safely return the first item from encryption configuration array, because it has a limit of 1 item + // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig + EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', + }, + }; + } + } + + private async isEksUpdateComplete(eksUpdateId: string) { + this.log({ isEksUpdateComplete: eksUpdateId }); + + const describeUpdateResponse = await this.eks.describeUpdate({ + name: this.clusterName, + updateId: eksUpdateId, + }); + + this.log({ describeUpdateResponse }); + + if (!describeUpdateResponse.update) { + throw new Error(`unable to describe update with id "${eksUpdateId}"`); + } + + switch (describeUpdateResponse.update.status) { + case 'InProgress': + return false; + case 'Successful': + return true; + case 'Failed': + case 'Cancelled': + throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); + default: + throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); + } + } + + private generateClusterName() { + const suffix = this.requestId.replace(/-/g, ''); // 32 chars + const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; + const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); + return `${prefix}-${suffix}`; + } +} + +function parseProps(props: any): aws.EKS.CreateClusterRequest { + + const parsed = props?.Config ?? {}; + + // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. + // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' + + if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; + } + + if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; + } + + if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { + parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; + } + + return parsed; + +} + +interface UpdateMap { + replaceName: boolean; // name + replaceVpc: boolean; // resourcesVpcConfig.subnetIds and securityGroupIds + replaceRole: boolean; // roleArn + + updateVersion: boolean; // version + updateLogging: boolean; // logging + updateEncryption: boolean; // encryption (cannot be updated) + updateAccess: boolean; // resourcesVpcConfig.endpointPrivateAccess and endpointPublicAccess +} + +function analyzeUpdate(oldProps: Partial, newProps: aws.EKS.CreateClusterRequest): UpdateMap { + console.log('old props: ', JSON.stringify(oldProps)); + console.log('new props: ', JSON.stringify(newProps)); + + const newVpcProps = newProps.resourcesVpcConfig || {}; + const oldVpcProps = oldProps.resourcesVpcConfig || {}; + + const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); + const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); + const newEnc = newProps.encryptionConfig || {}; + const oldEnc = oldProps.encryptionConfig || {}; + + return { + replaceName: newProps.name !== oldProps.name, + replaceVpc: + JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), + updateAccess: + newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || + newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || + !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), + replaceRole: newProps.roleArn !== oldProps.roleArn, + updateVersion: newProps.version !== oldProps.version, + updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), + updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), + }; +} + +function setsEqual(first: Set, second: Set) { + return first.size === second.size && [...first].every((e: string) => second.has(e)); +} diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.d.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.d.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.js b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.js rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.d.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.d.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.js b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.js rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.d.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.d.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.js b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.js rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.d.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.d.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.js b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.js rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip index 298edd40a09fc..f62fe1e5a06d6 100644 Binary files a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip and b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip differ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js deleted file mode 100644 index 1d08e9d7b865b..0000000000000 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js +++ /dev/null @@ -1,273 +0,0 @@ -"use strict"; -/* eslint-disable no-console */ -Object.defineProperty(exports, "__esModule", { value: true }); -exports.ClusterResourceHandler = void 0; -const common_1 = require("./common"); -const MAX_CLUSTER_NAME_LEN = 100; -class ClusterResourceHandler extends common_1.ResourceHandler { - constructor(eks, event) { - super(eks, event); - this.newProps = parseProps(this.event.ResourceProperties); - this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; - } - get clusterName() { - if (!this.physicalResourceId) { - throw new Error('Cannot determine cluster name without physical resource ID'); - } - return this.physicalResourceId; - } - // ------ - // CREATE - // ------ - async onCreate() { - console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); - if (!this.newProps.roleArn) { - throw new Error('"roleArn" is required'); - } - const clusterName = this.newProps.name || this.generateClusterName(); - const resp = await this.eks.createCluster({ - ...this.newProps, - name: clusterName, - }); - if (!resp.cluster) { - throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); - } - return { - PhysicalResourceId: resp.cluster.name, - }; - } - async isCreateComplete() { - return this.isActive(); - } - // ------ - // DELETE - // ------ - async onDelete() { - console.log(`onDelete: deleting cluster ${this.clusterName}`); - try { - await this.eks.deleteCluster({ name: this.clusterName }); - } - catch (e) { - if (e.code !== 'ResourceNotFoundException') { - throw e; - } - else { - console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); - } - } - return { - PhysicalResourceId: this.clusterName, - }; - } - async isDeleteComplete() { - console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); - try { - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); - } - catch (e) { - if (e.code === 'ResourceNotFoundException') { - console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); - return { IsComplete: true }; - } - console.log('describeCluster error:', e); - throw e; - } - return { - IsComplete: false, - }; - } - // ------ - // UPDATE - // ------ - async onUpdate() { - const updates = analyzeUpdate(this.oldProps, this.newProps); - console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); - // updates to encryption config is not supported - if (updates.updateEncryption) { - throw new Error('Cannot update cluster encryption configuration'); - } - // if there is an update that requires replacement, go ahead and just create - // a new cluster with the new config. The old cluster will automatically be - // deleted by cloudformation upon success. - if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { - // if we are replacing this cluster and the cluster has an explicit - // physical name, the creation of the new cluster will fail with "there is - // already a cluster with that name". this is a common behavior for - // CloudFormation resources that support specifying a physical name. - if (this.oldProps.name === this.newProps.name && this.oldProps.name) { - throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); - } - return this.onCreate(); - } - // if a version update is required, issue the version update - if (updates.updateVersion) { - if (!this.newProps.version) { - throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); - } - return this.updateClusterVersion(this.newProps.version); - } - if (updates.updateLogging && updates.updateAccess) { - throw new Error('Cannot update logging and access at the same time'); - } - if (updates.updateLogging || updates.updateAccess) { - const config = { - name: this.clusterName, - }; - if (updates.updateLogging) { - config.logging = this.newProps.logging; - } - ; - if (updates.updateAccess) { - // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: - // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) - // will fail, therefore we take only the access fields explicitly - config.resourcesVpcConfig = { - endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, - endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, - publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, - }; - } - const updateResponse = await this.eks.updateClusterConfig(config); - return { EksUpdateId: updateResponse.update?.id }; - } - // no updates - return; - } - async isUpdateComplete() { - console.log('isUpdateComplete'); - // if this is an EKS update, we will monitor the update event itself - if (this.event.EksUpdateId) { - const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); - if (!complete) { - return { IsComplete: false }; - } - // fall through: if the update is done, we simply delegate to isActive() - // in order to extract attributes and state from the cluster itself, which - // is supposed to be in an ACTIVE state after the update is complete. - } - return this.isActive(); - } - async updateClusterVersion(newVersion) { - console.log(`updating cluster version to ${newVersion}`); - // update-cluster-version will fail if we try to update to the same version, - // so skip in this case. - const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; - if (cluster?.version === newVersion) { - console.log(`cluster already at version ${cluster.version}, skipping version update`); - return; - } - const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); - return { EksUpdateId: updateResponse.update?.id }; - } - async isActive() { - console.log('waiting for cluster to become ACTIVE'); - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); - const cluster = resp.cluster; - // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are - // not complete. note that the custom resource provider framework forbids - // returning attributes (Data) if isComplete is false. - if (cluster?.status === 'FAILED') { - // not very informative, unfortunately the response doesn't contain any error - // information :\ - throw new Error('Cluster is in a FAILED status'); - } - else if (cluster?.status !== 'ACTIVE') { - return { - IsComplete: false, - }; - } - else { - return { - IsComplete: true, - Data: { - Name: cluster.name, - Endpoint: cluster.endpoint, - Arn: cluster.arn, - // IMPORTANT: CFN expects that attributes will *always* have values, - // so return an empty string in case the value is not defined. - // Otherwise, CFN will throw with `Vendor response doesn't contain - // XXXX key`. - CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', - ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', - OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', - OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', - // We can safely return the first item from encryption configuration array, because it has a limit of 1 item - // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig - EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', - }, - }; - } - } - async isEksUpdateComplete(eksUpdateId) { - this.log({ isEksUpdateComplete: eksUpdateId }); - const describeUpdateResponse = await this.eks.describeUpdate({ - name: this.clusterName, - updateId: eksUpdateId, - }); - this.log({ describeUpdateResponse }); - if (!describeUpdateResponse.update) { - throw new Error(`unable to describe update with id "${eksUpdateId}"`); - } - switch (describeUpdateResponse.update.status) { - case 'InProgress': - return false; - case 'Successful': - return true; - case 'Failed': - case 'Cancelled': - throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); - default: - throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); - } - } - generateClusterName() { - const suffix = this.requestId.replace(/-/g, ''); // 32 chars - const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; - const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); - return `${prefix}-${suffix}`; - } -} -exports.ClusterResourceHandler = ClusterResourceHandler; -function parseProps(props) { - const parsed = props?.Config ?? {}; - // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. - // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' - if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; - } - if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; - } - if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { - parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; - } - return parsed; -} -function analyzeUpdate(oldProps, newProps) { - console.log('old props: ', JSON.stringify(oldProps)); - console.log('new props: ', JSON.stringify(newProps)); - const newVpcProps = newProps.resourcesVpcConfig || {}; - const oldVpcProps = oldProps.resourcesVpcConfig || {}; - const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); - const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); - const newEnc = newProps.encryptionConfig || {}; - const oldEnc = oldProps.encryptionConfig || {}; - return { - replaceName: newProps.name !== oldProps.name, - replaceVpc: JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), - updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || - newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || - !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), - replaceRole: newProps.roleArn !== oldProps.roleArn, - updateVersion: newProps.version !== oldProps.version, - updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), - updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), - }; -} -function setsEqual(first, second) { - return first.size === second.size && [...first].every((e) => second.has(e)); -} -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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SSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBa0IsRUFBRSxNQUFtQjtJQUN4RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgRWtzQ2xpZW50LCBSZXNvdXJjZUV2ZW50LCBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX05BTUVfTEVOID0gMTAwO1xuXG5leHBvcnQgY2xhc3MgQ2x1c3RlclJlc291cmNlSGFuZGxlciBleHRlbmRzIFJlc291cmNlSGFuZGxlciB7XG4gIHB1YmxpYyBnZXQgY2x1c3Rlck5hbWUoKSB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZGV0ZXJtaW5lIGNsdXN0ZXIgbmFtZSB3aXRob3V0IHBoeXNpY2FsIHJlc291cmNlIElEJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PjtcblxuICBjb25zdHJ1Y3Rvcihla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICBzdXBlcihla3MsIGV2ZW50KTtcblxuICAgIHRoaXMubmV3UHJvcHMgPSBwYXJzZVByb3BzKHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLm9sZFByb3BzID0gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnID8gcGFyc2VQcm9wcyhldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMpIDoge307XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gQ1JFQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCdvbkNyZWF0ZTogY3JlYXRpbmcgY2x1c3RlciB3aXRoIG9wdGlvbnM6JywgSlNPTi5zdHJpbmdpZnkodGhpcy5uZXdQcm9wcywgdW5kZWZpbmVkLCAyKSk7XG4gICAgaWYgKCF0aGlzLm5ld1Byb3BzLnJvbGVBcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJyb2xlQXJuXCIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyTmFtZSA9IHRoaXMubmV3UHJvcHMubmFtZSB8fCB0aGlzLmdlbmVyYXRlQ2x1c3Rlck5hbWUoKTtcblxuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmVrcy5jcmVhdGVDbHVzdGVyKHtcbiAgICAgIC4uLnRoaXMubmV3UHJvcHMsXG4gICAgICBuYW1lOiBjbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcC5jbHVzdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBjbHVzdGVyICR7Y2x1c3Rlck5hbWV9OiBDcmVhdGVDbHVzdGVyIHJldHVybmVkIHdpdGhvdXQgY2x1c3RlciBpbmZvcm1hdGlvbmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHJlc3AuY2x1c3Rlci5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIERFTEVURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25EZWxldGUoKTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgb25EZWxldGU6IGRlbGV0aW5nIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfWApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVrcy5kZWxldGVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyICR7dGhpcy5jbHVzdGVyTmFtZX0gbm90IGZvdW5kLCBpZGVtcG90ZW50bHkgc3VjY2VlZGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coYGlzRGVsZXRlQ29tcGxldGU6IHdhaXRpbmcgZm9yIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSB0byBiZSBkZWxldGVkYCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJldHVybmVkOicsIEpTT04uc3RyaW5naWZ5KHJlc3AsIHVuZGVmaW5lZCwgMikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICBjb25zb2xlLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgY2x1c3RlciBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0cnVlIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgZXJyb3I6JywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIFVQREFURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IGFuYWx5emVVcGRhdGUodGhpcy5vbGRQcm9wcywgdGhpcy5uZXdQcm9wcyk7XG4gICAgY29uc29sZS5sb2coJ29uVXBkYXRlOicsIEpTT04uc3RyaW5naWZ5KHsgdXBkYXRlcyB9LCB1bmRlZmluZWQsIDIpKTtcblxuICAgIC8vIHVwZGF0ZXMgdG8gZW5jcnlwdGlvbiBjb25maWcgaXMgbm90IHN1cHBvcnRlZFxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUVuY3J5cHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHVwZGF0ZSBjbHVzdGVyIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZXJlIGlzIGFuIHVwZGF0ZSB0aGF0IHJlcXVpcmVzIHJlcGxhY2VtZW50LCBnbyBhaGVhZCBhbmQganVzdCBjcmVhdGVcbiAgICAvLyBhIG5ldyBjbHVzdGVyIHdpdGggdGhlIG5ldyBjb25maWcuIFRoZSBvbGQgY2x1c3RlciB3aWxsIGF1dG9tYXRpY2FsbHkgYmVcbiAgICAvLyBkZWxldGVkIGJ5IGNsb3VkZm9ybWF0aW9uIHVwb24gc3VjY2Vzcy5cbiAgICBpZiAodXBkYXRlcy5yZXBsYWNlTmFtZSB8fCB1cGRhdGVzLnJlcGxhY2VSb2xlIHx8IHVwZGF0ZXMucmVwbGFjZVZwYykge1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgcmVwbGFjaW5nIHRoaXMgY2x1c3RlciBhbmQgdGhlIGNsdXN0ZXIgaGFzIGFuIGV4cGxpY2l0XG4gICAgICAvLyBwaHlzaWNhbCBuYW1lLCB0aGUgY3JlYXRpb24gb2YgdGhlIG5ldyBjbHVzdGVyIHdpbGwgZmFpbCB3aXRoIFwidGhlcmUgaXNcbiAgICAgIC8vIGFscmVhZHkgYSBjbHVzdGVyIHdpdGggdGhhdCBuYW1lXCIuIHRoaXMgaXMgYSBjb21tb24gYmVoYXZpb3IgZm9yXG4gICAgICAvLyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZXMgdGhhdCBzdXBwb3J0IHNwZWNpZnlpbmcgYSBwaHlzaWNhbCBuYW1lLlxuICAgICAgaWYgKHRoaXMub2xkUHJvcHMubmFtZSA9PT0gdGhpcy5uZXdQcm9wcy5uYW1lICYmIHRoaXMub2xkUHJvcHMubmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXBsYWNlIGNsdXN0ZXIgXCIke3RoaXMub2xkUHJvcHMubmFtZX1cIiBzaW5jZSBpdCBoYXMgYW4gZXhwbGljaXQgcGh5c2ljYWwgbmFtZS4gRWl0aGVyIHJlbmFtZSB0aGUgY2x1c3RlciBvciByZW1vdmUgdGhlIFwibmFtZVwiIGNvbmZpZ3VyYXRpb25gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub25DcmVhdGUoKTtcbiAgICB9XG5cbiAgICAvLyBpZiBhIHZlcnNpb24gdXBkYXRlIGlzIHJlcXVpcmVkLCBpc3N1ZSB0aGUgdmVyc2lvbiB1cGRhdGVcbiAgICBpZiAodXBkYXRlcy51cGRhdGVWZXJzaW9uKSB7XG4gICAgICBpZiAoIXRoaXMubmV3UHJvcHMudmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZW1vdmUgY2x1c3RlciB2ZXJzaW9uIGNvbmZpZ3VyYXRpb24uIEN1cnJlbnQgdmVyc2lvbiBpcyAke3RoaXMub2xkUHJvcHMudmVyc2lvbn1gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlQ2x1c3RlclZlcnNpb24odGhpcy5uZXdQcm9wcy52ZXJzaW9uKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nICYmIHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1cGRhdGUgbG9nZ2luZyBhbmQgYWNjZXNzIGF0IHRoZSBzYW1lIHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nIHx8IHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICBjb25zdCBjb25maWc6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QgPSB7XG4gICAgICAgIG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgICB9O1xuICAgICAgaWYgKHVwZGF0ZXMudXBkYXRlTG9nZ2luZykge1xuICAgICAgICBjb25maWcubG9nZ2luZyA9IHRoaXMubmV3UHJvcHMubG9nZ2luZztcbiAgICAgIH07XG4gICAgICBpZiAodXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIGNsdXN0ZXIgd2l0aCBzZWN1cml0eUdyb3VwSWRzIGFuZCBzdWJuZXRJZHMgKGFzIHNwZWNpZmllZCBpbiB0aGUgd2FybmluZyBoZXJlOlxuICAgICAgICAvLyBodHRwczovL2F3c2NsaS5hbWF6b25hd3MuY29tL3YyL2RvY3VtZW50YXRpb24vYXBpL2xhdGVzdC9yZWZlcmVuY2UvZWtzL3VwZGF0ZS1jbHVzdGVyLWNvbmZpZy5odG1sKVxuICAgICAgICAvLyB3aWxsIGZhaWwsIHRoZXJlZm9yZSB3ZSB0YWtlIG9ubHkgdGhlIGFjY2VzcyBmaWVsZHMgZXhwbGljaXRseVxuICAgICAgICBjb25maWcucmVzb3VyY2VzVnBjQ29uZmlnID0ge1xuICAgICAgICAgIGVuZHBvaW50UHJpdmF0ZUFjY2VzczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzLFxuICAgICAgICAgIGVuZHBvaW50UHVibGljQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyxcbiAgICAgICAgICBwdWJsaWNBY2Nlc3NDaWRyczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcucHVibGljQWNjZXNzQ2lkcnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgICB9XG5cbiAgICAvLyBubyB1cGRhdGVzXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc29sZS5sb2coJ2lzVXBkYXRlQ29tcGxldGUnKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYW4gRUtTIHVwZGF0ZSwgd2Ugd2lsbCBtb25pdG9yIHRoZSB1cGRhdGUgZXZlbnQgaXRzZWxmXG4gICAgaWYgKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gYXdhaXQgdGhpcy5pc0Vrc1VwZGF0ZUNvbXBsZXRlKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpO1xuICAgICAgaWYgKCFjb21wbGV0ZSkge1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiBmYWxzZSB9O1xuICAgICAgfVxuXG4gICAgICAvLyBmYWxsIHRocm91Z2g6IGlmIHRoZSB1cGRhdGUgaXMgZG9uZSwgd2Ugc2ltcGx5IGRlbGVnYXRlIHRvIGlzQWN0aXZlKClcbiAgICAgIC8vIGluIG9yZGVyIHRvIGV4dHJhY3QgYXR0cmlidXRlcyBhbmQgc3RhdGUgZnJvbSB0aGUgY2x1c3RlciBpdHNlbGYsIHdoaWNoXG4gICAgICAvLyBpcyBzdXBwb3NlZCB0byBiZSBpbiBhbiBBQ1RJVkUgc3RhdGUgYWZ0ZXIgdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbHVzdGVyVmVyc2lvbihuZXdWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgdXBkYXRpbmcgY2x1c3RlciB2ZXJzaW9uIHRvICR7bmV3VmVyc2lvbn1gKTtcblxuICAgIC8vIHVwZGF0ZS1jbHVzdGVyLXZlcnNpb24gd2lsbCBmYWlsIGlmIHdlIHRyeSB0byB1cGRhdGUgdG8gdGhlIHNhbWUgdmVyc2lvbixcbiAgICAvLyBzbyBza2lwIGluIHRoaXMgY2FzZS5cbiAgICBjb25zdCBjbHVzdGVyID0gKGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSkpLmNsdXN0ZXI7XG4gICAgaWYgKGNsdXN0ZXI/LnZlcnNpb24gPT09IG5ld1ZlcnNpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyIGFscmVhZHkgYXQgdmVyc2lvbiAke2NsdXN0ZXIudmVyc2lvbn0sIHNraXBwaW5nIHZlcnNpb24gdXBkYXRlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy51cGRhdGVDbHVzdGVyVmVyc2lvbih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsIHZlcnNpb246IG5ld1ZlcnNpb24gfSk7XG4gICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNBY3RpdmUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZygnd2FpdGluZyBmb3IgY2x1c3RlciB0byBiZWNvbWUgQUNUSVZFJyk7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciByZXN1bHQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgY29uc3QgY2x1c3RlciA9IHJlc3AuY2x1c3RlcjtcblxuICAgIC8vIGlmIGNsdXN0ZXIgaXMgdW5kZWZpbmVkIChzaG91bGRudCBoYXBwZW4pIG9yIHN0YXR1cyBpcyBub3QgQUNUSVZFLCB3ZSBhcmVcbiAgICAvLyBub3QgY29tcGxldGUuIG5vdGUgdGhhdCB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZyYW1ld29yayBmb3JiaWRzXG4gICAgLy8gcmV0dXJuaW5nIGF0dHJpYnV0ZXMgKERhdGEpIGlmIGlzQ29tcGxldGUgaXMgZmFsc2UuXG4gICAgaWYgKGNsdXN0ZXI/LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgIC8vIG5vdCB2ZXJ5IGluZm9ybWF0aXZlLCB1bmZvcnR1bmF0ZWx5IHRoZSByZXNwb25zZSBkb2Vzbid0IGNvbnRhaW4gYW55IGVycm9yXG4gICAgICAvLyBpbmZvcm1hdGlvbiA6XFxcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2x1c3RlciBpcyBpbiBhIEZBSUxFRCBzdGF0dXMnKTtcbiAgICB9IGVsc2UgaWYgKGNsdXN0ZXI/LnN0YXR1cyAhPT0gJ0FDVElWRScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIE5hbWU6IGNsdXN0ZXIubmFtZSxcbiAgICAgICAgICBFbmRwb2ludDogY2x1c3Rlci5lbmRwb2ludCxcbiAgICAgICAgICBBcm46IGNsdXN0ZXIuYXJuLFxuXG4gICAgICAgICAgLy8gSU1QT1JUQU5UOiBDRk4gZXhwZWN0cyB0aGF0IGF0dHJpYnV0ZXMgd2lsbCAqYWx3YXlzKiBoYXZlIHZhbHVlcyxcbiAgICAgICAgICAvLyBzbyByZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGluIGNhc2UgdGhlIHZhbHVlIGlzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQ0ZOIHdpbGwgdGhyb3cgd2l0aCBgVmVuZG9yIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpblxuICAgICAgICAgIC8vIFhYWFgga2V5YC5cblxuICAgICAgICAgIENlcnRpZmljYXRlQXV0aG9yaXR5RGF0YTogY2x1c3Rlci5jZXJ0aWZpY2F0ZUF1dGhvcml0eT8uZGF0YSA/PyAnJyxcbiAgICAgICAgICBDbHVzdGVyU2VjdXJpdHlHcm91cElkOiBjbHVzdGVyLnJlc291cmNlc1ZwY0NvbmZpZz8uY2x1c3RlclNlY3VyaXR5R3JvdXBJZCA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyVXJsOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXIgPz8gJycsXG4gICAgICAgICAgT3BlbklkQ29ubmVjdElzc3VlcjogY2x1c3Rlci5pZGVudGl0eT8ub2lkYz8uaXNzdWVyPy5zdWJzdHJpbmcoOCkgPz8gJycsIC8vIFN0cmlwcyBvZmYgaHR0cHM6Ly8gZnJvbSB0aGUgaXNzdWVyIHVybFxuXG4gICAgICAgICAgLy8gV2UgY2FuIHNhZmVseSByZXR1cm4gdGhlIGZpcnN0IGl0ZW0gZnJvbSBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gYXJyYXksIGJlY2F1c2UgaXQgaGFzIGEgbGltaXQgb2YgMSBpdGVtXG4gICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vrcy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDbHVzdGVyLmh0bWwjQW1hem9uRUtTLUNyZWF0ZUNsdXN0ZXItcmVxdWVzdC1lbmNyeXB0aW9uQ29uZmlnXG4gICAgICAgICAgRW5jcnlwdGlvbkNvbmZpZ0tleUFybjogY2x1c3Rlci5lbmNyeXB0aW9uQ29uZmlnPy5zaGlmdCgpPy5wcm92aWRlcj8ua2V5QXJuID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzRWtzVXBkYXRlQ29tcGxldGUoZWtzVXBkYXRlSWQ6IHN0cmluZykge1xuICAgIHRoaXMubG9nKHsgaXNFa3NVcGRhdGVDb21wbGV0ZTogZWtzVXBkYXRlSWQgfSk7XG5cbiAgICBjb25zdCBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVVcGRhdGUoe1xuICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgIHVwZGF0ZUlkOiBla3NVcGRhdGVJZCxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nKHsgZGVzY3JpYmVVcGRhdGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5hYmxlIHRvIGRlc2NyaWJlIHVwZGF0ZSB3aXRoIGlkIFwiJHtla3NVcGRhdGVJZH1cImApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzKSB7XG4gICAgICBjYXNlICdJblByb2dyZXNzJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgY2FzZSAnU3VjY2Vzc2Z1bCc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnRmFpbGVkJzpcbiAgICAgIGNhc2UgJ0NhbmNlbGxlZCc6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2x1c3RlciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiIGZhaWxlZCB3aXRoIGVycm9yczogJHtKU09OLnN0cmluZ2lmeShkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5lcnJvcnMpfWApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIHN0YXR1cyBcIiR7ZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzfVwiIGZvciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNsdXN0ZXJOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9DTFVTVEVSX05BTUVfTEVOIC0gc3VmZml4Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5sb2dpY2FsUmVzb3VyY2VJZC5zbGljZSgwLCBvZmZzZXQgPiAwID8gb2Zmc2V0IDogMCk7XG4gICAgcmV0dXJuIGAke3ByZWZpeH0tJHtzdWZmaXh9YDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3BzKHByb3BzOiBhbnkpOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0IHtcblxuICBjb25zdCBwYXJzZWQgPSBwcm9wcz8uQ29uZmlnID8/IHt9O1xuXG4gIC8vIHRoaXMgaXMgd2VpcmQgYnV0IHRoZXNlIGJvb2xlYW4gcHJvcGVydGllcyBhcmUgcGFzc2VkIGJ5IENGTiBhcyBhIHN0cmluZywgYW5kIHdlIG5lZWQgdGhlbSB0byBiZSBib29sZWFuaWMgZm9yIHRoZSBTREsuXG4gIC8vIE90aGVyd2lzZSBpdCBmYWlscyB3aXRoICdVbmV4cGVjdGVkIFBhcmFtZXRlcjogcGFyYW1zLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgaXMgZXhwZWN0ZWQgdG8gYmUgYSBib29sZWFuJ1xuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWc/LmVuZHBvaW50UHJpdmF0ZUFjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9PT0gJ3RydWUnO1xuICB9XG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQdWJsaWNBY2Nlc3MpID09PSAnc3RyaW5nJykge1xuICAgIHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQubG9nZ2luZz8uY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCkgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9IHBhcnNlZC5sb2dnaW5nLmNsdXN0ZXJMb2dnaW5nWzBdLmVuYWJsZWQgPT09ICd0cnVlJztcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQ7XG5cbn1cblxuaW50ZXJmYWNlIFVwZGF0ZU1hcCB7XG4gIHJlcGxhY2VOYW1lOiBib29sZWFuOyAvLyBuYW1lXG4gIHJlcGxhY2VWcGM6IGJvb2xlYW47IC8vIHJlc291cmNlc1ZwY0NvbmZpZy5zdWJuZXRJZHMgYW5kIHNlY3VyaXR5R3JvdXBJZHNcbiAgcmVwbGFjZVJvbGU6IGJvb2xlYW47IC8vIHJvbGVBcm5cblxuICB1cGRhdGVWZXJzaW9uOiBib29sZWFuOyAvLyB2ZXJzaW9uXG4gIHVwZGF0ZUxvZ2dpbmc6IGJvb2xlYW47IC8vIGxvZ2dpbmdcbiAgdXBkYXRlRW5jcnlwdGlvbjogYm9vbGVhbjsgLy8gZW5jcnlwdGlvbiAoY2Fubm90IGJlIHVwZGF0ZWQpXG4gIHVwZGF0ZUFjY2VzczogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBhbmQgZW5kcG9pbnRQdWJsaWNBY2Nlc3Ncbn1cblxuZnVuY3Rpb24gYW5hbHl6ZVVwZGF0ZShvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PiwgbmV3UHJvcHM6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBVcGRhdGVNYXAge1xuICBjb25zb2xlLmxvZygnb2xkIHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShvbGRQcm9wcykpO1xuICBjb25zb2xlLmxvZygnbmV3IHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShuZXdQcm9wcykpO1xuXG4gIGNvbnN0IG5ld1ZwY1Byb3BzID0gbmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRWcGNQcm9wcyA9IG9sZFByb3BzLnJlc291cmNlc1ZwY0NvbmZpZyB8fCB7fTtcblxuICBjb25zdCBvbGRQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQob2xkVnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQobmV3VnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdFbmMgPSBuZXdQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRFbmMgPSBvbGRQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgcmVwbGFjZU5hbWU6IG5ld1Byb3BzLm5hbWUgIT09IG9sZFByb3BzLm5hbWUsXG4gICAgcmVwbGFjZVZwYzpcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnN1Ym5ldElkcykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFZwY1Byb3BzLnN1Ym5ldElkcykgfHxcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnNlY3VyaXR5R3JvdXBJZHMpICE9PSBKU09OLnN0cmluZ2lmeShvbGRWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzKSxcbiAgICB1cGRhdGVBY2Nlc3M6XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgIT09IG9sZFZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyB8fFxuICAgICAgbmV3VnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgIT09IG9sZFZwY1Byb3BzLmVuZHBvaW50UHVibGljQWNjZXNzIHx8XG4gICAgICAhc2V0c0VxdWFsKG5ld1B1YmxpY0FjY2Vzc0NpZHJzLCBvbGRQdWJsaWNBY2Nlc3NDaWRycyksXG4gICAgcmVwbGFjZVJvbGU6IG5ld1Byb3BzLnJvbGVBcm4gIT09IG9sZFByb3BzLnJvbGVBcm4sXG4gICAgdXBkYXRlVmVyc2lvbjogbmV3UHJvcHMudmVyc2lvbiAhPT0gb2xkUHJvcHMudmVyc2lvbixcbiAgICB1cGRhdGVFbmNyeXB0aW9uOiBKU09OLnN0cmluZ2lmeShuZXdFbmMpICE9PSBKU09OLnN0cmluZ2lmeShvbGRFbmMpLFxuICAgIHVwZGF0ZUxvZ2dpbmc6IEpTT04uc3RyaW5naWZ5KG5ld1Byb3BzLmxvZ2dpbmcpICE9PSBKU09OLnN0cmluZ2lmeShvbGRQcm9wcy5sb2dnaW5nKSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gc2V0c0VxdWFsKGZpcnN0OiBTZXQ8c3RyaW5nPiwgc2Vjb25kOiBTZXQ8c3RyaW5nPikge1xuICByZXR1cm4gZmlyc3Quc2l6ZSA9PT0gc2Vjb25kLnNpemUgJiYgWy4uLmZpcnN0XS5ldmVyeSgoZTogc3RyaW5nKSA9PiBzZWNvbmQuaGFzKGUpKTtcbn1cbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/helm/__init__.py b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/helm/__init__.py deleted file mode 100644 index a7b26b264118b..0000000000000 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/helm/__init__.py +++ /dev/null @@ -1,189 +0,0 @@ -import json -import logging -import os -import re -import subprocess -import shutil -import tempfile -import zipfile -from urllib.parse import urlparse, unquote - -logger = logging.getLogger() -logger.setLevel(logging.INFO) - -# these are coming from the kubectl layer -os.environ['PATH'] = '/opt/helm:/opt/awscli:' + os.environ['PATH'] - -outdir = os.environ.get('TEST_OUTDIR', '/tmp') -kubeconfig = os.path.join(outdir, 'kubeconfig') - -def get_chart_asset_from_url(chart_asset_url): - chart_zip = os.path.join(outdir, 'chart.zip') - shutil.rmtree(chart_zip, ignore_errors=True) - subprocess.check_call(['aws', 's3', 'cp', chart_asset_url, chart_zip]) - chart_dir = os.path.join(outdir, 'chart') - shutil.rmtree(chart_dir, ignore_errors=True) - os.mkdir(chart_dir) - with zipfile.ZipFile(chart_zip, 'r') as zip_ref: - zip_ref.extractall(chart_dir) - return chart_dir - -def helm_handler(event, context): - logger.info(json.dumps(dict(event, ResponseURL='...'))) - - request_type = event['RequestType'] - props = event['ResourceProperties'] - - # resource properties - cluster_name = props['ClusterName'] - role_arn = props['RoleArn'] - release = props['Release'] - chart = props.get('Chart', None) - chart_asset_url = props.get('ChartAssetURL', None) - version = props.get('Version', None) - wait = props.get('Wait', False) - timeout = props.get('Timeout', None) - namespace = props.get('Namespace', None) - create_namespace = props.get('CreateNamespace', None) - repository = props.get('Repository', None) - values_text = props.get('Values', None) - - # "log in" to the cluster - subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig', - '--role-arn', role_arn, - '--name', cluster_name, - '--kubeconfig', kubeconfig - ]) - - if os.path.isfile(kubeconfig): - os.chmod(kubeconfig, 0o600) - - # Write out the values to a file and include them with the install and upgrade - values_file = None - if not request_type == "Delete" and not values_text is None: - values = json.loads(values_text) - values_file = os.path.join(outdir, 'values.yaml') - with open(values_file, "w") as f: - f.write(json.dumps(values, indent=2)) - - if request_type == 'Create' or request_type == 'Update': - # Ensure chart or chart_asset_url are set - if chart == None and chart_asset_url == None: - raise RuntimeError(f'chart or chartAsset must be specified') - - if chart_asset_url != None: - assert(chart==None) - assert(repository==None) - assert(version==None) - if not chart_asset_url.startswith('s3://'): - raise RuntimeError(f'ChartAssetURL must point to as s3 location but is {chart_asset_url}') - # future work: support versions from s3 assets - chart = get_chart_asset_from_url(chart_asset_url) - - if repository is not None and repository.startswith('oci://'): - tmpdir = tempfile.TemporaryDirectory() - chart_dir = get_chart_from_oci(tmpdir.name, repository, version) - chart = chart_dir - - helm('upgrade', release, chart, repository, values_file, namespace, version, wait, timeout, create_namespace) - elif request_type == "Delete": - try: - helm('uninstall', release, namespace=namespace, timeout=timeout) - except Exception as e: - logger.info("delete error: %s" % e) - - -def get_oci_cmd(repository, version): - # Generates OCI command based on pattern. Public ECR vs Private ECR are treated differently. - cmnd = [] - private_ecr_pattern = '\d+.dkr.ecr.[a-z]+-[a-z]+-\d.amazonaws.com' - public_ecr = 'public.ecr.aws' - - registry = repository.rsplit('/', 1)[0].replace('oci://', '') - - if re.fullmatch(private_ecr_pattern, registry) is not None: - logger.info("Found AWS private repository") - region = registry.replace('.amazonaws.com', '').split('.')[-1] - cmnd = [ - f"aws ecr get-login-password --region {region} | " \ - f"helm registry login --username AWS --password-stdin {registry}; helm pull {repository} --version {version} --untar" - ] - elif registry.startswith(public_ecr): - logger.info("Found AWS public repository, will use default region as deployment") - region = os.environ.get('AWS_REGION', 'us-east-1') - - cmnd = [ - f"aws ecr-public get-login-password --region {region} | " \ - f"helm registry login --username AWS --password-stdin {public_ecr}; helm pull {repository} --version {version} --untar" - ] - else: - logger.error("OCI repository format not recognized, falling back to helm pull") - cmnd = ['helm', 'pull', repository, '--version', version, '--untar'] - - return cmnd - - -def get_chart_from_oci(tmpdir, repository = None, version = None): - - cmnd = get_oci_cmd(repository, version) - - maxAttempts = 3 - retry = maxAttempts - while retry > 0: - try: - logger.info(cmnd) - output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=tmpdir, shell=True) - logger.info(output) - - # effectively returns "$tmpDir/$lastPartOfOCIUrl", because this is how helm pull saves OCI artifact. - # Eg. if we have oci://9999999999.dkr.ecr.us-east-1.amazonaws.com/foo/bar/pet-service repository, helm saves artifact under $tmpDir/pet-service - return os.path.join(tmpdir, repository.rpartition('/')[-1]) - except subprocess.CalledProcessError as exc: - output = exc.output - if b'Broken pipe' in output: - retry = retry - 1 - logger.info("Broken pipe, retries left: %s" % retry) - else: - raise Exception(output) - raise Exception(f'Operation failed after {maxAttempts} attempts: {output}') - - -def helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None): - import subprocess - - cmnd = ['helm', verb, release] - if not chart is None: - cmnd.append(chart) - if verb == 'upgrade': - cmnd.append('--install') - if create_namespace: - cmnd.append('--create-namespace') - if not repo is None: - cmnd.extend(['--repo', repo]) - if not file is None: - cmnd.extend(['--values', file]) - if not version is None: - cmnd.extend(['--version', version]) - if not namespace is None: - cmnd.extend(['--namespace', namespace]) - if wait: - cmnd.append('--wait') - if not timeout is None: - cmnd.extend(['--timeout', timeout]) - cmnd.extend(['--kubeconfig', kubeconfig]) - - maxAttempts = 3 - retry = maxAttempts - while retry > 0: - try: - output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir) - logger.info(output) - return - except subprocess.CalledProcessError as exc: - output = exc.output - if b'Broken pipe' in output: - retry = retry - 1 - logger.info("Broken pipe, retries left: %s" % retry) - else: - raise Exception(output) - raise Exception(f'Operation failed after {maxAttempts} attempts: {output}') diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip index ce3ea448ac19d..13983109fc5f5 100644 Binary files a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip and b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip differ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/apply/__init__.py b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/apply/__init__.py rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/get/__init__.py b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/get/__init__.py rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py new file mode 100644 index 0000000000000..286976ced219a --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py @@ -0,0 +1,187 @@ +import json +import logging +import os +import re +import subprocess +import shutil +import tempfile +import zipfile + +logger = logging.getLogger() +logger.setLevel(logging.INFO) + +# these are coming from the kubectl layer +os.environ['PATH'] = '/opt/helm:/opt/awscli:' + os.environ['PATH'] + +outdir = os.environ.get('TEST_OUTDIR', '/tmp') +kubeconfig = os.path.join(outdir, 'kubeconfig') + +def get_chart_asset_from_url(chart_asset_url): + chart_zip = os.path.join(outdir, 'chart.zip') + shutil.rmtree(chart_zip, ignore_errors=True) + subprocess.check_call(['aws', 's3', 'cp', chart_asset_url, chart_zip]) + chart_dir = os.path.join(outdir, 'chart') + shutil.rmtree(chart_dir, ignore_errors=True) + os.mkdir(chart_dir) + with zipfile.ZipFile(chart_zip, 'r') as zip_ref: + zip_ref.extractall(chart_dir) + return chart_dir + +def helm_handler(event, context): + logger.info(json.dumps(dict(event, ResponseURL='...'))) + + request_type = event['RequestType'] + props = event['ResourceProperties'] + + # resource properties + cluster_name = props['ClusterName'] + role_arn = props['RoleArn'] + release = props['Release'] + chart = props.get('Chart', None) + chart_asset_url = props.get('ChartAssetURL', None) + version = props.get('Version', None) + wait = props.get('Wait', False) + timeout = props.get('Timeout', None) + namespace = props.get('Namespace', None) + create_namespace = props.get('CreateNamespace', None) + repository = props.get('Repository', None) + values_text = props.get('Values', None) + + # "log in" to the cluster + subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig', + '--role-arn', role_arn, + '--name', cluster_name, + '--kubeconfig', kubeconfig + ]) + + if os.path.isfile(kubeconfig): + os.chmod(kubeconfig, 0o600) + + # Write out the values to a file and include them with the install and upgrade + values_file = None + if not request_type == "Delete" and not values_text is None: + values = json.loads(values_text) + values_file = os.path.join(outdir, 'values.yaml') + with open(values_file, "w") as f: + f.write(json.dumps(values, indent=2)) + + if request_type == 'Create' or request_type == 'Update': + # Ensure chart or chart_asset_url are set + if chart == None and chart_asset_url == None: + raise RuntimeError(f'chart or chartAsset must be specified') + + if chart_asset_url != None: + assert(chart==None) + assert(repository==None) + assert(version==None) + if not chart_asset_url.startswith('s3://'): + raise RuntimeError(f'ChartAssetURL must point to as s3 location but is {chart_asset_url}') + # future work: support versions from s3 assets + chart = get_chart_asset_from_url(chart_asset_url) + + if repository is not None and repository.startswith('oci://'): + tmpdir = tempfile.TemporaryDirectory() + chart_dir = get_chart_from_oci(tmpdir.name, repository, version) + chart = chart_dir + + helm('upgrade', release, chart, repository, values_file, namespace, version, wait, timeout, create_namespace) + elif request_type == "Delete": + try: + helm('uninstall', release, namespace=namespace, timeout=timeout) + except Exception as e: + logger.info("delete error: %s" % e) + + +def get_oci_cmd(repository, version): + # Generates OCI command based on pattern. Public ECR vs Private ECR are treated differently. + private_ecr_pattern = 'oci://(?P\d+.dkr.ecr.(?P[a-z]+-[a-z]+-\d).amazonaws.com)*' + public_ecr_pattern = 'oci://(?Ppublic.ecr.aws)*' + + private_registry = re.match(private_ecr_pattern, repository).groupdict() + public_registry = re.match(public_ecr_pattern, repository).groupdict() + + if private_registry['registry'] is not None: + logger.info("Found AWS private repository") + cmnd = [ + f"aws ecr get-login-password --region {private_registry['region']} | " \ + f"helm registry login --username AWS --password-stdin {private_registry['registry']}; helm pull {repository} --version {version} --untar" + ] + elif public_registry['registry'] is not None: + logger.info("Found AWS public repository, will use default region as deployment") + region = os.environ.get('AWS_REGION', 'us-east-1') + + cmnd = [ + f"aws ecr-public get-login-password --region us-east-1 | " \ + f"helm registry login --username AWS --password-stdin {public_registry['registry']}; helm pull {repository} --version {version} --untar" + ] + else: + logger.error("OCI repository format not recognized, falling back to helm pull") + cmnd = ['helm', 'pull', repository, '--version', version, '--untar'] + + return cmnd + + +def get_chart_from_oci(tmpdir, repository = None, version = None): + + cmnd = get_oci_cmd(repository, version) + + maxAttempts = 3 + retry = maxAttempts + while retry > 0: + try: + logger.info(cmnd) + output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=tmpdir, shell=True) + logger.info(output) + + # effectively returns "$tmpDir/$lastPartOfOCIUrl", because this is how helm pull saves OCI artifact. + # Eg. if we have oci://9999999999.dkr.ecr.us-east-1.amazonaws.com/foo/bar/pet-service repository, helm saves artifact under $tmpDir/pet-service + return os.path.join(tmpdir, repository.rpartition('/')[-1]) + except subprocess.CalledProcessError as exc: + output = exc.output + if b'Broken pipe' in output: + retry = retry - 1 + logger.info("Broken pipe, retries left: %s" % retry) + else: + raise Exception(output) + raise Exception(f'Operation failed after {maxAttempts} attempts: {output}') + + +def helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None): + import subprocess + + cmnd = ['helm', verb, release] + if not chart is None: + cmnd.append(chart) + if verb == 'upgrade': + cmnd.append('--install') + if create_namespace: + cmnd.append('--create-namespace') + if not repo is None: + cmnd.extend(['--repo', repo]) + if not file is None: + cmnd.extend(['--values', file]) + if not version is None: + cmnd.extend(['--version', version]) + if not namespace is None: + cmnd.extend(['--namespace', namespace]) + if wait: + cmnd.append('--wait') + if not timeout is None: + cmnd.extend(['--timeout', timeout]) + cmnd.extend(['--kubeconfig', kubeconfig]) + + maxAttempts = 3 + retry = maxAttempts + while retry > 0: + try: + output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir) + logger.info(output) + return + except subprocess.CalledProcessError as exc: + output = exc.output + if b'Broken pipe' in output: + retry = retry - 1 + logger.info("Broken pipe, retries left: %s" % retry) + else: + raise Exception(output) + raise Exception(f'Operation failed after {maxAttempts} attempts: {output}') diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/index.py b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/index.py rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/patch/__init__.py b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/patch/__init__.py rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/aws-stepfunctions-tasks-emr-containers-all-services-test.assets.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/aws-stepfunctions-tasks-emr-containers-all-services-test.assets.json index 5264c7c63073b..4782f75a558a7 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/aws-stepfunctions-tasks-emr-containers-all-services-test.assets.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/aws-stepfunctions-tasks-emr-containers-all-services-test.assets.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "files": { "ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1": { "source": { @@ -14,15 +14,15 @@ } } }, - "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5": { + "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee": { "source": { - "path": "asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5", + "path": "asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip", + "objectKey": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -40,15 +40,15 @@ } } }, - "a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd": { + "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8": { "source": { - "path": "asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd", + "path": "asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd.zip", + "objectKey": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -79,7 +79,7 @@ } } }, - "885e8871bf0bbc96a133a56f1f7cdee17dd902d8967fd326b61d6f8b8901b9b4": { + "37b9bc4f34c2af7d98cff20053a09be46c63d26f7c9951e19230de787314a5f8": { "source": { "path": "awsstepfunctionstasksemrcontainersallservicestestawscdkawseksClusterResourceProvider6985269B.nested.template.json", "packaging": "file" @@ -87,12 +87,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "885e8871bf0bbc96a133a56f1f7cdee17dd902d8967fd326b61d6f8b8901b9b4.json", + "objectKey": "37b9bc4f34c2af7d98cff20053a09be46c63d26f7c9951e19230de787314a5f8.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "64935f5256b8a6a408fe03c069615fe7d74eedd9e98cfab64bfc6de60e4207bf": { + "1c293083c7ca2a85b9971a56b827528655c982c7cd525788c11f25281c50ff62": { "source": { "path": "awsstepfunctionstasksemrcontainersallservicestestawscdkawseksKubectlProviderD9DFA1E3.nested.template.json", "packaging": "file" @@ -100,12 +100,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "64935f5256b8a6a408fe03c069615fe7d74eedd9e98cfab64bfc6de60e4207bf.json", + "objectKey": "1c293083c7ca2a85b9971a56b827528655c982c7cd525788c11f25281c50ff62.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "fb60dad6258f36a2ef48b66ae220c4f7de6a319c89b75b23610f2803cbe36eb6": { + "8662d9a0c24ddd076682929e683932742480ec48e502a42fa69b66a32863c925": { "source": { "path": "aws-stepfunctions-tasks-emr-containers-all-services-test.template.json", "packaging": "file" @@ -113,7 +113,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "fb60dad6258f36a2ef48b66ae220c4f7de6a319c89b75b23610f2803cbe36eb6.json", + "objectKey": "8662d9a0c24ddd076682929e683932742480ec48e502a42fa69b66a32863c925.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/aws-stepfunctions-tasks-emr-containers-all-services-test.template.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/aws-stepfunctions-tasks-emr-containers-all-services-test.template.json index c53c4476e59d3..099bb579ed7c2 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/aws-stepfunctions-tasks-emr-containers-all-services-test.template.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/aws-stepfunctions-tasks-emr-containers-all-services-test.template.json @@ -921,7 +921,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/885e8871bf0bbc96a133a56f1f7cdee17dd902d8967fd326b61d6f8b8901b9b4.json" + "/37b9bc4f34c2af7d98cff20053a09be46c63d26f7c9951e19230de787314a5f8.json" ] ] }, @@ -956,7 +956,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/64935f5256b8a6a408fe03c069615fe7d74eedd9e98cfab64bfc6de60e4207bf.json" + "/1c293083c7ca2a85b9971a56b827528655c982c7cd525788c11f25281c50ff62.json" ] ] }, diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/awsstepfunctionstasksemrcontainersallservicesDefaultTestDeployAssertE09C88B0.assets.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/awsstepfunctionstasksemrcontainersallservicesDefaultTestDeployAssertE09C88B0.assets.json index 7eb8c3eed5b01..2bb5586770fdb 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/awsstepfunctionstasksemrcontainersallservicesDefaultTestDeployAssertE09C88B0.assets.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/awsstepfunctionstasksemrcontainersallservicesDefaultTestDeployAssertE09C88B0.assets.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/awsstepfunctionstasksemrcontainersallservicestestawscdkawseksClusterResourceProvider6985269B.nested.template.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/awsstepfunctionstasksemrcontainersallservicestestawscdkawseksClusterResourceProvider6985269B.nested.template.json index a348b53b52164..d7886f59f5435 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/awsstepfunctionstasksemrcontainersallservicestestawscdkawseksClusterResourceProvider6985269B.nested.template.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/awsstepfunctionstasksemrcontainersallservicestestawscdkawseksClusterResourceProvider6985269B.nested.template.json @@ -73,7 +73,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ @@ -162,7 +162,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/awsstepfunctionstasksemrcontainersallservicestestawscdkawseksKubectlProviderD9DFA1E3.nested.template.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/awsstepfunctionstasksemrcontainersallservicestestawscdkawseksKubectlProviderD9DFA1E3.nested.template.json index 3f50a0ca1ad50..a453d8d206b27 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/awsstepfunctionstasksemrcontainersallservicestestawscdkawseksKubectlProviderD9DFA1E3.nested.template.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/awsstepfunctionstasksemrcontainersallservicestestawscdkawseksKubectlProviderD9DFA1E3.nested.template.json @@ -51,6 +51,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -92,7 +104,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd.zip" + "S3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/cdk.out b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/cdk.out index ae4b03c54e770..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"30.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/integ.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/integ.json index ec0222b3a4e26..c88b2f61414ea 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "testCases": { "aws-stepfunctions-tasks-emr-containers-all-services/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/manifest.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/manifest.json index 40f081541857e..e932aaf072a48 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "artifacts": { "aws-stepfunctions-tasks-emr-containers-all-services-test.assets": { "type": "cdk:asset-manifest", @@ -17,7 +17,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/fb60dad6258f36a2ef48b66ae220c4f7de6a319c89b75b23610f2803cbe36eb6.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/8662d9a0c24ddd076682929e683932742480ec48e502a42fa69b66a32863c925.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/tree.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/tree.json index bcfbe83192ddd..08fe935f66e6a 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/tree.json @@ -960,7 +960,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } }, "KubectlReadyBarrier": { @@ -1426,7 +1426,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -1599,7 +1599,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -2440,7 +2440,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } } }, @@ -2497,7 +2497,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/885e8871bf0bbc96a133a56f1f7cdee17dd902d8967fd326b61d6f8b8901b9b4.json" + "/37b9bc4f34c2af7d98cff20053a09be46c63d26f7c9951e19230de787314a5f8.json" ] ] }, @@ -2519,7 +2519,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } }, "@aws-cdk--aws-eks.KubectlProvider": { @@ -2596,6 +2596,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -2695,7 +2707,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd.zip" + "s3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "role": { "Fn::GetAtt": [ @@ -3165,7 +3177,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/64935f5256b8a6a408fe03c069615fe7d74eedd9e98cfab64bfc6de60e4207bf.json" + "/1c293083c7ca2a85b9971a56b827528655c982c7cd525788c11f25281c50ff62.json" ] ] }, @@ -3205,7 +3217,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } }, "JobExecutionRole": { @@ -3748,7 +3760,7 @@ "path": "aws-stepfunctions-tasks-emr-containers-all-services/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } }, "DeployAssert": { @@ -3794,7 +3806,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } } }, diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.d.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.d.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js new file mode 100644 index 0000000000000..c9dc1b8d2c19a --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js @@ -0,0 +1,273 @@ +"use strict"; +/* eslint-disable no-console */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ClusterResourceHandler = void 0; +const common_1 = require("./common"); +const MAX_CLUSTER_NAME_LEN = 100; +class ClusterResourceHandler extends common_1.ResourceHandler { + constructor(eks, event) { + super(eks, event); + this.newProps = parseProps(this.event.ResourceProperties); + this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; + } + get clusterName() { + if (!this.physicalResourceId) { + throw new Error('Cannot determine cluster name without physical resource ID'); + } + return this.physicalResourceId; + } + // ------ + // CREATE + // ------ + async onCreate() { + console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); + if (!this.newProps.roleArn) { + throw new Error('"roleArn" is required'); + } + const clusterName = this.newProps.name || this.generateClusterName(); + const resp = await this.eks.createCluster({ + ...this.newProps, + name: clusterName, + }); + if (!resp.cluster) { + throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); + } + return { + PhysicalResourceId: resp.cluster.name, + }; + } + async isCreateComplete() { + return this.isActive(); + } + // ------ + // DELETE + // ------ + async onDelete() { + console.log(`onDelete: deleting cluster ${this.clusterName}`); + try { + await this.eks.deleteCluster({ name: this.clusterName }); + } + catch (e) { + if (e.code !== 'ResourceNotFoundException') { + throw e; + } + else { + console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); + } + } + return { + PhysicalResourceId: this.clusterName, + }; + } + async isDeleteComplete() { + console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); + try { + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); + } + catch (e) { + if (e.code === 'ResourceNotFoundException') { + console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); + return { IsComplete: true }; + } + console.log('describeCluster error:', e); + throw e; + } + return { + IsComplete: false, + }; + } + // ------ + // UPDATE + // ------ + async onUpdate() { + const updates = analyzeUpdate(this.oldProps, this.newProps); + console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); + // updates to encryption config is not supported + if (updates.updateEncryption) { + throw new Error('Cannot update cluster encryption configuration'); + } + // if there is an update that requires replacement, go ahead and just create + // a new cluster with the new config. The old cluster will automatically be + // deleted by cloudformation upon success. + if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { + // if we are replacing this cluster and the cluster has an explicit + // physical name, the creation of the new cluster will fail with "there is + // already a cluster with that name". this is a common behavior for + // CloudFormation resources that support specifying a physical name. + if (this.oldProps.name === this.newProps.name && this.oldProps.name) { + throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); + } + return this.onCreate(); + } + // if a version update is required, issue the version update + if (updates.updateVersion) { + if (!this.newProps.version) { + throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); + } + return this.updateClusterVersion(this.newProps.version); + } + if (updates.updateLogging && updates.updateAccess) { + throw new Error('Cannot update logging and access at the same time'); + } + if (updates.updateLogging || updates.updateAccess) { + const config = { + name: this.clusterName, + }; + if (updates.updateLogging) { + config.logging = this.newProps.logging; + } + ; + if (updates.updateAccess) { + // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: + // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) + // will fail, therefore we take only the access fields explicitly + config.resourcesVpcConfig = { + endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, + endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, + publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, + }; + } + const updateResponse = await this.eks.updateClusterConfig(config); + return { EksUpdateId: updateResponse.update?.id }; + } + // no updates + return; + } + async isUpdateComplete() { + console.log('isUpdateComplete'); + // if this is an EKS update, we will monitor the update event itself + if (this.event.EksUpdateId) { + const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); + if (!complete) { + return { IsComplete: false }; + } + // fall through: if the update is done, we simply delegate to isActive() + // in order to extract attributes and state from the cluster itself, which + // is supposed to be in an ACTIVE state after the update is complete. + } + return this.isActive(); + } + async updateClusterVersion(newVersion) { + console.log(`updating cluster version to ${newVersion}`); + // update-cluster-version will fail if we try to update to the same version, + // so skip in this case. + const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; + if (cluster?.version === newVersion) { + console.log(`cluster already at version ${cluster.version}, skipping version update`); + return; + } + const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); + return { EksUpdateId: updateResponse.update?.id }; + } + async isActive() { + console.log('waiting for cluster to become ACTIVE'); + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); + const cluster = resp.cluster; + // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are + // not complete. note that the custom resource provider framework forbids + // returning attributes (Data) if isComplete is false. + if (cluster?.status === 'FAILED') { + // not very informative, unfortunately the response doesn't contain any error + // information :\ + throw new Error('Cluster is in a FAILED status'); + } + else if (cluster?.status !== 'ACTIVE') { + return { + IsComplete: false, + }; + } + else { + return { + IsComplete: true, + Data: { + Name: cluster.name, + Endpoint: cluster.endpoint, + Arn: cluster.arn, + // IMPORTANT: CFN expects that attributes will *always* have values, + // so return an empty string in case the value is not defined. + // Otherwise, CFN will throw with `Vendor response doesn't contain + // XXXX key`. + CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', + ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', + OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', + OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', + // We can safely return the first item from encryption configuration array, because it has a limit of 1 item + // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig + EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', + }, + }; + } + } + async isEksUpdateComplete(eksUpdateId) { + this.log({ isEksUpdateComplete: eksUpdateId }); + const describeUpdateResponse = await this.eks.describeUpdate({ + name: this.clusterName, + updateId: eksUpdateId, + }); + this.log({ describeUpdateResponse }); + if (!describeUpdateResponse.update) { + throw new Error(`unable to describe update with id "${eksUpdateId}"`); + } + switch (describeUpdateResponse.update.status) { + case 'InProgress': + return false; + case 'Successful': + return true; + case 'Failed': + case 'Cancelled': + throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); + default: + throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); + } + } + generateClusterName() { + const suffix = this.requestId.replace(/-/g, ''); // 32 chars + const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; + const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); + return `${prefix}-${suffix}`; + } +} +exports.ClusterResourceHandler = ClusterResourceHandler; +function parseProps(props) { + const parsed = props?.Config ?? {}; + // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. + // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' + if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; + } + if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; + } + if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { + parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; + } + return parsed; +} +function analyzeUpdate(oldProps, newProps) { + console.log('old props: ', JSON.stringify(oldProps)); + console.log('new props: ', JSON.stringify(newProps)); + const newVpcProps = newProps.resourcesVpcConfig || {}; + const oldVpcProps = oldProps.resourcesVpcConfig || {}; + const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); + const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); + const newEnc = newProps.encryptionConfig || {}; + const oldEnc = oldProps.encryptionConfig || {}; + return { + replaceName: newProps.name !== oldProps.name, + replaceVpc: JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), + updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || + newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || + !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), + replaceRole: newProps.roleArn !== oldProps.roleArn, + updateVersion: newProps.version !== oldProps.version, + updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), + updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), + }; +} +function setsEqual(first, second) { + return first.size === second.size && [...first].every((e) => second.has(e)); +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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LENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztRQUNuRSxhQUFhLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBa0IsRUFBRSxNQUFtQjtJQUN4RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgRWtzQ2xpZW50LCBSZXNvdXJjZUV2ZW50LCBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX05BTUVfTEVOID0gMTAwO1xuXG5leHBvcnQgY2xhc3MgQ2x1c3RlclJlc291cmNlSGFuZGxlciBleHRlbmRzIFJlc291cmNlSGFuZGxlciB7XG4gIHB1YmxpYyBnZXQgY2x1c3Rlck5hbWUoKSB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZGV0ZXJtaW5lIGNsdXN0ZXIgbmFtZSB3aXRob3V0IHBoeXNpY2FsIHJlc291cmNlIElEJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PjtcblxuICBjb25zdHJ1Y3Rvcihla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICBzdXBlcihla3MsIGV2ZW50KTtcblxuICAgIHRoaXMubmV3UHJvcHMgPSBwYXJzZVByb3BzKHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLm9sZFByb3BzID0gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnID8gcGFyc2VQcm9wcyhldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMpIDoge307XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gQ1JFQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCdvbkNyZWF0ZTogY3JlYXRpbmcgY2x1c3RlciB3aXRoIG9wdGlvbnM6JywgSlNPTi5zdHJpbmdpZnkodGhpcy5uZXdQcm9wcywgdW5kZWZpbmVkLCAyKSk7XG4gICAgaWYgKCF0aGlzLm5ld1Byb3BzLnJvbGVBcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJyb2xlQXJuXCIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyTmFtZSA9IHRoaXMubmV3UHJvcHMubmFtZSB8fCB0aGlzLmdlbmVyYXRlQ2x1c3Rlck5hbWUoKTtcblxuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmVrcy5jcmVhdGVDbHVzdGVyKHtcbiAgICAgIC4uLnRoaXMubmV3UHJvcHMsXG4gICAgICBuYW1lOiBjbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcC5jbHVzdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBjbHVzdGVyICR7Y2x1c3Rlck5hbWV9OiBDcmVhdGVDbHVzdGVyIHJldHVybmVkIHdpdGhvdXQgY2x1c3RlciBpbmZvcm1hdGlvbmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHJlc3AuY2x1c3Rlci5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIERFTEVURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25EZWxldGUoKTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgb25EZWxldGU6IGRlbGV0aW5nIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfWApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVrcy5kZWxldGVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyICR7dGhpcy5jbHVzdGVyTmFtZX0gbm90IGZvdW5kLCBpZGVtcG90ZW50bHkgc3VjY2VlZGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coYGlzRGVsZXRlQ29tcGxldGU6IHdhaXRpbmcgZm9yIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSB0byBiZSBkZWxldGVkYCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJldHVybmVkOicsIEpTT04uc3RyaW5naWZ5KHJlc3AsIHVuZGVmaW5lZCwgMikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICBjb25zb2xlLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgY2x1c3RlciBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0cnVlIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgZXJyb3I6JywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIFVQREFURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IGFuYWx5emVVcGRhdGUodGhpcy5vbGRQcm9wcywgdGhpcy5uZXdQcm9wcyk7XG4gICAgY29uc29sZS5sb2coJ29uVXBkYXRlOicsIEpTT04uc3RyaW5naWZ5KHsgdXBkYXRlcyB9LCB1bmRlZmluZWQsIDIpKTtcblxuICAgIC8vIHVwZGF0ZXMgdG8gZW5jcnlwdGlvbiBjb25maWcgaXMgbm90IHN1cHBvcnRlZFxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUVuY3J5cHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHVwZGF0ZSBjbHVzdGVyIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZXJlIGlzIGFuIHVwZGF0ZSB0aGF0IHJlcXVpcmVzIHJlcGxhY2VtZW50LCBnbyBhaGVhZCBhbmQganVzdCBjcmVhdGVcbiAgICAvLyBhIG5ldyBjbHVzdGVyIHdpdGggdGhlIG5ldyBjb25maWcuIFRoZSBvbGQgY2x1c3RlciB3aWxsIGF1dG9tYXRpY2FsbHkgYmVcbiAgICAvLyBkZWxldGVkIGJ5IGNsb3VkZm9ybWF0aW9uIHVwb24gc3VjY2Vzcy5cbiAgICBpZiAodXBkYXRlcy5yZXBsYWNlTmFtZSB8fCB1cGRhdGVzLnJlcGxhY2VSb2xlIHx8IHVwZGF0ZXMucmVwbGFjZVZwYykge1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgcmVwbGFjaW5nIHRoaXMgY2x1c3RlciBhbmQgdGhlIGNsdXN0ZXIgaGFzIGFuIGV4cGxpY2l0XG4gICAgICAvLyBwaHlzaWNhbCBuYW1lLCB0aGUgY3JlYXRpb24gb2YgdGhlIG5ldyBjbHVzdGVyIHdpbGwgZmFpbCB3aXRoIFwidGhlcmUgaXNcbiAgICAgIC8vIGFscmVhZHkgYSBjbHVzdGVyIHdpdGggdGhhdCBuYW1lXCIuIHRoaXMgaXMgYSBjb21tb24gYmVoYXZpb3IgZm9yXG4gICAgICAvLyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZXMgdGhhdCBzdXBwb3J0IHNwZWNpZnlpbmcgYSBwaHlzaWNhbCBuYW1lLlxuICAgICAgaWYgKHRoaXMub2xkUHJvcHMubmFtZSA9PT0gdGhpcy5uZXdQcm9wcy5uYW1lICYmIHRoaXMub2xkUHJvcHMubmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXBsYWNlIGNsdXN0ZXIgXCIke3RoaXMub2xkUHJvcHMubmFtZX1cIiBzaW5jZSBpdCBoYXMgYW4gZXhwbGljaXQgcGh5c2ljYWwgbmFtZS4gRWl0aGVyIHJlbmFtZSB0aGUgY2x1c3RlciBvciByZW1vdmUgdGhlIFwibmFtZVwiIGNvbmZpZ3VyYXRpb25gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub25DcmVhdGUoKTtcbiAgICB9XG5cbiAgICAvLyBpZiBhIHZlcnNpb24gdXBkYXRlIGlzIHJlcXVpcmVkLCBpc3N1ZSB0aGUgdmVyc2lvbiB1cGRhdGVcbiAgICBpZiAodXBkYXRlcy51cGRhdGVWZXJzaW9uKSB7XG4gICAgICBpZiAoIXRoaXMubmV3UHJvcHMudmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZW1vdmUgY2x1c3RlciB2ZXJzaW9uIGNvbmZpZ3VyYXRpb24uIEN1cnJlbnQgdmVyc2lvbiBpcyAke3RoaXMub2xkUHJvcHMudmVyc2lvbn1gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlQ2x1c3RlclZlcnNpb24odGhpcy5uZXdQcm9wcy52ZXJzaW9uKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nICYmIHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1cGRhdGUgbG9nZ2luZyBhbmQgYWNjZXNzIGF0IHRoZSBzYW1lIHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nIHx8IHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICBjb25zdCBjb25maWc6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QgPSB7XG4gICAgICAgIG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgICB9O1xuICAgICAgaWYgKHVwZGF0ZXMudXBkYXRlTG9nZ2luZykge1xuICAgICAgICBjb25maWcubG9nZ2luZyA9IHRoaXMubmV3UHJvcHMubG9nZ2luZztcbiAgICAgIH07XG4gICAgICBpZiAodXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIGNsdXN0ZXIgd2l0aCBzZWN1cml0eUdyb3VwSWRzIGFuZCBzdWJuZXRJZHMgKGFzIHNwZWNpZmllZCBpbiB0aGUgd2FybmluZyBoZXJlOlxuICAgICAgICAvLyBodHRwczovL2F3c2NsaS5hbWF6b25hd3MuY29tL3YyL2RvY3VtZW50YXRpb24vYXBpL2xhdGVzdC9yZWZlcmVuY2UvZWtzL3VwZGF0ZS1jbHVzdGVyLWNvbmZpZy5odG1sKVxuICAgICAgICAvLyB3aWxsIGZhaWwsIHRoZXJlZm9yZSB3ZSB0YWtlIG9ubHkgdGhlIGFjY2VzcyBmaWVsZHMgZXhwbGljaXRseVxuICAgICAgICBjb25maWcucmVzb3VyY2VzVnBjQ29uZmlnID0ge1xuICAgICAgICAgIGVuZHBvaW50UHJpdmF0ZUFjY2VzczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzLFxuICAgICAgICAgIGVuZHBvaW50UHVibGljQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyxcbiAgICAgICAgICBwdWJsaWNBY2Nlc3NDaWRyczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcucHVibGljQWNjZXNzQ2lkcnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgICB9XG5cbiAgICAvLyBubyB1cGRhdGVzXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc29sZS5sb2coJ2lzVXBkYXRlQ29tcGxldGUnKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYW4gRUtTIHVwZGF0ZSwgd2Ugd2lsbCBtb25pdG9yIHRoZSB1cGRhdGUgZXZlbnQgaXRzZWxmXG4gICAgaWYgKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gYXdhaXQgdGhpcy5pc0Vrc1VwZGF0ZUNvbXBsZXRlKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpO1xuICAgICAgaWYgKCFjb21wbGV0ZSkge1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiBmYWxzZSB9O1xuICAgICAgfVxuXG4gICAgICAvLyBmYWxsIHRocm91Z2g6IGlmIHRoZSB1cGRhdGUgaXMgZG9uZSwgd2Ugc2ltcGx5IGRlbGVnYXRlIHRvIGlzQWN0aXZlKClcbiAgICAgIC8vIGluIG9yZGVyIHRvIGV4dHJhY3QgYXR0cmlidXRlcyBhbmQgc3RhdGUgZnJvbSB0aGUgY2x1c3RlciBpdHNlbGYsIHdoaWNoXG4gICAgICAvLyBpcyBzdXBwb3NlZCB0byBiZSBpbiBhbiBBQ1RJVkUgc3RhdGUgYWZ0ZXIgdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbHVzdGVyVmVyc2lvbihuZXdWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgdXBkYXRpbmcgY2x1c3RlciB2ZXJzaW9uIHRvICR7bmV3VmVyc2lvbn1gKTtcblxuICAgIC8vIHVwZGF0ZS1jbHVzdGVyLXZlcnNpb24gd2lsbCBmYWlsIGlmIHdlIHRyeSB0byB1cGRhdGUgdG8gdGhlIHNhbWUgdmVyc2lvbixcbiAgICAvLyBzbyBza2lwIGluIHRoaXMgY2FzZS5cbiAgICBjb25zdCBjbHVzdGVyID0gKGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSkpLmNsdXN0ZXI7XG4gICAgaWYgKGNsdXN0ZXI/LnZlcnNpb24gPT09IG5ld1ZlcnNpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyIGFscmVhZHkgYXQgdmVyc2lvbiAke2NsdXN0ZXIudmVyc2lvbn0sIHNraXBwaW5nIHZlcnNpb24gdXBkYXRlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy51cGRhdGVDbHVzdGVyVmVyc2lvbih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsIHZlcnNpb246IG5ld1ZlcnNpb24gfSk7XG4gICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNBY3RpdmUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZygnd2FpdGluZyBmb3IgY2x1c3RlciB0byBiZWNvbWUgQUNUSVZFJyk7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciByZXN1bHQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgY29uc3QgY2x1c3RlciA9IHJlc3AuY2x1c3RlcjtcblxuICAgIC8vIGlmIGNsdXN0ZXIgaXMgdW5kZWZpbmVkIChzaG91bGRudCBoYXBwZW4pIG9yIHN0YXR1cyBpcyBub3QgQUNUSVZFLCB3ZSBhcmVcbiAgICAvLyBub3QgY29tcGxldGUuIG5vdGUgdGhhdCB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZyYW1ld29yayBmb3JiaWRzXG4gICAgLy8gcmV0dXJuaW5nIGF0dHJpYnV0ZXMgKERhdGEpIGlmIGlzQ29tcGxldGUgaXMgZmFsc2UuXG4gICAgaWYgKGNsdXN0ZXI/LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgIC8vIG5vdCB2ZXJ5IGluZm9ybWF0aXZlLCB1bmZvcnR1bmF0ZWx5IHRoZSByZXNwb25zZSBkb2Vzbid0IGNvbnRhaW4gYW55IGVycm9yXG4gICAgICAvLyBpbmZvcm1hdGlvbiA6XFxcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2x1c3RlciBpcyBpbiBhIEZBSUxFRCBzdGF0dXMnKTtcbiAgICB9IGVsc2UgaWYgKGNsdXN0ZXI/LnN0YXR1cyAhPT0gJ0FDVElWRScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIE5hbWU6IGNsdXN0ZXIubmFtZSxcbiAgICAgICAgICBFbmRwb2ludDogY2x1c3Rlci5lbmRwb2ludCxcbiAgICAgICAgICBBcm46IGNsdXN0ZXIuYXJuLFxuXG4gICAgICAgICAgLy8gSU1QT1JUQU5UOiBDRk4gZXhwZWN0cyB0aGF0IGF0dHJpYnV0ZXMgd2lsbCAqYWx3YXlzKiBoYXZlIHZhbHVlcyxcbiAgICAgICAgICAvLyBzbyByZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGluIGNhc2UgdGhlIHZhbHVlIGlzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQ0ZOIHdpbGwgdGhyb3cgd2l0aCBgVmVuZG9yIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpblxuICAgICAgICAgIC8vIFhYWFgga2V5YC5cblxuICAgICAgICAgIENlcnRpZmljYXRlQXV0aG9yaXR5RGF0YTogY2x1c3Rlci5jZXJ0aWZpY2F0ZUF1dGhvcml0eT8uZGF0YSA/PyAnJyxcbiAgICAgICAgICBDbHVzdGVyU2VjdXJpdHlHcm91cElkOiBjbHVzdGVyLnJlc291cmNlc1ZwY0NvbmZpZz8uY2x1c3RlclNlY3VyaXR5R3JvdXBJZCA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyVXJsOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXIgPz8gJycsXG4gICAgICAgICAgT3BlbklkQ29ubmVjdElzc3VlcjogY2x1c3Rlci5pZGVudGl0eT8ub2lkYz8uaXNzdWVyPy5zdWJzdHJpbmcoOCkgPz8gJycsIC8vIFN0cmlwcyBvZmYgaHR0cHM6Ly8gZnJvbSB0aGUgaXNzdWVyIHVybFxuXG4gICAgICAgICAgLy8gV2UgY2FuIHNhZmVseSByZXR1cm4gdGhlIGZpcnN0IGl0ZW0gZnJvbSBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gYXJyYXksIGJlY2F1c2UgaXQgaGFzIGEgbGltaXQgb2YgMSBpdGVtXG4gICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vrcy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDbHVzdGVyLmh0bWwjQW1hem9uRUtTLUNyZWF0ZUNsdXN0ZXItcmVxdWVzdC1lbmNyeXB0aW9uQ29uZmlnXG4gICAgICAgICAgRW5jcnlwdGlvbkNvbmZpZ0tleUFybjogY2x1c3Rlci5lbmNyeXB0aW9uQ29uZmlnPy5zaGlmdCgpPy5wcm92aWRlcj8ua2V5QXJuID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzRWtzVXBkYXRlQ29tcGxldGUoZWtzVXBkYXRlSWQ6IHN0cmluZykge1xuICAgIHRoaXMubG9nKHsgaXNFa3NVcGRhdGVDb21wbGV0ZTogZWtzVXBkYXRlSWQgfSk7XG5cbiAgICBjb25zdCBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVVcGRhdGUoe1xuICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgIHVwZGF0ZUlkOiBla3NVcGRhdGVJZCxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nKHsgZGVzY3JpYmVVcGRhdGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5hYmxlIHRvIGRlc2NyaWJlIHVwZGF0ZSB3aXRoIGlkIFwiJHtla3NVcGRhdGVJZH1cImApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzKSB7XG4gICAgICBjYXNlICdJblByb2dyZXNzJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgY2FzZSAnU3VjY2Vzc2Z1bCc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnRmFpbGVkJzpcbiAgICAgIGNhc2UgJ0NhbmNlbGxlZCc6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2x1c3RlciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiIGZhaWxlZCB3aXRoIGVycm9yczogJHtKU09OLnN0cmluZ2lmeShkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5lcnJvcnMpfWApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIHN0YXR1cyBcIiR7ZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzfVwiIGZvciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNsdXN0ZXJOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9DTFVTVEVSX05BTUVfTEVOIC0gc3VmZml4Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5sb2dpY2FsUmVzb3VyY2VJZC5zbGljZSgwLCBvZmZzZXQgPiAwID8gb2Zmc2V0IDogMCk7XG4gICAgcmV0dXJuIGAke3ByZWZpeH0tJHtzdWZmaXh9YDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3BzKHByb3BzOiBhbnkpOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0IHtcblxuICBjb25zdCBwYXJzZWQgPSBwcm9wcz8uQ29uZmlnID8/IHt9O1xuXG4gIC8vIHRoaXMgaXMgd2VpcmQgYnV0IHRoZXNlIGJvb2xlYW4gcHJvcGVydGllcyBhcmUgcGFzc2VkIGJ5IENGTiBhcyBhIHN0cmluZywgYW5kIHdlIG5lZWQgdGhlbSB0byBiZSBib29sZWFuaWMgZm9yIHRoZSBTREsuXG4gIC8vIE90aGVyd2lzZSBpdCBmYWlscyB3aXRoICdVbmV4cGVjdGVkIFBhcmFtZXRlcjogcGFyYW1zLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgaXMgZXhwZWN0ZWQgdG8gYmUgYSBib29sZWFuJ1xuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWc/LmVuZHBvaW50UHJpdmF0ZUFjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9PT0gJ3RydWUnO1xuICB9XG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQdWJsaWNBY2Nlc3MpID09PSAnc3RyaW5nJykge1xuICAgIHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQubG9nZ2luZz8uY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCkgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9IHBhcnNlZC5sb2dnaW5nLmNsdXN0ZXJMb2dnaW5nWzBdLmVuYWJsZWQgPT09ICd0cnVlJztcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQ7XG5cbn1cblxuaW50ZXJmYWNlIFVwZGF0ZU1hcCB7XG4gIHJlcGxhY2VOYW1lOiBib29sZWFuOyAvLyBuYW1lXG4gIHJlcGxhY2VWcGM6IGJvb2xlYW47IC8vIHJlc291cmNlc1ZwY0NvbmZpZy5zdWJuZXRJZHMgYW5kIHNlY3VyaXR5R3JvdXBJZHNcbiAgcmVwbGFjZVJvbGU6IGJvb2xlYW47IC8vIHJvbGVBcm5cblxuICB1cGRhdGVWZXJzaW9uOiBib29sZWFuOyAvLyB2ZXJzaW9uXG4gIHVwZGF0ZUxvZ2dpbmc6IGJvb2xlYW47IC8vIGxvZ2dpbmdcbiAgdXBkYXRlRW5jcnlwdGlvbjogYm9vbGVhbjsgLy8gZW5jcnlwdGlvbiAoY2Fubm90IGJlIHVwZGF0ZWQpXG4gIHVwZGF0ZUFjY2VzczogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBhbmQgZW5kcG9pbnRQdWJsaWNBY2Nlc3Ncbn1cblxuZnVuY3Rpb24gYW5hbHl6ZVVwZGF0ZShvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PiwgbmV3UHJvcHM6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBVcGRhdGVNYXAge1xuICBjb25zb2xlLmxvZygnb2xkIHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShvbGRQcm9wcykpO1xuICBjb25zb2xlLmxvZygnbmV3IHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShuZXdQcm9wcykpO1xuXG4gIGNvbnN0IG5ld1ZwY1Byb3BzID0gbmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRWcGNQcm9wcyA9IG9sZFByb3BzLnJlc291cmNlc1ZwY0NvbmZpZyB8fCB7fTtcblxuICBjb25zdCBvbGRQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQob2xkVnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQobmV3VnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdFbmMgPSBuZXdQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRFbmMgPSBvbGRQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgcmVwbGFjZU5hbWU6IG5ld1Byb3BzLm5hbWUgIT09IG9sZFByb3BzLm5hbWUsXG4gICAgcmVwbGFjZVZwYzpcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnN1Ym5ldElkcz8uc29ydCgpKSAhPT0gSlNPTi5zdHJpbmdpZnkob2xkVnBjUHJvcHMuc3VibmV0SWRzPy5zb3J0KCkpIHx8XG4gICAgICBKU09OLnN0cmluZ2lmeShuZXdWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpICE9PSBKU09OLnN0cmluZ2lmeShvbGRWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpLFxuICAgIHVwZGF0ZUFjY2VzczpcbiAgICAgIG5ld1ZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQcml2YXRlQWNjZXNzIHx8XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFB1YmxpY0FjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgfHxcbiAgICAgICFzZXRzRXF1YWwobmV3UHVibGljQWNjZXNzQ2lkcnMsIG9sZFB1YmxpY0FjY2Vzc0NpZHJzKSxcbiAgICByZXBsYWNlUm9sZTogbmV3UHJvcHMucm9sZUFybiAhPT0gb2xkUHJvcHMucm9sZUFybixcbiAgICB1cGRhdGVWZXJzaW9uOiBuZXdQcm9wcy52ZXJzaW9uICE9PSBvbGRQcm9wcy52ZXJzaW9uLFxuICAgIHVwZGF0ZUVuY3J5cHRpb246IEpTT04uc3RyaW5naWZ5KG5ld0VuYykgIT09IEpTT04uc3RyaW5naWZ5KG9sZEVuYyksXG4gICAgdXBkYXRlTG9nZ2luZzogSlNPTi5zdHJpbmdpZnkobmV3UHJvcHMubG9nZ2luZykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFByb3BzLmxvZ2dpbmcpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzZXRzRXF1YWwoZmlyc3Q6IFNldDxzdHJpbmc+LCBzZWNvbmQ6IFNldDxzdHJpbmc+KSB7XG4gIHJldHVybiBmaXJzdC5zaXplID09PSBzZWNvbmQuc2l6ZSAmJiBbLi4uZmlyc3RdLmV2ZXJ5KChlOiBzdHJpbmcpID0+IHNlY29uZC5oYXMoZSkpO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts new file mode 100644 index 0000000000000..4b7fdda6d1dd1 --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts @@ -0,0 +1,344 @@ +/* eslint-disable no-console */ + +// eslint-disable-next-line import/no-extraneous-dependencies +import { IsCompleteResponse, OnEventResponse } from '@aws-cdk/custom-resources/lib/provider-framework/types'; +// eslint-disable-next-line import/no-extraneous-dependencies +import * as aws from 'aws-sdk'; +import { EksClient, ResourceEvent, ResourceHandler } from './common'; + +const MAX_CLUSTER_NAME_LEN = 100; + +export class ClusterResourceHandler extends ResourceHandler { + public get clusterName() { + if (!this.physicalResourceId) { + throw new Error('Cannot determine cluster name without physical resource ID'); + } + + return this.physicalResourceId; + } + + private readonly newProps: aws.EKS.CreateClusterRequest; + private readonly oldProps: Partial; + + constructor(eks: EksClient, event: ResourceEvent) { + super(eks, event); + + this.newProps = parseProps(this.event.ResourceProperties); + this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; + } + + // ------ + // CREATE + // ------ + + protected async onCreate(): Promise { + console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); + if (!this.newProps.roleArn) { + throw new Error('"roleArn" is required'); + } + + const clusterName = this.newProps.name || this.generateClusterName(); + + const resp = await this.eks.createCluster({ + ...this.newProps, + name: clusterName, + }); + + if (!resp.cluster) { + throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); + } + + return { + PhysicalResourceId: resp.cluster.name, + }; + } + + protected async isCreateComplete() { + return this.isActive(); + } + + // ------ + // DELETE + // ------ + + protected async onDelete(): Promise { + console.log(`onDelete: deleting cluster ${this.clusterName}`); + try { + await this.eks.deleteCluster({ name: this.clusterName }); + } catch (e) { + if (e.code !== 'ResourceNotFoundException') { + throw e; + } else { + console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); + } + } + return { + PhysicalResourceId: this.clusterName, + }; + } + + protected async isDeleteComplete(): Promise { + console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); + + try { + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); + } catch (e) { + if (e.code === 'ResourceNotFoundException') { + console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); + return { IsComplete: true }; + } + + console.log('describeCluster error:', e); + throw e; + } + + return { + IsComplete: false, + }; + } + + // ------ + // UPDATE + // ------ + + protected async onUpdate() { + const updates = analyzeUpdate(this.oldProps, this.newProps); + console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); + + // updates to encryption config is not supported + if (updates.updateEncryption) { + throw new Error('Cannot update cluster encryption configuration'); + } + + // if there is an update that requires replacement, go ahead and just create + // a new cluster with the new config. The old cluster will automatically be + // deleted by cloudformation upon success. + if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { + + // if we are replacing this cluster and the cluster has an explicit + // physical name, the creation of the new cluster will fail with "there is + // already a cluster with that name". this is a common behavior for + // CloudFormation resources that support specifying a physical name. + if (this.oldProps.name === this.newProps.name && this.oldProps.name) { + throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); + } + + return this.onCreate(); + } + + // if a version update is required, issue the version update + if (updates.updateVersion) { + if (!this.newProps.version) { + throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); + } + + return this.updateClusterVersion(this.newProps.version); + } + + if (updates.updateLogging && updates.updateAccess) { + throw new Error('Cannot update logging and access at the same time'); + } + + if (updates.updateLogging || updates.updateAccess) { + const config: aws.EKS.UpdateClusterConfigRequest = { + name: this.clusterName, + }; + if (updates.updateLogging) { + config.logging = this.newProps.logging; + }; + if (updates.updateAccess) { + // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: + // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) + // will fail, therefore we take only the access fields explicitly + config.resourcesVpcConfig = { + endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, + endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, + publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, + }; + } + const updateResponse = await this.eks.updateClusterConfig(config); + + return { EksUpdateId: updateResponse.update?.id }; + } + + // no updates + return; + } + + protected async isUpdateComplete() { + console.log('isUpdateComplete'); + + // if this is an EKS update, we will monitor the update event itself + if (this.event.EksUpdateId) { + const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); + if (!complete) { + return { IsComplete: false }; + } + + // fall through: if the update is done, we simply delegate to isActive() + // in order to extract attributes and state from the cluster itself, which + // is supposed to be in an ACTIVE state after the update is complete. + } + + return this.isActive(); + } + + private async updateClusterVersion(newVersion: string) { + console.log(`updating cluster version to ${newVersion}`); + + // update-cluster-version will fail if we try to update to the same version, + // so skip in this case. + const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; + if (cluster?.version === newVersion) { + console.log(`cluster already at version ${cluster.version}, skipping version update`); + return; + } + + const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); + return { EksUpdateId: updateResponse.update?.id }; + } + + private async isActive(): Promise { + console.log('waiting for cluster to become ACTIVE'); + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); + const cluster = resp.cluster; + + // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are + // not complete. note that the custom resource provider framework forbids + // returning attributes (Data) if isComplete is false. + if (cluster?.status === 'FAILED') { + // not very informative, unfortunately the response doesn't contain any error + // information :\ + throw new Error('Cluster is in a FAILED status'); + } else if (cluster?.status !== 'ACTIVE') { + return { + IsComplete: false, + }; + } else { + return { + IsComplete: true, + Data: { + Name: cluster.name, + Endpoint: cluster.endpoint, + Arn: cluster.arn, + + // IMPORTANT: CFN expects that attributes will *always* have values, + // so return an empty string in case the value is not defined. + // Otherwise, CFN will throw with `Vendor response doesn't contain + // XXXX key`. + + CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', + ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', + OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', + OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', // Strips off https:// from the issuer url + + // We can safely return the first item from encryption configuration array, because it has a limit of 1 item + // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig + EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', + }, + }; + } + } + + private async isEksUpdateComplete(eksUpdateId: string) { + this.log({ isEksUpdateComplete: eksUpdateId }); + + const describeUpdateResponse = await this.eks.describeUpdate({ + name: this.clusterName, + updateId: eksUpdateId, + }); + + this.log({ describeUpdateResponse }); + + if (!describeUpdateResponse.update) { + throw new Error(`unable to describe update with id "${eksUpdateId}"`); + } + + switch (describeUpdateResponse.update.status) { + case 'InProgress': + return false; + case 'Successful': + return true; + case 'Failed': + case 'Cancelled': + throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); + default: + throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); + } + } + + private generateClusterName() { + const suffix = this.requestId.replace(/-/g, ''); // 32 chars + const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; + const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); + return `${prefix}-${suffix}`; + } +} + +function parseProps(props: any): aws.EKS.CreateClusterRequest { + + const parsed = props?.Config ?? {}; + + // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. + // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' + + if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; + } + + if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; + } + + if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { + parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; + } + + return parsed; + +} + +interface UpdateMap { + replaceName: boolean; // name + replaceVpc: boolean; // resourcesVpcConfig.subnetIds and securityGroupIds + replaceRole: boolean; // roleArn + + updateVersion: boolean; // version + updateLogging: boolean; // logging + updateEncryption: boolean; // encryption (cannot be updated) + updateAccess: boolean; // resourcesVpcConfig.endpointPrivateAccess and endpointPublicAccess +} + +function analyzeUpdate(oldProps: Partial, newProps: aws.EKS.CreateClusterRequest): UpdateMap { + console.log('old props: ', JSON.stringify(oldProps)); + console.log('new props: ', JSON.stringify(newProps)); + + const newVpcProps = newProps.resourcesVpcConfig || {}; + const oldVpcProps = oldProps.resourcesVpcConfig || {}; + + const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); + const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); + const newEnc = newProps.encryptionConfig || {}; + const oldEnc = oldProps.encryptionConfig || {}; + + return { + replaceName: newProps.name !== oldProps.name, + replaceVpc: + JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), + updateAccess: + newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || + newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || + !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), + replaceRole: newProps.roleArn !== oldProps.roleArn, + updateVersion: newProps.version !== oldProps.version, + updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), + updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), + }; +} + +function setsEqual(first: Set, second: Set) { + return first.size === second.size && [...first].every((e: string) => second.has(e)); +} diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.d.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.d.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js new file mode 100644 index 0000000000000..5dbf4000517e4 --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js @@ -0,0 +1,43 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ResourceHandler = void 0; +class ResourceHandler { + constructor(eks, event) { + this.eks = eks; + this.requestType = event.RequestType; + this.requestId = event.RequestId; + this.logicalResourceId = event.LogicalResourceId; + this.physicalResourceId = event.PhysicalResourceId; + this.event = event; + const roleToAssume = event.ResourceProperties.AssumeRoleArn; + if (!roleToAssume) { + throw new Error('AssumeRoleArn must be provided'); + } + eks.configureAssumeRole({ + RoleArn: roleToAssume, + RoleSessionName: `AWSCDK.EKSCluster.${this.requestType}.${this.requestId}`, + }); + } + onEvent() { + switch (this.requestType) { + case 'Create': return this.onCreate(); + case 'Update': return this.onUpdate(); + case 'Delete': return this.onDelete(); + } + throw new Error(`Invalid request type ${this.requestType}`); + } + isComplete() { + switch (this.requestType) { + case 'Create': return this.isCreateComplete(); + case 'Update': return this.isUpdateComplete(); + case 'Delete': return this.isDeleteComplete(); + } + throw new Error(`Invalid request type ${this.requestType}`); + } + log(x) { + // eslint-disable-next-line no-console + console.log(JSON.stringify(x, undefined, 2)); + } +} +exports.ResourceHandler = ResourceHandler; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tbW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiY29tbW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQWlCQSxNQUFzQixlQUFlO0lBT25DLFlBQStCLEdBQWMsRUFBRSxLQUFvQjtRQUFwQyxRQUFHLEdBQUgsR0FBRyxDQUFXO1FBQzNDLElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSyxDQUFDLFdBQVcsQ0FBQztRQUNyQyxJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQyxTQUFTLENBQUM7UUFDakMsSUFBSSxDQUFDLGlCQUFpQixHQUFHLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQztRQUNqRCxJQUFJLENBQUMsa0JBQWtCLEdBQUksS0FBYSxDQUFDLGtCQUFrQixDQUFDO1FBQzVELElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO1FBRW5CLE1BQU0sWUFBWSxHQUFHLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxhQUFhLENBQUM7UUFDNUQsSUFBSSxDQUFDLFlBQVksRUFBRTtZQUNqQixNQUFNLElBQUksS0FBSyxDQUFDLGdDQUFnQyxDQUFDLENBQUM7U0FDbkQ7UUFFRCxHQUFHLENBQUMsbUJBQW1CLENBQUM7WUFDdEIsT0FBTyxFQUFFLFlBQVk7WUFDckIsZUFBZSxFQUFFLHFCQUFxQixJQUFJLENBQUMsV0FBVyxJQUFJLElBQUksQ0FBQyxTQUFTLEVBQUU7U0FDM0UsQ0FBQyxDQUFDO0tBQ0o7SUFFTSxPQUFPO1FBQ1osUUFBUSxJQUFJLENBQUMsV0FBVyxFQUFFO1lBQ3hCLEtBQUssUUFBUSxDQUFDLENBQUMsT0FBTyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDdEMsS0FBSyxRQUFRLENBQUMsQ0FBQyxPQUFPLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUN0QyxLQUFLLFFBQVEsQ0FBQyxDQUFDLE9BQU8sSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1NBQ3ZDO1FBRUQsTUFBTSxJQUFJLEtBQUssQ0FBQyx3QkFBd0IsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7S0FDN0Q7SUFFTSxVQUFVO1FBQ2YsUUFBUSxJQUFJLENBQUMsV0FBVyxFQUFFO1lBQ3hCLEtBQUssUUFBUSxDQUFDLENBQUMsT0FBTyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztZQUM5QyxLQUFLLFFBQVEsQ0FBQyxDQUFDLE9BQU8sSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7WUFDOUMsS0FBSyxRQUFRLENBQUMsQ0FBQyxPQUFPLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1NBQy9DO1FBRUQsTUFBTSxJQUFJLEtBQUssQ0FBQyx3QkFBd0IsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7S0FDN0Q7SUFFUyxHQUFHLENBQUMsQ0FBTTtRQUNsQixzQ0FBc0M7UUFDdEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztLQUM5QztDQVFGO0FBeERELDBDQXdEQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcbmltcG9ydCB7IElzQ29tcGxldGVSZXNwb25zZSwgT25FdmVudFJlc3BvbnNlIH0gZnJvbSAnQGF3cy1jZGsvY3VzdG9tLXJlc291cmNlcy9saWIvcHJvdmlkZXItZnJhbWV3b3JrL3R5cGVzJztcblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEVrc1VwZGF0ZUlkIHtcbiAgLyoqXG4gICAqIElmIHRoaXMgZmllbGQgaXMgaW5jbHVkZWQgaW4gYW4gZXZlbnQgcGFzc2VkIHRvIFwiSXNDb21wbGV0ZVwiLCBpdCBtZWFucyB3ZVxuICAgKiBpbml0aWF0ZWQgYW4gRUtTIHVwZGF0ZSB0aGF0IHNob3VsZCBiZSBtb25pdG9yZWQgdXNpbmcgZWtzOkRlc2NyaWJlVXBkYXRlXG4gICAqIGluc3RlYWQgb2YganVzdCBsb29raW5nIGF0IHRoZSBjbHVzdGVyIHN0YXR1cy5cbiAgICovXG4gIEVrc1VwZGF0ZUlkPzogc3RyaW5nXG59XG5cbmV4cG9ydCB0eXBlIFJlc291cmNlRXZlbnQgPSBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50ICYgRWtzVXBkYXRlSWQ7XG5cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBSZXNvdXJjZUhhbmRsZXIge1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgcmVxdWVzdElkOiBzdHJpbmc7XG4gIHByb3RlY3RlZCByZWFkb25seSBsb2dpY2FsUmVzb3VyY2VJZDogc3RyaW5nO1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgcmVxdWVzdFR5cGU6ICdDcmVhdGUnIHwgJ1VwZGF0ZScgfCAnRGVsZXRlJztcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IHBoeXNpY2FsUmVzb3VyY2VJZD86IHN0cmluZztcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGV2ZW50OiBSZXNvdXJjZUV2ZW50O1xuXG4gIGNvbnN0cnVjdG9yKHByb3RlY3RlZCByZWFkb25seSBla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICB0aGlzLnJlcXVlc3RUeXBlID0gZXZlbnQuUmVxdWVzdFR5cGU7XG4gICAgdGhpcy5yZXF1ZXN0SWQgPSBldmVudC5SZXF1ZXN0SWQ7XG4gICAgdGhpcy5sb2dpY2FsUmVzb3VyY2VJZCA9IGV2ZW50LkxvZ2ljYWxSZXNvdXJjZUlkO1xuICAgIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkID0gKGV2ZW50IGFzIGFueSkuUGh5c2ljYWxSZXNvdXJjZUlkO1xuICAgIHRoaXMuZXZlbnQgPSBldmVudDtcblxuICAgIGNvbnN0IHJvbGVUb0Fzc3VtZSA9IGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5Bc3N1bWVSb2xlQXJuO1xuICAgIGlmICghcm9sZVRvQXNzdW1lKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Fzc3VtZVJvbGVBcm4gbXVzdCBiZSBwcm92aWRlZCcpO1xuICAgIH1cblxuICAgIGVrcy5jb25maWd1cmVBc3N1bWVSb2xlKHtcbiAgICAgIFJvbGVBcm46IHJvbGVUb0Fzc3VtZSxcbiAgICAgIFJvbGVTZXNzaW9uTmFtZTogYEFXU0NESy5FS1NDbHVzdGVyLiR7dGhpcy5yZXF1ZXN0VHlwZX0uJHt0aGlzLnJlcXVlc3RJZH1gLFxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIG9uRXZlbnQoKSB7XG4gICAgc3dpdGNoICh0aGlzLnJlcXVlc3RUeXBlKSB7XG4gICAgICBjYXNlICdDcmVhdGUnOiByZXR1cm4gdGhpcy5vbkNyZWF0ZSgpO1xuICAgICAgY2FzZSAnVXBkYXRlJzogcmV0dXJuIHRoaXMub25VcGRhdGUoKTtcbiAgICAgIGNhc2UgJ0RlbGV0ZSc6IHJldHVybiB0aGlzLm9uRGVsZXRlKCk7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIHJlcXVlc3QgdHlwZSAke3RoaXMucmVxdWVzdFR5cGV9YCk7XG4gIH1cblxuICBwdWJsaWMgaXNDb21wbGV0ZSgpIHtcbiAgICBzd2l0Y2ggKHRoaXMucmVxdWVzdFR5cGUpIHtcbiAgICAgIGNhc2UgJ0NyZWF0ZSc6IHJldHVybiB0aGlzLmlzQ3JlYXRlQ29tcGxldGUoKTtcbiAgICAgIGNhc2UgJ1VwZGF0ZSc6IHJldHVybiB0aGlzLmlzVXBkYXRlQ29tcGxldGUoKTtcbiAgICAgIGNhc2UgJ0RlbGV0ZSc6IHJldHVybiB0aGlzLmlzRGVsZXRlQ29tcGxldGUoKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgcmVxdWVzdCB0eXBlICR7dGhpcy5yZXF1ZXN0VHlwZX1gKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBsb2coeDogYW55KSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICBjb25zb2xlLmxvZyhKU09OLnN0cmluZ2lmeSh4LCB1bmRlZmluZWQsIDIpKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhYnN0cmFjdCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT47XG4gIHByb3RlY3RlZCBhYnN0cmFjdCBhc3luYyBvbkRlbGV0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZSB8IHZvaWQ+O1xuICBwcm90ZWN0ZWQgYWJzdHJhY3QgYXN5bmMgb25VcGRhdGUoKTogUHJvbWlzZTwoT25FdmVudFJlc3BvbnNlICYgRWtzVXBkYXRlSWQpIHwgdm9pZD47XG4gIHByb3RlY3RlZCBhYnN0cmFjdCBhc3luYyBpc0NyZWF0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPjtcbiAgcHJvdGVjdGVkIGFic3RyYWN0IGFzeW5jIGlzRGVsZXRlQ29tcGxldGUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+O1xuICBwcm90ZWN0ZWQgYWJzdHJhY3QgYXN5bmMgaXNVcGRhdGVDb21wbGV0ZSgpOiBQcm9taXNlPElzQ29tcGxldGVSZXNwb25zZT47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRWtzQ2xpZW50IHtcbiAgY29uZmlndXJlQXNzdW1lUm9sZShyZXF1ZXN0OiBhd3MuU1RTLkFzc3VtZVJvbGVSZXF1ZXN0KTogdm9pZDtcbiAgY3JlYXRlQ2x1c3RlcihyZXF1ZXN0OiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0KTogUHJvbWlzZTxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXNwb25zZT47XG4gIGRlbGV0ZUNsdXN0ZXIocmVxdWVzdDogYXdzLkVLUy5EZWxldGVDbHVzdGVyUmVxdWVzdCk6IFByb21pc2U8YXdzLkVLUy5EZWxldGVDbHVzdGVyUmVzcG9uc2U+O1xuICBkZXNjcmliZUNsdXN0ZXIocmVxdWVzdDogYXdzLkVLUy5EZXNjcmliZUNsdXN0ZXJSZXF1ZXN0KTogUHJvbWlzZTxhd3MuRUtTLkRlc2NyaWJlQ2x1c3RlclJlc3BvbnNlPjtcbiAgdXBkYXRlQ2x1c3RlckNvbmZpZyhyZXF1ZXN0OiBhd3MuRUtTLlVwZGF0ZUNsdXN0ZXJDb25maWdSZXF1ZXN0KTogUHJvbWlzZTxhd3MuRUtTLlVwZGF0ZUNsdXN0ZXJDb25maWdSZXNwb25zZT47XG4gIHVwZGF0ZUNsdXN0ZXJWZXJzaW9uKHJlcXVlc3Q6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlclZlcnNpb25SZXF1ZXN0KTogUHJvbWlzZTxhd3MuRUtTLlVwZGF0ZUNsdXN0ZXJWZXJzaW9uUmVzcG9uc2U+O1xuICBkZXNjcmliZVVwZGF0ZShyZXE6IGF3cy5FS1MuRGVzY3JpYmVVcGRhdGVSZXF1ZXN0KTogUHJvbWlzZTxhd3MuRUtTLkRlc2NyaWJlVXBkYXRlUmVzcG9uc2U+O1xuICBjcmVhdGVGYXJnYXRlUHJvZmlsZShyZXF1ZXN0OiBhd3MuRUtTLkNyZWF0ZUZhcmdhdGVQcm9maWxlUmVxdWVzdCk6IFByb21pc2U8YXdzLkVLUy5DcmVhdGVGYXJnYXRlUHJvZmlsZVJlc3BvbnNlPjtcbiAgZGVzY3JpYmVGYXJnYXRlUHJvZmlsZShyZXF1ZXN0OiBhd3MuRUtTLkRlc2NyaWJlRmFyZ2F0ZVByb2ZpbGVSZXF1ZXN0KTogUHJvbWlzZTxhd3MuRUtTLkRlc2NyaWJlRmFyZ2F0ZVByb2ZpbGVSZXNwb25zZT47XG4gIGRlbGV0ZUZhcmdhdGVQcm9maWxlKHJlcXVlc3Q6IGF3cy5FS1MuRGVsZXRlRmFyZ2F0ZVByb2ZpbGVSZXF1ZXN0KTogUHJvbWlzZTxhd3MuRUtTLkRlbGV0ZUZhcmdhdGVQcm9maWxlUmVzcG9uc2U+O1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts new file mode 100644 index 0000000000000..21cf958df5a68 --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts @@ -0,0 +1,87 @@ +// eslint-disable-next-line import/no-extraneous-dependencies +import { IsCompleteResponse, OnEventResponse } from '@aws-cdk/custom-resources/lib/provider-framework/types'; + +// eslint-disable-next-line import/no-extraneous-dependencies +import * as aws from 'aws-sdk'; + +export interface EksUpdateId { + /** + * If this field is included in an event passed to "IsComplete", it means we + * initiated an EKS update that should be monitored using eks:DescribeUpdate + * instead of just looking at the cluster status. + */ + EksUpdateId?: string +} + +export type ResourceEvent = AWSLambda.CloudFormationCustomResourceEvent & EksUpdateId; + +export abstract class ResourceHandler { + protected readonly requestId: string; + protected readonly logicalResourceId: string; + protected readonly requestType: 'Create' | 'Update' | 'Delete'; + protected readonly physicalResourceId?: string; + protected readonly event: ResourceEvent; + + constructor(protected readonly eks: EksClient, event: ResourceEvent) { + this.requestType = event.RequestType; + this.requestId = event.RequestId; + this.logicalResourceId = event.LogicalResourceId; + this.physicalResourceId = (event as any).PhysicalResourceId; + this.event = event; + + const roleToAssume = event.ResourceProperties.AssumeRoleArn; + if (!roleToAssume) { + throw new Error('AssumeRoleArn must be provided'); + } + + eks.configureAssumeRole({ + RoleArn: roleToAssume, + RoleSessionName: `AWSCDK.EKSCluster.${this.requestType}.${this.requestId}`, + }); + } + + public onEvent() { + switch (this.requestType) { + case 'Create': return this.onCreate(); + case 'Update': return this.onUpdate(); + case 'Delete': return this.onDelete(); + } + + throw new Error(`Invalid request type ${this.requestType}`); + } + + public isComplete() { + switch (this.requestType) { + case 'Create': return this.isCreateComplete(); + case 'Update': return this.isUpdateComplete(); + case 'Delete': return this.isDeleteComplete(); + } + + throw new Error(`Invalid request type ${this.requestType}`); + } + + protected log(x: any) { + // eslint-disable-next-line no-console + console.log(JSON.stringify(x, undefined, 2)); + } + + protected abstract async onCreate(): Promise; + protected abstract async onDelete(): Promise; + protected abstract async onUpdate(): Promise<(OnEventResponse & EksUpdateId) | void>; + protected abstract async isCreateComplete(): Promise; + protected abstract async isDeleteComplete(): Promise; + protected abstract async isUpdateComplete(): Promise; +} + +export interface EksClient { + configureAssumeRole(request: aws.STS.AssumeRoleRequest): void; + createCluster(request: aws.EKS.CreateClusterRequest): Promise; + deleteCluster(request: aws.EKS.DeleteClusterRequest): Promise; + describeCluster(request: aws.EKS.DescribeClusterRequest): Promise; + updateClusterConfig(request: aws.EKS.UpdateClusterConfigRequest): Promise; + updateClusterVersion(request: aws.EKS.UpdateClusterVersionRequest): Promise; + describeUpdate(req: aws.EKS.DescribeUpdateRequest): Promise; + createFargateProfile(request: aws.EKS.CreateFargateProfileRequest): Promise; + describeFargateProfile(request: aws.EKS.DescribeFargateProfileRequest): Promise; + deleteFargateProfile(request: aws.EKS.DeleteFargateProfileRequest): Promise; +} diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.d.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.d.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.js b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.js rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts new file mode 100644 index 0000000000000..bae91b9ba79ca --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts @@ -0,0 +1,2 @@ +export const CLUSTER_RESOURCE_TYPE = 'Custom::AWSCDK-EKS-Cluster'; +export const FARGATE_PROFILE_RESOURCE_TYPE = 'Custom::AWSCDK-EKS-FargateProfile'; \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.d.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.d.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js new file mode 100644 index 0000000000000..f74022f9be26d --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js @@ -0,0 +1,102 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.FargateProfileResourceHandler = void 0; +const common_1 = require("./common"); +const MAX_NAME_LEN = 63; +class FargateProfileResourceHandler extends common_1.ResourceHandler { + async onCreate() { + const fargateProfileName = this.event.ResourceProperties.Config.fargateProfileName ?? this.generateProfileName(); + const createFargateProfile = { + fargateProfileName, + ...this.event.ResourceProperties.Config, + }; + this.log({ createFargateProfile }); + const createFargateProfileResponse = await this.eks.createFargateProfile(createFargateProfile); + this.log({ createFargateProfileResponse }); + if (!createFargateProfileResponse.fargateProfile) { + throw new Error('invalid CreateFargateProfile response'); + } + return { + PhysicalResourceId: createFargateProfileResponse.fargateProfile.fargateProfileName, + Data: { + fargateProfileArn: createFargateProfileResponse.fargateProfile.fargateProfileArn, + }, + }; + } + async onDelete() { + if (!this.physicalResourceId) { + throw new Error('Cannot delete a profile without a physical id'); + } + const deleteFargateProfile = { + clusterName: this.event.ResourceProperties.Config.clusterName, + fargateProfileName: this.physicalResourceId, + }; + this.log({ deleteFargateProfile }); + const deleteFargateProfileResponse = await this.eks.deleteFargateProfile(deleteFargateProfile); + this.log({ deleteFargateProfileResponse }); + return; + } + async onUpdate() { + // all updates require a replacement. as long as name is generated, we are + // good. if name is explicit, update will fail, which is common when trying + // to replace cfn resources with explicit physical names + return this.onCreate(); + } + async isCreateComplete() { + return this.isUpdateComplete(); + } + async isUpdateComplete() { + const status = await this.queryStatus(); + return { + IsComplete: status === 'ACTIVE', + }; + } + async isDeleteComplete() { + const status = await this.queryStatus(); + return { + IsComplete: status === 'NOT_FOUND', + }; + } + /** + * Generates a fargate profile name. + */ + generateProfileName() { + const suffix = this.requestId.replace(/-/g, ''); // 32 chars + const offset = MAX_NAME_LEN - suffix.length - 1; + const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); + return `${prefix}-${suffix}`; + } + /** + * Queries the Fargate profile's current status and returns the status or + * NOT_FOUND if the profile doesn't exist (i.e. it has been deleted). + */ + async queryStatus() { + if (!this.physicalResourceId) { + throw new Error('Unable to determine status for fargate profile without a resource name'); + } + const describeFargateProfile = { + clusterName: this.event.ResourceProperties.Config.clusterName, + fargateProfileName: this.physicalResourceId, + }; + try { + this.log({ describeFargateProfile }); + const describeFargateProfileResponse = await this.eks.describeFargateProfile(describeFargateProfile); + this.log({ describeFargateProfileResponse }); + const status = describeFargateProfileResponse.fargateProfile?.status; + if (status === 'CREATE_FAILED' || status === 'DELETE_FAILED') { + throw new Error(status); + } + return status; + } + catch (describeFargateProfileError) { + if (describeFargateProfileError.code === 'ResourceNotFoundException') { + this.log('received ResourceNotFoundException, this means the profile has been deleted (or never existed)'); + return 'NOT_FOUND'; + } + this.log({ describeFargateProfileError }); + throw describeFargateProfileError; + } + } +} +exports.FargateProfileResourceHandler = FargateProfileResourceHandler; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFyZ2F0ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImZhcmdhdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQ0EscUNBQTJDO0FBRTNDLE1BQU0sWUFBWSxHQUFHLEVBQUUsQ0FBQztBQUV4QixNQUFhLDZCQUE4QixTQUFRLHdCQUFlO0lBQ3RELEtBQUssQ0FBQyxRQUFRO1FBQ3RCLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsa0JBQWtCLElBQUksSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUM7UUFFakgsTUFBTSxvQkFBb0IsR0FBd0M7WUFDaEUsa0JBQWtCO1lBQ2xCLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNO1NBQ3hDLENBQUM7UUFFRixJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsb0JBQW9CLEVBQUUsQ0FBQyxDQUFDO1FBQ25DLE1BQU0sNEJBQTRCLEdBQUcsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLG9CQUFvQixDQUFDLG9CQUFvQixDQUFDLENBQUM7UUFDL0YsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLDRCQUE0QixFQUFFLENBQUMsQ0FBQztRQUUzQyxJQUFJLENBQUMsNEJBQTRCLENBQUMsY0FBYyxFQUFFO1lBQ2hELE1BQU0sSUFBSSxLQUFLLENBQUMsdUNBQXVDLENBQUMsQ0FBQztTQUMxRDtRQUVELE9BQU87WUFDTCxrQkFBa0IsRUFBRSw0QkFBNEIsQ0FBQyxjQUFjLENBQUMsa0JBQWtCO1lBQ2xGLElBQUksRUFBRTtnQkFDSixpQkFBaUIsRUFBRSw0QkFBNEIsQ0FBQyxjQUFjLENBQUMsaUJBQWlCO2FBQ2pGO1NBQ0YsQ0FBQztLQUNIO0lBRVMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsSUFBSSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsRUFBRTtZQUM1QixNQUFNLElBQUksS0FBSyxDQUFDLCtDQUErQyxDQUFDLENBQUM7U0FDbEU7UUFFRCxNQUFNLG9CQUFvQixHQUF3QztZQUNoRSxXQUFXLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsV0FBVztZQUM3RCxrQkFBa0IsRUFBRSxJQUFJLENBQUMsa0JBQWtCO1NBQzVDLENBQUM7UUFFRixJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsb0JBQW9CLEVBQUUsQ0FBQyxDQUFDO1FBQ25DLE1BQU0sNEJBQTRCLEdBQUcsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLG9CQUFvQixDQUFDLG9CQUFvQixDQUFDLENBQUM7UUFDL0YsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLDRCQUE0QixFQUFFLENBQUMsQ0FBQztRQUUzQyxPQUFPO0tBQ1I7SUFFUyxLQUFLLENBQUMsUUFBUTtRQUN0QiwwRUFBMEU7UUFDMUUsMkVBQTJFO1FBQzNFLHdEQUF3RDtRQUN4RCxPQUFPLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztLQUN4QjtJQUVTLEtBQUssQ0FBQyxnQkFBZ0I7UUFDOUIsT0FBTyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztLQUNoQztJQUVTLEtBQUssQ0FBQyxnQkFBZ0I7UUFDOUIsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDeEMsT0FBTztZQUNMLFVBQVUsRUFBRSxNQUFNLEtBQUssUUFBUTtTQUNoQyxDQUFDO0tBQ0g7SUFFUyxLQUFLLENBQUMsZ0JBQWdCO1FBQzlCLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ3hDLE9BQU87WUFDTCxVQUFVLEVBQUUsTUFBTSxLQUFLLFdBQVc7U0FDbkMsQ0FBQztLQUNIO0lBRUQ7O09BRUc7SUFDSyxtQkFBbUI7UUFDekIsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsV0FBVztRQUM1RCxNQUFNLE1BQU0sR0FBRyxZQUFZLEdBQUcsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7UUFDaEQsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN4RSxPQUFPLEdBQUcsTUFBTSxJQUFJLE1BQU0sRUFBRSxDQUFDO0tBQzlCO0lBRUQ7OztPQUdHO0lBQ0ssS0FBSyxDQUFDLFdBQVc7UUFDdkIsSUFBSSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsRUFBRTtZQUM1QixNQUFNLElBQUksS0FBSyxDQUFDLHdFQUF3RSxDQUFDLENBQUM7U0FDM0Y7UUFFRCxNQUFNLHNCQUFzQixHQUEwQztZQUNwRSxXQUFXLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsV0FBVztZQUM3RCxrQkFBa0IsRUFBRSxJQUFJLENBQUMsa0JBQWtCO1NBQzVDLENBQUM7UUFFRixJQUFJO1lBRUYsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLHNCQUFzQixFQUFFLENBQUMsQ0FBQztZQUNyQyxNQUFNLDhCQUE4QixHQUFHLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxzQkFBc0IsQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO1lBQ3JHLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSw4QkFBOEIsRUFBRSxDQUFDLENBQUM7WUFDN0MsTUFBTSxNQUFNLEdBQUcsOEJBQThCLENBQUMsY0FBYyxFQUFFLE1BQU0sQ0FBQztZQUVyRSxJQUFJLE1BQU0sS0FBSyxlQUFlLElBQUksTUFBTSxLQUFLLGVBQWUsRUFBRTtnQkFDNUQsTUFBTSxJQUFJLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQzthQUN6QjtZQUVELE9BQU8sTUFBTSxDQUFDO1NBQ2Y7UUFBQyxPQUFPLDJCQUEyQixFQUFFO1lBQ3BDLElBQUksMkJBQTJCLENBQUMsSUFBSSxLQUFLLDJCQUEyQixFQUFFO2dCQUNwRSxJQUFJLENBQUMsR0FBRyxDQUFDLGdHQUFnRyxDQUFDLENBQUM7Z0JBQzNHLE9BQU8sV0FBVyxDQUFDO2FBQ3BCO1lBRUQsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLDJCQUEyQixFQUFFLENBQUMsQ0FBQztZQUMxQyxNQUFNLDJCQUEyQixDQUFDO1NBQ25DO0tBQ0Y7Q0FDRjtBQWpIRCxzRUFpSEMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBhd3MgZnJvbSAnYXdzLXNkayc7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzXG5pbXBvcnQgeyBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9OQU1FX0xFTiA9IDYzO1xuXG5leHBvcnQgY2xhc3MgRmFyZ2F0ZVByb2ZpbGVSZXNvdXJjZUhhbmRsZXIgZXh0ZW5kcyBSZXNvdXJjZUhhbmRsZXIge1xuICBwcm90ZWN0ZWQgYXN5bmMgb25DcmVhdGUoKSB7XG4gICAgY29uc3QgZmFyZ2F0ZVByb2ZpbGVOYW1lID0gdGhpcy5ldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuQ29uZmlnLmZhcmdhdGVQcm9maWxlTmFtZSA/PyB0aGlzLmdlbmVyYXRlUHJvZmlsZU5hbWUoKTtcblxuICAgIGNvbnN0IGNyZWF0ZUZhcmdhdGVQcm9maWxlOiBhd3MuRUtTLkNyZWF0ZUZhcmdhdGVQcm9maWxlUmVxdWVzdCA9IHtcbiAgICAgIGZhcmdhdGVQcm9maWxlTmFtZSxcbiAgICAgIC4uLnRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLkNvbmZpZyxcbiAgICB9O1xuXG4gICAgdGhpcy5sb2coeyBjcmVhdGVGYXJnYXRlUHJvZmlsZSB9KTtcbiAgICBjb25zdCBjcmVhdGVGYXJnYXRlUHJvZmlsZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuY3JlYXRlRmFyZ2F0ZVByb2ZpbGUoY3JlYXRlRmFyZ2F0ZVByb2ZpbGUpO1xuICAgIHRoaXMubG9nKHsgY3JlYXRlRmFyZ2F0ZVByb2ZpbGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghY3JlYXRlRmFyZ2F0ZVByb2ZpbGVSZXNwb25zZS5mYXJnYXRlUHJvZmlsZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIENyZWF0ZUZhcmdhdGVQcm9maWxlIHJlc3BvbnNlJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogY3JlYXRlRmFyZ2F0ZVByb2ZpbGVSZXNwb25zZS5mYXJnYXRlUHJvZmlsZS5mYXJnYXRlUHJvZmlsZU5hbWUsXG4gICAgICBEYXRhOiB7XG4gICAgICAgIGZhcmdhdGVQcm9maWxlQXJuOiBjcmVhdGVGYXJnYXRlUHJvZmlsZVJlc3BvbnNlLmZhcmdhdGVQcm9maWxlLmZhcmdhdGVQcm9maWxlQXJuLFxuICAgICAgfSxcbiAgICB9O1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIG9uRGVsZXRlKCkge1xuICAgIGlmICghdGhpcy5waHlzaWNhbFJlc291cmNlSWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IGRlbGV0ZSBhIHByb2ZpbGUgd2l0aG91dCBhIHBoeXNpY2FsIGlkJyk7XG4gICAgfVxuXG4gICAgY29uc3QgZGVsZXRlRmFyZ2F0ZVByb2ZpbGU6IGF3cy5FS1MuRGVsZXRlRmFyZ2F0ZVByb2ZpbGVSZXF1ZXN0ID0ge1xuICAgICAgY2x1c3Rlck5hbWU6IHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLkNvbmZpZy5jbHVzdGVyTmFtZSxcbiAgICAgIGZhcmdhdGVQcm9maWxlTmFtZTogdGhpcy5waHlzaWNhbFJlc291cmNlSWQsXG4gICAgfTtcblxuICAgIHRoaXMubG9nKHsgZGVsZXRlRmFyZ2F0ZVByb2ZpbGUgfSk7XG4gICAgY29uc3QgZGVsZXRlRmFyZ2F0ZVByb2ZpbGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLmRlbGV0ZUZhcmdhdGVQcm9maWxlKGRlbGV0ZUZhcmdhdGVQcm9maWxlKTtcbiAgICB0aGlzLmxvZyh7IGRlbGV0ZUZhcmdhdGVQcm9maWxlUmVzcG9uc2UgfSk7XG5cbiAgICByZXR1cm47XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgLy8gYWxsIHVwZGF0ZXMgcmVxdWlyZSBhIHJlcGxhY2VtZW50LiBhcyBsb25nIGFzIG5hbWUgaXMgZ2VuZXJhdGVkLCB3ZSBhcmVcbiAgICAvLyBnb29kLiBpZiBuYW1lIGlzIGV4cGxpY2l0LCB1cGRhdGUgd2lsbCBmYWlsLCB3aGljaCBpcyBjb21tb24gd2hlbiB0cnlpbmdcbiAgICAvLyB0byByZXBsYWNlIGNmbiByZXNvdXJjZXMgd2l0aCBleHBsaWNpdCBwaHlzaWNhbCBuYW1lc1xuICAgIHJldHVybiB0aGlzLm9uQ3JlYXRlKCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc1VwZGF0ZUNvbXBsZXRlKCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNVcGRhdGVDb21wbGV0ZSgpIHtcbiAgICBjb25zdCBzdGF0dXMgPSBhd2FpdCB0aGlzLnF1ZXJ5U3RhdHVzKCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIElzQ29tcGxldGU6IHN0YXR1cyA9PT0gJ0FDVElWRScsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCkge1xuICAgIGNvbnN0IHN0YXR1cyA9IGF3YWl0IHRoaXMucXVlcnlTdGF0dXMoKTtcbiAgICByZXR1cm4ge1xuICAgICAgSXNDb21wbGV0ZTogc3RhdHVzID09PSAnTk9UX0ZPVU5EJyxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEdlbmVyYXRlcyBhIGZhcmdhdGUgcHJvZmlsZSBuYW1lLlxuICAgKi9cbiAgcHJpdmF0ZSBnZW5lcmF0ZVByb2ZpbGVOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9OQU1FX0xFTiAtIHN1ZmZpeC5sZW5ndGggLSAxO1xuICAgIGNvbnN0IHByZWZpeCA9IHRoaXMubG9naWNhbFJlc291cmNlSWQuc2xpY2UoMCwgb2Zmc2V0ID4gMCA/IG9mZnNldCA6IDApO1xuICAgIHJldHVybiBgJHtwcmVmaXh9LSR7c3VmZml4fWA7XG4gIH1cblxuICAvKipcbiAgICogUXVlcmllcyB0aGUgRmFyZ2F0ZSBwcm9maWxlJ3MgY3VycmVudCBzdGF0dXMgYW5kIHJldHVybnMgdGhlIHN0YXR1cyBvclxuICAgKiBOT1RfRk9VTkQgaWYgdGhlIHByb2ZpbGUgZG9lc24ndCBleGlzdCAoaS5lLiBpdCBoYXMgYmVlbiBkZWxldGVkKS5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgcXVlcnlTdGF0dXMoKTogUHJvbWlzZTxhd3MuRUtTLkZhcmdhdGVQcm9maWxlU3RhdHVzIHwgJ05PVF9GT1VORCcgfCB1bmRlZmluZWQ+IHtcbiAgICBpZiAoIXRoaXMucGh5c2ljYWxSZXNvdXJjZUlkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VuYWJsZSB0byBkZXRlcm1pbmUgc3RhdHVzIGZvciBmYXJnYXRlIHByb2ZpbGUgd2l0aG91dCBhIHJlc291cmNlIG5hbWUnKTtcbiAgICB9XG5cbiAgICBjb25zdCBkZXNjcmliZUZhcmdhdGVQcm9maWxlOiBhd3MuRUtTLkRlc2NyaWJlRmFyZ2F0ZVByb2ZpbGVSZXF1ZXN0ID0ge1xuICAgICAgY2x1c3Rlck5hbWU6IHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLkNvbmZpZy5jbHVzdGVyTmFtZSxcbiAgICAgIGZhcmdhdGVQcm9maWxlTmFtZTogdGhpcy5waHlzaWNhbFJlc291cmNlSWQsXG4gICAgfTtcblxuICAgIHRyeSB7XG5cbiAgICAgIHRoaXMubG9nKHsgZGVzY3JpYmVGYXJnYXRlUHJvZmlsZSB9KTtcbiAgICAgIGNvbnN0IGRlc2NyaWJlRmFyZ2F0ZVByb2ZpbGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlRmFyZ2F0ZVByb2ZpbGUoZGVzY3JpYmVGYXJnYXRlUHJvZmlsZSk7XG4gICAgICB0aGlzLmxvZyh7IGRlc2NyaWJlRmFyZ2F0ZVByb2ZpbGVSZXNwb25zZSB9KTtcbiAgICAgIGNvbnN0IHN0YXR1cyA9IGRlc2NyaWJlRmFyZ2F0ZVByb2ZpbGVSZXNwb25zZS5mYXJnYXRlUHJvZmlsZT8uc3RhdHVzO1xuXG4gICAgICBpZiAoc3RhdHVzID09PSAnQ1JFQVRFX0ZBSUxFRCcgfHwgc3RhdHVzID09PSAnREVMRVRFX0ZBSUxFRCcpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKHN0YXR1cyk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBzdGF0dXM7XG4gICAgfSBjYXRjaCAoZGVzY3JpYmVGYXJnYXRlUHJvZmlsZUVycm9yKSB7XG4gICAgICBpZiAoZGVzY3JpYmVGYXJnYXRlUHJvZmlsZUVycm9yLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICB0aGlzLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgcHJvZmlsZSBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4gJ05PVF9GT1VORCc7XG4gICAgICB9XG5cbiAgICAgIHRoaXMubG9nKHsgZGVzY3JpYmVGYXJnYXRlUHJvZmlsZUVycm9yIH0pO1xuICAgICAgdGhyb3cgZGVzY3JpYmVGYXJnYXRlUHJvZmlsZUVycm9yO1xuICAgIH1cbiAgfVxufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts new file mode 100644 index 0000000000000..b708690efd6d9 --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts @@ -0,0 +1,119 @@ +import * as aws from 'aws-sdk'; // eslint-disable-line import/no-extraneous-dependencies +import { ResourceHandler } from './common'; + +const MAX_NAME_LEN = 63; + +export class FargateProfileResourceHandler extends ResourceHandler { + protected async onCreate() { + const fargateProfileName = this.event.ResourceProperties.Config.fargateProfileName ?? this.generateProfileName(); + + const createFargateProfile: aws.EKS.CreateFargateProfileRequest = { + fargateProfileName, + ...this.event.ResourceProperties.Config, + }; + + this.log({ createFargateProfile }); + const createFargateProfileResponse = await this.eks.createFargateProfile(createFargateProfile); + this.log({ createFargateProfileResponse }); + + if (!createFargateProfileResponse.fargateProfile) { + throw new Error('invalid CreateFargateProfile response'); + } + + return { + PhysicalResourceId: createFargateProfileResponse.fargateProfile.fargateProfileName, + Data: { + fargateProfileArn: createFargateProfileResponse.fargateProfile.fargateProfileArn, + }, + }; + } + + protected async onDelete() { + if (!this.physicalResourceId) { + throw new Error('Cannot delete a profile without a physical id'); + } + + const deleteFargateProfile: aws.EKS.DeleteFargateProfileRequest = { + clusterName: this.event.ResourceProperties.Config.clusterName, + fargateProfileName: this.physicalResourceId, + }; + + this.log({ deleteFargateProfile }); + const deleteFargateProfileResponse = await this.eks.deleteFargateProfile(deleteFargateProfile); + this.log({ deleteFargateProfileResponse }); + + return; + } + + protected async onUpdate() { + // all updates require a replacement. as long as name is generated, we are + // good. if name is explicit, update will fail, which is common when trying + // to replace cfn resources with explicit physical names + return this.onCreate(); + } + + protected async isCreateComplete() { + return this.isUpdateComplete(); + } + + protected async isUpdateComplete() { + const status = await this.queryStatus(); + return { + IsComplete: status === 'ACTIVE', + }; + } + + protected async isDeleteComplete() { + const status = await this.queryStatus(); + return { + IsComplete: status === 'NOT_FOUND', + }; + } + + /** + * Generates a fargate profile name. + */ + private generateProfileName() { + const suffix = this.requestId.replace(/-/g, ''); // 32 chars + const offset = MAX_NAME_LEN - suffix.length - 1; + const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); + return `${prefix}-${suffix}`; + } + + /** + * Queries the Fargate profile's current status and returns the status or + * NOT_FOUND if the profile doesn't exist (i.e. it has been deleted). + */ + private async queryStatus(): Promise { + if (!this.physicalResourceId) { + throw new Error('Unable to determine status for fargate profile without a resource name'); + } + + const describeFargateProfile: aws.EKS.DescribeFargateProfileRequest = { + clusterName: this.event.ResourceProperties.Config.clusterName, + fargateProfileName: this.physicalResourceId, + }; + + try { + + this.log({ describeFargateProfile }); + const describeFargateProfileResponse = await this.eks.describeFargateProfile(describeFargateProfile); + this.log({ describeFargateProfileResponse }); + const status = describeFargateProfileResponse.fargateProfile?.status; + + if (status === 'CREATE_FAILED' || status === 'DELETE_FAILED') { + throw new Error(status); + } + + return status; + } catch (describeFargateProfileError) { + if (describeFargateProfileError.code === 'ResourceNotFoundException') { + this.log('received ResourceNotFoundException, this means the profile has been deleted (or never existed)'); + return 'NOT_FOUND'; + } + + this.log({ describeFargateProfileError }); + throw describeFargateProfileError; + } + } +} diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.d.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.d.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.js b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.js rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts new file mode 100644 index 0000000000000..f4db036cc6e48 --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts @@ -0,0 +1,67 @@ +/* eslint-disable no-console */ +// eslint-disable-next-line import/no-extraneous-dependencies +import { IsCompleteResponse } from '@aws-cdk/custom-resources/lib/provider-framework/types'; +// eslint-disable-next-line import/no-extraneous-dependencies +import * as aws from 'aws-sdk'; +import { ClusterResourceHandler } from './cluster'; +import { EksClient } from './common'; +import * as consts from './consts'; +import { FargateProfileResourceHandler } from './fargate'; + +// eslint-disable-next-line @typescript-eslint/no-require-imports, import/no-extraneous-dependencies +const ProxyAgent = require('proxy-agent'); + +aws.config.logger = console; +aws.config.update({ + httpOptions: { agent: new ProxyAgent() }, +}); + +let eks: aws.EKS | undefined; + +const defaultEksClient: EksClient = { + createCluster: req => getEksClient().createCluster(req).promise(), + deleteCluster: req => getEksClient().deleteCluster(req).promise(), + describeCluster: req => getEksClient().describeCluster(req).promise(), + describeUpdate: req => getEksClient().describeUpdate(req).promise(), + updateClusterConfig: req => getEksClient().updateClusterConfig(req).promise(), + updateClusterVersion: req => getEksClient().updateClusterVersion(req).promise(), + createFargateProfile: req => getEksClient().createFargateProfile(req).promise(), + deleteFargateProfile: req => getEksClient().deleteFargateProfile(req).promise(), + describeFargateProfile: req => getEksClient().describeFargateProfile(req).promise(), + configureAssumeRole: req => { + console.log(JSON.stringify({ assumeRole: req }, undefined, 2)); + const creds = new aws.ChainableTemporaryCredentials({ + params: req, + stsConfig: { stsRegionalEndpoints: 'regional' }, + }); + + eks = new aws.EKS({ credentials: creds }); + }, +}; + +function getEksClient() { + if (!eks) { + throw new Error('EKS client not initialized (call "configureAssumeRole")'); + } + + return eks; +} + +export async function onEvent(event: AWSLambda.CloudFormationCustomResourceEvent) { + const provider = createResourceHandler(event); + return provider.onEvent(); +} + +export async function isComplete(event: AWSLambda.CloudFormationCustomResourceEvent): Promise { + const provider = createResourceHandler(event); + return provider.isComplete(); +} + +function createResourceHandler(event: AWSLambda.CloudFormationCustomResourceEvent) { + switch (event.ResourceType) { + case consts.CLUSTER_RESOURCE_TYPE: return new ClusterResourceHandler(defaultEksClient, event); + case consts.FARGATE_PROFILE_RESOURCE_TYPE: return new FargateProfileResourceHandler(defaultEksClient, event); + default: + throw new Error(`Unsupported resource type "${event.ResourceType}`); + } +} diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip index 298edd40a09fc..f62fe1e5a06d6 100644 Binary files a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip and b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip differ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js deleted file mode 100644 index 1d08e9d7b865b..0000000000000 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js +++ /dev/null @@ -1,273 +0,0 @@ -"use strict"; -/* eslint-disable no-console */ -Object.defineProperty(exports, "__esModule", { value: true }); -exports.ClusterResourceHandler = void 0; -const common_1 = require("./common"); -const MAX_CLUSTER_NAME_LEN = 100; -class ClusterResourceHandler extends common_1.ResourceHandler { - constructor(eks, event) { - super(eks, event); - this.newProps = parseProps(this.event.ResourceProperties); - this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; - } - get clusterName() { - if (!this.physicalResourceId) { - throw new Error('Cannot determine cluster name without physical resource ID'); - } - return this.physicalResourceId; - } - // ------ - // CREATE - // ------ - async onCreate() { - console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); - if (!this.newProps.roleArn) { - throw new Error('"roleArn" is required'); - } - const clusterName = this.newProps.name || this.generateClusterName(); - const resp = await this.eks.createCluster({ - ...this.newProps, - name: clusterName, - }); - if (!resp.cluster) { - throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); - } - return { - PhysicalResourceId: resp.cluster.name, - }; - } - async isCreateComplete() { - return this.isActive(); - } - // ------ - // DELETE - // ------ - async onDelete() { - console.log(`onDelete: deleting cluster ${this.clusterName}`); - try { - await this.eks.deleteCluster({ name: this.clusterName }); - } - catch (e) { - if (e.code !== 'ResourceNotFoundException') { - throw e; - } - else { - console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); - } - } - return { - PhysicalResourceId: this.clusterName, - }; - } - async isDeleteComplete() { - console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); - try { - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); - } - catch (e) { - if (e.code === 'ResourceNotFoundException') { - console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); - return { IsComplete: true }; - } - console.log('describeCluster error:', e); - throw e; - } - return { - IsComplete: false, - }; - } - // ------ - // UPDATE - // ------ - async onUpdate() { - const updates = analyzeUpdate(this.oldProps, this.newProps); - console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); - // updates to encryption config is not supported - if (updates.updateEncryption) { - throw new Error('Cannot update cluster encryption configuration'); - } - // if there is an update that requires replacement, go ahead and just create - // a new cluster with the new config. The old cluster will automatically be - // deleted by cloudformation upon success. - if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { - // if we are replacing this cluster and the cluster has an explicit - // physical name, the creation of the new cluster will fail with "there is - // already a cluster with that name". this is a common behavior for - // CloudFormation resources that support specifying a physical name. - if (this.oldProps.name === this.newProps.name && this.oldProps.name) { - throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); - } - return this.onCreate(); - } - // if a version update is required, issue the version update - if (updates.updateVersion) { - if (!this.newProps.version) { - throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); - } - return this.updateClusterVersion(this.newProps.version); - } - if (updates.updateLogging && updates.updateAccess) { - throw new Error('Cannot update logging and access at the same time'); - } - if (updates.updateLogging || updates.updateAccess) { - const config = { - name: this.clusterName, - }; - if (updates.updateLogging) { - config.logging = this.newProps.logging; - } - ; - if (updates.updateAccess) { - // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: - // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) - // will fail, therefore we take only the access fields explicitly - config.resourcesVpcConfig = { - endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, - endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, - publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, - }; - } - const updateResponse = await this.eks.updateClusterConfig(config); - return { EksUpdateId: updateResponse.update?.id }; - } - // no updates - return; - } - async isUpdateComplete() { - console.log('isUpdateComplete'); - // if this is an EKS update, we will monitor the update event itself - if (this.event.EksUpdateId) { - const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); - if (!complete) { - return { IsComplete: false }; - } - // fall through: if the update is done, we simply delegate to isActive() - // in order to extract attributes and state from the cluster itself, which - // is supposed to be in an ACTIVE state after the update is complete. - } - return this.isActive(); - } - async updateClusterVersion(newVersion) { - console.log(`updating cluster version to ${newVersion}`); - // update-cluster-version will fail if we try to update to the same version, - // so skip in this case. - const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; - if (cluster?.version === newVersion) { - console.log(`cluster already at version ${cluster.version}, skipping version update`); - return; - } - const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); - return { EksUpdateId: updateResponse.update?.id }; - } - async isActive() { - console.log('waiting for cluster to become ACTIVE'); - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); - const cluster = resp.cluster; - // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are - // not complete. note that the custom resource provider framework forbids - // returning attributes (Data) if isComplete is false. - if (cluster?.status === 'FAILED') { - // not very informative, unfortunately the response doesn't contain any error - // information :\ - throw new Error('Cluster is in a FAILED status'); - } - else if (cluster?.status !== 'ACTIVE') { - return { - IsComplete: false, - }; - } - else { - return { - IsComplete: true, - Data: { - Name: cluster.name, - Endpoint: cluster.endpoint, - Arn: cluster.arn, - // IMPORTANT: CFN expects that attributes will *always* have values, - // so return an empty string in case the value is not defined. - // Otherwise, CFN will throw with `Vendor response doesn't contain - // XXXX key`. - CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', - ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', - OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', - OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', - // We can safely return the first item from encryption configuration array, because it has a limit of 1 item - // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig - EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', - }, - }; - } - } - async isEksUpdateComplete(eksUpdateId) { - this.log({ isEksUpdateComplete: eksUpdateId }); - const describeUpdateResponse = await this.eks.describeUpdate({ - name: this.clusterName, - updateId: eksUpdateId, - }); - this.log({ describeUpdateResponse }); - if (!describeUpdateResponse.update) { - throw new Error(`unable to describe update with id "${eksUpdateId}"`); - } - switch (describeUpdateResponse.update.status) { - case 'InProgress': - return false; - case 'Successful': - return true; - case 'Failed': - case 'Cancelled': - throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); - default: - throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); - } - } - generateClusterName() { - const suffix = this.requestId.replace(/-/g, ''); // 32 chars - const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; - const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); - return `${prefix}-${suffix}`; - } -} -exports.ClusterResourceHandler = ClusterResourceHandler; -function parseProps(props) { - const parsed = props?.Config ?? {}; - // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. - // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' - if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; - } - if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; - } - if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { - parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; - } - return parsed; -} -function analyzeUpdate(oldProps, newProps) { - console.log('old props: ', JSON.stringify(oldProps)); - console.log('new props: ', JSON.stringify(newProps)); - const newVpcProps = newProps.resourcesVpcConfig || {}; - const oldVpcProps = oldProps.resourcesVpcConfig || {}; - const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); - const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); - const newEnc = newProps.encryptionConfig || {}; - const oldEnc = oldProps.encryptionConfig || {}; - return { - replaceName: newProps.name !== oldProps.name, - replaceVpc: JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), - updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || - newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || - !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), - replaceRole: newProps.roleArn !== oldProps.roleArn, - updateVersion: newProps.version !== oldProps.version, - updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), - updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), - }; -} -function setsEqual(first, second) { - return first.size === second.size && [...first].every((e) => second.has(e)); -} -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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SSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBa0IsRUFBRSxNQUFtQjtJQUN4RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgRWtzQ2xpZW50LCBSZXNvdXJjZUV2ZW50LCBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX05BTUVfTEVOID0gMTAwO1xuXG5leHBvcnQgY2xhc3MgQ2x1c3RlclJlc291cmNlSGFuZGxlciBleHRlbmRzIFJlc291cmNlSGFuZGxlciB7XG4gIHB1YmxpYyBnZXQgY2x1c3Rlck5hbWUoKSB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZGV0ZXJtaW5lIGNsdXN0ZXIgbmFtZSB3aXRob3V0IHBoeXNpY2FsIHJlc291cmNlIElEJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PjtcblxuICBjb25zdHJ1Y3Rvcihla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICBzdXBlcihla3MsIGV2ZW50KTtcblxuICAgIHRoaXMubmV3UHJvcHMgPSBwYXJzZVByb3BzKHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLm9sZFByb3BzID0gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnID8gcGFyc2VQcm9wcyhldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMpIDoge307XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gQ1JFQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCdvbkNyZWF0ZTogY3JlYXRpbmcgY2x1c3RlciB3aXRoIG9wdGlvbnM6JywgSlNPTi5zdHJpbmdpZnkodGhpcy5uZXdQcm9wcywgdW5kZWZpbmVkLCAyKSk7XG4gICAgaWYgKCF0aGlzLm5ld1Byb3BzLnJvbGVBcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJyb2xlQXJuXCIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyTmFtZSA9IHRoaXMubmV3UHJvcHMubmFtZSB8fCB0aGlzLmdlbmVyYXRlQ2x1c3Rlck5hbWUoKTtcblxuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmVrcy5jcmVhdGVDbHVzdGVyKHtcbiAgICAgIC4uLnRoaXMubmV3UHJvcHMsXG4gICAgICBuYW1lOiBjbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcC5jbHVzdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBjbHVzdGVyICR7Y2x1c3Rlck5hbWV9OiBDcmVhdGVDbHVzdGVyIHJldHVybmVkIHdpdGhvdXQgY2x1c3RlciBpbmZvcm1hdGlvbmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHJlc3AuY2x1c3Rlci5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIERFTEVURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25EZWxldGUoKTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgb25EZWxldGU6IGRlbGV0aW5nIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfWApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVrcy5kZWxldGVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyICR7dGhpcy5jbHVzdGVyTmFtZX0gbm90IGZvdW5kLCBpZGVtcG90ZW50bHkgc3VjY2VlZGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coYGlzRGVsZXRlQ29tcGxldGU6IHdhaXRpbmcgZm9yIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSB0byBiZSBkZWxldGVkYCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJldHVybmVkOicsIEpTT04uc3RyaW5naWZ5KHJlc3AsIHVuZGVmaW5lZCwgMikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICBjb25zb2xlLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgY2x1c3RlciBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0cnVlIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgZXJyb3I6JywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIFVQREFURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IGFuYWx5emVVcGRhdGUodGhpcy5vbGRQcm9wcywgdGhpcy5uZXdQcm9wcyk7XG4gICAgY29uc29sZS5sb2coJ29uVXBkYXRlOicsIEpTT04uc3RyaW5naWZ5KHsgdXBkYXRlcyB9LCB1bmRlZmluZWQsIDIpKTtcblxuICAgIC8vIHVwZGF0ZXMgdG8gZW5jcnlwdGlvbiBjb25maWcgaXMgbm90IHN1cHBvcnRlZFxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUVuY3J5cHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHVwZGF0ZSBjbHVzdGVyIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZXJlIGlzIGFuIHVwZGF0ZSB0aGF0IHJlcXVpcmVzIHJlcGxhY2VtZW50LCBnbyBhaGVhZCBhbmQganVzdCBjcmVhdGVcbiAgICAvLyBhIG5ldyBjbHVzdGVyIHdpdGggdGhlIG5ldyBjb25maWcuIFRoZSBvbGQgY2x1c3RlciB3aWxsIGF1dG9tYXRpY2FsbHkgYmVcbiAgICAvLyBkZWxldGVkIGJ5IGNsb3VkZm9ybWF0aW9uIHVwb24gc3VjY2Vzcy5cbiAgICBpZiAodXBkYXRlcy5yZXBsYWNlTmFtZSB8fCB1cGRhdGVzLnJlcGxhY2VSb2xlIHx8IHVwZGF0ZXMucmVwbGFjZVZwYykge1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgcmVwbGFjaW5nIHRoaXMgY2x1c3RlciBhbmQgdGhlIGNsdXN0ZXIgaGFzIGFuIGV4cGxpY2l0XG4gICAgICAvLyBwaHlzaWNhbCBuYW1lLCB0aGUgY3JlYXRpb24gb2YgdGhlIG5ldyBjbHVzdGVyIHdpbGwgZmFpbCB3aXRoIFwidGhlcmUgaXNcbiAgICAgIC8vIGFscmVhZHkgYSBjbHVzdGVyIHdpdGggdGhhdCBuYW1lXCIuIHRoaXMgaXMgYSBjb21tb24gYmVoYXZpb3IgZm9yXG4gICAgICAvLyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZXMgdGhhdCBzdXBwb3J0IHNwZWNpZnlpbmcgYSBwaHlzaWNhbCBuYW1lLlxuICAgICAgaWYgKHRoaXMub2xkUHJvcHMubmFtZSA9PT0gdGhpcy5uZXdQcm9wcy5uYW1lICYmIHRoaXMub2xkUHJvcHMubmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXBsYWNlIGNsdXN0ZXIgXCIke3RoaXMub2xkUHJvcHMubmFtZX1cIiBzaW5jZSBpdCBoYXMgYW4gZXhwbGljaXQgcGh5c2ljYWwgbmFtZS4gRWl0aGVyIHJlbmFtZSB0aGUgY2x1c3RlciBvciByZW1vdmUgdGhlIFwibmFtZVwiIGNvbmZpZ3VyYXRpb25gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub25DcmVhdGUoKTtcbiAgICB9XG5cbiAgICAvLyBpZiBhIHZlcnNpb24gdXBkYXRlIGlzIHJlcXVpcmVkLCBpc3N1ZSB0aGUgdmVyc2lvbiB1cGRhdGVcbiAgICBpZiAodXBkYXRlcy51cGRhdGVWZXJzaW9uKSB7XG4gICAgICBpZiAoIXRoaXMubmV3UHJvcHMudmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZW1vdmUgY2x1c3RlciB2ZXJzaW9uIGNvbmZpZ3VyYXRpb24uIEN1cnJlbnQgdmVyc2lvbiBpcyAke3RoaXMub2xkUHJvcHMudmVyc2lvbn1gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlQ2x1c3RlclZlcnNpb24odGhpcy5uZXdQcm9wcy52ZXJzaW9uKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nICYmIHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1cGRhdGUgbG9nZ2luZyBhbmQgYWNjZXNzIGF0IHRoZSBzYW1lIHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nIHx8IHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICBjb25zdCBjb25maWc6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QgPSB7XG4gICAgICAgIG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgICB9O1xuICAgICAgaWYgKHVwZGF0ZXMudXBkYXRlTG9nZ2luZykge1xuICAgICAgICBjb25maWcubG9nZ2luZyA9IHRoaXMubmV3UHJvcHMubG9nZ2luZztcbiAgICAgIH07XG4gICAgICBpZiAodXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIGNsdXN0ZXIgd2l0aCBzZWN1cml0eUdyb3VwSWRzIGFuZCBzdWJuZXRJZHMgKGFzIHNwZWNpZmllZCBpbiB0aGUgd2FybmluZyBoZXJlOlxuICAgICAgICAvLyBodHRwczovL2F3c2NsaS5hbWF6b25hd3MuY29tL3YyL2RvY3VtZW50YXRpb24vYXBpL2xhdGVzdC9yZWZlcmVuY2UvZWtzL3VwZGF0ZS1jbHVzdGVyLWNvbmZpZy5odG1sKVxuICAgICAgICAvLyB3aWxsIGZhaWwsIHRoZXJlZm9yZSB3ZSB0YWtlIG9ubHkgdGhlIGFjY2VzcyBmaWVsZHMgZXhwbGljaXRseVxuICAgICAgICBjb25maWcucmVzb3VyY2VzVnBjQ29uZmlnID0ge1xuICAgICAgICAgIGVuZHBvaW50UHJpdmF0ZUFjY2VzczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzLFxuICAgICAgICAgIGVuZHBvaW50UHVibGljQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyxcbiAgICAgICAgICBwdWJsaWNBY2Nlc3NDaWRyczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcucHVibGljQWNjZXNzQ2lkcnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgICB9XG5cbiAgICAvLyBubyB1cGRhdGVzXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc29sZS5sb2coJ2lzVXBkYXRlQ29tcGxldGUnKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYW4gRUtTIHVwZGF0ZSwgd2Ugd2lsbCBtb25pdG9yIHRoZSB1cGRhdGUgZXZlbnQgaXRzZWxmXG4gICAgaWYgKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gYXdhaXQgdGhpcy5pc0Vrc1VwZGF0ZUNvbXBsZXRlKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpO1xuICAgICAgaWYgKCFjb21wbGV0ZSkge1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiBmYWxzZSB9O1xuICAgICAgfVxuXG4gICAgICAvLyBmYWxsIHRocm91Z2g6IGlmIHRoZSB1cGRhdGUgaXMgZG9uZSwgd2Ugc2ltcGx5IGRlbGVnYXRlIHRvIGlzQWN0aXZlKClcbiAgICAgIC8vIGluIG9yZGVyIHRvIGV4dHJhY3QgYXR0cmlidXRlcyBhbmQgc3RhdGUgZnJvbSB0aGUgY2x1c3RlciBpdHNlbGYsIHdoaWNoXG4gICAgICAvLyBpcyBzdXBwb3NlZCB0byBiZSBpbiBhbiBBQ1RJVkUgc3RhdGUgYWZ0ZXIgdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbHVzdGVyVmVyc2lvbihuZXdWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgdXBkYXRpbmcgY2x1c3RlciB2ZXJzaW9uIHRvICR7bmV3VmVyc2lvbn1gKTtcblxuICAgIC8vIHVwZGF0ZS1jbHVzdGVyLXZlcnNpb24gd2lsbCBmYWlsIGlmIHdlIHRyeSB0byB1cGRhdGUgdG8gdGhlIHNhbWUgdmVyc2lvbixcbiAgICAvLyBzbyBza2lwIGluIHRoaXMgY2FzZS5cbiAgICBjb25zdCBjbHVzdGVyID0gKGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSkpLmNsdXN0ZXI7XG4gICAgaWYgKGNsdXN0ZXI/LnZlcnNpb24gPT09IG5ld1ZlcnNpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyIGFscmVhZHkgYXQgdmVyc2lvbiAke2NsdXN0ZXIudmVyc2lvbn0sIHNraXBwaW5nIHZlcnNpb24gdXBkYXRlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy51cGRhdGVDbHVzdGVyVmVyc2lvbih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsIHZlcnNpb246IG5ld1ZlcnNpb24gfSk7XG4gICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNBY3RpdmUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZygnd2FpdGluZyBmb3IgY2x1c3RlciB0byBiZWNvbWUgQUNUSVZFJyk7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciByZXN1bHQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgY29uc3QgY2x1c3RlciA9IHJlc3AuY2x1c3RlcjtcblxuICAgIC8vIGlmIGNsdXN0ZXIgaXMgdW5kZWZpbmVkIChzaG91bGRudCBoYXBwZW4pIG9yIHN0YXR1cyBpcyBub3QgQUNUSVZFLCB3ZSBhcmVcbiAgICAvLyBub3QgY29tcGxldGUuIG5vdGUgdGhhdCB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZyYW1ld29yayBmb3JiaWRzXG4gICAgLy8gcmV0dXJuaW5nIGF0dHJpYnV0ZXMgKERhdGEpIGlmIGlzQ29tcGxldGUgaXMgZmFsc2UuXG4gICAgaWYgKGNsdXN0ZXI/LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgIC8vIG5vdCB2ZXJ5IGluZm9ybWF0aXZlLCB1bmZvcnR1bmF0ZWx5IHRoZSByZXNwb25zZSBkb2Vzbid0IGNvbnRhaW4gYW55IGVycm9yXG4gICAgICAvLyBpbmZvcm1hdGlvbiA6XFxcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2x1c3RlciBpcyBpbiBhIEZBSUxFRCBzdGF0dXMnKTtcbiAgICB9IGVsc2UgaWYgKGNsdXN0ZXI/LnN0YXR1cyAhPT0gJ0FDVElWRScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIE5hbWU6IGNsdXN0ZXIubmFtZSxcbiAgICAgICAgICBFbmRwb2ludDogY2x1c3Rlci5lbmRwb2ludCxcbiAgICAgICAgICBBcm46IGNsdXN0ZXIuYXJuLFxuXG4gICAgICAgICAgLy8gSU1QT1JUQU5UOiBDRk4gZXhwZWN0cyB0aGF0IGF0dHJpYnV0ZXMgd2lsbCAqYWx3YXlzKiBoYXZlIHZhbHVlcyxcbiAgICAgICAgICAvLyBzbyByZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGluIGNhc2UgdGhlIHZhbHVlIGlzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQ0ZOIHdpbGwgdGhyb3cgd2l0aCBgVmVuZG9yIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpblxuICAgICAgICAgIC8vIFhYWFgga2V5YC5cblxuICAgICAgICAgIENlcnRpZmljYXRlQXV0aG9yaXR5RGF0YTogY2x1c3Rlci5jZXJ0aWZpY2F0ZUF1dGhvcml0eT8uZGF0YSA/PyAnJyxcbiAgICAgICAgICBDbHVzdGVyU2VjdXJpdHlHcm91cElkOiBjbHVzdGVyLnJlc291cmNlc1ZwY0NvbmZpZz8uY2x1c3RlclNlY3VyaXR5R3JvdXBJZCA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyVXJsOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXIgPz8gJycsXG4gICAgICAgICAgT3BlbklkQ29ubmVjdElzc3VlcjogY2x1c3Rlci5pZGVudGl0eT8ub2lkYz8uaXNzdWVyPy5zdWJzdHJpbmcoOCkgPz8gJycsIC8vIFN0cmlwcyBvZmYgaHR0cHM6Ly8gZnJvbSB0aGUgaXNzdWVyIHVybFxuXG4gICAgICAgICAgLy8gV2UgY2FuIHNhZmVseSByZXR1cm4gdGhlIGZpcnN0IGl0ZW0gZnJvbSBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gYXJyYXksIGJlY2F1c2UgaXQgaGFzIGEgbGltaXQgb2YgMSBpdGVtXG4gICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vrcy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDbHVzdGVyLmh0bWwjQW1hem9uRUtTLUNyZWF0ZUNsdXN0ZXItcmVxdWVzdC1lbmNyeXB0aW9uQ29uZmlnXG4gICAgICAgICAgRW5jcnlwdGlvbkNvbmZpZ0tleUFybjogY2x1c3Rlci5lbmNyeXB0aW9uQ29uZmlnPy5zaGlmdCgpPy5wcm92aWRlcj8ua2V5QXJuID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzRWtzVXBkYXRlQ29tcGxldGUoZWtzVXBkYXRlSWQ6IHN0cmluZykge1xuICAgIHRoaXMubG9nKHsgaXNFa3NVcGRhdGVDb21wbGV0ZTogZWtzVXBkYXRlSWQgfSk7XG5cbiAgICBjb25zdCBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVVcGRhdGUoe1xuICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgIHVwZGF0ZUlkOiBla3NVcGRhdGVJZCxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nKHsgZGVzY3JpYmVVcGRhdGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5hYmxlIHRvIGRlc2NyaWJlIHVwZGF0ZSB3aXRoIGlkIFwiJHtla3NVcGRhdGVJZH1cImApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzKSB7XG4gICAgICBjYXNlICdJblByb2dyZXNzJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgY2FzZSAnU3VjY2Vzc2Z1bCc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnRmFpbGVkJzpcbiAgICAgIGNhc2UgJ0NhbmNlbGxlZCc6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2x1c3RlciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiIGZhaWxlZCB3aXRoIGVycm9yczogJHtKU09OLnN0cmluZ2lmeShkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5lcnJvcnMpfWApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIHN0YXR1cyBcIiR7ZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzfVwiIGZvciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNsdXN0ZXJOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9DTFVTVEVSX05BTUVfTEVOIC0gc3VmZml4Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5sb2dpY2FsUmVzb3VyY2VJZC5zbGljZSgwLCBvZmZzZXQgPiAwID8gb2Zmc2V0IDogMCk7XG4gICAgcmV0dXJuIGAke3ByZWZpeH0tJHtzdWZmaXh9YDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3BzKHByb3BzOiBhbnkpOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0IHtcblxuICBjb25zdCBwYXJzZWQgPSBwcm9wcz8uQ29uZmlnID8/IHt9O1xuXG4gIC8vIHRoaXMgaXMgd2VpcmQgYnV0IHRoZXNlIGJvb2xlYW4gcHJvcGVydGllcyBhcmUgcGFzc2VkIGJ5IENGTiBhcyBhIHN0cmluZywgYW5kIHdlIG5lZWQgdGhlbSB0byBiZSBib29sZWFuaWMgZm9yIHRoZSBTREsuXG4gIC8vIE90aGVyd2lzZSBpdCBmYWlscyB3aXRoICdVbmV4cGVjdGVkIFBhcmFtZXRlcjogcGFyYW1zLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgaXMgZXhwZWN0ZWQgdG8gYmUgYSBib29sZWFuJ1xuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWc/LmVuZHBvaW50UHJpdmF0ZUFjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9PT0gJ3RydWUnO1xuICB9XG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQdWJsaWNBY2Nlc3MpID09PSAnc3RyaW5nJykge1xuICAgIHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQubG9nZ2luZz8uY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCkgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9IHBhcnNlZC5sb2dnaW5nLmNsdXN0ZXJMb2dnaW5nWzBdLmVuYWJsZWQgPT09ICd0cnVlJztcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQ7XG5cbn1cblxuaW50ZXJmYWNlIFVwZGF0ZU1hcCB7XG4gIHJlcGxhY2VOYW1lOiBib29sZWFuOyAvLyBuYW1lXG4gIHJlcGxhY2VWcGM6IGJvb2xlYW47IC8vIHJlc291cmNlc1ZwY0NvbmZpZy5zdWJuZXRJZHMgYW5kIHNlY3VyaXR5R3JvdXBJZHNcbiAgcmVwbGFjZVJvbGU6IGJvb2xlYW47IC8vIHJvbGVBcm5cblxuICB1cGRhdGVWZXJzaW9uOiBib29sZWFuOyAvLyB2ZXJzaW9uXG4gIHVwZGF0ZUxvZ2dpbmc6IGJvb2xlYW47IC8vIGxvZ2dpbmdcbiAgdXBkYXRlRW5jcnlwdGlvbjogYm9vbGVhbjsgLy8gZW5jcnlwdGlvbiAoY2Fubm90IGJlIHVwZGF0ZWQpXG4gIHVwZGF0ZUFjY2VzczogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBhbmQgZW5kcG9pbnRQdWJsaWNBY2Nlc3Ncbn1cblxuZnVuY3Rpb24gYW5hbHl6ZVVwZGF0ZShvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PiwgbmV3UHJvcHM6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBVcGRhdGVNYXAge1xuICBjb25zb2xlLmxvZygnb2xkIHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShvbGRQcm9wcykpO1xuICBjb25zb2xlLmxvZygnbmV3IHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShuZXdQcm9wcykpO1xuXG4gIGNvbnN0IG5ld1ZwY1Byb3BzID0gbmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRWcGNQcm9wcyA9IG9sZFByb3BzLnJlc291cmNlc1ZwY0NvbmZpZyB8fCB7fTtcblxuICBjb25zdCBvbGRQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQob2xkVnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQobmV3VnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdFbmMgPSBuZXdQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRFbmMgPSBvbGRQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgcmVwbGFjZU5hbWU6IG5ld1Byb3BzLm5hbWUgIT09IG9sZFByb3BzLm5hbWUsXG4gICAgcmVwbGFjZVZwYzpcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnN1Ym5ldElkcykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFZwY1Byb3BzLnN1Ym5ldElkcykgfHxcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnNlY3VyaXR5R3JvdXBJZHMpICE9PSBKU09OLnN0cmluZ2lmeShvbGRWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzKSxcbiAgICB1cGRhdGVBY2Nlc3M6XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgIT09IG9sZFZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyB8fFxuICAgICAgbmV3VnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgIT09IG9sZFZwY1Byb3BzLmVuZHBvaW50UHVibGljQWNjZXNzIHx8XG4gICAgICAhc2V0c0VxdWFsKG5ld1B1YmxpY0FjY2Vzc0NpZHJzLCBvbGRQdWJsaWNBY2Nlc3NDaWRycyksXG4gICAgcmVwbGFjZVJvbGU6IG5ld1Byb3BzLnJvbGVBcm4gIT09IG9sZFByb3BzLnJvbGVBcm4sXG4gICAgdXBkYXRlVmVyc2lvbjogbmV3UHJvcHMudmVyc2lvbiAhPT0gb2xkUHJvcHMudmVyc2lvbixcbiAgICB1cGRhdGVFbmNyeXB0aW9uOiBKU09OLnN0cmluZ2lmeShuZXdFbmMpICE9PSBKU09OLnN0cmluZ2lmeShvbGRFbmMpLFxuICAgIHVwZGF0ZUxvZ2dpbmc6IEpTT04uc3RyaW5naWZ5KG5ld1Byb3BzLmxvZ2dpbmcpICE9PSBKU09OLnN0cmluZ2lmeShvbGRQcm9wcy5sb2dnaW5nKSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gc2V0c0VxdWFsKGZpcnN0OiBTZXQ8c3RyaW5nPiwgc2Vjb25kOiBTZXQ8c3RyaW5nPikge1xuICByZXR1cm4gZmlyc3Quc2l6ZSA9PT0gc2Vjb25kLnNpemUgJiYgWy4uLmZpcnN0XS5ldmVyeSgoZTogc3RyaW5nKSA9PiBzZWNvbmQuaGFzKGUpKTtcbn1cbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.ts deleted file mode 100644 index e6930b7844d32..0000000000000 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.ts +++ /dev/null @@ -1,344 +0,0 @@ -/* eslint-disable no-console */ - -// eslint-disable-next-line import/no-extraneous-dependencies -import { IsCompleteResponse, OnEventResponse } from '@aws-cdk/custom-resources/lib/provider-framework/types'; -// eslint-disable-next-line import/no-extraneous-dependencies -import * as aws from 'aws-sdk'; -import { EksClient, ResourceEvent, ResourceHandler } from './common'; - -const MAX_CLUSTER_NAME_LEN = 100; - -export class ClusterResourceHandler extends ResourceHandler { - public get clusterName() { - if (!this.physicalResourceId) { - throw new Error('Cannot determine cluster name without physical resource ID'); - } - - return this.physicalResourceId; - } - - private readonly newProps: aws.EKS.CreateClusterRequest; - private readonly oldProps: Partial; - - constructor(eks: EksClient, event: ResourceEvent) { - super(eks, event); - - this.newProps = parseProps(this.event.ResourceProperties); - this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; - } - - // ------ - // CREATE - // ------ - - protected async onCreate(): Promise { - console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); - if (!this.newProps.roleArn) { - throw new Error('"roleArn" is required'); - } - - const clusterName = this.newProps.name || this.generateClusterName(); - - const resp = await this.eks.createCluster({ - ...this.newProps, - name: clusterName, - }); - - if (!resp.cluster) { - throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); - } - - return { - PhysicalResourceId: resp.cluster.name, - }; - } - - protected async isCreateComplete() { - return this.isActive(); - } - - // ------ - // DELETE - // ------ - - protected async onDelete(): Promise { - console.log(`onDelete: deleting cluster ${this.clusterName}`); - try { - await this.eks.deleteCluster({ name: this.clusterName }); - } catch (e) { - if (e.code !== 'ResourceNotFoundException') { - throw e; - } else { - console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); - } - } - return { - PhysicalResourceId: this.clusterName, - }; - } - - protected async isDeleteComplete(): Promise { - console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); - - try { - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); - } catch (e) { - if (e.code === 'ResourceNotFoundException') { - console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); - return { IsComplete: true }; - } - - console.log('describeCluster error:', e); - throw e; - } - - return { - IsComplete: false, - }; - } - - // ------ - // UPDATE - // ------ - - protected async onUpdate() { - const updates = analyzeUpdate(this.oldProps, this.newProps); - console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); - - // updates to encryption config is not supported - if (updates.updateEncryption) { - throw new Error('Cannot update cluster encryption configuration'); - } - - // if there is an update that requires replacement, go ahead and just create - // a new cluster with the new config. The old cluster will automatically be - // deleted by cloudformation upon success. - if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { - - // if we are replacing this cluster and the cluster has an explicit - // physical name, the creation of the new cluster will fail with "there is - // already a cluster with that name". this is a common behavior for - // CloudFormation resources that support specifying a physical name. - if (this.oldProps.name === this.newProps.name && this.oldProps.name) { - throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); - } - - return this.onCreate(); - } - - // if a version update is required, issue the version update - if (updates.updateVersion) { - if (!this.newProps.version) { - throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); - } - - return this.updateClusterVersion(this.newProps.version); - } - - if (updates.updateLogging && updates.updateAccess) { - throw new Error('Cannot update logging and access at the same time'); - } - - if (updates.updateLogging || updates.updateAccess) { - const config: aws.EKS.UpdateClusterConfigRequest = { - name: this.clusterName, - }; - if (updates.updateLogging) { - config.logging = this.newProps.logging; - }; - if (updates.updateAccess) { - // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: - // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) - // will fail, therefore we take only the access fields explicitly - config.resourcesVpcConfig = { - endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, - endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, - publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, - }; - } - const updateResponse = await this.eks.updateClusterConfig(config); - - return { EksUpdateId: updateResponse.update?.id }; - } - - // no updates - return; - } - - protected async isUpdateComplete() { - console.log('isUpdateComplete'); - - // if this is an EKS update, we will monitor the update event itself - if (this.event.EksUpdateId) { - const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); - if (!complete) { - return { IsComplete: false }; - } - - // fall through: if the update is done, we simply delegate to isActive() - // in order to extract attributes and state from the cluster itself, which - // is supposed to be in an ACTIVE state after the update is complete. - } - - return this.isActive(); - } - - private async updateClusterVersion(newVersion: string) { - console.log(`updating cluster version to ${newVersion}`); - - // update-cluster-version will fail if we try to update to the same version, - // so skip in this case. - const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; - if (cluster?.version === newVersion) { - console.log(`cluster already at version ${cluster.version}, skipping version update`); - return; - } - - const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); - return { EksUpdateId: updateResponse.update?.id }; - } - - private async isActive(): Promise { - console.log('waiting for cluster to become ACTIVE'); - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); - const cluster = resp.cluster; - - // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are - // not complete. note that the custom resource provider framework forbids - // returning attributes (Data) if isComplete is false. - if (cluster?.status === 'FAILED') { - // not very informative, unfortunately the response doesn't contain any error - // information :\ - throw new Error('Cluster is in a FAILED status'); - } else if (cluster?.status !== 'ACTIVE') { - return { - IsComplete: false, - }; - } else { - return { - IsComplete: true, - Data: { - Name: cluster.name, - Endpoint: cluster.endpoint, - Arn: cluster.arn, - - // IMPORTANT: CFN expects that attributes will *always* have values, - // so return an empty string in case the value is not defined. - // Otherwise, CFN will throw with `Vendor response doesn't contain - // XXXX key`. - - CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', - ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', - OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', - OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', // Strips off https:// from the issuer url - - // We can safely return the first item from encryption configuration array, because it has a limit of 1 item - // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig - EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', - }, - }; - } - } - - private async isEksUpdateComplete(eksUpdateId: string) { - this.log({ isEksUpdateComplete: eksUpdateId }); - - const describeUpdateResponse = await this.eks.describeUpdate({ - name: this.clusterName, - updateId: eksUpdateId, - }); - - this.log({ describeUpdateResponse }); - - if (!describeUpdateResponse.update) { - throw new Error(`unable to describe update with id "${eksUpdateId}"`); - } - - switch (describeUpdateResponse.update.status) { - case 'InProgress': - return false; - case 'Successful': - return true; - case 'Failed': - case 'Cancelled': - throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); - default: - throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); - } - } - - private generateClusterName() { - const suffix = this.requestId.replace(/-/g, ''); // 32 chars - const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; - const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); - return `${prefix}-${suffix}`; - } -} - -function parseProps(props: any): aws.EKS.CreateClusterRequest { - - const parsed = props?.Config ?? {}; - - // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. - // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' - - if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; - } - - if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; - } - - if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { - parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; - } - - return parsed; - -} - -interface UpdateMap { - replaceName: boolean; // name - replaceVpc: boolean; // resourcesVpcConfig.subnetIds and securityGroupIds - replaceRole: boolean; // roleArn - - updateVersion: boolean; // version - updateLogging: boolean; // logging - updateEncryption: boolean; // encryption (cannot be updated) - updateAccess: boolean; // resourcesVpcConfig.endpointPrivateAccess and endpointPublicAccess -} - -function analyzeUpdate(oldProps: Partial, newProps: aws.EKS.CreateClusterRequest): UpdateMap { - console.log('old props: ', JSON.stringify(oldProps)); - console.log('new props: ', JSON.stringify(newProps)); - - const newVpcProps = newProps.resourcesVpcConfig || {}; - const oldVpcProps = oldProps.resourcesVpcConfig || {}; - - const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); - const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); - const newEnc = newProps.encryptionConfig || {}; - const oldEnc = oldProps.encryptionConfig || {}; - - return { - replaceName: newProps.name !== oldProps.name, - replaceVpc: - JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), - updateAccess: - newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || - newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || - !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), - replaceRole: newProps.roleArn !== oldProps.roleArn, - updateVersion: newProps.version !== oldProps.version, - updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), - updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), - }; -} - -function setsEqual(first: Set, second: Set) { - return first.size === second.size && [...first].every((e: string) => second.has(e)); -} diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/helm/__init__.py b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/helm/__init__.py deleted file mode 100644 index a7b26b264118b..0000000000000 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/helm/__init__.py +++ /dev/null @@ -1,189 +0,0 @@ -import json -import logging -import os -import re -import subprocess -import shutil -import tempfile -import zipfile -from urllib.parse import urlparse, unquote - -logger = logging.getLogger() -logger.setLevel(logging.INFO) - -# these are coming from the kubectl layer -os.environ['PATH'] = '/opt/helm:/opt/awscli:' + os.environ['PATH'] - -outdir = os.environ.get('TEST_OUTDIR', '/tmp') -kubeconfig = os.path.join(outdir, 'kubeconfig') - -def get_chart_asset_from_url(chart_asset_url): - chart_zip = os.path.join(outdir, 'chart.zip') - shutil.rmtree(chart_zip, ignore_errors=True) - subprocess.check_call(['aws', 's3', 'cp', chart_asset_url, chart_zip]) - chart_dir = os.path.join(outdir, 'chart') - shutil.rmtree(chart_dir, ignore_errors=True) - os.mkdir(chart_dir) - with zipfile.ZipFile(chart_zip, 'r') as zip_ref: - zip_ref.extractall(chart_dir) - return chart_dir - -def helm_handler(event, context): - logger.info(json.dumps(dict(event, ResponseURL='...'))) - - request_type = event['RequestType'] - props = event['ResourceProperties'] - - # resource properties - cluster_name = props['ClusterName'] - role_arn = props['RoleArn'] - release = props['Release'] - chart = props.get('Chart', None) - chart_asset_url = props.get('ChartAssetURL', None) - version = props.get('Version', None) - wait = props.get('Wait', False) - timeout = props.get('Timeout', None) - namespace = props.get('Namespace', None) - create_namespace = props.get('CreateNamespace', None) - repository = props.get('Repository', None) - values_text = props.get('Values', None) - - # "log in" to the cluster - subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig', - '--role-arn', role_arn, - '--name', cluster_name, - '--kubeconfig', kubeconfig - ]) - - if os.path.isfile(kubeconfig): - os.chmod(kubeconfig, 0o600) - - # Write out the values to a file and include them with the install and upgrade - values_file = None - if not request_type == "Delete" and not values_text is None: - values = json.loads(values_text) - values_file = os.path.join(outdir, 'values.yaml') - with open(values_file, "w") as f: - f.write(json.dumps(values, indent=2)) - - if request_type == 'Create' or request_type == 'Update': - # Ensure chart or chart_asset_url are set - if chart == None and chart_asset_url == None: - raise RuntimeError(f'chart or chartAsset must be specified') - - if chart_asset_url != None: - assert(chart==None) - assert(repository==None) - assert(version==None) - if not chart_asset_url.startswith('s3://'): - raise RuntimeError(f'ChartAssetURL must point to as s3 location but is {chart_asset_url}') - # future work: support versions from s3 assets - chart = get_chart_asset_from_url(chart_asset_url) - - if repository is not None and repository.startswith('oci://'): - tmpdir = tempfile.TemporaryDirectory() - chart_dir = get_chart_from_oci(tmpdir.name, repository, version) - chart = chart_dir - - helm('upgrade', release, chart, repository, values_file, namespace, version, wait, timeout, create_namespace) - elif request_type == "Delete": - try: - helm('uninstall', release, namespace=namespace, timeout=timeout) - except Exception as e: - logger.info("delete error: %s" % e) - - -def get_oci_cmd(repository, version): - # Generates OCI command based on pattern. Public ECR vs Private ECR are treated differently. - cmnd = [] - private_ecr_pattern = '\d+.dkr.ecr.[a-z]+-[a-z]+-\d.amazonaws.com' - public_ecr = 'public.ecr.aws' - - registry = repository.rsplit('/', 1)[0].replace('oci://', '') - - if re.fullmatch(private_ecr_pattern, registry) is not None: - logger.info("Found AWS private repository") - region = registry.replace('.amazonaws.com', '').split('.')[-1] - cmnd = [ - f"aws ecr get-login-password --region {region} | " \ - f"helm registry login --username AWS --password-stdin {registry}; helm pull {repository} --version {version} --untar" - ] - elif registry.startswith(public_ecr): - logger.info("Found AWS public repository, will use default region as deployment") - region = os.environ.get('AWS_REGION', 'us-east-1') - - cmnd = [ - f"aws ecr-public get-login-password --region {region} | " \ - f"helm registry login --username AWS --password-stdin {public_ecr}; helm pull {repository} --version {version} --untar" - ] - else: - logger.error("OCI repository format not recognized, falling back to helm pull") - cmnd = ['helm', 'pull', repository, '--version', version, '--untar'] - - return cmnd - - -def get_chart_from_oci(tmpdir, repository = None, version = None): - - cmnd = get_oci_cmd(repository, version) - - maxAttempts = 3 - retry = maxAttempts - while retry > 0: - try: - logger.info(cmnd) - output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=tmpdir, shell=True) - logger.info(output) - - # effectively returns "$tmpDir/$lastPartOfOCIUrl", because this is how helm pull saves OCI artifact. - # Eg. if we have oci://9999999999.dkr.ecr.us-east-1.amazonaws.com/foo/bar/pet-service repository, helm saves artifact under $tmpDir/pet-service - return os.path.join(tmpdir, repository.rpartition('/')[-1]) - except subprocess.CalledProcessError as exc: - output = exc.output - if b'Broken pipe' in output: - retry = retry - 1 - logger.info("Broken pipe, retries left: %s" % retry) - else: - raise Exception(output) - raise Exception(f'Operation failed after {maxAttempts} attempts: {output}') - - -def helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None): - import subprocess - - cmnd = ['helm', verb, release] - if not chart is None: - cmnd.append(chart) - if verb == 'upgrade': - cmnd.append('--install') - if create_namespace: - cmnd.append('--create-namespace') - if not repo is None: - cmnd.extend(['--repo', repo]) - if not file is None: - cmnd.extend(['--values', file]) - if not version is None: - cmnd.extend(['--version', version]) - if not namespace is None: - cmnd.extend(['--namespace', namespace]) - if wait: - cmnd.append('--wait') - if not timeout is None: - cmnd.extend(['--timeout', timeout]) - cmnd.extend(['--kubeconfig', kubeconfig]) - - maxAttempts = 3 - retry = maxAttempts - while retry > 0: - try: - output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir) - logger.info(output) - return - except subprocess.CalledProcessError as exc: - output = exc.output - if b'Broken pipe' in output: - retry = retry - 1 - logger.info("Broken pipe, retries left: %s" % retry) - else: - raise Exception(output) - raise Exception(f'Operation failed after {maxAttempts} attempts: {output}') diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip index ce3ea448ac19d..13983109fc5f5 100644 Binary files a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip and b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip differ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/apply/__init__.py b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/apply/__init__.py rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/get/__init__.py b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/get/__init__.py rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py new file mode 100644 index 0000000000000..286976ced219a --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py @@ -0,0 +1,187 @@ +import json +import logging +import os +import re +import subprocess +import shutil +import tempfile +import zipfile + +logger = logging.getLogger() +logger.setLevel(logging.INFO) + +# these are coming from the kubectl layer +os.environ['PATH'] = '/opt/helm:/opt/awscli:' + os.environ['PATH'] + +outdir = os.environ.get('TEST_OUTDIR', '/tmp') +kubeconfig = os.path.join(outdir, 'kubeconfig') + +def get_chart_asset_from_url(chart_asset_url): + chart_zip = os.path.join(outdir, 'chart.zip') + shutil.rmtree(chart_zip, ignore_errors=True) + subprocess.check_call(['aws', 's3', 'cp', chart_asset_url, chart_zip]) + chart_dir = os.path.join(outdir, 'chart') + shutil.rmtree(chart_dir, ignore_errors=True) + os.mkdir(chart_dir) + with zipfile.ZipFile(chart_zip, 'r') as zip_ref: + zip_ref.extractall(chart_dir) + return chart_dir + +def helm_handler(event, context): + logger.info(json.dumps(dict(event, ResponseURL='...'))) + + request_type = event['RequestType'] + props = event['ResourceProperties'] + + # resource properties + cluster_name = props['ClusterName'] + role_arn = props['RoleArn'] + release = props['Release'] + chart = props.get('Chart', None) + chart_asset_url = props.get('ChartAssetURL', None) + version = props.get('Version', None) + wait = props.get('Wait', False) + timeout = props.get('Timeout', None) + namespace = props.get('Namespace', None) + create_namespace = props.get('CreateNamespace', None) + repository = props.get('Repository', None) + values_text = props.get('Values', None) + + # "log in" to the cluster + subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig', + '--role-arn', role_arn, + '--name', cluster_name, + '--kubeconfig', kubeconfig + ]) + + if os.path.isfile(kubeconfig): + os.chmod(kubeconfig, 0o600) + + # Write out the values to a file and include them with the install and upgrade + values_file = None + if not request_type == "Delete" and not values_text is None: + values = json.loads(values_text) + values_file = os.path.join(outdir, 'values.yaml') + with open(values_file, "w") as f: + f.write(json.dumps(values, indent=2)) + + if request_type == 'Create' or request_type == 'Update': + # Ensure chart or chart_asset_url are set + if chart == None and chart_asset_url == None: + raise RuntimeError(f'chart or chartAsset must be specified') + + if chart_asset_url != None: + assert(chart==None) + assert(repository==None) + assert(version==None) + if not chart_asset_url.startswith('s3://'): + raise RuntimeError(f'ChartAssetURL must point to as s3 location but is {chart_asset_url}') + # future work: support versions from s3 assets + chart = get_chart_asset_from_url(chart_asset_url) + + if repository is not None and repository.startswith('oci://'): + tmpdir = tempfile.TemporaryDirectory() + chart_dir = get_chart_from_oci(tmpdir.name, repository, version) + chart = chart_dir + + helm('upgrade', release, chart, repository, values_file, namespace, version, wait, timeout, create_namespace) + elif request_type == "Delete": + try: + helm('uninstall', release, namespace=namespace, timeout=timeout) + except Exception as e: + logger.info("delete error: %s" % e) + + +def get_oci_cmd(repository, version): + # Generates OCI command based on pattern. Public ECR vs Private ECR are treated differently. + private_ecr_pattern = 'oci://(?P\d+.dkr.ecr.(?P[a-z]+-[a-z]+-\d).amazonaws.com)*' + public_ecr_pattern = 'oci://(?Ppublic.ecr.aws)*' + + private_registry = re.match(private_ecr_pattern, repository).groupdict() + public_registry = re.match(public_ecr_pattern, repository).groupdict() + + if private_registry['registry'] is not None: + logger.info("Found AWS private repository") + cmnd = [ + f"aws ecr get-login-password --region {private_registry['region']} | " \ + f"helm registry login --username AWS --password-stdin {private_registry['registry']}; helm pull {repository} --version {version} --untar" + ] + elif public_registry['registry'] is not None: + logger.info("Found AWS public repository, will use default region as deployment") + region = os.environ.get('AWS_REGION', 'us-east-1') + + cmnd = [ + f"aws ecr-public get-login-password --region us-east-1 | " \ + f"helm registry login --username AWS --password-stdin {public_registry['registry']}; helm pull {repository} --version {version} --untar" + ] + else: + logger.error("OCI repository format not recognized, falling back to helm pull") + cmnd = ['helm', 'pull', repository, '--version', version, '--untar'] + + return cmnd + + +def get_chart_from_oci(tmpdir, repository = None, version = None): + + cmnd = get_oci_cmd(repository, version) + + maxAttempts = 3 + retry = maxAttempts + while retry > 0: + try: + logger.info(cmnd) + output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=tmpdir, shell=True) + logger.info(output) + + # effectively returns "$tmpDir/$lastPartOfOCIUrl", because this is how helm pull saves OCI artifact. + # Eg. if we have oci://9999999999.dkr.ecr.us-east-1.amazonaws.com/foo/bar/pet-service repository, helm saves artifact under $tmpDir/pet-service + return os.path.join(tmpdir, repository.rpartition('/')[-1]) + except subprocess.CalledProcessError as exc: + output = exc.output + if b'Broken pipe' in output: + retry = retry - 1 + logger.info("Broken pipe, retries left: %s" % retry) + else: + raise Exception(output) + raise Exception(f'Operation failed after {maxAttempts} attempts: {output}') + + +def helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None): + import subprocess + + cmnd = ['helm', verb, release] + if not chart is None: + cmnd.append(chart) + if verb == 'upgrade': + cmnd.append('--install') + if create_namespace: + cmnd.append('--create-namespace') + if not repo is None: + cmnd.extend(['--repo', repo]) + if not file is None: + cmnd.extend(['--values', file]) + if not version is None: + cmnd.extend(['--version', version]) + if not namespace is None: + cmnd.extend(['--namespace', namespace]) + if wait: + cmnd.append('--wait') + if not timeout is None: + cmnd.extend(['--timeout', timeout]) + cmnd.extend(['--kubeconfig', kubeconfig]) + + maxAttempts = 3 + retry = maxAttempts + while retry > 0: + try: + output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir) + logger.info(output) + return + except subprocess.CalledProcessError as exc: + output = exc.output + if b'Broken pipe' in output: + retry = retry - 1 + logger.info("Broken pipe, retries left: %s" % retry) + else: + raise Exception(output) + raise Exception(f'Operation failed after {maxAttempts} attempts: {output}') diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/index.py b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/index.py rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/patch/__init__.py b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/patch/__init__.py rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/aws-stepfunctions-tasks-emr-containers-start-job-run-test.assets.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/aws-stepfunctions-tasks-emr-containers-start-job-run-test.assets.json index 1e3ca12d1507f..0b979f6032486 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/aws-stepfunctions-tasks-emr-containers-start-job-run-test.assets.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/aws-stepfunctions-tasks-emr-containers-start-job-run-test.assets.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "files": { "ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1": { "source": { @@ -14,15 +14,15 @@ } } }, - "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5": { + "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee": { "source": { - "path": "asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5", + "path": "asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip", + "objectKey": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -40,15 +40,15 @@ } } }, - "a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd": { + "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8": { "source": { - "path": "asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd", + "path": "asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd.zip", + "objectKey": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -105,7 +105,7 @@ } } }, - "f61e6013fd4f150889ad36f3bb7e03ff8bb8ec47c6246f1aa662f111b6229ae8": { + "d808c7b09f17a5b8142a9ee7eff4287d5ce8461eced11312cb8d647602e4f2f4": { "source": { "path": "awsstepfunctionstasksemrcontainersstartjobruntestawscdkawseksClusterResourceProvider2391B7F7.nested.template.json", "packaging": "file" @@ -113,12 +113,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "f61e6013fd4f150889ad36f3bb7e03ff8bb8ec47c6246f1aa662f111b6229ae8.json", + "objectKey": "d808c7b09f17a5b8142a9ee7eff4287d5ce8461eced11312cb8d647602e4f2f4.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "2c4bbd9bfdca8d0c8d329000c43b16b2ec52206c08b4027657c1d76a41a4185e": { + "e5f80caa912def8e04aa645be0d878c4be62a3c71e5ed2335f37702f0e365e33": { "source": { "path": "awsstepfunctionstasksemrcontainersstartjobruntestawscdkawseksKubectlProviderEB85BF5A.nested.template.json", "packaging": "file" @@ -126,12 +126,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "2c4bbd9bfdca8d0c8d329000c43b16b2ec52206c08b4027657c1d76a41a4185e.json", + "objectKey": "e5f80caa912def8e04aa645be0d878c4be62a3c71e5ed2335f37702f0e365e33.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "e6eaca5f95d8be16472cdbd60817d3e874e920852d04c07132fa19e7d6be6e9e": { + "6953b4416f5110b908a0830d060a2ddcbb7af91e54cabc9231ddbc773f7a3e90": { "source": { "path": "aws-stepfunctions-tasks-emr-containers-start-job-run-test.template.json", "packaging": "file" @@ -139,7 +139,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "e6eaca5f95d8be16472cdbd60817d3e874e920852d04c07132fa19e7d6be6e9e.json", + "objectKey": "6953b4416f5110b908a0830d060a2ddcbb7af91e54cabc9231ddbc773f7a3e90.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/aws-stepfunctions-tasks-emr-containers-start-job-run-test.template.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/aws-stepfunctions-tasks-emr-containers-start-job-run-test.template.json index c1627f1b76a6b..3e2c2241e73ec 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/aws-stepfunctions-tasks-emr-containers-start-job-run-test.template.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/aws-stepfunctions-tasks-emr-containers-start-job-run-test.template.json @@ -980,7 +980,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/f61e6013fd4f150889ad36f3bb7e03ff8bb8ec47c6246f1aa662f111b6229ae8.json" + "/d808c7b09f17a5b8142a9ee7eff4287d5ce8461eced11312cb8d647602e4f2f4.json" ] ] }, @@ -1015,7 +1015,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/2c4bbd9bfdca8d0c8d329000c43b16b2ec52206c08b4027657c1d76a41a4185e.json" + "/e5f80caa912def8e04aa645be0d878c4be62a3c71e5ed2335f37702f0e365e33.json" ] ] }, diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/awsstepfunctionstasksemrcontainersstartjobrunDefaultTestDeployAssert0C0D5C7F.assets.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/awsstepfunctionstasksemrcontainersstartjobrunDefaultTestDeployAssert0C0D5C7F.assets.json index d458abf6274ab..3a39787a6ccf1 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/awsstepfunctionstasksemrcontainersstartjobrunDefaultTestDeployAssert0C0D5C7F.assets.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/awsstepfunctionstasksemrcontainersstartjobrunDefaultTestDeployAssert0C0D5C7F.assets.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/awsstepfunctionstasksemrcontainersstartjobruntestawscdkawseksClusterResourceProvider2391B7F7.nested.template.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/awsstepfunctionstasksemrcontainersstartjobruntestawscdkawseksClusterResourceProvider2391B7F7.nested.template.json index 06eef5274ca63..d6a92efeec8a2 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/awsstepfunctionstasksemrcontainersstartjobruntestawscdkawseksClusterResourceProvider2391B7F7.nested.template.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/awsstepfunctionstasksemrcontainersstartjobruntestawscdkawseksClusterResourceProvider2391B7F7.nested.template.json @@ -73,7 +73,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ @@ -162,7 +162,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/awsstepfunctionstasksemrcontainersstartjobruntestawscdkawseksKubectlProviderEB85BF5A.nested.template.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/awsstepfunctionstasksemrcontainersstartjobruntestawscdkawseksKubectlProviderEB85BF5A.nested.template.json index 603f101ac4aa1..e18726ae92e89 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/awsstepfunctionstasksemrcontainersstartjobruntestawscdkawseksKubectlProviderEB85BF5A.nested.template.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/awsstepfunctionstasksemrcontainersstartjobruntestawscdkawseksKubectlProviderEB85BF5A.nested.template.json @@ -51,6 +51,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -92,7 +104,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd.zip" + "S3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/cdk.out b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/cdk.out index ae4b03c54e770..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"30.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/integ.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/integ.json index 23859f1ee4f00..b97117768e83d 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "testCases": { "aws-stepfunctions-tasks-emr-containers-start-job-run/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/manifest.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/manifest.json index d8c9b2b4f4be5..60e1218926392 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "artifacts": { "aws-stepfunctions-tasks-emr-containers-start-job-run-test.assets": { "type": "cdk:asset-manifest", @@ -17,7 +17,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/e6eaca5f95d8be16472cdbd60817d3e874e920852d04c07132fa19e7d6be6e9e.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/6953b4416f5110b908a0830d060a2ddcbb7af91e54cabc9231ddbc773f7a3e90.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/tree.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/tree.json index 8a1f2ae75f6c1..b180568b42669 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/tree.json @@ -960,7 +960,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } }, "KubectlReadyBarrier": { @@ -1482,7 +1482,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -1655,7 +1655,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -2496,7 +2496,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } } }, @@ -2553,7 +2553,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/f61e6013fd4f150889ad36f3bb7e03ff8bb8ec47c6246f1aa662f111b6229ae8.json" + "/d808c7b09f17a5b8142a9ee7eff4287d5ce8461eced11312cb8d647602e4f2f4.json" ] ] }, @@ -2575,7 +2575,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } }, "@aws-cdk--aws-eks.KubectlProvider": { @@ -2652,6 +2652,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -2751,7 +2763,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd.zip" + "s3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "role": { "Fn::GetAtt": [ @@ -3221,7 +3233,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/2c4bbd9bfdca8d0c8d329000c43b16b2ec52206c08b4027657c1d76a41a4185e.json" + "/e5f80caa912def8e04aa645be0d878c4be62a3c71e5ed2335f37702f0e365e33.json" ] ] }, @@ -3261,7 +3273,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } }, "Virtual Cluster": { @@ -4327,7 +4339,7 @@ "path": "aws-stepfunctions-tasks-emr-containers-start-job-run/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } }, "DeployAssert": { @@ -4373,7 +4385,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } } },