agent-claw: automated task changes
This commit is contained in:
0
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/.is_custom_resource
generated
vendored
Normal file
0
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/.is_custom_resource
generated
vendored
Normal file
5
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-certificatemanager/certificate-request-provider.generated.d.ts
generated
vendored
Normal file
5
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-certificatemanager/certificate-request-provider.generated.d.ts
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import { Construct } from "constructs";
|
||||
import * as lambda from "../../../aws-lambda";
|
||||
export declare class CertificateRequestCertificateRequestFunction extends lambda.Function {
|
||||
constructor(scope: Construct, id: string, props?: lambda.FunctionOptions);
|
||||
}
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-certificatemanager/certificate-request-provider.generated.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-certificatemanager/certificate-request-provider.generated.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.CertificateRequestCertificateRequestFunction=void 0;const path=require("path"),lambda=require("../../../aws-lambda");class CertificateRequestCertificateRequestFunction extends lambda.Function{constructor(scope,id,props){super(scope,id,{...props,code:lambda.Code.fromAsset(path.join(__dirname,"dns-validated-certificate-handler")),handler:"index.certificateRequestHandler",runtime:lambda.determineLatestNodeRuntime(scope)}),this.node.addMetadata("aws:cdk:is-custom-resource-handler-runtime-family",this.runtime.family)}}exports.CertificateRequestCertificateRequestFunction=CertificateRequestCertificateRequestFunction;
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-certificatemanager/dns-validated-certificate-handler/index.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-certificatemanager/dns-validated-certificate-handler/index.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
13
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-cloudfront/cross-region-string-param-reader-provider.generated.d.ts
generated
vendored
Normal file
13
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-cloudfront/cross-region-string-param-reader-provider.generated.d.ts
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Construct } from "constructs";
|
||||
import { CustomResourceProviderBase, CustomResourceProviderOptions } from "../../../core";
|
||||
export declare class CrossRegionStringParamReaderProvider extends CustomResourceProviderBase {
|
||||
/**
|
||||
* Returns a stack-level singleton ARN (service token) for the custom resource provider.
|
||||
*/
|
||||
static getOrCreate(scope: Construct, uniqueid: string, props?: CustomResourceProviderOptions): string;
|
||||
/**
|
||||
* Returns a stack-level singleton for the custom resource provider.
|
||||
*/
|
||||
static getOrCreateProvider(scope: Construct, uniqueid: string, props?: CustomResourceProviderOptions): CrossRegionStringParamReaderProvider;
|
||||
private constructor();
|
||||
}
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-cloudfront/cross-region-string-param-reader-provider.generated.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-cloudfront/cross-region-string-param-reader-provider.generated.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.CrossRegionStringParamReaderProvider=void 0;const path=require("path"),core_1=require("../../../core");class CrossRegionStringParamReaderProvider extends core_1.CustomResourceProviderBase{static getOrCreate(scope,uniqueid,props){return this.getOrCreateProvider(scope,uniqueid,props).serviceToken}static getOrCreateProvider(scope,uniqueid,props){const id=`${uniqueid}CustomResourceProvider`,stack=core_1.Stack.of(scope);return stack.node.tryFindChild(id)??new CrossRegionStringParamReaderProvider(stack,id,props)}constructor(scope,id,props){super(scope,id,{...props,codeDirectory:path.join(__dirname,"edge-function"),runtimeName:(0,core_1.determineLatestNodeRuntimeName)(scope)}),this.node.addMetadata("aws:cdk:is-custom-resource-handler-customResourceProvider",!0)}}exports.CrossRegionStringParamReaderProvider=CrossRegionStringParamReaderProvider;
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-cloudfront/edge-function/index.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-cloudfront/edge-function/index.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.handler=a;var t=require("@aws-sdk/client-ssm");async function a(n){let e=n.ResourceProperties;if(console.info(`Reading function ARN from SSM parameter ${e.ParameterName} in region ${e.Region}`),n.RequestType==="Create"||n.RequestType==="Update"){let r=await new t.SSM({region:e.Region}).getParameter({Name:e.ParameterName});return console.info("Response: %j",r),{Data:{FunctionArn:r.Parameter?.Value??""}}}}
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-dynamodb/replica-handler/index.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-dynamodb/replica-handler/index.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";var n=Object.defineProperty,d=Object.getOwnPropertyDescriptor,u=Object.getOwnPropertyNames,m=Object.prototype.hasOwnProperty,b=(e,s)=>{for(var t in s)n(e,t,{get:s[t],enumerable:!0})},T=(e,s,t,o)=>{if(s&&typeof s=="object"||typeof s=="function")for(let a of u(s))!m.call(e,a)&&a!==t&&n(e,a,{get:()=>s[a],enumerable:!(o=d(s,a))||o.enumerable});return e},g=e=>T(n({},"__esModule",{value:!0}),e),f={};b(f,{isCompleteHandler:()=>y,onEventHandler:()=>C}),module.exports=g(f);var c=require("@aws-sdk/client-dynamodb");async function C(e){console.log("Event: %j",{...e,ResponseURL:"..."});let s=new c.DynamoDB({}),t=e.ResourceProperties.TableName,o=e.ResourceProperties.Region,a=e.ResourceProperties.SkipReplicaDeletion==="true",i;if(e.RequestType==="Create"||e.RequestType==="Delete")i=e.RequestType;else{let l=await s.describeTable({TableName:t});console.log("Describe table: %j",l),i=l.Table?.Replicas?.some(p=>p.RegionName===o)?void 0:"Create"}if(i)if(i==="Delete"&&a)console.log("Skipping deleting replica table as replica table is set to retain.");else{let l=await s.updateTable({TableName:t,ReplicaUpdates:[{[i]:{RegionName:o}}]});console.log("Update table: %j",l)}else console.log("Skipping updating Table, as a replica in '%s' already exists",o);return e.RequestType==="Create"||e.RequestType==="Update"?{PhysicalResourceId:`${t}-${o}`}:{}}async function y(e){console.log("Event: %j",{...e,ResponseURL:"..."});let t=await new c.DynamoDB({}).describeTable({TableName:e.ResourceProperties.TableName});console.log("Describe table: %j",t);let o=t.Table?.TableStatus==="ACTIVE",i=(t.Table?.Replicas??[]).find(R=>R.RegionName===e.ResourceProperties.Region),l=i?.ReplicaStatus==="ACTIVE",r=e.ResourceProperties.SkipReplicationCompletedWait==="true",p=e.ResourceProperties.SkipReplicaDeletion==="true";switch(e.RequestType){case"Create":case"Update":return{IsComplete:o&&(l||r)};case"Delete":return p?(console.log("Skipping replica deletion check since replica is set to retain."),{IsComplete:!0}):{IsComplete:o&&i===void 0}}}
|
||||
8
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-dynamodb/replica-provider.generated.d.ts
generated
vendored
Normal file
8
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-dynamodb/replica-provider.generated.d.ts
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
import { Construct } from "constructs";
|
||||
import * as lambda from "../../../aws-lambda";
|
||||
export declare class ReplicaOnEventFunction extends lambda.Function {
|
||||
constructor(scope: Construct, id: string, props?: lambda.FunctionOptions);
|
||||
}
|
||||
export declare class ReplicaIsCompleteFunction extends lambda.Function {
|
||||
constructor(scope: Construct, id: string, props?: lambda.FunctionOptions);
|
||||
}
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-dynamodb/replica-provider.generated.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-dynamodb/replica-provider.generated.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ReplicaIsCompleteFunction=exports.ReplicaOnEventFunction=void 0;const path=require("path"),lambda=require("../../../aws-lambda");class ReplicaOnEventFunction extends lambda.Function{constructor(scope,id,props){super(scope,id,{...props,code:lambda.Code.fromAsset(path.join(__dirname,"replica-handler")),handler:"index.onEventHandler",runtime:lambda.determineLatestNodeRuntime(scope)}),this.node.addMetadata("aws:cdk:is-custom-resource-handler-runtime-family",this.runtime.family)}}exports.ReplicaOnEventFunction=ReplicaOnEventFunction;class ReplicaIsCompleteFunction extends lambda.Function{constructor(scope,id,props){super(scope,id,{...props,code:lambda.Code.fromAsset(path.join(__dirname,"replica-handler")),handler:"index.isCompleteHandler",runtime:lambda.determineLatestNodeRuntime(scope)}),this.node.addMetadata("aws:cdk:is-custom-resource-handler-runtime-family",this.runtime.family)}}exports.ReplicaIsCompleteFunction=ReplicaIsCompleteFunction;
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-ec2/restrict-default-security-group-handler/index.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-ec2/restrict-default-security-group-handler/index.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";var I=Object.create,t=Object.defineProperty,y=Object.getOwnPropertyDescriptor,P=Object.getOwnPropertyNames,g=Object.getPrototypeOf,l=Object.prototype.hasOwnProperty,G=(r,e)=>{for(var o in e)t(r,o,{get:e[o],enumerable:!0})},n=(r,e,o,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of P(e))!l.call(r,s)&&s!==o&&t(r,s,{get:()=>e[s],enumerable:!(i=y(e,s))||i.enumerable});return r},R=(r,e,o)=>(o=r!=null?I(g(r)):{},n(e||!r||!r.__esModule?t(o,"default",{value:r,enumerable:!0}):o,r)),S=r=>n(t({},"__esModule",{value:!0}),r),k={};G(k,{handler:()=>f}),module.exports=S(k);var a=R(require("@aws-sdk/client-ec2")),u=new a.EC2({});function c(r,e){return{GroupId:r,IpPermissions:[{UserIdGroupPairs:[{GroupId:r,UserId:e}],IpProtocol:"-1"}]}}function d(r){return{GroupId:r,IpPermissions:[{IpRanges:[{CidrIp:"0.0.0.0/0"}],IpProtocol:"-1"}]}}async function f(r){let e=r.ResourceProperties.DefaultSecurityGroupId,o=r.ResourceProperties.Account;switch(r.RequestType){case"Create":return p(e,o);case"Update":return h(r);case"Delete":return m(e,o)}}async function h(r){let e=r.OldResourceProperties.DefaultSecurityGroupId,o=r.ResourceProperties.DefaultSecurityGroupId;e!==o&&(await m(e,r.ResourceProperties.Account),await p(o,r.ResourceProperties.Account))}async function p(r,e){try{await u.revokeSecurityGroupEgress(d(r))}catch(o){if(o.name!=="InvalidPermission.NotFound")throw o}try{await u.revokeSecurityGroupIngress(c(r,e))}catch(o){if(o.name!=="InvalidPermission.NotFound")throw o}}async function m(r,e){await u.authorizeSecurityGroupIngress(c(r,e)),await u.authorizeSecurityGroupEgress(d(r))}
|
||||
13
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-ec2/restrict-default-sg-provider.generated.d.ts
generated
vendored
Normal file
13
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-ec2/restrict-default-sg-provider.generated.d.ts
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Construct } from "constructs";
|
||||
import { CustomResourceProviderBase, CustomResourceProviderOptions } from "../../../core";
|
||||
export declare class RestrictDefaultSgProvider extends CustomResourceProviderBase {
|
||||
/**
|
||||
* Returns a stack-level singleton ARN (service token) for the custom resource provider.
|
||||
*/
|
||||
static getOrCreate(scope: Construct, uniqueid: string, props?: CustomResourceProviderOptions): string;
|
||||
/**
|
||||
* Returns a stack-level singleton for the custom resource provider.
|
||||
*/
|
||||
static getOrCreateProvider(scope: Construct, uniqueid: string, props?: CustomResourceProviderOptions): RestrictDefaultSgProvider;
|
||||
private constructor();
|
||||
}
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-ec2/restrict-default-sg-provider.generated.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-ec2/restrict-default-sg-provider.generated.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.RestrictDefaultSgProvider=void 0;const path=require("path"),core_1=require("../../../core");class RestrictDefaultSgProvider extends core_1.CustomResourceProviderBase{static getOrCreate(scope,uniqueid,props){return this.getOrCreateProvider(scope,uniqueid,props).serviceToken}static getOrCreateProvider(scope,uniqueid,props){const id=`${uniqueid}CustomResourceProvider`,stack=core_1.Stack.of(scope);return stack.node.tryFindChild(id)??new RestrictDefaultSgProvider(stack,id,props)}constructor(scope,id,props){super(scope,id,{...props,codeDirectory:path.join(__dirname,"restrict-default-security-group-handler"),runtimeName:(0,core_1.determineLatestNodeRuntimeName)(scope)}),this.node.addMetadata("aws:cdk:is-custom-resource-handler-customResourceProvider",!0)}}exports.RestrictDefaultSgProvider=RestrictDefaultSgProvider;
|
||||
2
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-ecr/auto-delete-images-handler/index.js
generated
vendored
Normal file
2
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-ecr/auto-delete-images-handler/index.js
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
"use strict";var C=Object.create,c=Object.defineProperty,w=Object.getOwnPropertyDescriptor,S=Object.getOwnPropertyNames,A=Object.getPrototypeOf,P=Object.prototype.hasOwnProperty,L=(e,t)=>{for(var o in t)c(e,o,{get:t[o],enumerable:!0})},d=(e,t,o,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of S(t))!P.call(e,r)&&r!==o&&c(e,r,{get:()=>t[r],enumerable:!(s=w(t,r))||s.enumerable});return e},l=(e,t,o)=>(o=e!=null?C(A(e)):{},d(t||!e||!e.__esModule?c(o,"default",{value:e,enumerable:!0}):o,e)),T=e=>d(c({},"__esModule",{value:!0}),e),W={};L(W,{autoDeleteHandler:()=>I,handler:()=>k}),module.exports=T(W);var h=require("@aws-sdk/client-ecr"),m=l(require("https")),R=l(require("url")),n={sendHttpRequest:x,log:N,includeStackTraces:!0,userHandlerIndex:"./index"},p="AWSCDK::CustomResourceProviderFramework::CREATE_FAILED",D="AWSCDK::CustomResourceProviderFramework::MISSING_PHYSICAL_ID";function y(e){return async(t,o)=>{let s={...t,ResponseURL:"..."};if(n.log(JSON.stringify(s,void 0,2)),t.RequestType==="Delete"&&t.PhysicalResourceId===p){n.log("ignoring DELETE event caused by a failed CREATE event"),await u("SUCCESS",t);return}try{let r=await e(s,o),a=b(t,r);await u("SUCCESS",a)}catch(r){let a={...t,Reason:n.includeStackTraces?r.stack:r.message};a.PhysicalResourceId||(t.RequestType==="Create"?(n.log("CREATE failed, responding with a marker physical resource id so that the subsequent DELETE will be ignored"),a.PhysicalResourceId=p):n.log(`ERROR: Malformed event. "PhysicalResourceId" is required: ${JSON.stringify(t)}`)),await u("FAILED",a)}}}function b(e,t={}){let o=t.PhysicalResourceId??e.PhysicalResourceId??e.RequestId;if(e.RequestType==="Delete"&&o!==e.PhysicalResourceId)throw new Error(`DELETE: cannot change the physical resource ID from "${e.PhysicalResourceId}" to "${t.PhysicalResourceId}" during deletion`);return{...e,...t,PhysicalResourceId:o}}async function u(e,t){let o={Status:e,Reason:t.Reason??e,StackId:t.StackId,RequestId:t.RequestId,PhysicalResourceId:t.PhysicalResourceId||D,LogicalResourceId:t.LogicalResourceId,NoEcho:t.NoEcho,Data:t.Data},s=R.parse(t.ResponseURL),r=`${s.protocol}//${s.hostname}/${s.pathname}?***`;n.log("submit response to cloudformation",r,o);let a=JSON.stringify(o),E={hostname:s.hostname,path:s.path,method:"PUT",headers:{"content-type":"","content-length":Buffer.byteLength(a,"utf8")}};await F({attempts:5,sleep:1e3},n.sendHttpRequest)(E,a)}async function x(e,t){return new Promise((o,s)=>{try{let r=m.request(e,a=>{a.resume(),!a.statusCode||a.statusCode>=400?s(new Error(`Unsuccessful HTTP response: ${a.statusCode}`)):o()});r.on("error",s),r.write(t),r.end()}catch(r){s(r)}})}function N(e,...t){console.log(e,...t)}function F(e,t){return async(...o)=>{let s=e.attempts,r=e.sleep;for(;;)try{return await t(...o)}catch(a){if(s--<=0)throw a;await H(Math.floor(Math.random()*r)),r*=2}}}async function H(e){return new Promise(t=>setTimeout(t,e))}var g="aws-cdk:auto-delete-images",i=new h.ECR({}),k=y(I);async function I(e){switch(e.RequestType){case"Create":break;case"Update":return{PhysicalResourceId:(await q(e)).PhysicalResourceId};case"Delete":return U(e.ResourceProperties?.RepositoryName)}}async function q(e){let t=e,o=t.OldResourceProperties?.RepositoryName;return{PhysicalResourceId:t.ResourceProperties?.RepositoryName??o}}async function f(e){let t=await i.listImages(e),o=[],s=[];(t.imageIds??[]).forEach(a=>{"imageTag"in a?s.push(a):o.push(a)});let r=t.nextToken??null;o.length===0&&s.length===0||(s.length!==0&&await i.batchDeleteImage({repositoryName:e.repositoryName,imageIds:s}),o.length!==0&&await i.batchDeleteImage({repositoryName:e.repositoryName,imageIds:o}),r&&await f({...e,nextToken:r}))}async function U(e){if(!e)throw new Error("No RepositoryName was provided.");let o=(await i.describeRepositories({repositoryNames:[e]})).repositories?.find(s=>s.repositoryName===e);if(!await _(o?.repositoryArn)){process.stdout.write(`Repository does not have '${g}' tag, skipping cleaning.
|
||||
`);return}try{await f({repositoryName:e})}catch(s){if(s.name!=="RepositoryNotFoundException")throw s}}async function _(e){return(await i.listTagsForResource({resourceArn:e})).tags?.some(o=>o.Key===g&&o.Value==="true")}
|
||||
13
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-ecr/auto-delete-images-provider.generated.d.ts
generated
vendored
Normal file
13
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-ecr/auto-delete-images-provider.generated.d.ts
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Construct } from "constructs";
|
||||
import { CustomResourceProviderBase, CustomResourceProviderOptions } from "../../../core";
|
||||
export declare class AutoDeleteImagesProvider extends CustomResourceProviderBase {
|
||||
/**
|
||||
* Returns a stack-level singleton ARN (service token) for the custom resource provider.
|
||||
*/
|
||||
static getOrCreate(scope: Construct, uniqueid: string, props?: CustomResourceProviderOptions): string;
|
||||
/**
|
||||
* Returns a stack-level singleton for the custom resource provider.
|
||||
*/
|
||||
static getOrCreateProvider(scope: Construct, uniqueid: string, props?: CustomResourceProviderOptions): AutoDeleteImagesProvider;
|
||||
private constructor();
|
||||
}
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-ecr/auto-delete-images-provider.generated.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-ecr/auto-delete-images-provider.generated.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.AutoDeleteImagesProvider=void 0;const path=require("path"),core_1=require("../../../core");class AutoDeleteImagesProvider extends core_1.CustomResourceProviderBase{static getOrCreate(scope,uniqueid,props){return this.getOrCreateProvider(scope,uniqueid,props).serviceToken}static getOrCreateProvider(scope,uniqueid,props){const id=`${uniqueid}CustomResourceProvider`,stack=core_1.Stack.of(scope);return stack.node.tryFindChild(id)??new AutoDeleteImagesProvider(stack,id,props)}constructor(scope,id,props){super(scope,id,{...props,codeDirectory:path.join(__dirname,"auto-delete-images-handler"),runtimeName:(0,core_1.determineLatestNodeRuntimeName)(scope)}),this.node.addMetadata("aws:cdk:is-custom-resource-handler-customResourceProvider",!0)}}exports.AutoDeleteImagesProvider=AutoDeleteImagesProvider;
|
||||
5
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-ecs/drain-hook-provider.generated.d.ts
generated
vendored
Normal file
5
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-ecs/drain-hook-provider.generated.d.ts
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import { Construct } from "constructs";
|
||||
import * as lambda from "../../../aws-lambda";
|
||||
export declare class DrainHookLambda_Function extends lambda.Function {
|
||||
constructor(scope: Construct, id: string, props?: lambda.FunctionOptions);
|
||||
}
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-ecs/drain-hook-provider.generated.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-ecs/drain-hook-provider.generated.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.DrainHookLambda_Function=void 0;const path=require("path"),lambda=require("../../../aws-lambda");class DrainHookLambda_Function extends lambda.Function{constructor(scope,id,props){super(scope,id,{...props,code:lambda.Code.fromAsset(path.join(__dirname,"lambda-source")),handler:"index.lambda_handler",runtime:lambda.Runtime.PYTHON_3_13}),this.node.addMetadata("aws:cdk:is-custom-resource-handler-runtime-family",this.runtime.family)}}exports.DrainHookLambda_Function=DrainHookLambda_Function;
|
||||
90
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-ecs/lambda-source/index.py
generated
vendored
Normal file
90
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-ecs/lambda-source/index.py
generated
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
import boto3, json, os, time
|
||||
|
||||
ecs = boto3.client('ecs')
|
||||
autoscaling = boto3.client('autoscaling')
|
||||
|
||||
|
||||
def lambda_handler(event, context):
|
||||
print(json.dumps(dict(event, ResponseURL='...')))
|
||||
cluster = os.environ['CLUSTER']
|
||||
snsTopicArn = event['Records'][0]['Sns']['TopicArn']
|
||||
lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])
|
||||
instance_id = lifecycle_event.get('EC2InstanceId')
|
||||
if not instance_id:
|
||||
print(f"Got event without EC2InstanceId: { json.dumps(dict(event, ResponseURL='...')) }")
|
||||
return
|
||||
|
||||
instance_arn = container_instance_arn(cluster, instance_id)
|
||||
print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))
|
||||
|
||||
if not instance_arn:
|
||||
return
|
||||
|
||||
task_arns = container_instance_task_arns(cluster, instance_arn)
|
||||
|
||||
if task_arns:
|
||||
print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))
|
||||
|
||||
while has_tasks(cluster, instance_arn, task_arns):
|
||||
time.sleep(10)
|
||||
|
||||
try:
|
||||
print('Terminating instance %s' % instance_id)
|
||||
autoscaling.complete_lifecycle_action(
|
||||
LifecycleActionResult='CONTINUE',
|
||||
**pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))
|
||||
except Exception as e:
|
||||
# Lifecycle action may have already completed.
|
||||
print(str(e))
|
||||
|
||||
|
||||
def container_instance_arn(cluster, instance_id):
|
||||
"""Turn an instance ID into a container instance ARN."""
|
||||
arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']
|
||||
if not arns:
|
||||
return None
|
||||
return arns[0]
|
||||
|
||||
def container_instance_task_arns(cluster, instance_arn):
|
||||
"""Fetch tasks for a container instance ARN."""
|
||||
arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']
|
||||
return arns
|
||||
|
||||
def has_tasks(cluster, instance_arn, task_arns):
|
||||
"""Return True if the instance is running tasks for the given cluster."""
|
||||
instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']
|
||||
if not instances:
|
||||
return False
|
||||
instance = instances[0]
|
||||
|
||||
if instance['status'] == 'ACTIVE':
|
||||
# Start draining, then try again later
|
||||
set_container_instance_to_draining(cluster, instance_arn)
|
||||
return True
|
||||
|
||||
task_count = None
|
||||
|
||||
if task_arns:
|
||||
# Fetch details for tasks running on the container instance
|
||||
tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']
|
||||
if tasks:
|
||||
# Consider any non-stopped tasks as running
|
||||
task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']
|
||||
|
||||
if not task_count:
|
||||
# Fallback to instance task counts if detailed task information is unavailable
|
||||
task_count = instance['runningTasksCount'] + instance['pendingTasksCount']
|
||||
|
||||
print('Instance %s has %s tasks' % (instance_arn, task_count))
|
||||
|
||||
return task_count > 0
|
||||
|
||||
def set_container_instance_to_draining(cluster, instance_arn):
|
||||
ecs.update_container_instances_state(
|
||||
cluster=cluster,
|
||||
containerInstances=[instance_arn], status='DRAINING')
|
||||
|
||||
|
||||
def pick(dct, *keys):
|
||||
"""Pick a subset of a dict."""
|
||||
return {k: v for k, v in dct.items() if k in keys}
|
||||
93
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-eks-v2/kubectl-handler/apply/__init__.py
generated
vendored
Normal file
93
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-eks-v2/kubectl-handler/apply/__init__.py
generated
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
logger = logging.getLogger()
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
# these are coming from the kubectl layer
|
||||
os.environ['PATH'] = '/opt/kubectl:/opt/awscli:' + os.environ['PATH']
|
||||
|
||||
outdir = os.environ.get('TEST_OUTDIR', '/tmp')
|
||||
kubeconfig = os.path.join(outdir, 'kubeconfig')
|
||||
|
||||
|
||||
def apply_handler(event, context):
|
||||
logger.info(json.dumps(dict(event, ResponseURL='...')))
|
||||
|
||||
request_type = event['RequestType']
|
||||
props = event['ResourceProperties']
|
||||
|
||||
# resource properties (all required)
|
||||
cluster_name = props['ClusterName']
|
||||
manifest_text = props['Manifest']
|
||||
prune_label = props.get('PruneLabel', None)
|
||||
overwrite = props.get('Overwrite', 'false').lower() == 'true'
|
||||
skip_validation = props.get('SkipValidation', 'false').lower() == 'true'
|
||||
|
||||
# "log in" to the cluster
|
||||
cmd = [ 'aws', 'eks', 'update-kubeconfig',
|
||||
'--name', cluster_name,
|
||||
'--kubeconfig', kubeconfig
|
||||
]
|
||||
logger.info(f'Running command: {cmd}')
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
if os.path.isfile(kubeconfig):
|
||||
os.chmod(kubeconfig, 0o600)
|
||||
|
||||
# write resource manifests in sequence: { r1 }{ r2 }{ r3 } (this is how
|
||||
# a stream of JSON objects can be included in a k8s manifest).
|
||||
manifest_list = json.loads(manifest_text)
|
||||
manifest_file = os.path.join(outdir, 'manifest.yaml')
|
||||
with open(manifest_file, "w") as f:
|
||||
f.writelines(map(lambda obj: json.dumps(obj), manifest_list))
|
||||
|
||||
logger.info("manifest written to: %s" % manifest_file)
|
||||
|
||||
kubectl_opts = []
|
||||
if skip_validation:
|
||||
kubectl_opts.extend(['--validate=false'])
|
||||
|
||||
if request_type == 'Create':
|
||||
# if "overwrite" is enabled, then we use "apply" for CREATE operations
|
||||
# which technically means we can determine the desired state of an
|
||||
# existing resource.
|
||||
if overwrite:
|
||||
kubectl('apply', manifest_file, *kubectl_opts)
|
||||
else:
|
||||
# --save-config will allow us to use "apply" later
|
||||
kubectl_opts.extend(['--save-config'])
|
||||
kubectl('create', manifest_file, *kubectl_opts)
|
||||
elif request_type == 'Update':
|
||||
if prune_label is not None:
|
||||
kubectl_opts.extend(['--prune', '-l', prune_label])
|
||||
|
||||
kubectl('apply', manifest_file, *kubectl_opts)
|
||||
elif request_type == "Delete":
|
||||
try:
|
||||
kubectl('delete', manifest_file)
|
||||
except Exception as e:
|
||||
logger.info("delete error: %s" % e)
|
||||
|
||||
|
||||
def kubectl(verb, file, *opts):
|
||||
maxAttempts = 3
|
||||
retry = maxAttempts
|
||||
while retry > 0:
|
||||
try:
|
||||
cmd = ['kubectl', verb, '--kubeconfig', kubeconfig, '-f', file] + list(opts)
|
||||
logger.info(f'Running command: {cmd}')
|
||||
output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError as exc:
|
||||
output = exc.output
|
||||
if b'i/o timeout' in output and retry > 0:
|
||||
retry = retry - 1
|
||||
logger.info("kubectl timed out, retries left: %s" % retry)
|
||||
else:
|
||||
raise Exception(output)
|
||||
else:
|
||||
logger.info(output)
|
||||
return
|
||||
raise Exception(f'Operation failed after {maxAttempts} attempts: {output}')
|
||||
86
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-eks-v2/kubectl-handler/get/__init__.py
generated
vendored
Normal file
86
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-eks-v2/kubectl-handler/get/__init__.py
generated
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
logger = logging.getLogger()
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
# these are coming from the kubectl layer
|
||||
os.environ['PATH'] = '/opt/kubectl:/opt/awscli:' + os.environ['PATH']
|
||||
|
||||
outdir = os.environ.get('TEST_OUTDIR', '/tmp')
|
||||
kubeconfig = os.path.join(outdir, 'kubeconfig')
|
||||
|
||||
|
||||
def get_handler(event, context):
|
||||
logger.info(json.dumps(dict(event, ResponseURL='...')))
|
||||
|
||||
request_type = event['RequestType']
|
||||
props = event['ResourceProperties']
|
||||
|
||||
# resource properties (all required)
|
||||
cluster_name = props['ClusterName']
|
||||
|
||||
# "log in" to the cluster
|
||||
subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig',
|
||||
'--name', cluster_name,
|
||||
'--kubeconfig', kubeconfig
|
||||
])
|
||||
|
||||
if os.path.isfile(kubeconfig):
|
||||
os.chmod(kubeconfig, 0o600)
|
||||
|
||||
object_type = props['ObjectType']
|
||||
object_name = props['ObjectName']
|
||||
object_namespace = props['ObjectNamespace']
|
||||
json_path = props['JsonPath']
|
||||
timeout_seconds = props['TimeoutSeconds']
|
||||
|
||||
# json path should be surrouded with '{}'
|
||||
path = '{{{0}}}'.format(json_path)
|
||||
if request_type == 'Create' or request_type == 'Update':
|
||||
output = wait_for_output(['get', '-n', object_namespace, object_type, object_name, "-o=jsonpath='{{{0}}}'".format(json_path)], int(timeout_seconds))
|
||||
return {'Data': {'Value': output}}
|
||||
elif request_type == 'Delete':
|
||||
pass
|
||||
else:
|
||||
raise Exception("invalid request type %s" % request_type)
|
||||
|
||||
def wait_for_output(args, timeout_seconds):
|
||||
|
||||
end_time = time.time() + timeout_seconds
|
||||
error = None
|
||||
|
||||
while time.time() < end_time:
|
||||
try:
|
||||
# the output is surrounded with '', so we unquote
|
||||
output = kubectl(args).decode('utf-8')[1:-1]
|
||||
if output:
|
||||
return output
|
||||
except Exception as e:
|
||||
error = str(e)
|
||||
# also a recoverable error
|
||||
if 'NotFound' in error:
|
||||
pass
|
||||
time.sleep(10)
|
||||
|
||||
raise RuntimeError(f'Timeout waiting for output from kubectl command: {args} (last_error={error})')
|
||||
|
||||
def kubectl(args):
|
||||
retry = 3
|
||||
while retry > 0:
|
||||
try:
|
||||
cmd = [ 'kubectl', '--kubeconfig', kubeconfig ] + args
|
||||
output = subprocess.check_output(cmd, stderr=subprocess.PIPE)
|
||||
except subprocess.CalledProcessError as exc:
|
||||
output = exc.output + exc.stderr
|
||||
if b'i/o timeout' in output and retry > 0:
|
||||
logger.info("kubectl timed out, retries left: %s" % retry)
|
||||
retry = retry - 1
|
||||
else:
|
||||
raise Exception(output)
|
||||
else:
|
||||
logger.info(output)
|
||||
return output
|
||||
255
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-eks-v2/kubectl-handler/helm/__init__.py
generated
vendored
Normal file
255
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-eks-v2/kubectl-handler/helm/__init__.py
generated
vendored
Normal file
@@ -0,0 +1,255 @@
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import shutil
|
||||
import tempfile
|
||||
import zipfile
|
||||
import boto3
|
||||
|
||||
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 is_ecr_public_available(region):
|
||||
s = boto3.Session()
|
||||
return s.get_partition_for_region(region) == 'aws'
|
||||
|
||||
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']
|
||||
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)
|
||||
atomic = props.get('Atomic', 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)
|
||||
skip_crds = props.get('SkipCrds', False)
|
||||
|
||||
# "log in" to the cluster
|
||||
subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig',
|
||||
'--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
|
||||
# Chart is now local — clear repository and version so helm() doesn't
|
||||
# pass --repo/--version to "helm upgrade". Helm v4 (kubectl-v35+)
|
||||
# rejects --repo with oci:// URLs ("invalid reference"), unlike v3.
|
||||
repository = None
|
||||
version = None
|
||||
|
||||
helm('upgrade', release, chart, repository, values_file, namespace, version, wait, timeout, create_namespace, atomic=atomic)
|
||||
elif request_type == "Delete":
|
||||
try:
|
||||
helm('uninstall', release, namespace=namespace, wait=wait, 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<registry>\d+\.dkr\.ecr\.(?P<region>[a-z0-9\-]+)\.(?P<domain>[a-z0-9\.-]+))*'
|
||||
public_ecr_pattern = 'oci://(?P<registry>public\.ecr\.aws)*'
|
||||
|
||||
private_registry = re.match(private_ecr_pattern, repository).groupdict()
|
||||
public_registry = re.match(public_ecr_pattern, repository).groupdict()
|
||||
|
||||
# Build helm pull command as array
|
||||
helm_cmd = ['helm', 'pull', repository, '--version', version , '--untar']
|
||||
|
||||
if private_registry['registry'] is not None:
|
||||
logger.info("Found AWS private repository")
|
||||
ecr_login = ['aws', 'ecr', 'get-login-password', '--region', private_registry['region']]
|
||||
helm_registry_login = ['helm', 'registry', 'login', '--username', 'AWS', '--password-stdin', private_registry['registry']]
|
||||
return {'ecr_login': ecr_login, 'helm_registry_login': helm_registry_login, 'helm': helm_cmd}
|
||||
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')
|
||||
|
||||
if is_ecr_public_available(region):
|
||||
# Public ECR auth is always in us-east-1: https://docs.aws.amazon.com/AmazonECR/latest/public/public-registry-auth.html
|
||||
ecr_login = ['aws', 'ecr-public', 'get-login-password', '--region', 'us-east-1']
|
||||
helm_registry_login = ['helm', 'registry', 'login', '--username', 'AWS', '--password-stdin', public_registry['registry']]
|
||||
return {'ecr_login': ecr_login, 'helm_registry_login': helm_registry_login, 'helm': helm_cmd}
|
||||
else:
|
||||
# No login required for public ECR in non-aws regions
|
||||
# see https://helm.sh/docs/helm/helm_registry_login/
|
||||
return {'helm': helm_cmd}
|
||||
else:
|
||||
logger.error("OCI repository format not recognized, falling back to helm pull")
|
||||
return {'helm': helm_cmd}
|
||||
|
||||
|
||||
def get_chart_from_oci(tmpdir, repository=None, version=None):
|
||||
from subprocess import Popen, PIPE
|
||||
|
||||
commands = get_oci_cmd(repository, version)
|
||||
|
||||
maxAttempts = 3
|
||||
retry = maxAttempts
|
||||
while retry > 0:
|
||||
try:
|
||||
# Execute login commands if needed
|
||||
if 'ecr_login' in commands and 'helm_registry_login' in commands:
|
||||
logger.info("Running login command: %s", commands['ecr_login'])
|
||||
logger.info("Running registry login command: %s", commands['helm_registry_login'])
|
||||
|
||||
# Start first process: aws ecr get-login-password
|
||||
# NOTE: We do NOT call p1.wait() here before starting p2.
|
||||
# Doing so could deadlock if p1's output fills the pipe buffer
|
||||
# before p2 starts reading. Instead, start p2 immediately so it
|
||||
# can consume p1's stdout as it's produced.
|
||||
p1 = Popen(commands['ecr_login'], stdout=PIPE, stderr=PIPE, cwd=tmpdir)
|
||||
|
||||
# Start second process: helm registry login
|
||||
p2 = Popen(commands['helm_registry_login'], stdin=p1.stdout, stdout=PIPE, stderr=PIPE, cwd=tmpdir)
|
||||
p1.stdout.close() # Allow p1 to receive SIGPIPE if p2 exits early
|
||||
|
||||
# Wait for p2 to finish first (ensures full pipeline completes)
|
||||
_, p2_err = p2.communicate()
|
||||
|
||||
# Now wait for p1 so we have a complete stderr and an exit code
|
||||
p1.wait()
|
||||
|
||||
# Handle p1 failure
|
||||
if p1.returncode != 0:
|
||||
p1_err = p1.stderr.read().decode('utf-8', errors='replace') if p1.stderr else ''
|
||||
logger.error(
|
||||
"ECR get-login-password failed for repository %s. Error: %s",
|
||||
repository,
|
||||
p1_err or "No error details"
|
||||
)
|
||||
raise subprocess.CalledProcessError(p1.returncode, commands['ecr_login'], p1_err.encode())
|
||||
|
||||
# Handle p2 failure
|
||||
if p2.returncode != 0:
|
||||
logger.error(
|
||||
"Helm registry authentication failed for repository %s. Error: %s",
|
||||
repository,
|
||||
p2_err.decode('utf-8', errors='replace') or "No error details"
|
||||
)
|
||||
raise subprocess.CalledProcessError(p2.returncode, commands['helm_registry_login'], p2_err)
|
||||
|
||||
# Execute helm pull command
|
||||
logger.info("Running helm command: %s", commands['helm'])
|
||||
output = subprocess.check_output(commands['helm'], stderr=subprocess.STDOUT, cwd=tmpdir)
|
||||
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, skip_crds = False, atomic = False):
|
||||
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 skip_crds:
|
||||
cmnd.append('--skip-crds')
|
||||
if not timeout is None:
|
||||
cmnd.extend(['--timeout', timeout])
|
||||
if atomic:
|
||||
cmnd.append('--atomic')
|
||||
cmnd.extend(['--kubeconfig', kubeconfig])
|
||||
|
||||
# Log the full helm command for better troubleshooting
|
||||
logger.info("Running command: %s", cmnd)
|
||||
|
||||
maxAttempts = 3
|
||||
retry = maxAttempts
|
||||
while retry > 0:
|
||||
try:
|
||||
output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir)
|
||||
logger.info(output.decode('utf-8', errors='replace'))
|
||||
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:
|
||||
error_message = output.decode('utf-8', errors='replace')
|
||||
logger.error("Command failed: %s", cmnd)
|
||||
logger.error("Error output: %s", error_message)
|
||||
raise Exception(output)
|
||||
raise Exception(f'Operation failed after {maxAttempts} attempts: {output.decode("utf-8", errors="replace")}')
|
||||
26
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-eks-v2/kubectl-handler/index.py
generated
vendored
Normal file
26
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-eks-v2/kubectl-handler/index.py
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
import json
|
||||
import logging
|
||||
|
||||
from apply import apply_handler
|
||||
from helm import helm_handler
|
||||
from patch import patch_handler
|
||||
from get import get_handler
|
||||
|
||||
def handler(event, context):
|
||||
print(json.dumps(dict(event, ResponseURL='...')))
|
||||
|
||||
resource_type = event['ResourceType']
|
||||
if resource_type == 'Custom::AWSCDK-EKS-KubernetesResource':
|
||||
return apply_handler(event, context)
|
||||
|
||||
if resource_type == 'Custom::AWSCDK-EKS-HelmChart':
|
||||
return helm_handler(event, context)
|
||||
|
||||
if resource_type == 'Custom::AWSCDK-EKS-KubernetesPatch':
|
||||
return patch_handler(event, context)
|
||||
|
||||
if resource_type == 'Custom::AWSCDK-EKS-KubernetesObjectValue':
|
||||
return get_handler(event, context)
|
||||
|
||||
raise Exception("unknown resource type %s" % resource_type)
|
||||
|
||||
68
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-eks-v2/kubectl-handler/patch/__init__.py
generated
vendored
Normal file
68
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-eks-v2/kubectl-handler/patch/__init__.py
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
logger = logging.getLogger()
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
# these are coming from the kubectl layer
|
||||
os.environ['PATH'] = '/opt/kubectl:/opt/awscli:' + os.environ['PATH']
|
||||
|
||||
outdir = os.environ.get('TEST_OUTDIR', '/tmp')
|
||||
kubeconfig = os.path.join(outdir, 'kubeconfig')
|
||||
|
||||
|
||||
def patch_handler(event, context):
|
||||
logger.info(json.dumps(dict(event, ResponseURL='...')))
|
||||
|
||||
request_type = event['RequestType']
|
||||
props = event['ResourceProperties']
|
||||
|
||||
# resource properties (all required)
|
||||
cluster_name = props['ClusterName']
|
||||
|
||||
# "log in" to the cluster
|
||||
subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig',
|
||||
'--name', cluster_name,
|
||||
'--kubeconfig', kubeconfig
|
||||
])
|
||||
|
||||
if os.path.isfile(kubeconfig):
|
||||
os.chmod(kubeconfig, 0o600)
|
||||
|
||||
resource_name = props['ResourceName']
|
||||
resource_namespace = props['ResourceNamespace']
|
||||
apply_patch_json = props['ApplyPatchJson']
|
||||
restore_patch_json = props['RestorePatchJson']
|
||||
patch_type = props['PatchType']
|
||||
|
||||
patch_json = None
|
||||
if request_type == 'Create' or request_type == 'Update':
|
||||
patch_json = apply_patch_json
|
||||
elif request_type == 'Delete':
|
||||
patch_json = restore_patch_json
|
||||
else:
|
||||
raise Exception("invalid request type %s" % request_type)
|
||||
|
||||
kubectl([ 'patch', resource_name, '-n', resource_namespace, '-p', patch_json, '--type', patch_type ])
|
||||
|
||||
|
||||
def kubectl(args):
|
||||
maxAttempts = 3
|
||||
retry = maxAttempts
|
||||
while retry > 0:
|
||||
try:
|
||||
cmd = [ 'kubectl', '--kubeconfig', kubeconfig ] + args
|
||||
output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError as exc:
|
||||
output = exc.output
|
||||
if b'i/o timeout' in output and retry > 0:
|
||||
retry = retry - 1
|
||||
logger.info("kubectl timed out, retries left: %s" % retry)
|
||||
else:
|
||||
raise Exception(output)
|
||||
else:
|
||||
logger.info(output)
|
||||
return
|
||||
raise Exception(f'Operation failed after {maxAttempts} attempts: {output}')
|
||||
5
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-eks-v2/kubectl-provider.generated.d.ts
generated
vendored
Normal file
5
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-eks-v2/kubectl-provider.generated.d.ts
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import { Construct } from "constructs";
|
||||
import * as lambda from "../../../aws-lambda";
|
||||
export declare class KubectlFunction extends lambda.Function {
|
||||
constructor(scope: Construct, id: string, props?: lambda.FunctionOptions);
|
||||
}
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-eks-v2/kubectl-provider.generated.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-eks-v2/kubectl-provider.generated.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.KubectlFunction=void 0;const path=require("path"),lambda=require("../../../aws-lambda");class KubectlFunction extends lambda.Function{constructor(scope,id,props){super(scope,id,{...props,code:lambda.Code.fromAsset(path.join(__dirname,"kubectl-handler")),handler:"index.handler",runtime:lambda.Runtime.PYTHON_3_13}),this.node.addMetadata("aws:cdk:is-custom-resource-handler-runtime-family",this.runtime.family)}}exports.KubectlFunction=KubectlFunction;
|
||||
51
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-eks/cluster-resource-handler/index.js
generated
vendored
Normal file
51
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-eks/cluster-resource-handler/index.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
8
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-eks/cluster-resource-provider.generated.d.ts
generated
vendored
Normal file
8
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-eks/cluster-resource-provider.generated.d.ts
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
import { Construct } from "constructs";
|
||||
import * as lambda from "../../../aws-lambda";
|
||||
export declare class ClusterResourceOnEventFunction extends lambda.Function {
|
||||
constructor(scope: Construct, id: string, props?: lambda.FunctionOptions);
|
||||
}
|
||||
export declare class ClusterResourceIsCompleteFunction extends lambda.Function {
|
||||
constructor(scope: Construct, id: string, props?: lambda.FunctionOptions);
|
||||
}
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-eks/cluster-resource-provider.generated.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-eks/cluster-resource-provider.generated.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ClusterResourceIsCompleteFunction=exports.ClusterResourceOnEventFunction=void 0;const path=require("path"),lambda=require("../../../aws-lambda");class ClusterResourceOnEventFunction extends lambda.Function{constructor(scope,id,props){super(scope,id,{...props,code:lambda.Code.fromAsset(path.join(__dirname,"cluster-resource-handler")),handler:"index.onEvent",runtime:lambda.determineLatestNodeRuntime(scope)}),this.node.addMetadata("aws:cdk:is-custom-resource-handler-runtime-family",this.runtime.family)}}exports.ClusterResourceOnEventFunction=ClusterResourceOnEventFunction;class ClusterResourceIsCompleteFunction extends lambda.Function{constructor(scope,id,props){super(scope,id,{...props,code:lambda.Code.fromAsset(path.join(__dirname,"cluster-resource-handler")),handler:"index.isComplete",runtime:lambda.determineLatestNodeRuntime(scope)}),this.node.addMetadata("aws:cdk:is-custom-resource-handler-runtime-family",this.runtime.family)}}exports.ClusterResourceIsCompleteFunction=ClusterResourceIsCompleteFunction;
|
||||
95
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-eks/kubectl-handler/apply/__init__.py
generated
vendored
Normal file
95
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-eks/kubectl-handler/apply/__init__.py
generated
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
logger = logging.getLogger()
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
# these are coming from the kubectl layer
|
||||
os.environ['PATH'] = '/opt/kubectl:/opt/awscli:' + os.environ['PATH']
|
||||
|
||||
outdir = os.environ.get('TEST_OUTDIR', '/tmp')
|
||||
kubeconfig = os.path.join(outdir, 'kubeconfig')
|
||||
|
||||
|
||||
def apply_handler(event, context):
|
||||
logger.info(json.dumps(dict(event, ResponseURL='...')))
|
||||
|
||||
request_type = event['RequestType']
|
||||
props = event['ResourceProperties']
|
||||
|
||||
# resource properties (all required)
|
||||
cluster_name = props['ClusterName']
|
||||
manifest_text = props['Manifest']
|
||||
role_arn = props['RoleArn']
|
||||
prune_label = props.get('PruneLabel', None)
|
||||
overwrite = props.get('Overwrite', 'false').lower() == 'true'
|
||||
skip_validation = props.get('SkipValidation', 'false').lower() == 'true'
|
||||
|
||||
# "log in" to the cluster
|
||||
cmd = [ 'aws', 'eks', 'update-kubeconfig',
|
||||
'--role-arn', role_arn,
|
||||
'--name', cluster_name,
|
||||
'--kubeconfig', kubeconfig
|
||||
]
|
||||
logger.info(f'Running command: {cmd}')
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
if os.path.isfile(kubeconfig):
|
||||
os.chmod(kubeconfig, 0o600)
|
||||
|
||||
# write resource manifests in sequence: { r1 }{ r2 }{ r3 } (this is how
|
||||
# a stream of JSON objects can be included in a k8s manifest).
|
||||
manifest_list = json.loads(manifest_text)
|
||||
manifest_file = os.path.join(outdir, 'manifest.yaml')
|
||||
with open(manifest_file, "w") as f:
|
||||
f.writelines(map(lambda obj: json.dumps(obj), manifest_list))
|
||||
|
||||
logger.info("manifest written to: %s" % manifest_file)
|
||||
|
||||
kubectl_opts = []
|
||||
if skip_validation:
|
||||
kubectl_opts.extend(['--validate=false'])
|
||||
|
||||
if request_type == 'Create':
|
||||
# if "overwrite" is enabled, then we use "apply" for CREATE operations
|
||||
# which technically means we can determine the desired state of an
|
||||
# existing resource.
|
||||
if overwrite:
|
||||
kubectl('apply', manifest_file, *kubectl_opts)
|
||||
else:
|
||||
# --save-config will allow us to use "apply" later
|
||||
kubectl_opts.extend(['--save-config'])
|
||||
kubectl('create', manifest_file, *kubectl_opts)
|
||||
elif request_type == 'Update':
|
||||
if prune_label is not None:
|
||||
kubectl_opts.extend(['--prune', '-l', prune_label])
|
||||
|
||||
kubectl('apply', manifest_file, *kubectl_opts)
|
||||
elif request_type == "Delete":
|
||||
try:
|
||||
kubectl('delete', manifest_file)
|
||||
except Exception as e:
|
||||
logger.info("delete error: %s" % e)
|
||||
|
||||
|
||||
def kubectl(verb, file, *opts):
|
||||
maxAttempts = 3
|
||||
retry = maxAttempts
|
||||
while retry > 0:
|
||||
try:
|
||||
cmd = ['kubectl', verb, '--kubeconfig', kubeconfig, '-f', file] + list(opts)
|
||||
logger.info(f'Running command: {cmd}')
|
||||
output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError as exc:
|
||||
output = exc.output
|
||||
if b'i/o timeout' in output and retry > 0:
|
||||
retry = retry - 1
|
||||
logger.info("kubectl timed out, retries left: %s" % retry)
|
||||
else:
|
||||
raise Exception(output)
|
||||
else:
|
||||
logger.info(output)
|
||||
return
|
||||
raise Exception(f'Operation failed after {maxAttempts} attempts: {output}')
|
||||
88
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-eks/kubectl-handler/get/__init__.py
generated
vendored
Normal file
88
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-eks/kubectl-handler/get/__init__.py
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
logger = logging.getLogger()
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
# these are coming from the kubectl layer
|
||||
os.environ['PATH'] = '/opt/kubectl:/opt/awscli:' + os.environ['PATH']
|
||||
|
||||
outdir = os.environ.get('TEST_OUTDIR', '/tmp')
|
||||
kubeconfig = os.path.join(outdir, 'kubeconfig')
|
||||
|
||||
|
||||
def get_handler(event, context):
|
||||
logger.info(json.dumps(dict(event, ResponseURL='...')))
|
||||
|
||||
request_type = event['RequestType']
|
||||
props = event['ResourceProperties']
|
||||
|
||||
# resource properties (all required)
|
||||
cluster_name = props['ClusterName']
|
||||
role_arn = props['RoleArn']
|
||||
|
||||
# "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)
|
||||
|
||||
object_type = props['ObjectType']
|
||||
object_name = props['ObjectName']
|
||||
object_namespace = props['ObjectNamespace']
|
||||
json_path = props['JsonPath']
|
||||
timeout_seconds = props['TimeoutSeconds']
|
||||
|
||||
# json path should be surrounded with '{}'
|
||||
path = '{{{0}}}'.format(json_path)
|
||||
if request_type == 'Create' or request_type == 'Update':
|
||||
output = wait_for_output(['get', '-n', object_namespace, object_type, object_name, "-o=jsonpath='{{{0}}}'".format(json_path)], int(timeout_seconds))
|
||||
return {'Data': {'Value': output}}
|
||||
elif request_type == 'Delete':
|
||||
pass
|
||||
else:
|
||||
raise Exception("invalid request type %s" % request_type)
|
||||
|
||||
def wait_for_output(args, timeout_seconds):
|
||||
|
||||
end_time = time.time() + timeout_seconds
|
||||
error = None
|
||||
|
||||
while time.time() < end_time:
|
||||
try:
|
||||
# the output is surrounded with '', so we unquote
|
||||
output = kubectl(args).decode('utf-8')[1:-1]
|
||||
if output:
|
||||
return output
|
||||
except Exception as e:
|
||||
error = str(e)
|
||||
# also a recoverable error
|
||||
if 'NotFound' in error:
|
||||
pass
|
||||
time.sleep(10)
|
||||
|
||||
raise RuntimeError(f'Timeout waiting for output from kubectl command: {args} (last_error={error})')
|
||||
|
||||
def kubectl(args):
|
||||
retry = 3
|
||||
while retry > 0:
|
||||
try:
|
||||
cmd = [ 'kubectl', '--kubeconfig', kubeconfig ] + args
|
||||
output = subprocess.check_output(cmd, stderr=subprocess.PIPE)
|
||||
except subprocess.CalledProcessError as exc:
|
||||
output = exc.output + exc.stderr
|
||||
if b'i/o timeout' in output and retry > 0:
|
||||
logger.info("kubectl timed out, retries left: %s" % retry)
|
||||
retry = retry - 1
|
||||
else:
|
||||
raise Exception(output)
|
||||
else:
|
||||
logger.info(output)
|
||||
return output
|
||||
263
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-eks/kubectl-handler/helm/__init__.py
generated
vendored
Normal file
263
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-eks/kubectl-handler/helm/__init__.py
generated
vendored
Normal file
@@ -0,0 +1,263 @@
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import shutil
|
||||
import tempfile
|
||||
import zipfile
|
||||
import boto3
|
||||
|
||||
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 is_ecr_public_available(region):
|
||||
s = boto3.Session()
|
||||
return s.get_partition_for_region(region) == 'aws'
|
||||
|
||||
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)
|
||||
atomic = props.get('Atomic', 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)
|
||||
skip_crds = props.get('SkipCrds', False)
|
||||
|
||||
# "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
|
||||
# Chart is now local — clear repository and version so helm() doesn't
|
||||
# pass --repo/--version to "helm upgrade". Helm v4 (kubectl-v35+)
|
||||
# rejects --repo with oci:// URLs ("invalid reference"), unlike v3.
|
||||
repository = None
|
||||
version = None
|
||||
|
||||
helm('upgrade', release, chart, repository, values_file, namespace, version, wait, timeout, create_namespace, skip_crds, atomic=atomic)
|
||||
elif request_type == "Delete":
|
||||
try:
|
||||
helm('uninstall', release, namespace=namespace, wait=wait, timeout=timeout)
|
||||
except Exception as e:
|
||||
logger.error("Delete error: %s", str(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<registry>\d+\.dkr\.ecr\.(?P<region>[a-z0-9\-]+)\.(?P<domain>[a-z0-9\.-]+))*'
|
||||
public_ecr_pattern = 'oci://(?P<registry>public\.ecr\.aws)*'
|
||||
|
||||
private_registry = re.match(private_ecr_pattern, repository).groupdict()
|
||||
public_registry = re.match(public_ecr_pattern, repository).groupdict()
|
||||
|
||||
# Build helm pull command as array
|
||||
helm_cmd = ['helm', 'pull', repository, '--version', version , '--untar']
|
||||
|
||||
if private_registry['registry'] is not None:
|
||||
logger.info("Found AWS private repository")
|
||||
ecr_login = ['aws', 'ecr', 'get-login-password', '--region', private_registry['region']]
|
||||
helm_registry_login = ['helm', 'registry', 'login', '--username', 'AWS', '--password-stdin', private_registry['registry']]
|
||||
return {'ecr_login': ecr_login, 'helm_registry_login': helm_registry_login, 'helm': helm_cmd}
|
||||
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')
|
||||
|
||||
if is_ecr_public_available(region):
|
||||
# Public ECR auth is always in us-east-1: https://docs.aws.amazon.com/AmazonECR/latest/public/public-registry-auth.html
|
||||
ecr_login = ['aws', 'ecr-public', 'get-login-password', '--region', 'us-east-1']
|
||||
helm_registry_login = ['helm', 'registry', 'login', '--username', 'AWS', '--password-stdin', public_registry['registry']]
|
||||
return {'ecr_login': ecr_login, 'helm_registry_login': helm_registry_login, 'helm': helm_cmd}
|
||||
else:
|
||||
# No login required for public ECR in non-aws regions
|
||||
# see https://helm.sh/docs/helm/helm_registry_login/
|
||||
return {'helm': helm_cmd}
|
||||
else:
|
||||
logger.error("OCI repository format not recognized, falling back to helm pull")
|
||||
return {'helm': helm_cmd}
|
||||
|
||||
|
||||
def get_chart_from_oci(tmpdir, repository=None, version=None):
|
||||
from subprocess import Popen, PIPE
|
||||
|
||||
commands = get_oci_cmd(repository, version)
|
||||
|
||||
maxAttempts = 3
|
||||
retry = maxAttempts
|
||||
while retry > 0:
|
||||
try:
|
||||
# Execute login commands if needed
|
||||
if 'ecr_login' in commands and 'helm_registry_login' in commands:
|
||||
logger.info("Running login command: %s", commands['ecr_login'])
|
||||
logger.info("Running registry login command: %s", commands['helm_registry_login'])
|
||||
|
||||
# Start first process: aws ecr get-login-password
|
||||
# NOTE: We do NOT call p1.wait() here before starting p2.
|
||||
# Doing so could deadlock if p1's output fills the pipe buffer
|
||||
# before p2 starts reading. Instead, start p2 immediately so it
|
||||
# can consume p1's stdout as it's produced.
|
||||
p1 = Popen(commands['ecr_login'], stdout=PIPE, stderr=PIPE, cwd=tmpdir)
|
||||
|
||||
# Start second process: helm registry login
|
||||
p2 = Popen(commands['helm_registry_login'], stdin=p1.stdout, stdout=PIPE, stderr=PIPE, cwd=tmpdir)
|
||||
p1.stdout.close() # Allow p1 to receive SIGPIPE if p2 exits early
|
||||
|
||||
# Wait for p2 to finish first (ensures full pipeline completes)
|
||||
_, p2_err = p2.communicate()
|
||||
|
||||
# Now wait for p1 so we have a complete stderr and an exit code
|
||||
p1.wait()
|
||||
|
||||
# Handle p1 failure
|
||||
if p1.returncode != 0:
|
||||
p1_err = p1.stderr.read().decode('utf-8', errors='replace') if p1.stderr else ''
|
||||
logger.error(
|
||||
"ECR get-login-password failed for repository %s. Error: %s",
|
||||
repository,
|
||||
p1_err or "No error details"
|
||||
)
|
||||
raise subprocess.CalledProcessError(p1.returncode, commands['ecr_login'], p1_err.encode())
|
||||
|
||||
# Handle p2 failure
|
||||
if p2.returncode != 0:
|
||||
p1.kill()
|
||||
logger.error(
|
||||
"Helm registry authentication failed for repository %s. Error: %s",
|
||||
repository,
|
||||
p2_err.decode('utf-8', errors='replace') or "No error details"
|
||||
)
|
||||
raise subprocess.CalledProcessError(p2.returncode, commands['helm_registry_login'], p2_err)
|
||||
|
||||
# Execute helm pull command
|
||||
logger.info("Running helm command: %s", commands['helm'])
|
||||
output = subprocess.check_output(commands['helm'], stderr=subprocess.STDOUT, cwd=tmpdir)
|
||||
logger.info(output.decode('utf-8', errors='replace'))
|
||||
|
||||
# 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:
|
||||
error_message = output.decode('utf-8', errors='replace')
|
||||
logger.error("OCI command failed: %s", commands['helm'])
|
||||
logger.error("Error output: %s", error_message)
|
||||
raise Exception(output)
|
||||
|
||||
raise Exception(f'Operation failed after {maxAttempts} attempts: {output.decode("utf-8", errors="replace")}')
|
||||
|
||||
|
||||
def helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None, skip_crds = False, atomic = False):
|
||||
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 skip_crds:
|
||||
cmnd.append('--skip-crds')
|
||||
if not timeout is None:
|
||||
cmnd.extend(['--timeout', timeout])
|
||||
if atomic:
|
||||
cmnd.append('--atomic')
|
||||
cmnd.extend(['--kubeconfig', kubeconfig])
|
||||
|
||||
# Log the full helm command for better troubleshooting
|
||||
logger.info("Running command: %s", cmnd)
|
||||
|
||||
maxAttempts = 3
|
||||
retry = maxAttempts
|
||||
while retry > 0:
|
||||
try:
|
||||
output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir)
|
||||
logger.info(output.decode('utf-8', errors='replace'))
|
||||
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:
|
||||
error_message = output.decode('utf-8', errors='replace')
|
||||
logger.error("Command failed: %s", cmnd)
|
||||
logger.error("Error output: %s", error_message)
|
||||
raise Exception(output)
|
||||
raise Exception(f'Operation failed after {maxAttempts} attempts: {output.decode("utf-8", errors="replace")}')
|
||||
26
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-eks/kubectl-handler/index.py
generated
vendored
Normal file
26
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-eks/kubectl-handler/index.py
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
import json
|
||||
import logging
|
||||
|
||||
from apply import apply_handler
|
||||
from helm import helm_handler
|
||||
from patch import patch_handler
|
||||
from get import get_handler
|
||||
|
||||
def handler(event, context):
|
||||
print(json.dumps(dict(event, ResponseURL='...')))
|
||||
|
||||
resource_type = event['ResourceType']
|
||||
if resource_type == 'Custom::AWSCDK-EKS-KubernetesResource':
|
||||
return apply_handler(event, context)
|
||||
|
||||
if resource_type == 'Custom::AWSCDK-EKS-HelmChart':
|
||||
return helm_handler(event, context)
|
||||
|
||||
if resource_type == 'Custom::AWSCDK-EKS-KubernetesPatch':
|
||||
return patch_handler(event, context)
|
||||
|
||||
if resource_type == 'Custom::AWSCDK-EKS-KubernetesObjectValue':
|
||||
return get_handler(event, context)
|
||||
|
||||
raise Exception("unknown resource type %s" % resource_type)
|
||||
|
||||
70
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-eks/kubectl-handler/patch/__init__.py
generated
vendored
Normal file
70
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-eks/kubectl-handler/patch/__init__.py
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
logger = logging.getLogger()
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
# these are coming from the kubectl layer
|
||||
os.environ['PATH'] = '/opt/kubectl:/opt/awscli:' + os.environ['PATH']
|
||||
|
||||
outdir = os.environ.get('TEST_OUTDIR', '/tmp')
|
||||
kubeconfig = os.path.join(outdir, 'kubeconfig')
|
||||
|
||||
|
||||
def patch_handler(event, context):
|
||||
logger.info(json.dumps(dict(event, ResponseURL='...')))
|
||||
|
||||
request_type = event['RequestType']
|
||||
props = event['ResourceProperties']
|
||||
|
||||
# resource properties (all required)
|
||||
cluster_name = props['ClusterName']
|
||||
role_arn = props['RoleArn']
|
||||
|
||||
# "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)
|
||||
|
||||
resource_name = props['ResourceName']
|
||||
resource_namespace = props['ResourceNamespace']
|
||||
apply_patch_json = props['ApplyPatchJson']
|
||||
restore_patch_json = props['RestorePatchJson']
|
||||
patch_type = props['PatchType']
|
||||
|
||||
patch_json = None
|
||||
if request_type == 'Create' or request_type == 'Update':
|
||||
patch_json = apply_patch_json
|
||||
elif request_type == 'Delete':
|
||||
patch_json = restore_patch_json
|
||||
else:
|
||||
raise Exception("invalid request type %s" % request_type)
|
||||
|
||||
kubectl([ 'patch', resource_name, '-n', resource_namespace, '-p', patch_json, '--type', patch_type ])
|
||||
|
||||
|
||||
def kubectl(args):
|
||||
maxAttempts = 3
|
||||
retry = maxAttempts
|
||||
while retry > 0:
|
||||
try:
|
||||
cmd = [ 'kubectl', '--kubeconfig', kubeconfig ] + args
|
||||
output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError as exc:
|
||||
output = exc.output
|
||||
if b'i/o timeout' in output and retry > 0:
|
||||
retry = retry - 1
|
||||
logger.info("kubectl timed out, retries left: %s" % retry)
|
||||
else:
|
||||
raise Exception(output)
|
||||
else:
|
||||
logger.info(output)
|
||||
return
|
||||
raise Exception(f'Operation failed after {maxAttempts} attempts: {output}')
|
||||
5
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-eks/kubectl-provider.generated.d.ts
generated
vendored
Normal file
5
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-eks/kubectl-provider.generated.d.ts
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import { Construct } from "constructs";
|
||||
import * as lambda from "../../../aws-lambda";
|
||||
export declare class KubectlFunction extends lambda.Function {
|
||||
constructor(scope: Construct, id: string, props?: lambda.FunctionOptions);
|
||||
}
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-eks/kubectl-provider.generated.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-eks/kubectl-provider.generated.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.KubectlFunction=void 0;const path=require("path"),lambda=require("../../../aws-lambda");class KubectlFunction extends lambda.Function{constructor(scope,id,props){super(scope,id,{...props,code:lambda.Code.fromAsset(path.join(__dirname,"kubectl-handler")),handler:"index.handler",runtime:lambda.Runtime.PYTHON_3_13}),this.node.addMetadata("aws:cdk:is-custom-resource-handler-runtime-family",this.runtime.family)}}exports.KubectlFunction=KubectlFunction;
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-events-targets/aws-api-handler/index.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-events-targets/aws-api-handler/index.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
27
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-events-targets/aws-api-provider.generated.d.ts
generated
vendored
Normal file
27
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-events-targets/aws-api-provider.generated.d.ts
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import { Construct } from "constructs";
|
||||
import * as lambda from "../../../aws-lambda";
|
||||
export declare class AwsApiSingletonFunction extends lambda.SingletonFunction {
|
||||
constructor(scope: Construct, id: string, props: AwsApiSingletonFunctionProps);
|
||||
}
|
||||
/**
|
||||
* Initialization properties for AwsApiSingletonFunction
|
||||
*/
|
||||
export interface AwsApiSingletonFunctionProps extends lambda.FunctionOptions {
|
||||
/**
|
||||
* A unique identifier to identify this Lambda.
|
||||
*
|
||||
* The identifier should be unique across all custom resource providers.
|
||||
* We recommend generating a UUID per provider.
|
||||
*/
|
||||
readonly uuid: string;
|
||||
/**
|
||||
* A descriptive name for the purpose of this Lambda.
|
||||
*
|
||||
* If the Lambda does not have a physical name, this string will be
|
||||
* reflected in its generated name. The combination of lambdaPurpose
|
||||
* and uuid must be unique.
|
||||
*
|
||||
* @default SingletonLambda
|
||||
*/
|
||||
readonly lambdaPurpose?: string;
|
||||
}
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-events-targets/aws-api-provider.generated.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-events-targets/aws-api-provider.generated.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.AwsApiSingletonFunction=void 0;const path=require("path"),lambda=require("../../../aws-lambda");class AwsApiSingletonFunction extends lambda.SingletonFunction{constructor(scope,id,props){super(scope,id,{...props,code:lambda.Code.fromAsset(path.join(__dirname,"aws-api-handler")),handler:"index.handler",runtime:lambda.determineLatestNodeRuntime(scope)}),this.addMetadata("aws:cdk:is-custom-resource-handler-singleton",!0),this.addMetadata("aws:cdk:is-custom-resource-handler-runtime-family",this.runtime.family),props?.logGroup&&this.logGroup.node.addMetadata("aws:cdk:is-custom-resource-handler-logGroup",!0),props?.logRetention&&this.lambdaFunction._logRetention?.node.addMetadata("aws:cdk:is-custom-resource-handler-logRetention",!0)}}exports.AwsApiSingletonFunction=AwsApiSingletonFunction;
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-iam/oidc-handler/index.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-iam/oidc-handler/index.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";var y=Object.create,l=Object.defineProperty,v=Object.getOwnPropertyDescriptor,O=Object.getOwnPropertyNames,w=Object.getPrototypeOf,R=Object.prototype.hasOwnProperty,A=(e,r)=>{for(var t in r)l(e,t,{get:r[t],enumerable:!0})},D=(e,r,t,i)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of O(r))!R.call(e,o)&&o!==t&&l(e,o,{get:()=>r[o],enumerable:!(i=v(r,o))||i.enumerable});return e},m=(e,r,t)=>(t=e!=null?y(w(e)):{},D(r||!e||!e.__esModule?l(t,"default",{value:e,enumerable:!0}):t,e)),$=e=>D(l({},"__esModule",{value:!0}),e),j={};A(j,{handler:()=>x}),module.exports=$(j);function h(e,r){let t=new Set(e),i=new Set;for(let o of new Set(r))t.has(o)?t.delete(o):i.add(o);return{adds:Array.from(i),deletes:Array.from(t)}}var g=m(require("tls")),P=m(require("url")),T=m(require("@aws-sdk/client-iam")),C;function u(){return C||(C=new T.IAM({})),C}function U(e,...r){console.log(e,...r)}async function L(e,r){return new Promise((t,i)=>{let o=P.parse(e),p=o.port?parseInt(o.port,10):443;if(!o.host)return i(new Error(`unable to determine host from issuer url ${e}`));n.log(`Fetching x509 certificate chain from issuer ${e}`);let s=g.connect(p,o.host,{rejectUnauthorized:r,servername:o.host});s.once("error",i),s.once("secureConnect",()=>{let a=s.getPeerX509Certificate();if(!a)throw new Error(`Unable to retrieve X509 certificate from host ${o.host}`);for(;a.issuerCertificate;)E(a),a=a.issuerCertificate;let d=new Date(a.validTo),c=S(d);if(c<0)return i(new Error(`The certificate has already expired on: ${d.toUTCString()}`));c<180&&console.warn(`The root certificate obtained would expire in ${c} days!`),s.end();let I=f(a);n.log(`Certificate Authority thumbprint for ${e} is ${I}`),t(I)})})}function f(e){return e.fingerprint.split(":").join("")}function E(e){n.log("-------------BEGIN CERT----------------"),n.log(`Thumbprint: ${f(e)}`),n.log(`Valid To: ${e.validTo}`),e.issuerCertificate&&n.log(`Issuer Thumbprint: ${f(e.issuerCertificate)}`),n.log(`Issuer: ${e.issuer}`),n.log(`Subject: ${e.subject}`),n.log("-------------END CERT------------------")}function S(e){let t=new Date;return Math.round((e.getTime()-t.getTime())/864e5)}var n={downloadThumbprint:L,log:U,createOpenIDConnectProvider:e=>u().createOpenIDConnectProvider(e),deleteOpenIDConnectProvider:e=>u().deleteOpenIDConnectProvider(e),updateOpenIDConnectProviderThumbprint:e=>u().updateOpenIDConnectProviderThumbprint(e),addClientIDToOpenIDConnectProvider:e=>u().addClientIDToOpenIDConnectProvider(e),removeClientIDFromOpenIDConnectProvider:e=>u().removeClientIDFromOpenIDConnectProvider(e)};async function x(e){if(e.RequestType==="Create")return b(e);if(e.RequestType==="Update")return F(e);if(e.RequestType==="Delete")return k(e);throw new Error("invalid request type")}async function b(e){let r=e.ResourceProperties.Url,t=(e.ResourceProperties.ThumbprintList??[]).sort(),i=(e.ResourceProperties.ClientIDList??[]).sort(),o=e.ResourceProperties.RejectUnauthorized??!1;return t.length===0&&t.push(await n.downloadThumbprint(r,o)),{PhysicalResourceId:(await n.createOpenIDConnectProvider({Url:r,ClientIDList:i,ThumbprintList:t})).OpenIDConnectProviderArn,Data:{Thumbprints:JSON.stringify(t)}}}async function F(e){let r=e.ResourceProperties.Url,t=(e.ResourceProperties.ThumbprintList??[]).sort(),i=(e.ResourceProperties.ClientIDList??[]).sort(),o=e.ResourceProperties.RejectUnauthorized??!1;if(e.OldResourceProperties.Url!==r)return b({...e,RequestType:"Create"});let s=e.PhysicalResourceId;t.length===0&&t.push(await n.downloadThumbprint(r,o)),n.log("updating thumbprint to",t),await n.updateOpenIDConnectProviderThumbprint({OpenIDConnectProviderArn:s,ThumbprintList:t});let a=(e.OldResourceProperties.ClientIDList||[]).sort(),d=h(a,i);n.log(`client ID diff: ${JSON.stringify(d)}`);for(let c of d.adds)n.log(`adding client id "${c}" to provider ${s}`),await n.addClientIDToOpenIDConnectProvider({OpenIDConnectProviderArn:s,ClientID:c});for(let c of d.deletes)n.log(`removing client id "${c}" from provider ${s}`),await n.removeClientIDFromOpenIDConnectProvider({OpenIDConnectProviderArn:s,ClientID:c});return{Data:{Thumbprints:JSON.stringify(t)}}}async function k(e){await n.deleteOpenIDConnectProvider({OpenIDConnectProviderArn:e.PhysicalResourceId})}
|
||||
13
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-iam/oidc-provider.generated.d.ts
generated
vendored
Normal file
13
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-iam/oidc-provider.generated.d.ts
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Construct } from "constructs";
|
||||
import { CustomResourceProviderBase, CustomResourceProviderOptions } from "../../../core";
|
||||
export declare class OidcProvider extends CustomResourceProviderBase {
|
||||
/**
|
||||
* Returns a stack-level singleton ARN (service token) for the custom resource provider.
|
||||
*/
|
||||
static getOrCreate(scope: Construct, uniqueid: string, props?: CustomResourceProviderOptions): string;
|
||||
/**
|
||||
* Returns a stack-level singleton for the custom resource provider.
|
||||
*/
|
||||
static getOrCreateProvider(scope: Construct, uniqueid: string, props?: CustomResourceProviderOptions): OidcProvider;
|
||||
private constructor();
|
||||
}
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-iam/oidc-provider.generated.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-iam/oidc-provider.generated.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.OidcProvider=void 0;const path=require("path"),core_1=require("../../../core");class OidcProvider extends core_1.CustomResourceProviderBase{static getOrCreate(scope,uniqueid,props){return this.getOrCreateProvider(scope,uniqueid,props).serviceToken}static getOrCreateProvider(scope,uniqueid,props){const id=`${uniqueid}CustomResourceProvider`,stack=core_1.Stack.of(scope);return stack.node.tryFindChild(id)??new OidcProvider(stack,id,props)}constructor(scope,id,props){super(scope,id,{...props,codeDirectory:path.join(__dirname,"oidc-handler"),runtimeName:(0,core_1.determineLatestNodeRuntimeName)(scope)}),this.node.addMetadata("aws:cdk:is-custom-resource-handler-customResourceProvider",!0)}}exports.OidcProvider=OidcProvider;
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-logs/log-retention-handler/index.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-logs/log-retention-handler/index.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";var h=Object.create,d=Object.defineProperty,P=Object.getOwnPropertyDescriptor,C=Object.getOwnPropertyNames,b=Object.getPrototypeOf,S=Object.prototype.hasOwnProperty,E=(e,o)=>{for(var n in o)d(e,n,{get:o[n],enumerable:!0})},p=(e,o,n,t)=>{if(o&&typeof o=="object"||typeof o=="function")for(let r of C(o))!S.call(e,r)&&r!==n&&d(e,r,{get:()=>o[r],enumerable:!(t=P(o,r))||t.enumerable});return e},G=(e,o,n)=>(n=e!=null?h(b(e)):{},p(o||!e||!e.__esModule?d(n,"default",{value:e,enumerable:!0}):n,e)),x=e=>p(d({},"__esModule",{value:!0}),e),O={};E(O,{disableSleepForTesting:()=>I,handler:()=>q}),module.exports=x(O);var i=G(require("@aws-sdk/client-cloudwatch-logs")),w=!1;function I(){w=!0}async function R(e,o,n){await n(async()=>{try{let t={logGroupName:e},r=new i.CreateLogGroupCommand(t);await o.send(r)}catch(t){if(t.name==="ResourceAlreadyExistsException")return;throw t}})}async function k(e,o,n){await n(async()=>{try{let t={logGroupName:e},r=new i.DeleteLogGroupCommand(t);await o.send(r)}catch(t){if(t.name==="ResourceNotFoundException")return;throw t}})}async function y(e,o,n,t){await n(async()=>{if(t){let r={logGroupName:e,retentionInDays:t},s=new i.PutRetentionPolicyCommand(r);await o.send(s)}else{let r={logGroupName:e},s=new i.DeleteRetentionPolicyCommand(r);await o.send(s)}})}async function q(e,o){try{console.log(JSON.stringify({...e,ResponseURL:"..."}));let t=e.ResourceProperties.LogGroupName,r=e.ResourceProperties.LogGroupRegion,s=L(e.ResourceProperties.SdkRetry?.maxRetries)??10,a=N(s),m={logger:console,region:r},c=new i.CloudWatchLogsClient(m);if((e.RequestType==="Create"||e.RequestType==="Update")&&(await R(t,c,a),await y(t,c,a,L(e.ResourceProperties.RetentionInDays)),e.RequestType==="Create")){let g=new i.CloudWatchLogsClient({logger:console,region:process.env.AWS_REGION});await R(`/aws/lambda/${o.functionName}`,g,a),await y(`/aws/lambda/${o.functionName}`,g,a,1)}e.RequestType==="Delete"&&e.ResourceProperties.RemovalPolicy==="destroy"&&await k(t,c,a),await n("SUCCESS","OK",t)}catch(t){console.log(t),await n("FAILED",t.message,e.ResourceProperties.LogGroupName)}function n(t,r,s){let a=JSON.stringify({Status:t,Reason:r,PhysicalResourceId:s,StackId:e.StackId,RequestId:e.RequestId,LogicalResourceId:e.LogicalResourceId,Data:{LogGroupName:e.ResourceProperties.LogGroupName}});console.log("Responding",a);let m=require("url").parse(e.ResponseURL),c={hostname:m.hostname,path:m.path,method:"PUT",headers:{"content-type":"","content-length":Buffer.byteLength(a,"utf8")}};return new Promise((g,l)=>{try{let u=require("https").request(c,g);u.on("error",l),u.write(a),u.end()}catch(u){l(u)}})}}function L(e,o=10){if(e!==void 0)return parseInt(e,o)}function N(e,o=1e3,n=6e4){return async t=>{let r=0;do try{return await t()}catch(s){if(f("OperationAbortedException",s)||f("ThrottlingException",s))if(r<e){r++,await D(W(r,o,n));continue}else throw new Error("Out of attempts to change log group");throw s}while(!0)}}function f(e,o){return o.name===e||o.message.includes(e)}function W(e,o,n){return Math.min(Math.round(Math.random()*o*2**e),n)}async function D(e){w&&(e=0),await new Promise(o=>setTimeout(o,e))}
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-route53/cross-account-zone-delegation-handler/index.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-route53/cross-account-zone-delegation-handler/index.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";var c=Object.defineProperty,Z=Object.getOwnPropertyDescriptor,N=Object.getOwnPropertyNames,P=Object.prototype.hasOwnProperty,h=(o,e)=>{for(var n in e)c(o,n,{get:e[n],enumerable:!0})},E=(o,e,n,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of N(e))!P.call(o,s)&&s!==n&&c(o,s,{get:()=>e[s],enumerable:!(t=Z(e,s))||t.enumerable});return o},A=o=>E(c({},"__esModule",{value:!0}),o),T={};h(T,{handler:()=>w}),module.exports=A(T);var m=require("@aws-sdk/client-route-53"),d=require("@aws-sdk/credential-providers");async function w(o){let e=o.ResourceProperties;switch(o.RequestType){case"Create":return r(e,!1);case"Update":return D(e,o.OldResourceProperties);case"Delete":return r(e,!0)}}async function D(o,e){e&&o.DelegatedZoneName!==e.DelegatedZoneName&&await r(e,!0),await r(o,!1)}async function r(o,e){let{AssumeRoleArn:n,ParentZoneId:t,ParentZoneName:s,DelegatedZoneName:a,DelegatedZoneNameServers:i,TTL:g,AssumeRoleRegion:R}=o;if(!t&&!s)throw Error("One of ParentZoneId or ParentZoneName must be specified");let l=new Date().getTime(),u=new m.Route53({credentials:(0,d.fromTemporaryCredentials)({clientConfig:{region:R??S(process.env.AWS_REGION??process.env.AWS_DEFAULT_REGION??"")},params:{RoleArn:n,RoleSessionName:`cross-account-zone-delegation-${l}`}})}),f=t??await v(s,u);await u.changeResourceRecordSets({HostedZoneId:f,ChangeBatch:{Changes:[{Action:e?"DELETE":"UPSERT",ResourceRecordSet:{Name:a,Type:"NS",TTL:g,ResourceRecords:i.map(p=>({Value:p}))}}]}})}async function v(o,e){let t=(await e.listHostedZonesByName({DNSName:o})).HostedZones?.filter(s=>{let a=s.Name===`${o}.`,i=s.Config?.PrivateZone!==!0;return a&&i})??[];if(t&&t.length!==1)throw Error(`Expected one hosted zone to match the given name but found ${t.length}`);return t[0].Id}function S(o){let e={cn:"cn-northwest-1","us-gov":"us-gov-west-1","us-iso":"us-iso-east-1","us-isob":"us-isob-east-1","eu-isoe":"eu-isoe-west-1","us-isof":"us-isof-south-1","eusc-de":"eusc-de-east-1"};for(let[n,t]of Object.entries(e))if(o.startsWith(`${n}-`))return t;return"us-east-1"}
|
||||
13
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-route53/cross-account-zone-delegation-provider.generated.d.ts
generated
vendored
Normal file
13
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-route53/cross-account-zone-delegation-provider.generated.d.ts
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Construct } from "constructs";
|
||||
import { CustomResourceProviderBase, CustomResourceProviderOptions } from "../../../core";
|
||||
export declare class CrossAccountZoneDelegationProvider extends CustomResourceProviderBase {
|
||||
/**
|
||||
* Returns a stack-level singleton ARN (service token) for the custom resource provider.
|
||||
*/
|
||||
static getOrCreate(scope: Construct, uniqueid: string, props?: CustomResourceProviderOptions): string;
|
||||
/**
|
||||
* Returns a stack-level singleton for the custom resource provider.
|
||||
*/
|
||||
static getOrCreateProvider(scope: Construct, uniqueid: string, props?: CustomResourceProviderOptions): CrossAccountZoneDelegationProvider;
|
||||
private constructor();
|
||||
}
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-route53/cross-account-zone-delegation-provider.generated.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-route53/cross-account-zone-delegation-provider.generated.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.CrossAccountZoneDelegationProvider=void 0;const path=require("path"),core_1=require("../../../core");class CrossAccountZoneDelegationProvider extends core_1.CustomResourceProviderBase{static getOrCreate(scope,uniqueid,props){return this.getOrCreateProvider(scope,uniqueid,props).serviceToken}static getOrCreateProvider(scope,uniqueid,props){const id=`${uniqueid}CustomResourceProvider`,stack=core_1.Stack.of(scope);return stack.node.tryFindChild(id)??new CrossAccountZoneDelegationProvider(stack,id,props)}constructor(scope,id,props){super(scope,id,{...props,codeDirectory:path.join(__dirname,"cross-account-zone-delegation-handler"),runtimeName:(0,core_1.determineLatestNodeRuntimeName)(scope)}),this.node.addMetadata("aws:cdk:is-custom-resource-handler-customResourceProvider",!0)}}exports.CrossAccountZoneDelegationProvider=CrossAccountZoneDelegationProvider;
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-route53/delete-existing-record-set-handler/index.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-route53/delete-existing-record-set-handler/index.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";var c=Object.defineProperty,R=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,u=Object.prototype.hasOwnProperty,T=(r,e)=>{for(var t in e)c(r,t,{get:e[t],enumerable:!0})},p=(r,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of i(e))!u.call(r,o)&&o!==t&&c(r,o,{get:()=>e[o],enumerable:!(s=R(e,o))||s.enumerable});return r},y=r=>p(c({},"__esModule",{value:!0}),r),f={};T(f,{handler:()=>m}),module.exports=y(f);var n=require("@aws-sdk/client-route-53");async function m(r){let e=r.ResourceProperties;if(r.RequestType!=="Create")return;let t=new n.Route53,o=(await t.listResourceRecordSets({HostedZoneId:e.HostedZoneId,StartRecordName:e.RecordName,StartRecordType:e.RecordType})).ResourceRecordSets?.find(a=>a.Name===e.RecordName&&a.Type===e.RecordType);if(!o)return;let d=await t.changeResourceRecordSets({HostedZoneId:e.HostedZoneId,ChangeBatch:{Changes:[{Action:"DELETE",ResourceRecordSet:g({Name:o.Name,Type:o.Type,TTL:o.TTL,AliasTarget:o.AliasTarget,ResourceRecords:o.ResourceRecords})}]}});return await(0,n.waitUntilResourceRecordSetsChanged)({client:t,maxWaitTime:890},{Id:d?.ChangeInfo?.Id}),{PhysicalResourceId:`${o.Name}-${o.Type}`}}function g(r){let e={};for(let[t,s]of Object.entries(r))s&&(!Array.isArray(s)||s.length!==0)&&(e[t]=s);return e}
|
||||
13
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-route53/delete-existing-record-set-provider.generated.d.ts
generated
vendored
Normal file
13
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-route53/delete-existing-record-set-provider.generated.d.ts
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Construct } from "constructs";
|
||||
import { CustomResourceProviderBase, CustomResourceProviderOptions } from "../../../core";
|
||||
export declare class DeleteExistingRecordSetProvider extends CustomResourceProviderBase {
|
||||
/**
|
||||
* Returns a stack-level singleton ARN (service token) for the custom resource provider.
|
||||
*/
|
||||
static getOrCreate(scope: Construct, uniqueid: string, props?: CustomResourceProviderOptions): string;
|
||||
/**
|
||||
* Returns a stack-level singleton for the custom resource provider.
|
||||
*/
|
||||
static getOrCreateProvider(scope: Construct, uniqueid: string, props?: CustomResourceProviderOptions): DeleteExistingRecordSetProvider;
|
||||
private constructor();
|
||||
}
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-route53/delete-existing-record-set-provider.generated.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-route53/delete-existing-record-set-provider.generated.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.DeleteExistingRecordSetProvider=void 0;const path=require("path"),core_1=require("../../../core");class DeleteExistingRecordSetProvider extends core_1.CustomResourceProviderBase{static getOrCreate(scope,uniqueid,props){return this.getOrCreateProvider(scope,uniqueid,props).serviceToken}static getOrCreateProvider(scope,uniqueid,props){const id=`${uniqueid}CustomResourceProvider`,stack=core_1.Stack.of(scope);return stack.node.tryFindChild(id)??new DeleteExistingRecordSetProvider(stack,id,props)}constructor(scope,id,props){super(scope,id,{...props,codeDirectory:path.join(__dirname,"delete-existing-record-set-handler"),runtimeName:(0,core_1.determineLatestNodeRuntimeName)(scope)}),this.node.addMetadata("aws:cdk:is-custom-resource-handler-customResourceProvider",!0)}}exports.DeleteExistingRecordSetProvider=DeleteExistingRecordSetProvider;
|
||||
406
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-s3-deployment/bucket-deployment-handler/index.py
generated
vendored
Normal file
406
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-s3-deployment/bucket-deployment-handler/index.py
generated
vendored
Normal file
@@ -0,0 +1,406 @@
|
||||
import contextlib
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
import urllib.parse
|
||||
from urllib.request import Request, urlopen
|
||||
from uuid import uuid4
|
||||
from zipfile import ZipFile
|
||||
|
||||
import boto3
|
||||
from botocore.config import Config
|
||||
from botocore.exceptions import WaiterError
|
||||
|
||||
logger = logging.getLogger()
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
cloudfront = boto3.client('cloudfront', config=Config(
|
||||
retries = {
|
||||
'max_attempts': 10,
|
||||
'mode': 'standard',
|
||||
}
|
||||
))
|
||||
s3 = boto3.client('s3')
|
||||
|
||||
CFN_SUCCESS = "SUCCESS"
|
||||
CFN_FAILED = "FAILED"
|
||||
ENV_KEY_MOUNT_PATH = "MOUNT_PATH"
|
||||
ENV_KEY_SKIP_CLEANUP = "SKIP_CLEANUP"
|
||||
|
||||
AWS_CLI_CONFIG_FILE = "/tmp/aws_cli_config"
|
||||
CUSTOM_RESOURCE_OWNER_TAG = "aws-cdk:cr-owned"
|
||||
|
||||
os.putenv('AWS_CONFIG_FILE', AWS_CLI_CONFIG_FILE)
|
||||
|
||||
def handler(event, context):
|
||||
|
||||
def cfn_error(message=None):
|
||||
if message:
|
||||
logger.error("| cfn_error: %s" % message.encode())
|
||||
cfn_send(event, context, CFN_FAILED, reason=message, physicalResourceId=event.get('PhysicalResourceId', None))
|
||||
|
||||
|
||||
try:
|
||||
# We are not logging ResponseURL as this is a pre-signed S3 URL, and could be used to tamper
|
||||
# with the response CloudFormation sees from this Custom Resource execution.
|
||||
logger.info({ key:value for (key, value) in event.items() if key != 'ResponseURL'})
|
||||
|
||||
# cloudformation request type (create/update/delete)
|
||||
request_type = event['RequestType']
|
||||
|
||||
# extract resource properties
|
||||
props = event['ResourceProperties']
|
||||
old_props = event.get('OldResourceProperties', {})
|
||||
physical_id = event.get('PhysicalResourceId', None)
|
||||
|
||||
try:
|
||||
source_bucket_names = props['SourceBucketNames']
|
||||
source_object_keys = props['SourceObjectKeys']
|
||||
source_markers = props.get('SourceMarkers', None)
|
||||
source_markers_config = props.get('SourceMarkersConfig', None)
|
||||
dest_bucket_name = props['DestinationBucketName']
|
||||
dest_bucket_prefix = props.get('DestinationBucketKeyPrefix', '')
|
||||
extract = props.get('Extract', 'true') == 'true'
|
||||
retain_on_delete = props.get('RetainOnDelete', "true") == "true"
|
||||
distribution_id = props.get('DistributionId', '')
|
||||
wait_for_distribution_invalidation = props.get('WaitForDistributionInvalidation', True)
|
||||
user_metadata = props.get('UserMetadata', {})
|
||||
system_metadata = props.get('SystemMetadata', {})
|
||||
prune = props.get('Prune', 'true').lower() == 'true'
|
||||
exclude = props.get('Exclude', [])
|
||||
include = props.get('Include', [])
|
||||
sign_content = props.get('SignContent', 'false').lower() == 'true'
|
||||
output_object_keys = props.get('OutputObjectKeys', 'true') == 'true'
|
||||
|
||||
# backwards compatibility - if "SourceMarkers" is not specified,
|
||||
# assume all sources have an empty market map
|
||||
if source_markers is None:
|
||||
source_markers = [{} for i in range(len(source_bucket_names))]
|
||||
if source_markers_config is None:
|
||||
source_markers_config = [{} for i in range(len(source_bucket_names))]
|
||||
|
||||
default_distribution_path = dest_bucket_prefix
|
||||
if not default_distribution_path.endswith("/"):
|
||||
default_distribution_path += "/"
|
||||
if not default_distribution_path.startswith("/"):
|
||||
default_distribution_path = "/" + default_distribution_path
|
||||
default_distribution_path += "*"
|
||||
|
||||
distribution_paths = props.get('DistributionPaths', [default_distribution_path])
|
||||
except KeyError as e:
|
||||
cfn_error("missing request resource property %s. props: %s" % (str(e), props))
|
||||
return
|
||||
|
||||
# configure aws cli options after resetting back to the defaults for each request
|
||||
if os.path.exists(AWS_CLI_CONFIG_FILE):
|
||||
os.remove(AWS_CLI_CONFIG_FILE)
|
||||
if sign_content:
|
||||
aws_command("configure", "set", "default.s3.payload_signing_enabled", "true")
|
||||
|
||||
# treat "/" as if no prefix was specified
|
||||
if dest_bucket_prefix == "/":
|
||||
dest_bucket_prefix = ""
|
||||
|
||||
s3_source_zips = list(map(lambda name, key: "s3://%s/%s" % (name, key), source_bucket_names, source_object_keys))
|
||||
s3_dest = "s3://%s/%s" % (dest_bucket_name, dest_bucket_prefix)
|
||||
old_s3_dest = "s3://%s/%s" % (old_props.get("DestinationBucketName", ""), old_props.get("DestinationBucketKeyPrefix", ""))
|
||||
|
||||
|
||||
# obviously this is not
|
||||
if old_s3_dest == "s3:///":
|
||||
old_s3_dest = None
|
||||
|
||||
logger.info("| s3_dest: %s" % sanitize_message(s3_dest))
|
||||
logger.info("| old_s3_dest: %s" % sanitize_message(old_s3_dest))
|
||||
|
||||
# if we are creating a new resource, allocate a physical id for it
|
||||
# otherwise, we expect physical id to be relayed by cloudformation
|
||||
if request_type == "Create":
|
||||
physical_id = "aws.cdk.s3deployment.%s" % str(uuid4())
|
||||
else:
|
||||
if not physical_id:
|
||||
cfn_error("invalid request: request type is '%s' but 'PhysicalResourceId' is not defined" % request_type)
|
||||
return
|
||||
|
||||
# delete or create/update (only if "retain_on_delete" is false)
|
||||
if request_type == "Delete" and not retain_on_delete:
|
||||
if not bucket_owned(dest_bucket_name, dest_bucket_prefix):
|
||||
aws_command("s3", "rm", s3_dest, "--recursive")
|
||||
|
||||
# if we are updating without retention and the destination changed, delete first
|
||||
if request_type == "Update" and not retain_on_delete and old_s3_dest != s3_dest:
|
||||
if not old_s3_dest:
|
||||
logger.warn("cannot delete old resource without old resource properties")
|
||||
return
|
||||
|
||||
aws_command("s3", "rm", old_s3_dest, "--recursive")
|
||||
|
||||
if request_type == "Update" or request_type == "Create":
|
||||
s3_deploy(s3_source_zips, s3_dest, user_metadata, system_metadata, prune, exclude, include, source_markers, extract, source_markers_config)
|
||||
|
||||
if distribution_id:
|
||||
cloudfront_invalidate(distribution_id, distribution_paths, wait_for_distribution_invalidation)
|
||||
|
||||
cfn_send(event, context, CFN_SUCCESS, physicalResourceId=physical_id, responseData={
|
||||
# Passing through the ARN sequences dependencees on the deployment
|
||||
'DestinationBucketArn': props.get('DestinationBucketArn'),
|
||||
**({'SourceObjectKeys': props.get('SourceObjectKeys')} if output_object_keys else {'SourceObjectKeys': []})
|
||||
})
|
||||
except KeyError as e:
|
||||
cfn_error("invalid request. Missing key %s" % str(e))
|
||||
except Exception as e:
|
||||
logger.exception(e)
|
||||
cfn_error(str(e))
|
||||
|
||||
#---------------------------------------------------------------------------------------------------
|
||||
# Sanitize the message to mitigate CWE-117 and CWE-93 vulnerabilities
|
||||
def sanitize_message(message):
|
||||
if not message:
|
||||
return message
|
||||
|
||||
# Sanitize the message to prevent log injection and HTTP response splitting
|
||||
sanitized_message = message.replace('\n', '').replace('\r', '')
|
||||
|
||||
# Encode the message to handle special characters
|
||||
encoded_message = urllib.parse.quote(sanitized_message)
|
||||
|
||||
return encoded_message
|
||||
|
||||
#---------------------------------------------------------------------------------------------------
|
||||
# populate all files from s3_source_zips to a destination bucket
|
||||
def s3_deploy(s3_source_zips, s3_dest, user_metadata, system_metadata, prune, exclude, include, source_markers, extract, source_markers_config):
|
||||
# list lengths are equal
|
||||
if len(s3_source_zips) != len(source_markers):
|
||||
raise Exception("'source_markers' and 's3_source_zips' must be the same length")
|
||||
|
||||
# create a temporary working directory in /tmp or if enabled an attached efs volume
|
||||
if ENV_KEY_MOUNT_PATH in os.environ:
|
||||
workdir = os.getenv(ENV_KEY_MOUNT_PATH) + "/" + str(uuid4())
|
||||
os.mkdir(workdir)
|
||||
else:
|
||||
workdir = tempfile.mkdtemp()
|
||||
|
||||
logger.info("| workdir: %s" % workdir)
|
||||
|
||||
# create a directory into which we extract the contents of the zip file
|
||||
contents_dir=os.path.join(workdir, 'contents')
|
||||
os.mkdir(contents_dir)
|
||||
|
||||
try:
|
||||
# download the archive from the source and extract to "contents"
|
||||
for i in range(len(s3_source_zips)):
|
||||
s3_source_zip = s3_source_zips[i]
|
||||
markers = source_markers[i]
|
||||
markers_config = source_markers_config[i]
|
||||
|
||||
if extract:
|
||||
archive=os.path.join(workdir, str(uuid4()))
|
||||
logger.info("archive: %s" % archive)
|
||||
aws_command("s3", "cp", s3_source_zip, archive)
|
||||
logger.info("| extracting archive to: %s\n" % contents_dir)
|
||||
logger.info("| markers: %s" % markers)
|
||||
extract_and_replace_markers(archive, contents_dir, markers, markers_config)
|
||||
else:
|
||||
logger.info("| copying archive to: %s\n" % contents_dir)
|
||||
aws_command("s3", "cp", s3_source_zip, contents_dir)
|
||||
|
||||
# sync from "contents" to destination
|
||||
|
||||
s3_command = ["s3", "sync"]
|
||||
|
||||
if prune:
|
||||
s3_command.append("--delete")
|
||||
|
||||
if exclude:
|
||||
for filter in exclude:
|
||||
s3_command.extend(["--exclude", filter])
|
||||
|
||||
if include:
|
||||
for filter in include:
|
||||
s3_command.extend(["--include", filter])
|
||||
|
||||
s3_command.extend([contents_dir, s3_dest])
|
||||
s3_command.extend(create_metadata_args(user_metadata, system_metadata))
|
||||
aws_command(*s3_command)
|
||||
finally:
|
||||
if not os.getenv(ENV_KEY_SKIP_CLEANUP):
|
||||
shutil.rmtree(workdir)
|
||||
|
||||
#---------------------------------------------------------------------------------------------------
|
||||
# invalidate files in the CloudFront distribution edge caches
|
||||
def cloudfront_invalidate(distribution_id, distribution_paths, wait_for_invalidation):
|
||||
invalidation_resp = cloudfront.create_invalidation(
|
||||
DistributionId=distribution_id,
|
||||
InvalidationBatch={
|
||||
'Paths': {
|
||||
'Quantity': len(distribution_paths),
|
||||
'Items': distribution_paths
|
||||
},
|
||||
'CallerReference': str(uuid4()),
|
||||
})
|
||||
if wait_for_invalidation:
|
||||
try:
|
||||
# Wait for a maximum of 13 minutes for invalidation to complete.
|
||||
cloudfront.get_waiter('invalidation_completed').wait(
|
||||
DistributionId=distribution_id,
|
||||
Id=invalidation_resp['Invalidation']['Id'],
|
||||
WaiterConfig={
|
||||
'Delay': 20,
|
||||
'MaxAttempts': (13*60)//20,
|
||||
}
|
||||
)
|
||||
except WaiterError as e:
|
||||
raise RuntimeError(f"Unable to confirm that cache invalidation was successful. This may be a CloudFront regression as reported in https://github.com/aws/aws-cdk/issues/15891") from e
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------------------------
|
||||
# set metadata
|
||||
def create_metadata_args(raw_user_metadata, raw_system_metadata):
|
||||
if len(raw_user_metadata) == 0 and len(raw_system_metadata) == 0:
|
||||
return []
|
||||
|
||||
format_system_metadata_key = lambda k: k.lower()
|
||||
format_user_metadata_key = lambda k: k.lower()
|
||||
|
||||
system_metadata = { format_system_metadata_key(k): v for k, v in raw_system_metadata.items() }
|
||||
user_metadata = { format_user_metadata_key(k): v for k, v in raw_user_metadata.items() }
|
||||
|
||||
flatten = lambda l: [item for sublist in l for item in sublist]
|
||||
system_args = flatten([[f"--{k}", v] for k, v in system_metadata.items()])
|
||||
user_args = ["--metadata", json.dumps(user_metadata, separators=(',', ':'))] if len(user_metadata) > 0 else []
|
||||
|
||||
return system_args + user_args + ["--metadata-directive", "REPLACE"]
|
||||
|
||||
#---------------------------------------------------------------------------------------------------
|
||||
# executes an "aws" cli command
|
||||
def aws_command(*args):
|
||||
aws="/opt/awscli/aws" # from AwsCliLayer
|
||||
logger.info("| aws %s" % ' '.join(args))
|
||||
subprocess.check_call([aws] + list(args))
|
||||
|
||||
#---------------------------------------------------------------------------------------------------
|
||||
# sends a response to cloudformation
|
||||
def cfn_send(event, context, responseStatus, responseData={}, physicalResourceId=None, noEcho=False, reason=None):
|
||||
|
||||
responseUrl = event['ResponseURL']
|
||||
|
||||
responseBody = {}
|
||||
responseBody['Status'] = responseStatus
|
||||
responseBody['Reason'] = reason or ('See the details in CloudWatch Log Stream: ' + context.log_stream_name)
|
||||
responseBody['PhysicalResourceId'] = physicalResourceId or context.log_stream_name
|
||||
responseBody['StackId'] = event['StackId']
|
||||
responseBody['RequestId'] = event['RequestId']
|
||||
responseBody['LogicalResourceId'] = event['LogicalResourceId']
|
||||
responseBody['NoEcho'] = noEcho
|
||||
responseBody['Data'] = responseData
|
||||
|
||||
body = json.dumps(responseBody)
|
||||
logger.info("| response body:\n" + body)
|
||||
|
||||
headers = {
|
||||
'content-type' : '',
|
||||
'content-length' : str(len(body))
|
||||
}
|
||||
|
||||
try:
|
||||
request = Request(responseUrl, method='PUT', data=bytes(body.encode('utf-8')), headers=headers)
|
||||
with contextlib.closing(urlopen(request)) as response:
|
||||
logger.info("| status code: " + response.reason)
|
||||
except Exception as e:
|
||||
logger.error("| unable to send response to CloudFormation")
|
||||
logger.exception(e)
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------------------------
|
||||
# check if bucket is owned by a custom resource
|
||||
# if it is then we don't want to delete content
|
||||
def bucket_owned(bucketName, keyPrefix):
|
||||
tag = CUSTOM_RESOURCE_OWNER_TAG
|
||||
if keyPrefix != "":
|
||||
tag = tag + ':' + keyPrefix
|
||||
try:
|
||||
request = s3.get_bucket_tagging(
|
||||
Bucket=bucketName,
|
||||
)
|
||||
return any((x["Key"].startswith(tag)) for x in request["TagSet"])
|
||||
except Exception as e:
|
||||
logger.info("| error getting tags from bucket")
|
||||
logger.exception(e)
|
||||
return False
|
||||
|
||||
# extract archive and replace markers in output files
|
||||
def extract_and_replace_markers(archive, contents_dir, markers, markers_config):
|
||||
with ZipFile(archive, "r") as zip:
|
||||
zip.extractall(contents_dir)
|
||||
|
||||
# replace markers for this source
|
||||
for file in zip.namelist():
|
||||
file_path = os.path.join(contents_dir, file)
|
||||
if os.path.isdir(file_path): continue
|
||||
replace_markers(file_path, markers, markers_config)
|
||||
|
||||
def prepare_json_safe_markers(markers):
|
||||
"""Pre-process markers to ensure JSON-safe values"""
|
||||
safe_markers = {}
|
||||
for key, value in markers.items():
|
||||
# Serialize the value as JSON to handle escaping if the value is a string
|
||||
serialized = json.dumps(value)
|
||||
if serialized.startswith('"') and serialized.endswith('"'):
|
||||
json_safe_value = json.dumps(value)[1:-1] # Remove surrounding quotes
|
||||
else:
|
||||
json_safe_value = serialized
|
||||
safe_markers[key.encode('utf-8')] = json_safe_value.encode('utf-8')
|
||||
return safe_markers
|
||||
|
||||
def replace_markers(filename, markers, markers_config):
|
||||
"""Replace markers in a file, with special handling for JSON files."""
|
||||
# if there are no markers, skip
|
||||
if not markers:
|
||||
return
|
||||
|
||||
outfile = filename + '.new'
|
||||
json_escape = markers_config.get('jsonEscape', 'false').lower()
|
||||
if json_escape == 'true':
|
||||
replace_tokens = prepare_json_safe_markers(markers)
|
||||
else:
|
||||
replace_tokens = dict([(k.encode('utf-8'), v.encode('utf-8')) for k, v in markers.items()])
|
||||
|
||||
# Handle content with line-by-line binary replacement
|
||||
with open(filename, 'rb') as fi, open(outfile, 'wb') as fo:
|
||||
# Process line by line to handle large files
|
||||
for line in fi:
|
||||
for token, replacement in replace_tokens.items():
|
||||
line = line.replace(token, replacement)
|
||||
fo.write(line)
|
||||
|
||||
# Delete the original file and rename the new one to the original
|
||||
os.remove(filename)
|
||||
os.rename(outfile, filename)
|
||||
|
||||
def replace_markers_in_json(json_object, replace_tokens):
|
||||
"""Replace markers in JSON content with proper escaping."""
|
||||
try:
|
||||
def replace_in_structure(obj):
|
||||
if isinstance(obj, str):
|
||||
# Convert string to bytes for consistent replacement
|
||||
result = obj.encode('utf-8')
|
||||
for token, replacement in replace_tokens.items():
|
||||
result = result.replace(token, replacement)
|
||||
# Convert back to string
|
||||
return result.decode('utf-8')
|
||||
elif isinstance(obj, dict):
|
||||
return {k: replace_in_structure(v) for k, v in obj.items()}
|
||||
elif isinstance(obj, list):
|
||||
return [replace_in_structure(item) for item in obj]
|
||||
return obj
|
||||
|
||||
# Process the whole structure
|
||||
processed = replace_in_structure(json_object)
|
||||
return json.dumps(processed)
|
||||
except Exception as e:
|
||||
logger.error(f'Error processing JSON: {e}')
|
||||
logger.exception(e)
|
||||
return json_object
|
||||
27
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-s3-deployment/bucket-deployment-provider.generated.d.ts
generated
vendored
Normal file
27
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-s3-deployment/bucket-deployment-provider.generated.d.ts
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import { Construct } from "constructs";
|
||||
import * as lambda from "../../../aws-lambda";
|
||||
export declare class BucketDeploymentSingletonFunction extends lambda.SingletonFunction {
|
||||
constructor(scope: Construct, id: string, props: BucketDeploymentSingletonFunctionProps);
|
||||
}
|
||||
/**
|
||||
* Initialization properties for BucketDeploymentSingletonFunction
|
||||
*/
|
||||
export interface BucketDeploymentSingletonFunctionProps extends lambda.FunctionOptions {
|
||||
/**
|
||||
* A unique identifier to identify this Lambda.
|
||||
*
|
||||
* The identifier should be unique across all custom resource providers.
|
||||
* We recommend generating a UUID per provider.
|
||||
*/
|
||||
readonly uuid: string;
|
||||
/**
|
||||
* A descriptive name for the purpose of this Lambda.
|
||||
*
|
||||
* If the Lambda does not have a physical name, this string will be
|
||||
* reflected in its generated name. The combination of lambdaPurpose
|
||||
* and uuid must be unique.
|
||||
*
|
||||
* @default SingletonLambda
|
||||
*/
|
||||
readonly lambdaPurpose?: string;
|
||||
}
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-s3-deployment/bucket-deployment-provider.generated.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-s3-deployment/bucket-deployment-provider.generated.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.BucketDeploymentSingletonFunction=void 0;const path=require("path"),lambda=require("../../../aws-lambda");class BucketDeploymentSingletonFunction extends lambda.SingletonFunction{constructor(scope,id,props){super(scope,id,{...props,code:lambda.Code.fromAsset(path.join(__dirname,"bucket-deployment-handler")),handler:"index.handler",runtime:lambda.Runtime.PYTHON_3_13}),this.addMetadata("aws:cdk:is-custom-resource-handler-singleton",!0),this.addMetadata("aws:cdk:is-custom-resource-handler-runtime-family",this.runtime.family),props?.logGroup&&this.logGroup.node.addMetadata("aws:cdk:is-custom-resource-handler-logGroup",!0),props?.logRetention&&this.lambdaFunction._logRetention?.node.addMetadata("aws:cdk:is-custom-resource-handler-logRetention",!0)}}exports.BucketDeploymentSingletonFunction=BucketDeploymentSingletonFunction;
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-s3/auto-delete-objects-handler/index.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-s3/auto-delete-objects-handler/index.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";var f=Object.create,i=Object.defineProperty,I=Object.getOwnPropertyDescriptor,C=Object.getOwnPropertyNames,w=Object.getPrototypeOf,P=Object.prototype.hasOwnProperty,A=(t,e)=>{for(var o in e)i(t,o,{get:e[o],enumerable:!0})},d=(t,e,o,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of C(e))!P.call(t,s)&&s!==o&&i(t,s,{get:()=>e[s],enumerable:!(r=I(e,s))||r.enumerable});return t},l=(t,e,o)=>(o=t!=null?f(w(t)):{},d(e||!t||!t.__esModule?i(o,"default",{value:t,enumerable:!0}):o,t)),B=t=>d(i({},"__esModule",{value:!0}),t),q={};A(q,{autoDeleteHandler:()=>S,handler:()=>H}),module.exports=B(q);var h=require("@aws-sdk/client-s3"),y=l(require("https")),m=l(require("url")),a={sendHttpRequest:D,log:T,includeStackTraces:!0,userHandlerIndex:"./index"},p="AWSCDK::CustomResourceProviderFramework::CREATE_FAILED",L="AWSCDK::CustomResourceProviderFramework::MISSING_PHYSICAL_ID";function R(t){return async(e,o)=>{let r={...e,ResponseURL:"..."};if(a.log(JSON.stringify(r,void 0,2)),e.RequestType==="Delete"&&e.PhysicalResourceId===p){a.log("ignoring DELETE event caused by a failed CREATE event"),await u("SUCCESS",e);return}try{let s=await t(r,o),n=k(e,s);await u("SUCCESS",n)}catch(s){let n={...e,Reason:a.includeStackTraces?s.stack:s.message};n.PhysicalResourceId||(e.RequestType==="Create"?(a.log("CREATE failed, responding with a marker physical resource id so that the subsequent DELETE will be ignored"),n.PhysicalResourceId=p):a.log(`ERROR: Malformed event. "PhysicalResourceId" is required: ${JSON.stringify(e)}`)),await u("FAILED",n)}}}function k(t,e={}){let o=e.PhysicalResourceId??t.PhysicalResourceId??t.RequestId;if(t.RequestType==="Delete"&&o!==t.PhysicalResourceId)throw new Error(`DELETE: cannot change the physical resource ID from "${t.PhysicalResourceId}" to "${e.PhysicalResourceId}" during deletion`);return{...t,...e,PhysicalResourceId:o}}async function u(t,e){let o={Status:t,Reason:e.Reason??t,StackId:e.StackId,RequestId:e.RequestId,PhysicalResourceId:e.PhysicalResourceId||L,LogicalResourceId:e.LogicalResourceId,NoEcho:e.NoEcho,Data:e.Data},r=m.parse(e.ResponseURL),s=`${r.protocol}//${r.hostname}/${r.pathname}?***`;a.log("submit response to cloudformation",s,o);let n=JSON.stringify(o),E={hostname:r.hostname,path:r.path,method:"PUT",headers:{"content-type":"","content-length":Buffer.byteLength(n,"utf8")}};await O({attempts:5,sleep:1e3},a.sendHttpRequest)(E,n)}async function D(t,e){return new Promise((o,r)=>{try{let s=y.request(t,n=>{n.resume(),!n.statusCode||n.statusCode>=400?r(new Error(`Unsuccessful HTTP response: ${n.statusCode}`)):o()});s.on("error",r),s.write(e),s.end()}catch(s){r(s)}})}function T(t,...e){console.log(t,...e)}function O(t,e){return async(...o)=>{let r=t.attempts,s=t.sleep;for(;;)try{return await e(...o)}catch(n){if(r--<=0)throw n;await b(Math.floor(Math.random()*s)),s*=2}}}async function b(t){return new Promise(e=>setTimeout(e,t))}var g="aws-cdk:auto-delete-objects",x=JSON.stringify({Version:"2012-10-17",Statement:[]}),c=new h.S3({}),H=R(S);async function S(t){switch(t.RequestType){case"Create":return;case"Update":return{PhysicalResourceId:(await F(t)).PhysicalResourceId};case"Delete":return N(t.ResourceProperties?.BucketName)}}async function F(t){let e=t,o=e.OldResourceProperties?.BucketName;return{PhysicalResourceId:e.ResourceProperties?.BucketName??o}}async function _(t){try{let e=(await c.getBucketPolicy({Bucket:t}))?.Policy??x,o=JSON.parse(e);o.Statement.push({Principal:"*",Effect:"Deny",Action:["s3:PutObject"],Resource:[`arn:aws:s3:::${t}/*`]}),await c.putBucketPolicy({Bucket:t,Policy:JSON.stringify(o)})}catch(e){if(e.name==="NoSuchBucket")throw e;console.log(`Could not set new object deny policy on bucket '${t}' prior to deletion.`)}}async function U(t){let e;do{e=await c.listObjectVersions({Bucket:t});let o=[...e.Versions??[],...e.DeleteMarkers??[]];if(o.length===0)return;let r=o.map(s=>({Key:s.Key,VersionId:s.VersionId}));await c.deleteObjects({Bucket:t,Delete:{Objects:r}})}while(e?.IsTruncated)}async function N(t){if(!t)throw new Error("No BucketName was provided.");try{if(!await W(t)){console.log(`Bucket does not have '${g}' tag, skipping cleaning.`);return}await _(t),await U(t)}catch(e){if(e.name==="NoSuchBucket"){console.log(`Bucket '${t}' does not exist.`);return}throw e}}async function W(t){return(await c.getBucketTagging({Bucket:t})).TagSet?.some(o=>o.Key===g&&o.Value==="true")}
|
||||
13
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-s3/auto-delete-objects-provider.generated.d.ts
generated
vendored
Normal file
13
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-s3/auto-delete-objects-provider.generated.d.ts
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Construct } from "constructs";
|
||||
import { CustomResourceProviderBase, CustomResourceProviderOptions } from "../../../core";
|
||||
export declare class AutoDeleteObjectsProvider extends CustomResourceProviderBase {
|
||||
/**
|
||||
* Returns a stack-level singleton ARN (service token) for the custom resource provider.
|
||||
*/
|
||||
static getOrCreate(scope: Construct, uniqueid: string, props?: CustomResourceProviderOptions): string;
|
||||
/**
|
||||
* Returns a stack-level singleton for the custom resource provider.
|
||||
*/
|
||||
static getOrCreateProvider(scope: Construct, uniqueid: string, props?: CustomResourceProviderOptions): AutoDeleteObjectsProvider;
|
||||
private constructor();
|
||||
}
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-s3/auto-delete-objects-provider.generated.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-s3/auto-delete-objects-provider.generated.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.AutoDeleteObjectsProvider=void 0;const path=require("path"),core_1=require("../../../core");class AutoDeleteObjectsProvider extends core_1.CustomResourceProviderBase{static getOrCreate(scope,uniqueid,props){return this.getOrCreateProvider(scope,uniqueid,props).serviceToken}static getOrCreateProvider(scope,uniqueid,props){const id=`${uniqueid}CustomResourceProvider`,stack=core_1.Stack.of(scope);return stack.node.tryFindChild(id)??new AutoDeleteObjectsProvider(stack,id,props)}constructor(scope,id,props){super(scope,id,{...props,codeDirectory:path.join(__dirname,"auto-delete-objects-handler"),runtimeName:(0,core_1.determineLatestNodeRuntimeName)(scope)}),this.node.addMetadata("aws:cdk:is-custom-resource-handler-customResourceProvider",!0)}}exports.AutoDeleteObjectsProvider=AutoDeleteObjectsProvider;
|
||||
123
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-s3/notifications-resource-handler/index.py
generated
vendored
Normal file
123
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-s3/notifications-resource-handler/index.py
generated
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
import boto3 # type: ignore
|
||||
import json
|
||||
import logging
|
||||
import urllib.request
|
||||
|
||||
s3 = boto3.client("s3")
|
||||
|
||||
EVENTBRIDGE_CONFIGURATION = 'EventBridgeConfiguration'
|
||||
CONFIGURATION_TYPES = ["TopicConfigurations", "QueueConfigurations", "LambdaFunctionConfigurations"]
|
||||
|
||||
def handler(event: dict, context):
|
||||
response_status = "SUCCESS"
|
||||
error_message = ""
|
||||
try:
|
||||
props = event["ResourceProperties"]
|
||||
notification_configuration = props["NotificationConfiguration"]
|
||||
managed = props.get('Managed', 'true').lower() == 'true'
|
||||
skipDestinationValidation = props.get('SkipDestinationValidation', 'false').lower() == 'true'
|
||||
stack_id = event['StackId']
|
||||
old = event.get("OldResourceProperties", {}).get("NotificationConfiguration", {})
|
||||
if managed:
|
||||
config = handle_managed(event["RequestType"], notification_configuration)
|
||||
else:
|
||||
config = handle_unmanaged(props["BucketName"], stack_id, event["RequestType"], notification_configuration, old)
|
||||
s3.put_bucket_notification_configuration(Bucket=props["BucketName"], NotificationConfiguration=config, SkipDestinationValidation=skipDestinationValidation)
|
||||
except Exception as e:
|
||||
logging.exception("Failed to put bucket notification configuration")
|
||||
response_status = "FAILED"
|
||||
error_message = f"Error: {str(e)}. "
|
||||
finally:
|
||||
submit_response(event, context, response_status, error_message)
|
||||
|
||||
def handle_managed(request_type, notification_configuration):
|
||||
if request_type == 'Delete':
|
||||
return {}
|
||||
return notification_configuration
|
||||
|
||||
def handle_unmanaged(bucket, stack_id, request_type, notification_configuration, old):
|
||||
def get_id(n):
|
||||
n['Id'] = ''
|
||||
sorted_notifications = sort_filter_rules(n)
|
||||
strToHash=json.dumps(sorted_notifications, sort_keys=True).replace('"Name": "prefix"', '"Name": "Prefix"').replace('"Name": "suffix"', '"Name": "Suffix"')
|
||||
return f"{stack_id}-{hash(strToHash)}"
|
||||
def with_id(n):
|
||||
n['Id'] = get_id(n)
|
||||
return n
|
||||
|
||||
# find external notifications
|
||||
external_notifications = {}
|
||||
existing_notifications = s3.get_bucket_notification_configuration(Bucket=bucket)
|
||||
for t in CONFIGURATION_TYPES:
|
||||
if request_type == 'Update':
|
||||
old_incoming_ids = [get_id(n) for n in old.get(t, [])]
|
||||
# if the notification was created by us, we know what id to expect so we can filter by it.
|
||||
external_notifications[t] = [n for n in existing_notifications.get(t, []) if not get_id(n) in old_incoming_ids]
|
||||
elif request_type == 'Delete':
|
||||
# For 'Delete' request, old parameter is an empty dict so we cannot use this to determine which are external
|
||||
# notifications. Fall back to rely on the stack naming logic.
|
||||
external_notifications[t] = [n for n in existing_notifications.get(t, []) if not n['Id'].startswith(f"{stack_id}-")]
|
||||
elif request_type == 'Create':
|
||||
# if this is a create event then all existing notifications are external
|
||||
external_notifications[t] = [n for n in existing_notifications.get(t, [])]
|
||||
# always treat EventBridge configuration as an external config if it already exists
|
||||
# as there is no way to determine whether it's managed by us or not
|
||||
if EVENTBRIDGE_CONFIGURATION in existing_notifications:
|
||||
external_notifications[EVENTBRIDGE_CONFIGURATION] = existing_notifications[EVENTBRIDGE_CONFIGURATION]
|
||||
|
||||
# if delete, that's all we need
|
||||
if request_type == 'Delete':
|
||||
return external_notifications
|
||||
|
||||
# otherwise, merge external with incoming config and augment with id
|
||||
notifications = {}
|
||||
for t in CONFIGURATION_TYPES:
|
||||
external = external_notifications.get(t, [])
|
||||
incoming = [with_id(n) for n in notification_configuration.get(t, [])]
|
||||
notifications[t] = external + incoming
|
||||
|
||||
# EventBridge configuration is a special case because it's just an empty object if it exists
|
||||
if EVENTBRIDGE_CONFIGURATION in notification_configuration:
|
||||
notifications[EVENTBRIDGE_CONFIGURATION] = notification_configuration[EVENTBRIDGE_CONFIGURATION]
|
||||
elif EVENTBRIDGE_CONFIGURATION in external_notifications:
|
||||
notifications[EVENTBRIDGE_CONFIGURATION] = external_notifications[EVENTBRIDGE_CONFIGURATION]
|
||||
|
||||
return notifications
|
||||
|
||||
def submit_response(event: dict, context, response_status: str, error_message: str):
|
||||
response_body = json.dumps(
|
||||
{
|
||||
"Status": response_status,
|
||||
"Reason": f"{error_message}See the details in CloudWatch Log Stream: {context.log_stream_name}",
|
||||
"PhysicalResourceId": event.get("PhysicalResourceId") or event["LogicalResourceId"],
|
||||
"StackId": event["StackId"],
|
||||
"RequestId": event["RequestId"],
|
||||
"LogicalResourceId": event["LogicalResourceId"],
|
||||
"NoEcho": False,
|
||||
}
|
||||
).encode("utf-8")
|
||||
headers = {"content-type": "", "content-length": str(len(response_body))}
|
||||
try:
|
||||
req = urllib.request.Request(url=event["ResponseURL"], headers=headers, data=response_body, method="PUT")
|
||||
with urllib.request.urlopen(req) as response:
|
||||
print(response.read().decode("utf-8"))
|
||||
print("Status code: " + response.reason)
|
||||
except Exception as e:
|
||||
print("send(..) failed executing request.urlopen(..): " + str(e))
|
||||
|
||||
def sort_filter_rules(json_obj):
|
||||
# Check if the input is a dictionary
|
||||
if not isinstance(json_obj, dict):
|
||||
return json_obj
|
||||
# Recursively sort the filter rules for nested dictionaries
|
||||
for key, value in json_obj.items():
|
||||
if isinstance(value, dict):
|
||||
json_obj[key] = sort_filter_rules(value)
|
||||
elif isinstance(value, list):
|
||||
json_obj[key] = [sort_filter_rules(item) for item in value]
|
||||
# Sort the FilterRules list if it exists
|
||||
if "Filter" in json_obj and "Key" in json_obj["Filter"] and "FilterRules" in json_obj["Filter"]["Key"]:
|
||||
filter_rules = json_obj["Filter"]["Key"]["FilterRules"]
|
||||
sorted_filter_rules = sorted(filter_rules, key=lambda x: x["Name"])
|
||||
json_obj["Filter"]["Key"]["FilterRules"] = sorted_filter_rules
|
||||
return json_obj
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-ses/drop-spam-handler/index.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-ses/drop-spam-handler/index.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";var o=Object.defineProperty,n=Object.getOwnPropertyDescriptor,c=Object.getOwnPropertyNames,a=Object.prototype.hasOwnProperty,p=(i,t)=>{for(var e in t)o(i,e,{get:t[e],enumerable:!0})},l=(i,t,e,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of c(t))!a.call(i,s)&&s!==e&&o(i,s,{get:()=>t[s],enumerable:!(r=n(t,s))||r.enumerable});return i},d=i=>l(o({},"__esModule",{value:!0}),i),S={};p(S,{handler:()=>u}),module.exports=d(S);async function u(i){console.log("Spam filter");let t=i.Records[0].ses;return console.log("SES Notification: %j",t),t.receipt.spfVerdict.status==="FAIL"||t.receipt.dkimVerdict.status==="FAIL"||t.receipt.spamVerdict.status==="FAIL"||t.receipt.virusVerdict.status==="FAIL"?(console.log("Dropping spam"),{disposition:"STOP_RULE_SET"}):null}
|
||||
27
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-ses/drop-spam-provider.generated.d.ts
generated
vendored
Normal file
27
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-ses/drop-spam-provider.generated.d.ts
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import { Construct } from "constructs";
|
||||
import * as lambda from "../../../aws-lambda";
|
||||
export declare class DropSpamSingletonFunction extends lambda.SingletonFunction {
|
||||
constructor(scope: Construct, id: string, props: DropSpamSingletonFunctionProps);
|
||||
}
|
||||
/**
|
||||
* Initialization properties for DropSpamSingletonFunction
|
||||
*/
|
||||
export interface DropSpamSingletonFunctionProps extends lambda.FunctionOptions {
|
||||
/**
|
||||
* A unique identifier to identify this Lambda.
|
||||
*
|
||||
* The identifier should be unique across all custom resource providers.
|
||||
* We recommend generating a UUID per provider.
|
||||
*/
|
||||
readonly uuid: string;
|
||||
/**
|
||||
* A descriptive name for the purpose of this Lambda.
|
||||
*
|
||||
* If the Lambda does not have a physical name, this string will be
|
||||
* reflected in its generated name. The combination of lambdaPurpose
|
||||
* and uuid must be unique.
|
||||
*
|
||||
* @default SingletonLambda
|
||||
*/
|
||||
readonly lambdaPurpose?: string;
|
||||
}
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-ses/drop-spam-provider.generated.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-ses/drop-spam-provider.generated.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.DropSpamSingletonFunction=void 0;const path=require("path"),lambda=require("../../../aws-lambda");class DropSpamSingletonFunction extends lambda.SingletonFunction{constructor(scope,id,props){super(scope,id,{...props,code:lambda.Code.fromAsset(path.join(__dirname,"drop-spam-handler")),handler:"index.handler",runtime:lambda.determineLatestNodeRuntime(scope)}),this.addMetadata("aws:cdk:is-custom-resource-handler-singleton",!0),this.addMetadata("aws:cdk:is-custom-resource-handler-runtime-family",this.runtime.family),props?.logGroup&&this.logGroup.node.addMetadata("aws:cdk:is-custom-resource-handler-logGroup",!0),props?.logRetention&&this.lambdaFunction._logRetention?.node.addMetadata("aws:cdk:is-custom-resource-handler-logRetention",!0)}}exports.DropSpamSingletonFunction=DropSpamSingletonFunction;
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-stepfunctions-tasks/cross-region-aws-sdk-handler/index.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-stepfunctions-tasks/cross-region-aws-sdk-handler/index.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";var i=Object.defineProperty,l=Object.getOwnPropertyDescriptor,m=Object.getOwnPropertyNames,f=Object.prototype.hasOwnProperty,g=(e,n)=>{for(var r in n)i(e,r,{get:n[r],enumerable:!0})},y=(e,n,r,a)=>{if(n&&typeof n=="object"||typeof n=="function")for(let o of m(n))!f.call(e,o)&&o!==r&&i(e,o,{get:()=>n[o],enumerable:!(a=l(n,o))||a.enumerable});return e},p=e=>y(i({},"__esModule",{value:!0}),e),P={};g(P,{handler:()=>u}),module.exports=p(P);function w(e){let n=Object.entries(e).filter(([r])=>r.endsWith("Client")&&r!=="__Client");if(n.length==0)throw new Error("There is no *Client class in the package.");if(n.length>1)throw new Error(`There are more than one *Client classes in the package: ${n.map(r=>r[0]).join(",")}`);return n[0][1]}function h(e){return e.charAt(0).toUpperCase()+e.slice(1)}function C(e,n){let r=`${h(n)}Command`,a=Object.entries(e).find(([o])=>o.toLowerCase()===r.toLowerCase())?.[1];if(!a)throw new Error(`Unable to find command named: ${r} for action: ${n} in service package`);return a}var u=async e=>{console.log("Event: ",e);try{let n=require(`@aws-sdk/client-${e.service}`),r=w(n),a=C(n,e.action),o=new r({region:e.region,endpoint:e.endpoint}),c=new a(e.parameters??{}),t=await o.send(c);if(t.Payload&&(t.Payload instanceof Uint8Array||t.Payload instanceof Buffer))try{let s=new TextDecoder().decode(t.Payload);t.Payload=JSON.parse(s)}catch{t.Payload=new TextDecoder().decode(t.Payload)}let d=JSON.stringify(t);return JSON.parse(d)}catch(n){throw console.error("Error: ",n),n}};
|
||||
27
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-stepfunctions-tasks/cross-region-aws-sdk-provider.generated.d.ts
generated
vendored
Normal file
27
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-stepfunctions-tasks/cross-region-aws-sdk-provider.generated.d.ts
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import { Construct } from "constructs";
|
||||
import * as lambda from "../../../aws-lambda";
|
||||
export declare class CrossRegionAwsSdkSingletonFunction extends lambda.SingletonFunction {
|
||||
constructor(scope: Construct, id: string, props: CrossRegionAwsSdkSingletonFunctionProps);
|
||||
}
|
||||
/**
|
||||
* Initialization properties for CrossRegionAwsSdkSingletonFunction
|
||||
*/
|
||||
export interface CrossRegionAwsSdkSingletonFunctionProps extends lambda.FunctionOptions {
|
||||
/**
|
||||
* A unique identifier to identify this Lambda.
|
||||
*
|
||||
* The identifier should be unique across all custom resource providers.
|
||||
* We recommend generating a UUID per provider.
|
||||
*/
|
||||
readonly uuid: string;
|
||||
/**
|
||||
* A descriptive name for the purpose of this Lambda.
|
||||
*
|
||||
* If the Lambda does not have a physical name, this string will be
|
||||
* reflected in its generated name. The combination of lambdaPurpose
|
||||
* and uuid must be unique.
|
||||
*
|
||||
* @default SingletonLambda
|
||||
*/
|
||||
readonly lambdaPurpose?: string;
|
||||
}
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-stepfunctions-tasks/cross-region-aws-sdk-provider.generated.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-stepfunctions-tasks/cross-region-aws-sdk-provider.generated.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.CrossRegionAwsSdkSingletonFunction=void 0;const path=require("path"),lambda=require("../../../aws-lambda");class CrossRegionAwsSdkSingletonFunction extends lambda.SingletonFunction{constructor(scope,id,props){super(scope,id,{...props,code:lambda.Code.fromAsset(path.join(__dirname,"cross-region-aws-sdk-handler")),handler:"index.handler",runtime:lambda.determineLatestNodeRuntime(scope)}),this.addMetadata("aws:cdk:is-custom-resource-handler-singleton",!0),this.addMetadata("aws:cdk:is-custom-resource-handler-runtime-family",this.runtime.family),props?.logGroup&&this.logGroup.node.addMetadata("aws:cdk:is-custom-resource-handler-logGroup",!0),props?.logRetention&&this.lambdaFunction._logRetention?.node.addMetadata("aws:cdk:is-custom-resource-handler-logRetention",!0)}}exports.CrossRegionAwsSdkSingletonFunction=CrossRegionAwsSdkSingletonFunction;
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-stepfunctions-tasks/eval-nodejs-handler/index.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-stepfunctions-tasks/eval-nodejs-handler/index.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";var o=Object.defineProperty,i=Object.getOwnPropertyDescriptor,a=Object.getOwnPropertyNames,p=Object.prototype.hasOwnProperty,c=(e,n)=>{for(var s in n)o(e,s,{get:n[s],enumerable:!0})},l=(e,n,s,t)=>{if(n&&typeof n=="object"||typeof n=="function")for(let r of a(n))!p.call(e,r)&&r!==s&&o(e,r,{get:()=>n[r],enumerable:!(t=i(n,r))||t.enumerable});return e},g=e=>l(o({},"__esModule",{value:!0}),e),y={};c(y,{handler:()=>u}),module.exports=g(y);function x(e){return e.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}async function u(e){console.log("Event: %j",{...e,ResponseURL:"..."});let n=Object.entries(e.expressionAttributeValues).reduce((s,[t,r])=>s.replace(new RegExp(x(t),"g"),JSON.stringify(r)),e.expression);return console.log(`Expression: ${n}`),[eval][0](n)}
|
||||
33
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-stepfunctions-tasks/eval-nodejs-provider.generated.d.ts
generated
vendored
Normal file
33
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-stepfunctions-tasks/eval-nodejs-provider.generated.d.ts
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
import { Construct } from "constructs";
|
||||
import * as lambda from "../../../aws-lambda";
|
||||
export declare class EvalNodejsSingletonFunction extends lambda.SingletonFunction {
|
||||
constructor(scope: Construct, id: string, props: EvalNodejsSingletonFunctionProps);
|
||||
}
|
||||
/**
|
||||
* Initialization properties for EvalNodejsSingletonFunction
|
||||
*/
|
||||
export interface EvalNodejsSingletonFunctionProps extends lambda.FunctionOptions {
|
||||
/**
|
||||
* A unique identifier to identify this Lambda.
|
||||
*
|
||||
* The identifier should be unique across all custom resource providers.
|
||||
* We recommend generating a UUID per provider.
|
||||
*/
|
||||
readonly uuid: string;
|
||||
/**
|
||||
* A descriptive name for the purpose of this Lambda.
|
||||
*
|
||||
* If the Lambda does not have a physical name, this string will be
|
||||
* reflected in its generated name. The combination of lambdaPurpose
|
||||
* and uuid must be unique.
|
||||
*
|
||||
* @default SingletonLambda
|
||||
*/
|
||||
readonly lambdaPurpose?: string;
|
||||
/**
|
||||
* The runtime that this Lambda will use.
|
||||
*
|
||||
* @default - the latest Lambda node runtime available in your region.
|
||||
*/
|
||||
readonly runtime?: lambda.Runtime;
|
||||
}
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-stepfunctions-tasks/eval-nodejs-provider.generated.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-stepfunctions-tasks/eval-nodejs-provider.generated.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.EvalNodejsSingletonFunction=void 0;const path=require("path"),lambda=require("../../../aws-lambda");class EvalNodejsSingletonFunction extends lambda.SingletonFunction{constructor(scope,id,props){super(scope,id,{...props,code:lambda.Code.fromAsset(path.join(__dirname,"eval-nodejs-handler")),handler:"index.handler",runtime:props.runtime?props.runtime:lambda.determineLatestNodeRuntime(scope)}),this.addMetadata("aws:cdk:is-custom-resource-handler-singleton",!0),this.addMetadata("aws:cdk:is-custom-resource-handler-runtime-family",this.runtime.family),props?.logGroup&&this.logGroup.node.addMetadata("aws:cdk:is-custom-resource-handler-logGroup",!0),props?.logRetention&&this.lambdaFunction._logRetention?.node.addMetadata("aws:cdk:is-custom-resource-handler-logRetention",!0)}}exports.EvalNodejsSingletonFunction=EvalNodejsSingletonFunction;
|
||||
16
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-stepfunctions-tasks/role-policy-handler/index.py
generated
vendored
Normal file
16
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-stepfunctions-tasks/role-policy-handler/index.py
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
import subprocess as sp
|
||||
import os
|
||||
import logging
|
||||
|
||||
#https://github.com/aws/aws-cdk/tree/main/packages/%40aws-cdk/aws-stepfunctions#custom-state
|
||||
def handler(event, context):
|
||||
logger = logging.getLogger()
|
||||
logger.setLevel(logging.INFO)
|
||||
command = ["/opt/awscli/aws", "emr-containers", "update-role-trust-policy", "--cluster-name", f"{event['ResourceProperties']['eksClusterId']}", "--namespace", f"{event['ResourceProperties']['eksNamespace']}", "--role-name", f"{event['ResourceProperties']['roleName']}"]
|
||||
if event['RequestType'] == 'Create' or event['RequestType'] == 'Update' :
|
||||
try:
|
||||
res = sp.check_output(command)
|
||||
logger.info(f"Successfully ran {command}")
|
||||
except Exception as e:
|
||||
logger.info(f"ERROR: {str(e)}")
|
||||
|
||||
27
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-stepfunctions-tasks/role-policy-provider.generated.d.ts
generated
vendored
Normal file
27
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-stepfunctions-tasks/role-policy-provider.generated.d.ts
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import { Construct } from "constructs";
|
||||
import * as lambda from "../../../aws-lambda";
|
||||
export declare class RolePolicySingletonFunction extends lambda.SingletonFunction {
|
||||
constructor(scope: Construct, id: string, props: RolePolicySingletonFunctionProps);
|
||||
}
|
||||
/**
|
||||
* Initialization properties for RolePolicySingletonFunction
|
||||
*/
|
||||
export interface RolePolicySingletonFunctionProps extends lambda.FunctionOptions {
|
||||
/**
|
||||
* A unique identifier to identify this Lambda.
|
||||
*
|
||||
* The identifier should be unique across all custom resource providers.
|
||||
* We recommend generating a UUID per provider.
|
||||
*/
|
||||
readonly uuid: string;
|
||||
/**
|
||||
* A descriptive name for the purpose of this Lambda.
|
||||
*
|
||||
* If the Lambda does not have a physical name, this string will be
|
||||
* reflected in its generated name. The combination of lambdaPurpose
|
||||
* and uuid must be unique.
|
||||
*
|
||||
* @default SingletonLambda
|
||||
*/
|
||||
readonly lambdaPurpose?: string;
|
||||
}
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-stepfunctions-tasks/role-policy-provider.generated.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-stepfunctions-tasks/role-policy-provider.generated.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.RolePolicySingletonFunction=void 0;const path=require("path"),lambda=require("../../../aws-lambda");class RolePolicySingletonFunction extends lambda.SingletonFunction{constructor(scope,id,props){super(scope,id,{...props,code:lambda.Code.fromAsset(path.join(__dirname,"role-policy-handler")),handler:"index.handler",runtime:lambda.Runtime.PYTHON_3_13}),this.addMetadata("aws:cdk:is-custom-resource-handler-singleton",!0),this.addMetadata("aws:cdk:is-custom-resource-handler-runtime-family",this.runtime.family),props?.logGroup&&this.logGroup.node.addMetadata("aws:cdk:is-custom-resource-handler-logGroup",!0),props?.logRetention&&this.lambdaFunction._logRetention?.node.addMetadata("aws:cdk:is-custom-resource-handler-logRetention",!0)}}exports.RolePolicySingletonFunction=RolePolicySingletonFunction;
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-synthetics/auto-delete-underlying-resources-handler/index.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-synthetics/auto-delete-underlying-resources-handler/index.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";var I=Object.create,i=Object.defineProperty,g=Object.getOwnPropertyDescriptor,S=Object.getOwnPropertyNames,w=Object.getPrototypeOf,A=Object.prototype.hasOwnProperty,P=(o,e)=>{for(var t in e)i(o,t,{get:e[t],enumerable:!0})},l=(o,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of S(e))!A.call(o,s)&&s!==t&&i(o,s,{get:()=>e[s],enumerable:!(n=g(e,s))||n.enumerable});return o},m=(o,e,t)=>(t=o!=null?I(w(o)):{},l(e||!o||!o.__esModule?i(t,"default",{value:o,enumerable:!0}):t,o)),L=o=>l(i({},"__esModule",{value:!0}),o),W={};P(W,{autoDeleteHandler:()=>E,handler:()=>_}),module.exports=L(W);var c=require("@aws-sdk/client-lambda"),u=require("@aws-sdk/client-synthetics"),y=m(require("https")),R=m(require("url")),a={sendHttpRequest:T,log:F,includeStackTraces:!0,userHandlerIndex:"./index"},p="AWSCDK::CustomResourceProviderFramework::CREATE_FAILED",D="AWSCDK::CustomResourceProviderFramework::MISSING_PHYSICAL_ID";function C(o){return async(e,t)=>{let n={...e,ResponseURL:"..."};if(a.log(JSON.stringify(n,void 0,2)),e.RequestType==="Delete"&&e.PhysicalResourceId===p){a.log("ignoring DELETE event caused by a failed CREATE event"),await d("SUCCESS",e);return}try{let s=await o(n,t),r=b(e,s);await d("SUCCESS",r)}catch(s){let r={...e,Reason:a.includeStackTraces?s.stack:s.message};r.PhysicalResourceId||(e.RequestType==="Create"?(a.log("CREATE failed, responding with a marker physical resource id so that the subsequent DELETE will be ignored"),r.PhysicalResourceId=p):a.log(`ERROR: Malformed event. "PhysicalResourceId" is required: ${JSON.stringify(e)}`)),await d("FAILED",r)}}}function b(o,e={}){let t=e.PhysicalResourceId??o.PhysicalResourceId??o.RequestId;if(o.RequestType==="Delete"&&t!==o.PhysicalResourceId)throw new Error(`DELETE: cannot change the physical resource ID from "${o.PhysicalResourceId}" to "${e.PhysicalResourceId}" during deletion`);return{...o,...e,PhysicalResourceId:t}}async function d(o,e){let t={Status:o,Reason:e.Reason??o,StackId:e.StackId,RequestId:e.RequestId,PhysicalResourceId:e.PhysicalResourceId||D,LogicalResourceId:e.LogicalResourceId,NoEcho:e.NoEcho,Data:e.Data},n=R.parse(e.ResponseURL),s=`${n.protocol}//${n.hostname}/${n.pathname}?***`;a.log("submit response to cloudformation",s,t);let r=JSON.stringify(t),f={hostname:n.hostname,path:n.path,method:"PUT",headers:{"content-type":"","content-length":Buffer.byteLength(r,"utf8")}};await x({attempts:5,sleep:1e3},a.sendHttpRequest)(f,r)}async function T(o,e){return new Promise((t,n)=>{try{let s=y.request(o,r=>{r.resume(),!r.statusCode||r.statusCode>=400?n(new Error(`Unsuccessful HTTP response: ${r.statusCode}`)):t()});s.on("error",n),s.write(e),s.end()}catch(s){n(s)}})}function F(o,...e){console.log(o,...e)}function x(o,e){return async(...t)=>{let n=o.attempts,s=o.sleep;for(;;)try{return await e(...t)}catch(r){if(n--<=0)throw r;await N(Math.floor(Math.random()*s)),s*=2}}}async function N(o){return new Promise(e=>setTimeout(e,o))}var h="aws-cdk:auto-delete-underlying-resources",H=new c.LambdaClient({}),U=new u.SyntheticsClient({}),_=C(E);async function E(o){switch(o.RequestType){case"Create":return{PhyscialResourceId:o.ResourceProperties?.CanaryName};case"Update":return{PhysicalResourceId:(await k(o)).PhysicalResourceId};case"Delete":return q(o.ResourceProperties?.CanaryName)}}async function k(o){return{PhysicalResourceId:o.ResourceProperties?.CanaryName}}async function q(o){if(console.log(`Deleting lambda function associated with ${o}`),!o)throw new Error("No CanaryName was provided.");try{let e=await U.send(new u.GetCanaryCommand({Name:o}));if(e.Canary===void 0||e.Canary.Id===void 0||e.Canary.EngineArn===void 0)return;if(!O(e.Canary.Tags)){console.log(`Canary does not have '${h}' tag, skipping deletion.`);return}let t=e.Canary.EngineArn.split(":");t.at(-1)?.includes(e.Canary.Id)||t.pop();let n=t.join(":");console.log(`Deleting lambda ${n}`),await H.send(new c.DeleteFunctionCommand({FunctionName:n}))}catch(e){if(e.name!=="ResourceNotFoundException")throw e}}function O(o){return o?Object.keys(o).some(e=>e===h&&o[e]==="true"):!1}
|
||||
13
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-synthetics/auto-delete-underlying-resources-provider.generated.d.ts
generated
vendored
Normal file
13
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-synthetics/auto-delete-underlying-resources-provider.generated.d.ts
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Construct } from "constructs";
|
||||
import { CustomResourceProviderBase, CustomResourceProviderOptions } from "../../../core";
|
||||
export declare class AutoDeleteUnderlyingResourcesProvider extends CustomResourceProviderBase {
|
||||
/**
|
||||
* Returns a stack-level singleton ARN (service token) for the custom resource provider.
|
||||
*/
|
||||
static getOrCreate(scope: Construct, uniqueid: string, props?: CustomResourceProviderOptions): string;
|
||||
/**
|
||||
* Returns a stack-level singleton for the custom resource provider.
|
||||
*/
|
||||
static getOrCreateProvider(scope: Construct, uniqueid: string, props?: CustomResourceProviderOptions): AutoDeleteUnderlyingResourcesProvider;
|
||||
private constructor();
|
||||
}
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-synthetics/auto-delete-underlying-resources-provider.generated.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/aws-synthetics/auto-delete-underlying-resources-provider.generated.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.AutoDeleteUnderlyingResourcesProvider=void 0;const path=require("path"),core_1=require("../../../core");class AutoDeleteUnderlyingResourcesProvider extends core_1.CustomResourceProviderBase{static getOrCreate(scope,uniqueid,props){return this.getOrCreateProvider(scope,uniqueid,props).serviceToken}static getOrCreateProvider(scope,uniqueid,props){const id=`${uniqueid}CustomResourceProvider`,stack=core_1.Stack.of(scope);return stack.node.tryFindChild(id)??new AutoDeleteUnderlyingResourcesProvider(stack,id,props)}constructor(scope,id,props){super(scope,id,{...props,codeDirectory:path.join(__dirname,"auto-delete-underlying-resources-handler"),runtimeName:(0,core_1.determineLatestNodeRuntimeName)(scope)}),this.node.addMetadata("aws:cdk:is-custom-resource-handler-customResourceProvider",!0)}}exports.AutoDeleteUnderlyingResourcesProvider=AutoDeleteUnderlyingResourcesProvider;
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/core/nodejs-entrypoint-handler/index.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/core/nodejs-entrypoint-handler/index.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.external=void 0,exports.handler=handler,exports.withRetries=withRetries;const https=require("https"),url=require("url");exports.external={sendHttpRequest:defaultSendHttpRequest,log:defaultLog,includeStackTraces:!0,userHandlerIndex:"./index"};const CREATE_FAILED_PHYSICAL_ID_MARKER="AWSCDK::CustomResourceProviderFramework::CREATE_FAILED",MISSING_PHYSICAL_ID_MARKER="AWSCDK::CustomResourceProviderFramework::MISSING_PHYSICAL_ID";async function handler(event,context){const sanitizedEvent={...event,ResponseURL:"..."};if(exports.external.log(JSON.stringify(sanitizedEvent,void 0,2)),event.RequestType==="Delete"&&event.PhysicalResourceId===CREATE_FAILED_PHYSICAL_ID_MARKER){exports.external.log("ignoring DELETE event caused by a failed CREATE event"),await submitResponse("SUCCESS",event);return}try{const userHandler=require(exports.external.userHandlerIndex).handler,result=await userHandler(sanitizedEvent,context),responseEvent=renderResponse(event,result);await submitResponse("SUCCESS",responseEvent)}catch(e){const resp={...event,Reason:exports.external.includeStackTraces?e.stack:e.message};resp.PhysicalResourceId||(event.RequestType==="Create"?(exports.external.log("CREATE failed, responding with a marker physical resource id so that the subsequent DELETE will be ignored"),resp.PhysicalResourceId=CREATE_FAILED_PHYSICAL_ID_MARKER):exports.external.log(`ERROR: Malformed event. "PhysicalResourceId" is required: ${JSON.stringify(event)}`)),await submitResponse("FAILED",resp)}}function renderResponse(cfnRequest,handlerResponse={}){const physicalResourceId=handlerResponse.PhysicalResourceId??cfnRequest.PhysicalResourceId??cfnRequest.RequestId;if(cfnRequest.RequestType==="Delete"&&physicalResourceId!==cfnRequest.PhysicalResourceId)throw new Error(`DELETE: cannot change the physical resource ID from "${cfnRequest.PhysicalResourceId}" to "${handlerResponse.PhysicalResourceId}" during deletion`);return{...cfnRequest,...handlerResponse,PhysicalResourceId:physicalResourceId}}async function submitResponse(status,event){const json={Status:status,Reason:event.Reason??status,StackId:event.StackId,RequestId:event.RequestId,PhysicalResourceId:event.PhysicalResourceId||MISSING_PHYSICAL_ID_MARKER,LogicalResourceId:event.LogicalResourceId,NoEcho:event.NoEcho,Data:event.Data},parsedUrl=url.parse(event.ResponseURL),loggingSafeUrl=`${parsedUrl.protocol}//${parsedUrl.hostname}/${parsedUrl.pathname}?***`;exports.external.log("submit response to cloudformation",loggingSafeUrl,json);const responseBody=JSON.stringify(json),req={hostname:parsedUrl.hostname,path:parsedUrl.path,method:"PUT",headers:{"content-type":"","content-length":Buffer.byteLength(responseBody,"utf8")}};await withRetries({attempts:5,sleep:1e3},exports.external.sendHttpRequest)(req,responseBody)}async function defaultSendHttpRequest(options,requestBody){return new Promise((resolve,reject)=>{try{const request=https.request(options,response=>{response.resume(),!response.statusCode||response.statusCode>=400?reject(new Error(`Unsuccessful HTTP response: ${response.statusCode}`)):resolve()});request.on("error",reject),request.write(requestBody),request.end()}catch(e){reject(e)}})}function defaultLog(fmt,...params){console.log(fmt,...params)}function withRetries(options,fn){return async(...xs)=>{let attempts=options.attempts,ms=options.sleep;for(;;)try{return await fn(...xs)}catch(e){if(attempts--<=0)throw e;await sleep(Math.floor(Math.random()*ms)),ms*=2}}}async function sleep(ms){return new Promise(ok=>setTimeout(ok,ms))}
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/custom-resources/aws-custom-resource-handler/index.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/custom-resources/aws-custom-resource-handler/index.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
27
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/custom-resources/aws-custom-resource-provider.generated.d.ts
generated
vendored
Normal file
27
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/custom-resources/aws-custom-resource-provider.generated.d.ts
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import { Construct } from "constructs";
|
||||
import * as lambda from "../../../aws-lambda";
|
||||
export declare class AwsCustomResourceSingletonFunction extends lambda.SingletonFunction {
|
||||
constructor(scope: Construct, id: string, props: AwsCustomResourceSingletonFunctionProps);
|
||||
}
|
||||
/**
|
||||
* Initialization properties for AwsCustomResourceSingletonFunction
|
||||
*/
|
||||
export interface AwsCustomResourceSingletonFunctionProps extends lambda.FunctionOptions {
|
||||
/**
|
||||
* A unique identifier to identify this Lambda.
|
||||
*
|
||||
* The identifier should be unique across all custom resource providers.
|
||||
* We recommend generating a UUID per provider.
|
||||
*/
|
||||
readonly uuid: string;
|
||||
/**
|
||||
* A descriptive name for the purpose of this Lambda.
|
||||
*
|
||||
* If the Lambda does not have a physical name, this string will be
|
||||
* reflected in its generated name. The combination of lambdaPurpose
|
||||
* and uuid must be unique.
|
||||
*
|
||||
* @default SingletonLambda
|
||||
*/
|
||||
readonly lambdaPurpose?: string;
|
||||
}
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/custom-resources/aws-custom-resource-provider.generated.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/custom-resources/aws-custom-resource-provider.generated.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.AwsCustomResourceSingletonFunction=void 0;const path=require("path"),lambda=require("../../../aws-lambda");class AwsCustomResourceSingletonFunction extends lambda.SingletonFunction{constructor(scope,id,props){super(scope,id,{...props,code:lambda.Code.fromAsset(path.join(__dirname,"aws-custom-resource-handler")),handler:"index.handler",runtime:lambda.determineLatestNodeRuntime(scope)}),this.addMetadata("aws:cdk:is-custom-resource-handler-singleton",!0),this.addMetadata("aws:cdk:is-custom-resource-handler-runtime-family",this.runtime.family),props?.logGroup&&this.logGroup.node.addMetadata("aws:cdk:is-custom-resource-handler-logGroup",!0),props?.logRetention&&this.lambdaFunction._logRetention?.node.addMetadata("aws:cdk:is-custom-resource-handler-logRetention",!0)}}exports.AwsCustomResourceSingletonFunction=AwsCustomResourceSingletonFunction;
|
||||
5
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/pipelines/approve-lambda.generated.d.ts
generated
vendored
Normal file
5
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/pipelines/approve-lambda.generated.d.ts
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import { Construct } from "constructs";
|
||||
import * as lambda from "../../../aws-lambda";
|
||||
export declare class ApproveLambdaFunction extends lambda.Function {
|
||||
constructor(scope: Construct, id: string, props?: lambda.FunctionOptions);
|
||||
}
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/pipelines/approve-lambda.generated.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/pipelines/approve-lambda.generated.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ApproveLambdaFunction=void 0;const path=require("path"),lambda=require("../../../aws-lambda");class ApproveLambdaFunction extends lambda.Function{constructor(scope,id,props){super(scope,id,{...props,code:lambda.Code.fromAsset(path.join(__dirname,"approve-lambda")),handler:"index.handler",runtime:lambda.determineLatestNodeRuntime(scope)}),this.node.addMetadata("aws:cdk:is-custom-resource-handler-runtime-family",this.runtime.family)}}exports.ApproveLambdaFunction=ApproveLambdaFunction;
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/pipelines/approve-lambda/index.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/pipelines/approve-lambda/index.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";var l=Object.defineProperty,y=Object.getOwnPropertyDescriptor,f=Object.getOwnPropertyNames,w=Object.prototype.hasOwnProperty,S=(t,e)=>{for(var n in e)l(t,n,{get:e[n],enumerable:!0})},v=(t,e,n,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of f(e))!w.call(t,a)&&a!==n&&l(t,a,{get:()=>e[a],enumerable:!(s=y(e,a))||s.enumerable});return t},h=t=>v(l({},"__esModule",{value:!0}),t),b={};S(b,{handler:()=>T}),module.exports=h(b);var d=require("@aws-sdk/client-codepipeline"),u=new d.CodePipeline,A=5,P=t=>new Promise(e=>setTimeout(e,t*1e3));async function T(t,e){let{PipelineName:n,StageName:s,ActionName:a}=t;function g(o){let m=o.stageStates?.filter(r=>r.stageName===s),c=m.length&&m[0].actionStates.filter(r=>r.actionName===a),p=c&&c.length&&c[0].latestExecution;return p?p.token:void 0}let N=Date.now()+A*6e4;for(;Date.now()<N;){let o=await u.getPipelineState({name:n}),i=g(o);if(i){await u.putApprovalResult({pipelineName:n,actionName:a,stageName:s,result:{summary:"No security changes detected. Automatically approved by Lambda.",status:"Approved"},token:i});return}await P(5)}}
|
||||
4
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/triggers/lambda/index.js
generated
vendored
Normal file
4
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/triggers/lambda/index.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
13
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/triggers/trigger-provider.generated.d.ts
generated
vendored
Normal file
13
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/triggers/trigger-provider.generated.d.ts
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Construct } from "constructs";
|
||||
import { CustomResourceProviderBase, CustomResourceProviderOptions } from "../../../core";
|
||||
export declare class TriggerProvider extends CustomResourceProviderBase {
|
||||
/**
|
||||
* Returns a stack-level singleton ARN (service token) for the custom resource provider.
|
||||
*/
|
||||
static getOrCreate(scope: Construct, uniqueid: string, props?: CustomResourceProviderOptions): string;
|
||||
/**
|
||||
* Returns a stack-level singleton for the custom resource provider.
|
||||
*/
|
||||
static getOrCreateProvider(scope: Construct, uniqueid: string, props?: CustomResourceProviderOptions): TriggerProvider;
|
||||
private constructor();
|
||||
}
|
||||
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/triggers/trigger-provider.generated.js
generated
vendored
Normal file
1
cdk/node_modules/aws-cdk-lib/custom-resource-handlers/dist/triggers/trigger-provider.generated.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.TriggerProvider=void 0;const path=require("path"),core_1=require("../../../core");class TriggerProvider extends core_1.CustomResourceProviderBase{static getOrCreate(scope,uniqueid,props){return this.getOrCreateProvider(scope,uniqueid,props).serviceToken}static getOrCreateProvider(scope,uniqueid,props){const id=`${uniqueid}CustomResourceProvider`,stack=core_1.Stack.of(scope);return stack.node.tryFindChild(id)??new TriggerProvider(stack,id,props)}constructor(scope,id,props){super(scope,id,{...props,codeDirectory:path.join(__dirname,"lambda"),runtimeName:(0,core_1.determineLatestNodeRuntimeName)(scope)}),this.node.addMetadata("aws:cdk:is-custom-resource-handler-customResourceProvider",!0)}}exports.TriggerProvider=TriggerProvider;
|
||||
Reference in New Issue
Block a user