From 48fba98f9ea5bab293f4c9e3ebc4f82da00f6a69 Mon Sep 17 00:00:00 2001 From: Braden Mars Date: Fri, 4 Oct 2024 13:02:21 -0500 Subject: [PATCH 01/13] feat(stacks.api/addons): implement `VerticalPodAutoscalerStackAddOn` to deploy vpa resources Signed-off-by: Braden Mars --- packages/stacks/api/src/addons/index.ts | 1 + .../api/src/addons/vertical-pod-autoscaler.ts | 38 +++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 packages/stacks/api/src/addons/vertical-pod-autoscaler.ts diff --git a/packages/stacks/api/src/addons/index.ts b/packages/stacks/api/src/addons/index.ts index 18f1d627..bf31d327 100644 --- a/packages/stacks/api/src/addons/index.ts +++ b/packages/stacks/api/src/addons/index.ts @@ -2,3 +2,4 @@ export * from './redis-stack' export * from './crisiscleanup' export * from './arc' export * from './kube-prometheus-stack' +export * from './vertical-pod-autoscaler' diff --git a/packages/stacks/api/src/addons/vertical-pod-autoscaler.ts b/packages/stacks/api/src/addons/vertical-pod-autoscaler.ts new file mode 100644 index 00000000..7dd0a8d0 --- /dev/null +++ b/packages/stacks/api/src/addons/vertical-pod-autoscaler.ts @@ -0,0 +1,38 @@ +import * as blueprints from '@aws-quickstart/eks-blueprints' +import { type Construct } from 'constructs' +import defu from 'defu' + +export interface VerticalPodAutoscalerStackAddOnProps + extends blueprints.HelmAddOnProps {} + +const vpaStackDefaults: VerticalPodAutoscalerStackAddOnProps = { + name: 'vertical-pod-autoscaler', + version: '9.9.0', + chart: 'vertical-pod-autoscaler', + namespace: 'kube-system', + release: 'vertical-pod-autoscaler', + repository: 'https://cowboysysop.github.io/charts', +} + +export class VerticalPodAutoscalerStackAddOn extends blueprints.HelmAddOn { + readonly props: VerticalPodAutoscalerStackAddOnProps + + constructor(props?: Partial) { + const withDefaults = defu( + props ?? {}, + vpaStackDefaults, + ) as VerticalPodAutoscalerStackAddOnProps + super(withDefaults) + this.props = withDefaults + } + + deploy(clusterInfo: blueprints.ClusterInfo): void | Promise { + return Promise.resolve( + this.addHelmChart( + clusterInfo, + this.props.values, + this.props.namespace !== 'kube-system', + ), + ) + } +} From 0c630c3a8020e872e962aa5c3e7fba8529d829a1 Mon Sep 17 00:00:00 2001 From: Braden Mars Date: Fri, 4 Oct 2024 13:09:05 -0500 Subject: [PATCH 02/13] test(stacks.api): add test for `VerticalPodAutoscalerAddon` Signed-off-by: Braden Mars --- .../api/test/__snapshots__/main.spec.ts.snap | 1856 +++++++++++++++++ packages/stacks/api/test/main.spec.ts | 33 +- 2 files changed, 1888 insertions(+), 1 deletion(-) diff --git a/packages/stacks/api/test/__snapshots__/main.spec.ts.snap b/packages/stacks/api/test/__snapshots__/main.spec.ts.snap index e58ae5a4..62d6ec91 100644 --- a/packages/stacks/api/test/__snapshots__/main.spec.ts.snap +++ b/packages/stacks/api/test/__snapshots__/main.spec.ts.snap @@ -4304,3 +4304,1859 @@ exports[`Snapshot 1`] = ` }, } `; + +exports[`VerticalPodAutoscalerAddon 1`] = ` +{ + "Conditions": { + "testvpastackHasEcrPublic0FD62BCC": { + "Fn::Equals": [ + { + "Ref": "AWS::Partition", + }, + "aws", + ], + }, + }, + "Description": "Blueprints tracking (qs-1s1r465hk)", + "Outputs": { + "testvpastackClusterName3B556AD6": { + "Value": { + "Ref": "testvpastackA44B24A4", + }, + }, + "testvpastackConfigCommand316A2FDA": { + "Value": { + "Fn::Join": [ + "", + [ + "aws eks update-kubeconfig --name ", + { + "Ref": "testvpastackA44B24A4", + }, + " --region us-east-1 --role-arn ", + { + "Fn::GetAtt": [ + "testvpastackAccessRole8A386431", + "Arn", + ], + }, + ], + ], + }, + }, + "testvpastackGetTokenCommand6255EA02": { + "Value": { + "Fn::Join": [ + "", + [ + "aws eks get-token --cluster-name ", + { + "Ref": "testvpastackA44B24A4", + }, + " --region us-east-1 --role-arn ", + { + "Fn::GetAtt": [ + "testvpastackAccessRole8A386431", + "Arn", + ], + }, + ], + ], + }, + }, + }, + "Parameters": { + "BootstrapVersion": { + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]", + "Type": "AWS::SSM::Parameter::Value", + }, + }, + "Resources": { + "awscdkawseksClusterResourceProviderNestedStackawscdkawseksClusterResourceProviderNestedStackResource9827C454": { + "DeletionPolicy": "Delete", + "Properties": { + "TemplateURL": { + "Fn::Join": [ + "", + [ + "https://s3.us-east-1.", + { + "Ref": "AWS::URLSuffix", + }, + "/cdk-hnb659fds-assets-1234567890-us-east-1/4bc80ff775abe98c1c926c54b831f8852c6c5561d8406ff9300f56e6aec20e6a.json", + ], + ], + }, + }, + "Type": "AWS::CloudFormation::Stack", + "UpdateReplacePolicy": "Delete", + }, + "awscdkawseksKubectlProviderNestedStackawscdkawseksKubectlProviderNestedStackResourceA7AEBA6B": { + "DeletionPolicy": "Delete", + "DependsOn": [ + "testvpastackvpcPrivateSubnet1DefaultRouteDB1163E7", + "testvpastackvpcPrivateSubnet1RouteTableAssociationB1567A03", + "testvpastackvpcPrivateSubnet2DefaultRoute084776BA", + "testvpastackvpcPrivateSubnet2RouteTableAssociationE95EDD63", + "testvpastackvpcPrivateSubnet3DefaultRoute2C6FEAE7", + "testvpastackvpcPrivateSubnet3RouteTableAssociation0188DDB9", + "testvpastackKubectlHandlerRoleDefaultPolicyD76393FE", + "testvpastackKubectlHandlerRole108ED1D6", + ], + "Properties": { + "Parameters": { + "referencetotestvpastack8CD69CC6ClusterSecurityGroupId": { + "Fn::GetAtt": [ + "testvpastackA44B24A4", + "ClusterSecurityGroupId", + ], + }, + "referencetotestvpastackKubectlHandlerRoleA756BA66Arn": { + "Fn::GetAtt": [ + "testvpastackKubectlHandlerRole108ED1D6", + "Arn", + ], + }, + "referencetotestvpastacktestvpastackvpcPrivateSubnet1Subnet90A30CA9Ref": { + "Ref": "testvpastackvpcPrivateSubnet1SubnetC54635A4", + }, + "referencetotestvpastacktestvpastackvpcPrivateSubnet2SubnetBF14062CRef": { + "Ref": "testvpastackvpcPrivateSubnet2Subnet75DEF204", + }, + "referencetotestvpastacktestvpastackvpcPrivateSubnet3Subnet8F497521Ref": { + "Ref": "testvpastackvpcPrivateSubnet3Subnet73275763", + }, + }, + "TemplateURL": { + "Fn::Join": [ + "", + [ + "https://s3.us-east-1.", + { + "Ref": "AWS::URLSuffix", + }, + "/cdk-hnb659fds-assets-1234567890-us-east-1/6d46c512a946ee5c90db3496adcc7cadf5dc059e88b86ba7342cbbe099a24c39.json", + ], + ], + }, + }, + "Type": "AWS::CloudFormation::Stack", + "UpdateReplacePolicy": "Delete", + }, + "kubectllayer275BD88CD2": { + "Properties": { + "Content": { + "S3Bucket": "cdk-hnb659fds-assets-1234567890-us-east-1", + "S3Key": "8e18eb5caccd2617fb76e648fa6a35dc0ece98c4681942bc6861f41afdff6a1b.zip", + }, + "Description": "/opt/kubectl/kubectl 1.27; /opt/helm/helm 3.12", + "LicenseInfo": "Apache-2.0", + }, + "Type": "AWS::Lambda::LayerVersion", + }, + "testvpastackA44B24A4": { + "DeletionPolicy": "Delete", + "DependsOn": [ + "testvpastackvpcIGW626F1E20", + "testvpastackvpcPrivateSubnet1DefaultRouteDB1163E7", + "testvpastackvpcPrivateSubnet1RouteTableDC248E4C", + "testvpastackvpcPrivateSubnet1RouteTableAssociationB1567A03", + "testvpastackvpcPrivateSubnet1SubnetC54635A4", + "testvpastackvpcPrivateSubnet2DefaultRoute084776BA", + "testvpastackvpcPrivateSubnet2RouteTableF950E7E4", + "testvpastackvpcPrivateSubnet2RouteTableAssociationE95EDD63", + "testvpastackvpcPrivateSubnet2Subnet75DEF204", + "testvpastackvpcPrivateSubnet3DefaultRoute2C6FEAE7", + "testvpastackvpcPrivateSubnet3RouteTable8B746899", + "testvpastackvpcPrivateSubnet3RouteTableAssociation0188DDB9", + "testvpastackvpcPrivateSubnet3Subnet73275763", + "testvpastackvpcPublicSubnet1DefaultRoute53D0CA69", + "testvpastackvpcPublicSubnet1EIP877A95D5", + "testvpastackvpcPublicSubnet1NATGatewayDECAD558", + "testvpastackvpcPublicSubnet1RouteTable8558F55A", + "testvpastackvpcPublicSubnet1RouteTableAssociation74FF9906", + "testvpastackvpcPublicSubnet1Subnet04627F09", + "testvpastackvpcPublicSubnet2DefaultRoute3FC28FBE", + "testvpastackvpcPublicSubnet2EIP6732590D", + "testvpastackvpcPublicSubnet2NATGateway68090B44", + "testvpastackvpcPublicSubnet2RouteTableB217972E", + "testvpastackvpcPublicSubnet2RouteTableAssociationED9522C4", + "testvpastackvpcPublicSubnet2SubnetA12075B4", + "testvpastackvpcPublicSubnet3DefaultRoute9DA5C897", + "testvpastackvpcPublicSubnet3EIPD9E40A79", + "testvpastackvpcPublicSubnet3NATGateway53C95A43", + "testvpastackvpcPublicSubnet3RouteTable601CC309", + "testvpastackvpcPublicSubnet3RouteTableAssociation2ADDB3AE", + "testvpastackvpcPublicSubnet3Subnet42F4C57D", + "testvpastackvpcDE690657", + "testvpastackvpcVPCGWB95BCDC6", + "testvpastackCreationRoleDefaultPolicyC5F5CF94", + "testvpastackCreationRole3D272630", + ], + "Properties": { + "AssumeRoleArn": { + "Fn::GetAtt": [ + "testvpastackCreationRole3D272630", + "Arn", + ], + }, + "AttributesRevision": 2, + "Config": { + "encryptionConfig": [ + { + "provider": { + "keyArn": { + "Fn::GetAtt": [ + "testvpastackkmskeyF167D305", + "Arn", + ], + }, + }, + "resources": [ + "secrets", + ], + }, + ], + "kubernetesNetworkConfig": { + "ipFamily": "ipv4", + }, + "name": "test-vpa-stack", + "resourcesVpcConfig": { + "endpointPrivateAccess": true, + "endpointPublicAccess": true, + "securityGroupIds": [ + { + "Fn::GetAtt": [ + "testvpastackControlPlaneSecurityGroup22F4EFCD", + "GroupId", + ], + }, + ], + "subnetIds": [ + { + "Ref": "testvpastackvpcPublicSubnet1Subnet04627F09", + }, + { + "Ref": "testvpastackvpcPublicSubnet2SubnetA12075B4", + }, + { + "Ref": "testvpastackvpcPublicSubnet3Subnet42F4C57D", + }, + { + "Ref": "testvpastackvpcPrivateSubnet1SubnetC54635A4", + }, + { + "Ref": "testvpastackvpcPrivateSubnet2Subnet75DEF204", + }, + { + "Ref": "testvpastackvpcPrivateSubnet3Subnet73275763", + }, + ], + }, + "roleArn": { + "Fn::GetAtt": [ + "testvpastackRole472FAAE9", + "Arn", + ], + }, + "version": "1.27", + }, + "ServiceToken": { + "Fn::GetAtt": [ + "awscdkawseksClusterResourceProviderNestedStackawscdkawseksClusterResourceProviderNestedStackResource9827C454", + "Outputs.testvpastackawscdkawseksClusterResourceProviderframeworkonEvent4C9A5815Arn", + ], + }, + }, + "Type": "Custom::AWSCDK-EKS-Cluster", + "UpdateReplacePolicy": "Delete", + }, + "testvpastackAccessRole8A386431": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::1234567890:root", + ], + ], + }, + }, + }, + ], + "Version": "2012-10-17", + }, + }, + "Type": "AWS::IAM::Role", + }, + "testvpastackAwsAuthmanifest6A043ECC": { + "DeletionPolicy": "Delete", + "DependsOn": [ + "testvpastackvpcIGW626F1E20", + "testvpastackvpcPrivateSubnet1DefaultRouteDB1163E7", + "testvpastackvpcPrivateSubnet1RouteTableDC248E4C", + "testvpastackvpcPrivateSubnet1RouteTableAssociationB1567A03", + "testvpastackvpcPrivateSubnet1SubnetC54635A4", + "testvpastackvpcPrivateSubnet2DefaultRoute084776BA", + "testvpastackvpcPrivateSubnet2RouteTableF950E7E4", + "testvpastackvpcPrivateSubnet2RouteTableAssociationE95EDD63", + "testvpastackvpcPrivateSubnet2Subnet75DEF204", + "testvpastackvpcPrivateSubnet3DefaultRoute2C6FEAE7", + "testvpastackvpcPrivateSubnet3RouteTable8B746899", + "testvpastackvpcPrivateSubnet3RouteTableAssociation0188DDB9", + "testvpastackvpcPrivateSubnet3Subnet73275763", + "testvpastackvpcPublicSubnet1DefaultRoute53D0CA69", + "testvpastackvpcPublicSubnet1EIP877A95D5", + "testvpastackvpcPublicSubnet1NATGatewayDECAD558", + "testvpastackvpcPublicSubnet1RouteTable8558F55A", + "testvpastackvpcPublicSubnet1RouteTableAssociation74FF9906", + "testvpastackvpcPublicSubnet1Subnet04627F09", + "testvpastackvpcPublicSubnet2DefaultRoute3FC28FBE", + "testvpastackvpcPublicSubnet2EIP6732590D", + "testvpastackvpcPublicSubnet2NATGateway68090B44", + "testvpastackvpcPublicSubnet2RouteTableB217972E", + "testvpastackvpcPublicSubnet2RouteTableAssociationED9522C4", + "testvpastackvpcPublicSubnet2SubnetA12075B4", + "testvpastackvpcPublicSubnet3DefaultRoute9DA5C897", + "testvpastackvpcPublicSubnet3EIPD9E40A79", + "testvpastackvpcPublicSubnet3NATGateway53C95A43", + "testvpastackvpcPublicSubnet3RouteTable601CC309", + "testvpastackvpcPublicSubnet3RouteTableAssociation2ADDB3AE", + "testvpastackvpcPublicSubnet3Subnet42F4C57D", + "testvpastackvpcDE690657", + "testvpastackvpcVPCGWB95BCDC6", + "testvpastackKubectlReadyBarrier59EC1861", + ], + "Properties": { + "ClusterName": { + "Ref": "testvpastackA44B24A4", + }, + "Manifest": { + "Fn::Join": [ + "", + [ + "[{\\"apiVersion\\":\\"v1\\",\\"kind\\":\\"ConfigMap\\",\\"metadata\\":{\\"name\\":\\"aws-auth\\",\\"namespace\\":\\"kube-system\\",\\"labels\\":{\\"aws.cdk.eks/prune-c8ea8e708b3c427b825a1b3445e0d83c4e9b341d40\\":\\"\\"}},\\"data\\":{\\"mapRoles\\":\\"[{\\\\\\"rolearn\\\\\\":\\\\\\"", + { + "Fn::GetAtt": [ + "testvpastackAccessRole8A386431", + "Arn", + ], + }, + "\\\\\\",\\\\\\"username\\\\\\":\\\\\\"", + { + "Fn::GetAtt": [ + "testvpastackAccessRole8A386431", + "Arn", + ], + }, + "\\\\\\",\\\\\\"groups\\\\\\":[\\\\\\"system:masters\\\\\\"]},{\\\\\\"rolearn\\\\\\":\\\\\\"", + { + "Fn::GetAtt": [ + "testvpastackfargateprofileserverlessPodExecutionRole7C68BDC1", + "Arn", + ], + }, + "\\\\\\",\\\\\\"username\\\\\\":\\\\\\"system:node:{{SessionName}}\\\\\\",\\\\\\"groups\\\\\\":[\\\\\\"system:bootstrappers\\\\\\",\\\\\\"system:nodes\\\\\\",\\\\\\"system:node-proxier\\\\\\"]}]\\",\\"mapUsers\\":\\"[]\\",\\"mapAccounts\\":\\"[]\\"}}]", + ], + ], + }, + "Overwrite": true, + "PruneLabel": "aws.cdk.eks/prune-c8ea8e708b3c427b825a1b3445e0d83c4e9b341d40", + "RoleArn": { + "Fn::GetAtt": [ + "testvpastackCreationRole3D272630", + "Arn", + ], + }, + "ServiceToken": { + "Fn::GetAtt": [ + "awscdkawseksKubectlProviderNestedStackawscdkawseksKubectlProviderNestedStackResourceA7AEBA6B", + "Outputs.testvpastackawscdkawseksKubectlProviderframeworkonEventB682DB3CArn", + ], + }, + }, + "Type": "Custom::AWSCDK-EKS-KubernetesResource", + "UpdateReplacePolicy": "Delete", + }, + "testvpastackControlPlaneSecurityGroup22F4EFCD": { + "DependsOn": [ + "testvpastackvpcIGW626F1E20", + "testvpastackvpcPrivateSubnet1DefaultRouteDB1163E7", + "testvpastackvpcPrivateSubnet1RouteTableDC248E4C", + "testvpastackvpcPrivateSubnet1RouteTableAssociationB1567A03", + "testvpastackvpcPrivateSubnet1SubnetC54635A4", + "testvpastackvpcPrivateSubnet2DefaultRoute084776BA", + "testvpastackvpcPrivateSubnet2RouteTableF950E7E4", + "testvpastackvpcPrivateSubnet2RouteTableAssociationE95EDD63", + "testvpastackvpcPrivateSubnet2Subnet75DEF204", + "testvpastackvpcPrivateSubnet3DefaultRoute2C6FEAE7", + "testvpastackvpcPrivateSubnet3RouteTable8B746899", + "testvpastackvpcPrivateSubnet3RouteTableAssociation0188DDB9", + "testvpastackvpcPrivateSubnet3Subnet73275763", + "testvpastackvpcPublicSubnet1DefaultRoute53D0CA69", + "testvpastackvpcPublicSubnet1EIP877A95D5", + "testvpastackvpcPublicSubnet1NATGatewayDECAD558", + "testvpastackvpcPublicSubnet1RouteTable8558F55A", + "testvpastackvpcPublicSubnet1RouteTableAssociation74FF9906", + "testvpastackvpcPublicSubnet1Subnet04627F09", + "testvpastackvpcPublicSubnet2DefaultRoute3FC28FBE", + "testvpastackvpcPublicSubnet2EIP6732590D", + "testvpastackvpcPublicSubnet2NATGateway68090B44", + "testvpastackvpcPublicSubnet2RouteTableB217972E", + "testvpastackvpcPublicSubnet2RouteTableAssociationED9522C4", + "testvpastackvpcPublicSubnet2SubnetA12075B4", + "testvpastackvpcPublicSubnet3DefaultRoute9DA5C897", + "testvpastackvpcPublicSubnet3EIPD9E40A79", + "testvpastackvpcPublicSubnet3NATGateway53C95A43", + "testvpastackvpcPublicSubnet3RouteTable601CC309", + "testvpastackvpcPublicSubnet3RouteTableAssociation2ADDB3AE", + "testvpastackvpcPublicSubnet3Subnet42F4C57D", + "testvpastackvpcDE690657", + "testvpastackvpcVPCGWB95BCDC6", + ], + "Properties": { + "GroupDescription": "EKS Control Plane Security Group", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1", + }, + ], + "VpcId": { + "Ref": "testvpastackvpcDE690657", + }, + }, + "Type": "AWS::EC2::SecurityGroup", + }, + "testvpastackCreationRole3D272630": { + "DependsOn": [ + "testvpastackvpcIGW626F1E20", + "testvpastackvpcPrivateSubnet1DefaultRouteDB1163E7", + "testvpastackvpcPrivateSubnet1RouteTableDC248E4C", + "testvpastackvpcPrivateSubnet1RouteTableAssociationB1567A03", + "testvpastackvpcPrivateSubnet1SubnetC54635A4", + "testvpastackvpcPrivateSubnet2DefaultRoute084776BA", + "testvpastackvpcPrivateSubnet2RouteTableF950E7E4", + "testvpastackvpcPrivateSubnet2RouteTableAssociationE95EDD63", + "testvpastackvpcPrivateSubnet2Subnet75DEF204", + "testvpastackvpcPrivateSubnet3DefaultRoute2C6FEAE7", + "testvpastackvpcPrivateSubnet3RouteTable8B746899", + "testvpastackvpcPrivateSubnet3RouteTableAssociation0188DDB9", + "testvpastackvpcPrivateSubnet3Subnet73275763", + "testvpastackvpcPublicSubnet1DefaultRoute53D0CA69", + "testvpastackvpcPublicSubnet1EIP877A95D5", + "testvpastackvpcPublicSubnet1NATGatewayDECAD558", + "testvpastackvpcPublicSubnet1RouteTable8558F55A", + "testvpastackvpcPublicSubnet1RouteTableAssociation74FF9906", + "testvpastackvpcPublicSubnet1Subnet04627F09", + "testvpastackvpcPublicSubnet2DefaultRoute3FC28FBE", + "testvpastackvpcPublicSubnet2EIP6732590D", + "testvpastackvpcPublicSubnet2NATGateway68090B44", + "testvpastackvpcPublicSubnet2RouteTableB217972E", + "testvpastackvpcPublicSubnet2RouteTableAssociationED9522C4", + "testvpastackvpcPublicSubnet2SubnetA12075B4", + "testvpastackvpcPublicSubnet3DefaultRoute9DA5C897", + "testvpastackvpcPublicSubnet3EIPD9E40A79", + "testvpastackvpcPublicSubnet3NATGateway53C95A43", + "testvpastackvpcPublicSubnet3RouteTable601CC309", + "testvpastackvpcPublicSubnet3RouteTableAssociation2ADDB3AE", + "testvpastackvpcPublicSubnet3Subnet42F4C57D", + "testvpastackvpcDE690657", + "testvpastackvpcVPCGWB95BCDC6", + ], + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::GetAtt": [ + "awscdkawseksClusterResourceProviderNestedStackawscdkawseksClusterResourceProviderNestedStackResource9827C454", + "Outputs.testvpastackawscdkawseksClusterResourceProviderOnEventHandlerServiceRole0D588D6CArn", + ], + }, + }, + }, + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::GetAtt": [ + "awscdkawseksClusterResourceProviderNestedStackawscdkawseksClusterResourceProviderNestedStackResource9827C454", + "Outputs.testvpastackawscdkawseksClusterResourceProviderIsCompleteHandlerServiceRoleFE1BD10DArn", + ], + }, + }, + }, + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::GetAtt": [ + "testvpastackKubectlHandlerRole108ED1D6", + "Arn", + ], + }, + }, + }, + ], + "Version": "2012-10-17", + }, + }, + "Type": "AWS::IAM::Role", + }, + "testvpastackCreationRoleDefaultPolicyC5F5CF94": { + "DependsOn": [ + "testvpastackvpcIGW626F1E20", + "testvpastackvpcPrivateSubnet1DefaultRouteDB1163E7", + "testvpastackvpcPrivateSubnet1RouteTableDC248E4C", + "testvpastackvpcPrivateSubnet1RouteTableAssociationB1567A03", + "testvpastackvpcPrivateSubnet1SubnetC54635A4", + "testvpastackvpcPrivateSubnet2DefaultRoute084776BA", + "testvpastackvpcPrivateSubnet2RouteTableF950E7E4", + "testvpastackvpcPrivateSubnet2RouteTableAssociationE95EDD63", + "testvpastackvpcPrivateSubnet2Subnet75DEF204", + "testvpastackvpcPrivateSubnet3DefaultRoute2C6FEAE7", + "testvpastackvpcPrivateSubnet3RouteTable8B746899", + "testvpastackvpcPrivateSubnet3RouteTableAssociation0188DDB9", + "testvpastackvpcPrivateSubnet3Subnet73275763", + "testvpastackvpcPublicSubnet1DefaultRoute53D0CA69", + "testvpastackvpcPublicSubnet1EIP877A95D5", + "testvpastackvpcPublicSubnet1NATGatewayDECAD558", + "testvpastackvpcPublicSubnet1RouteTable8558F55A", + "testvpastackvpcPublicSubnet1RouteTableAssociation74FF9906", + "testvpastackvpcPublicSubnet1Subnet04627F09", + "testvpastackvpcPublicSubnet2DefaultRoute3FC28FBE", + "testvpastackvpcPublicSubnet2EIP6732590D", + "testvpastackvpcPublicSubnet2NATGateway68090B44", + "testvpastackvpcPublicSubnet2RouteTableB217972E", + "testvpastackvpcPublicSubnet2RouteTableAssociationED9522C4", + "testvpastackvpcPublicSubnet2SubnetA12075B4", + "testvpastackvpcPublicSubnet3DefaultRoute9DA5C897", + "testvpastackvpcPublicSubnet3EIPD9E40A79", + "testvpastackvpcPublicSubnet3NATGateway53C95A43", + "testvpastackvpcPublicSubnet3RouteTable601CC309", + "testvpastackvpcPublicSubnet3RouteTableAssociation2ADDB3AE", + "testvpastackvpcPublicSubnet3Subnet42F4C57D", + "testvpastackvpcDE690657", + "testvpastackvpcVPCGWB95BCDC6", + ], + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "iam:PassRole", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "testvpastackRole472FAAE9", + "Arn", + ], + }, + }, + { + "Action": [ + "eks:CreateCluster", + "eks:DescribeCluster", + "eks:DescribeUpdate", + "eks:DeleteCluster", + "eks:UpdateClusterVersion", + "eks:UpdateClusterConfig", + "eks:CreateFargateProfile", + "eks:TagResource", + "eks:UntagResource", + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":eks:us-east-1:1234567890:cluster/test-vpa-stack", + ], + ], + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":eks:us-east-1:1234567890:cluster/test-vpa-stack/*", + ], + ], + }, + ], + }, + { + "Action": [ + "eks:DescribeFargateProfile", + "eks:DeleteFargateProfile", + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":eks:us-east-1:1234567890:fargateprofile/test-vpa-stack/*", + ], + ], + }, + }, + { + "Action": [ + "iam:GetRole", + "iam:listAttachedRolePolicies", + ], + "Effect": "Allow", + "Resource": "*", + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Effect": "Allow", + "Resource": "*", + }, + { + "Action": [ + "ec2:DescribeInstances", + "ec2:DescribeNetworkInterfaces", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeRouteTables", + "ec2:DescribeDhcpOptions", + "ec2:DescribeVpcs", + ], + "Effect": "Allow", + "Resource": "*", + }, + { + "Action": [ + "kms:Encrypt", + "kms:Decrypt", + "kms:DescribeKey", + "kms:CreateGrant", + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "testvpastackkmskeyF167D305", + "Arn", + ], + }, + }, + { + "Action": "iam:PassRole", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "testvpastackfargateprofileserverlessPodExecutionRole7C68BDC1", + "Arn", + ], + }, + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "testvpastackCreationRoleDefaultPolicyC5F5CF94", + "Roles": [ + { + "Ref": "testvpastackCreationRole3D272630", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "testvpastackKubectlHandlerRole108ED1D6": { + "DependsOn": [ + "testvpastackvpcIGW626F1E20", + "testvpastackvpcPrivateSubnet1DefaultRouteDB1163E7", + "testvpastackvpcPrivateSubnet1RouteTableDC248E4C", + "testvpastackvpcPrivateSubnet1RouteTableAssociationB1567A03", + "testvpastackvpcPrivateSubnet1SubnetC54635A4", + "testvpastackvpcPrivateSubnet2DefaultRoute084776BA", + "testvpastackvpcPrivateSubnet2RouteTableF950E7E4", + "testvpastackvpcPrivateSubnet2RouteTableAssociationE95EDD63", + "testvpastackvpcPrivateSubnet2Subnet75DEF204", + "testvpastackvpcPrivateSubnet3DefaultRoute2C6FEAE7", + "testvpastackvpcPrivateSubnet3RouteTable8B746899", + "testvpastackvpcPrivateSubnet3RouteTableAssociation0188DDB9", + "testvpastackvpcPrivateSubnet3Subnet73275763", + "testvpastackvpcPublicSubnet1DefaultRoute53D0CA69", + "testvpastackvpcPublicSubnet1EIP877A95D5", + "testvpastackvpcPublicSubnet1NATGatewayDECAD558", + "testvpastackvpcPublicSubnet1RouteTable8558F55A", + "testvpastackvpcPublicSubnet1RouteTableAssociation74FF9906", + "testvpastackvpcPublicSubnet1Subnet04627F09", + "testvpastackvpcPublicSubnet2DefaultRoute3FC28FBE", + "testvpastackvpcPublicSubnet2EIP6732590D", + "testvpastackvpcPublicSubnet2NATGateway68090B44", + "testvpastackvpcPublicSubnet2RouteTableB217972E", + "testvpastackvpcPublicSubnet2RouteTableAssociationED9522C4", + "testvpastackvpcPublicSubnet2SubnetA12075B4", + "testvpastackvpcPublicSubnet3DefaultRoute9DA5C897", + "testvpastackvpcPublicSubnet3EIPD9E40A79", + "testvpastackvpcPublicSubnet3NATGateway53C95A43", + "testvpastackvpcPublicSubnet3RouteTable601CC309", + "testvpastackvpcPublicSubnet3RouteTableAssociation2ADDB3AE", + "testvpastackvpcPublicSubnet3Subnet42F4C57D", + "testvpastackvpcDE690657", + "testvpastackvpcVPCGWB95BCDC6", + ], + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + ], + ], + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole", + ], + ], + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly", + ], + ], + }, + { + "Fn::If": [ + "testvpastackHasEcrPublic0FD62BCC", + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly", + ], + ], + }, + { + "Ref": "AWS::NoValue", + }, + ], + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "testvpastackKubectlHandlerRoleDefaultPolicyD76393FE": { + "DependsOn": [ + "testvpastackvpcIGW626F1E20", + "testvpastackvpcPrivateSubnet1DefaultRouteDB1163E7", + "testvpastackvpcPrivateSubnet1RouteTableDC248E4C", + "testvpastackvpcPrivateSubnet1RouteTableAssociationB1567A03", + "testvpastackvpcPrivateSubnet1SubnetC54635A4", + "testvpastackvpcPrivateSubnet2DefaultRoute084776BA", + "testvpastackvpcPrivateSubnet2RouteTableF950E7E4", + "testvpastackvpcPrivateSubnet2RouteTableAssociationE95EDD63", + "testvpastackvpcPrivateSubnet2Subnet75DEF204", + "testvpastackvpcPrivateSubnet3DefaultRoute2C6FEAE7", + "testvpastackvpcPrivateSubnet3RouteTable8B746899", + "testvpastackvpcPrivateSubnet3RouteTableAssociation0188DDB9", + "testvpastackvpcPrivateSubnet3Subnet73275763", + "testvpastackvpcPublicSubnet1DefaultRoute53D0CA69", + "testvpastackvpcPublicSubnet1EIP877A95D5", + "testvpastackvpcPublicSubnet1NATGatewayDECAD558", + "testvpastackvpcPublicSubnet1RouteTable8558F55A", + "testvpastackvpcPublicSubnet1RouteTableAssociation74FF9906", + "testvpastackvpcPublicSubnet1Subnet04627F09", + "testvpastackvpcPublicSubnet2DefaultRoute3FC28FBE", + "testvpastackvpcPublicSubnet2EIP6732590D", + "testvpastackvpcPublicSubnet2NATGateway68090B44", + "testvpastackvpcPublicSubnet2RouteTableB217972E", + "testvpastackvpcPublicSubnet2RouteTableAssociationED9522C4", + "testvpastackvpcPublicSubnet2SubnetA12075B4", + "testvpastackvpcPublicSubnet3DefaultRoute9DA5C897", + "testvpastackvpcPublicSubnet3EIPD9E40A79", + "testvpastackvpcPublicSubnet3NATGateway53C95A43", + "testvpastackvpcPublicSubnet3RouteTable601CC309", + "testvpastackvpcPublicSubnet3RouteTableAssociation2ADDB3AE", + "testvpastackvpcPublicSubnet3Subnet42F4C57D", + "testvpastackvpcDE690657", + "testvpastackvpcVPCGWB95BCDC6", + ], + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "eks:DescribeCluster", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "testvpastackA44B24A4", + "Arn", + ], + }, + }, + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "testvpastackCreationRole3D272630", + "Arn", + ], + }, + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "testvpastackKubectlHandlerRoleDefaultPolicyD76393FE", + "Roles": [ + { + "Ref": "testvpastackKubectlHandlerRole108ED1D6", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "testvpastackKubectlReadyBarrier59EC1861": { + "DependsOn": [ + "testvpastackvpcIGW626F1E20", + "testvpastackvpcPrivateSubnet1DefaultRouteDB1163E7", + "testvpastackvpcPrivateSubnet1RouteTableDC248E4C", + "testvpastackvpcPrivateSubnet1RouteTableAssociationB1567A03", + "testvpastackvpcPrivateSubnet1SubnetC54635A4", + "testvpastackvpcPrivateSubnet2DefaultRoute084776BA", + "testvpastackvpcPrivateSubnet2RouteTableF950E7E4", + "testvpastackvpcPrivateSubnet2RouteTableAssociationE95EDD63", + "testvpastackvpcPrivateSubnet2Subnet75DEF204", + "testvpastackvpcPrivateSubnet3DefaultRoute2C6FEAE7", + "testvpastackvpcPrivateSubnet3RouteTable8B746899", + "testvpastackvpcPrivateSubnet3RouteTableAssociation0188DDB9", + "testvpastackvpcPrivateSubnet3Subnet73275763", + "testvpastackvpcPublicSubnet1DefaultRoute53D0CA69", + "testvpastackvpcPublicSubnet1EIP877A95D5", + "testvpastackvpcPublicSubnet1NATGatewayDECAD558", + "testvpastackvpcPublicSubnet1RouteTable8558F55A", + "testvpastackvpcPublicSubnet1RouteTableAssociation74FF9906", + "testvpastackvpcPublicSubnet1Subnet04627F09", + "testvpastackvpcPublicSubnet2DefaultRoute3FC28FBE", + "testvpastackvpcPublicSubnet2EIP6732590D", + "testvpastackvpcPublicSubnet2NATGateway68090B44", + "testvpastackvpcPublicSubnet2RouteTableB217972E", + "testvpastackvpcPublicSubnet2RouteTableAssociationED9522C4", + "testvpastackvpcPublicSubnet2SubnetA12075B4", + "testvpastackvpcPublicSubnet3DefaultRoute9DA5C897", + "testvpastackvpcPublicSubnet3EIPD9E40A79", + "testvpastackvpcPublicSubnet3NATGateway53C95A43", + "testvpastackvpcPublicSubnet3RouteTable601CC309", + "testvpastackvpcPublicSubnet3RouteTableAssociation2ADDB3AE", + "testvpastackvpcPublicSubnet3Subnet42F4C57D", + "testvpastackvpcDE690657", + "testvpastackvpcVPCGWB95BCDC6", + "testvpastackfargateprofileserverlessPodExecutionRole7C68BDC1", + "testvpastackfargateprofileserverlessCA08010C", + "testvpastackCreationRoleDefaultPolicyC5F5CF94", + "testvpastackCreationRole3D272630", + "testvpastackA44B24A4", + ], + "Properties": { + "Type": "String", + "Value": "aws:cdk:eks:kubectl-ready", + }, + "Type": "AWS::SSM::Parameter", + }, + "testvpastackRole472FAAE9": { + "DependsOn": [ + "testvpastackvpcIGW626F1E20", + "testvpastackvpcPrivateSubnet1DefaultRouteDB1163E7", + "testvpastackvpcPrivateSubnet1RouteTableDC248E4C", + "testvpastackvpcPrivateSubnet1RouteTableAssociationB1567A03", + "testvpastackvpcPrivateSubnet1SubnetC54635A4", + "testvpastackvpcPrivateSubnet2DefaultRoute084776BA", + "testvpastackvpcPrivateSubnet2RouteTableF950E7E4", + "testvpastackvpcPrivateSubnet2RouteTableAssociationE95EDD63", + "testvpastackvpcPrivateSubnet2Subnet75DEF204", + "testvpastackvpcPrivateSubnet3DefaultRoute2C6FEAE7", + "testvpastackvpcPrivateSubnet3RouteTable8B746899", + "testvpastackvpcPrivateSubnet3RouteTableAssociation0188DDB9", + "testvpastackvpcPrivateSubnet3Subnet73275763", + "testvpastackvpcPublicSubnet1DefaultRoute53D0CA69", + "testvpastackvpcPublicSubnet1EIP877A95D5", + "testvpastackvpcPublicSubnet1NATGatewayDECAD558", + "testvpastackvpcPublicSubnet1RouteTable8558F55A", + "testvpastackvpcPublicSubnet1RouteTableAssociation74FF9906", + "testvpastackvpcPublicSubnet1Subnet04627F09", + "testvpastackvpcPublicSubnet2DefaultRoute3FC28FBE", + "testvpastackvpcPublicSubnet2EIP6732590D", + "testvpastackvpcPublicSubnet2NATGateway68090B44", + "testvpastackvpcPublicSubnet2RouteTableB217972E", + "testvpastackvpcPublicSubnet2RouteTableAssociationED9522C4", + "testvpastackvpcPublicSubnet2SubnetA12075B4", + "testvpastackvpcPublicSubnet3DefaultRoute9DA5C897", + "testvpastackvpcPublicSubnet3EIPD9E40A79", + "testvpastackvpcPublicSubnet3NATGateway53C95A43", + "testvpastackvpcPublicSubnet3RouteTable601CC309", + "testvpastackvpcPublicSubnet3RouteTableAssociation2ADDB3AE", + "testvpastackvpcPublicSubnet3Subnet42F4C57D", + "testvpastackvpcDE690657", + "testvpastackvpcVPCGWB95BCDC6", + ], + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "eks.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/AmazonEKSClusterPolicy", + ], + ], + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "testvpastackchartverticalpodautoscaler72E5B2F6": { + "DeletionPolicy": "Delete", + "DependsOn": [ + "testvpastackvpcIGW626F1E20", + "testvpastackvpcPrivateSubnet1DefaultRouteDB1163E7", + "testvpastackvpcPrivateSubnet1RouteTableDC248E4C", + "testvpastackvpcPrivateSubnet1RouteTableAssociationB1567A03", + "testvpastackvpcPrivateSubnet1SubnetC54635A4", + "testvpastackvpcPrivateSubnet2DefaultRoute084776BA", + "testvpastackvpcPrivateSubnet2RouteTableF950E7E4", + "testvpastackvpcPrivateSubnet2RouteTableAssociationE95EDD63", + "testvpastackvpcPrivateSubnet2Subnet75DEF204", + "testvpastackvpcPrivateSubnet3DefaultRoute2C6FEAE7", + "testvpastackvpcPrivateSubnet3RouteTable8B746899", + "testvpastackvpcPrivateSubnet3RouteTableAssociation0188DDB9", + "testvpastackvpcPrivateSubnet3Subnet73275763", + "testvpastackvpcPublicSubnet1DefaultRoute53D0CA69", + "testvpastackvpcPublicSubnet1EIP877A95D5", + "testvpastackvpcPublicSubnet1NATGatewayDECAD558", + "testvpastackvpcPublicSubnet1RouteTable8558F55A", + "testvpastackvpcPublicSubnet1RouteTableAssociation74FF9906", + "testvpastackvpcPublicSubnet1Subnet04627F09", + "testvpastackvpcPublicSubnet2DefaultRoute3FC28FBE", + "testvpastackvpcPublicSubnet2EIP6732590D", + "testvpastackvpcPublicSubnet2NATGateway68090B44", + "testvpastackvpcPublicSubnet2RouteTableB217972E", + "testvpastackvpcPublicSubnet2RouteTableAssociationED9522C4", + "testvpastackvpcPublicSubnet2SubnetA12075B4", + "testvpastackvpcPublicSubnet3DefaultRoute9DA5C897", + "testvpastackvpcPublicSubnet3EIPD9E40A79", + "testvpastackvpcPublicSubnet3NATGateway53C95A43", + "testvpastackvpcPublicSubnet3RouteTable601CC309", + "testvpastackvpcPublicSubnet3RouteTableAssociation2ADDB3AE", + "testvpastackvpcPublicSubnet3Subnet42F4C57D", + "testvpastackvpcDE690657", + "testvpastackvpcVPCGWB95BCDC6", + "testvpastackKubectlReadyBarrier59EC1861", + ], + "Properties": { + "Chart": "vertical-pod-autoscaler", + "ClusterName": { + "Ref": "testvpastackA44B24A4", + }, + "Namespace": "kube-system", + "Release": "vertical-pod-autoscaler", + "Repository": "https://cowboysysop.github.io/charts", + "RoleArn": { + "Fn::GetAtt": [ + "testvpastackCreationRole3D272630", + "Arn", + ], + }, + "ServiceToken": { + "Fn::GetAtt": [ + "awscdkawseksKubectlProviderNestedStackawscdkawseksKubectlProviderNestedStackResourceA7AEBA6B", + "Outputs.testvpastackawscdkawseksKubectlProviderframeworkonEventB682DB3CArn", + ], + }, + "Values": "{}", + "Version": "9.9.0", + }, + "Type": "Custom::AWSCDK-EKS-HelmChart", + "UpdateReplacePolicy": "Delete", + }, + "testvpastackfargateprofileserverlessCA08010C": { + "DeletionPolicy": "Delete", + "DependsOn": [ + "testvpastackvpcIGW626F1E20", + "testvpastackvpcPrivateSubnet1DefaultRouteDB1163E7", + "testvpastackvpcPrivateSubnet1RouteTableDC248E4C", + "testvpastackvpcPrivateSubnet1RouteTableAssociationB1567A03", + "testvpastackvpcPrivateSubnet1SubnetC54635A4", + "testvpastackvpcPrivateSubnet2DefaultRoute084776BA", + "testvpastackvpcPrivateSubnet2RouteTableF950E7E4", + "testvpastackvpcPrivateSubnet2RouteTableAssociationE95EDD63", + "testvpastackvpcPrivateSubnet2Subnet75DEF204", + "testvpastackvpcPrivateSubnet3DefaultRoute2C6FEAE7", + "testvpastackvpcPrivateSubnet3RouteTable8B746899", + "testvpastackvpcPrivateSubnet3RouteTableAssociation0188DDB9", + "testvpastackvpcPrivateSubnet3Subnet73275763", + "testvpastackvpcPublicSubnet1DefaultRoute53D0CA69", + "testvpastackvpcPublicSubnet1EIP877A95D5", + "testvpastackvpcPublicSubnet1NATGatewayDECAD558", + "testvpastackvpcPublicSubnet1RouteTable8558F55A", + "testvpastackvpcPublicSubnet1RouteTableAssociation74FF9906", + "testvpastackvpcPublicSubnet1Subnet04627F09", + "testvpastackvpcPublicSubnet2DefaultRoute3FC28FBE", + "testvpastackvpcPublicSubnet2EIP6732590D", + "testvpastackvpcPublicSubnet2NATGateway68090B44", + "testvpastackvpcPublicSubnet2RouteTableB217972E", + "testvpastackvpcPublicSubnet2RouteTableAssociationED9522C4", + "testvpastackvpcPublicSubnet2SubnetA12075B4", + "testvpastackvpcPublicSubnet3DefaultRoute9DA5C897", + "testvpastackvpcPublicSubnet3EIPD9E40A79", + "testvpastackvpcPublicSubnet3NATGateway53C95A43", + "testvpastackvpcPublicSubnet3RouteTable601CC309", + "testvpastackvpcPublicSubnet3RouteTableAssociation2ADDB3AE", + "testvpastackvpcPublicSubnet3Subnet42F4C57D", + "testvpastackvpcDE690657", + "testvpastackvpcVPCGWB95BCDC6", + ], + "Properties": { + "AssumeRoleArn": { + "Fn::GetAtt": [ + "testvpastackCreationRole3D272630", + "Arn", + ], + }, + "Config": { + "clusterName": { + "Ref": "testvpastackA44B24A4", + }, + "podExecutionRoleArn": { + "Fn::GetAtt": [ + "testvpastackfargateprofileserverlessPodExecutionRole7C68BDC1", + "Arn", + ], + }, + "selectors": [ + { + "namespace": "karpenter", + }, + { + "namespace": "cert-manager", + }, + ], + "subnets": [ + { + "Ref": "testvpastackvpcPrivateSubnet1SubnetC54635A4", + }, + { + "Ref": "testvpastackvpcPrivateSubnet2Subnet75DEF204", + }, + { + "Ref": "testvpastackvpcPrivateSubnet3Subnet73275763", + }, + ], + }, + "ServiceToken": { + "Fn::GetAtt": [ + "awscdkawseksClusterResourceProviderNestedStackawscdkawseksClusterResourceProviderNestedStackResource9827C454", + "Outputs.testvpastackawscdkawseksClusterResourceProviderframeworkonEvent4C9A5815Arn", + ], + }, + }, + "Type": "Custom::AWSCDK-EKS-FargateProfile", + "UpdateReplacePolicy": "Delete", + }, + "testvpastackfargateprofileserverlessPodExecutionRole7C68BDC1": { + "DependsOn": [ + "testvpastackvpcIGW626F1E20", + "testvpastackvpcPrivateSubnet1DefaultRouteDB1163E7", + "testvpastackvpcPrivateSubnet1RouteTableDC248E4C", + "testvpastackvpcPrivateSubnet1RouteTableAssociationB1567A03", + "testvpastackvpcPrivateSubnet1SubnetC54635A4", + "testvpastackvpcPrivateSubnet2DefaultRoute084776BA", + "testvpastackvpcPrivateSubnet2RouteTableF950E7E4", + "testvpastackvpcPrivateSubnet2RouteTableAssociationE95EDD63", + "testvpastackvpcPrivateSubnet2Subnet75DEF204", + "testvpastackvpcPrivateSubnet3DefaultRoute2C6FEAE7", + "testvpastackvpcPrivateSubnet3RouteTable8B746899", + "testvpastackvpcPrivateSubnet3RouteTableAssociation0188DDB9", + "testvpastackvpcPrivateSubnet3Subnet73275763", + "testvpastackvpcPublicSubnet1DefaultRoute53D0CA69", + "testvpastackvpcPublicSubnet1EIP877A95D5", + "testvpastackvpcPublicSubnet1NATGatewayDECAD558", + "testvpastackvpcPublicSubnet1RouteTable8558F55A", + "testvpastackvpcPublicSubnet1RouteTableAssociation74FF9906", + "testvpastackvpcPublicSubnet1Subnet04627F09", + "testvpastackvpcPublicSubnet2DefaultRoute3FC28FBE", + "testvpastackvpcPublicSubnet2EIP6732590D", + "testvpastackvpcPublicSubnet2NATGateway68090B44", + "testvpastackvpcPublicSubnet2RouteTableB217972E", + "testvpastackvpcPublicSubnet2RouteTableAssociationED9522C4", + "testvpastackvpcPublicSubnet2SubnetA12075B4", + "testvpastackvpcPublicSubnet3DefaultRoute9DA5C897", + "testvpastackvpcPublicSubnet3EIPD9E40A79", + "testvpastackvpcPublicSubnet3NATGateway53C95A43", + "testvpastackvpcPublicSubnet3RouteTable601CC309", + "testvpastackvpcPublicSubnet3RouteTableAssociation2ADDB3AE", + "testvpastackvpcPublicSubnet3Subnet42F4C57D", + "testvpastackvpcDE690657", + "testvpastackvpcVPCGWB95BCDC6", + ], + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "eks-fargate-pods.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/AmazonEKSFargatePodExecutionRolePolicy", + ], + ], + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "testvpastackkmskeyF167D305": { + "DeletionPolicy": "Retain", + "Properties": { + "Description": "Key for EKS Cluster 'test-vpa-stack'", + "KeyPolicy": { + "Statement": [ + { + "Action": "kms:*", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::1234567890:root", + ], + ], + }, + }, + "Resource": "*", + }, + ], + "Version": "2012-10-17", + }, + }, + "Type": "AWS::KMS::Key", + "UpdateReplacePolicy": "Retain", + }, + "testvpastackvpcDE690657": { + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default", + "Tags": [ + { + "Key": "Name", + "Value": "test-vpa-stack/test-vpa-stack-vpc", + }, + ], + }, + "Type": "AWS::EC2::VPC", + }, + "testvpastackvpcIGW626F1E20": { + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "test-vpa-stack/test-vpa-stack-vpc", + }, + ], + }, + "Type": "AWS::EC2::InternetGateway", + }, + "testvpastackvpcPrivateSubnet1DefaultRouteDB1163E7": { + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "testvpastackvpcPublicSubnet1NATGatewayDECAD558", + }, + "RouteTableId": { + "Ref": "testvpastackvpcPrivateSubnet1RouteTableDC248E4C", + }, + }, + "Type": "AWS::EC2::Route", + }, + "testvpastackvpcPrivateSubnet1RouteTableAssociationB1567A03": { + "Properties": { + "RouteTableId": { + "Ref": "testvpastackvpcPrivateSubnet1RouteTableDC248E4C", + }, + "SubnetId": { + "Ref": "testvpastackvpcPrivateSubnet1SubnetC54635A4", + }, + }, + "Type": "AWS::EC2::SubnetRouteTableAssociation", + }, + "testvpastackvpcPrivateSubnet1RouteTableDC248E4C": { + "Properties": { + "Tags": [ + { + "Key": "kubernetes.io/role/internal-elb", + "Value": "1", + }, + { + "Key": "Name", + "Value": "test-vpa-stack/test-vpa-stack-vpc/PrivateSubnet1", + }, + ], + "VpcId": { + "Ref": "testvpastackvpcDE690657", + }, + }, + "Type": "AWS::EC2::RouteTable", + }, + "testvpastackvpcPrivateSubnet1SubnetC54635A4": { + "Properties": { + "AvailabilityZone": "dummy1a", + "CidrBlock": "10.0.96.0/19", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private", + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private", + }, + { + "Key": "kubernetes.io/role/internal-elb", + "Value": "1", + }, + { + "Key": "Name", + "Value": "test-vpa-stack/test-vpa-stack-vpc/PrivateSubnet1", + }, + ], + "VpcId": { + "Ref": "testvpastackvpcDE690657", + }, + }, + "Type": "AWS::EC2::Subnet", + }, + "testvpastackvpcPrivateSubnet2DefaultRoute084776BA": { + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "testvpastackvpcPublicSubnet2NATGateway68090B44", + }, + "RouteTableId": { + "Ref": "testvpastackvpcPrivateSubnet2RouteTableF950E7E4", + }, + }, + "Type": "AWS::EC2::Route", + }, + "testvpastackvpcPrivateSubnet2RouteTableAssociationE95EDD63": { + "Properties": { + "RouteTableId": { + "Ref": "testvpastackvpcPrivateSubnet2RouteTableF950E7E4", + }, + "SubnetId": { + "Ref": "testvpastackvpcPrivateSubnet2Subnet75DEF204", + }, + }, + "Type": "AWS::EC2::SubnetRouteTableAssociation", + }, + "testvpastackvpcPrivateSubnet2RouteTableF950E7E4": { + "Properties": { + "Tags": [ + { + "Key": "kubernetes.io/role/internal-elb", + "Value": "1", + }, + { + "Key": "Name", + "Value": "test-vpa-stack/test-vpa-stack-vpc/PrivateSubnet2", + }, + ], + "VpcId": { + "Ref": "testvpastackvpcDE690657", + }, + }, + "Type": "AWS::EC2::RouteTable", + }, + "testvpastackvpcPrivateSubnet2Subnet75DEF204": { + "Properties": { + "AvailabilityZone": "dummy1b", + "CidrBlock": "10.0.128.0/19", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private", + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private", + }, + { + "Key": "kubernetes.io/role/internal-elb", + "Value": "1", + }, + { + "Key": "Name", + "Value": "test-vpa-stack/test-vpa-stack-vpc/PrivateSubnet2", + }, + ], + "VpcId": { + "Ref": "testvpastackvpcDE690657", + }, + }, + "Type": "AWS::EC2::Subnet", + }, + "testvpastackvpcPrivateSubnet3DefaultRoute2C6FEAE7": { + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "testvpastackvpcPublicSubnet3NATGateway53C95A43", + }, + "RouteTableId": { + "Ref": "testvpastackvpcPrivateSubnet3RouteTable8B746899", + }, + }, + "Type": "AWS::EC2::Route", + }, + "testvpastackvpcPrivateSubnet3RouteTable8B746899": { + "Properties": { + "Tags": [ + { + "Key": "kubernetes.io/role/internal-elb", + "Value": "1", + }, + { + "Key": "Name", + "Value": "test-vpa-stack/test-vpa-stack-vpc/PrivateSubnet3", + }, + ], + "VpcId": { + "Ref": "testvpastackvpcDE690657", + }, + }, + "Type": "AWS::EC2::RouteTable", + }, + "testvpastackvpcPrivateSubnet3RouteTableAssociation0188DDB9": { + "Properties": { + "RouteTableId": { + "Ref": "testvpastackvpcPrivateSubnet3RouteTable8B746899", + }, + "SubnetId": { + "Ref": "testvpastackvpcPrivateSubnet3Subnet73275763", + }, + }, + "Type": "AWS::EC2::SubnetRouteTableAssociation", + }, + "testvpastackvpcPrivateSubnet3Subnet73275763": { + "Properties": { + "AvailabilityZone": "dummy1c", + "CidrBlock": "10.0.160.0/19", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private", + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private", + }, + { + "Key": "kubernetes.io/role/internal-elb", + "Value": "1", + }, + { + "Key": "Name", + "Value": "test-vpa-stack/test-vpa-stack-vpc/PrivateSubnet3", + }, + ], + "VpcId": { + "Ref": "testvpastackvpcDE690657", + }, + }, + "Type": "AWS::EC2::Subnet", + }, + "testvpastackvpcPublicSubnet1DefaultRoute53D0CA69": { + "DependsOn": [ + "testvpastackvpcVPCGWB95BCDC6", + ], + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "testvpastackvpcIGW626F1E20", + }, + "RouteTableId": { + "Ref": "testvpastackvpcPublicSubnet1RouteTable8558F55A", + }, + }, + "Type": "AWS::EC2::Route", + }, + "testvpastackvpcPublicSubnet1EIP877A95D5": { + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "kubernetes.io/role/elb", + "Value": "1", + }, + { + "Key": "Name", + "Value": "test-vpa-stack/test-vpa-stack-vpc/PublicSubnet1", + }, + ], + }, + "Type": "AWS::EC2::EIP", + }, + "testvpastackvpcPublicSubnet1NATGatewayDECAD558": { + "DependsOn": [ + "testvpastackvpcPublicSubnet1DefaultRoute53D0CA69", + "testvpastackvpcPublicSubnet1RouteTableAssociation74FF9906", + ], + "Properties": { + "AllocationId": { + "Fn::GetAtt": [ + "testvpastackvpcPublicSubnet1EIP877A95D5", + "AllocationId", + ], + }, + "SubnetId": { + "Ref": "testvpastackvpcPublicSubnet1Subnet04627F09", + }, + "Tags": [ + { + "Key": "kubernetes.io/role/elb", + "Value": "1", + }, + { + "Key": "Name", + "Value": "test-vpa-stack/test-vpa-stack-vpc/PublicSubnet1", + }, + ], + }, + "Type": "AWS::EC2::NatGateway", + }, + "testvpastackvpcPublicSubnet1RouteTable8558F55A": { + "Properties": { + "Tags": [ + { + "Key": "kubernetes.io/role/elb", + "Value": "1", + }, + { + "Key": "Name", + "Value": "test-vpa-stack/test-vpa-stack-vpc/PublicSubnet1", + }, + ], + "VpcId": { + "Ref": "testvpastackvpcDE690657", + }, + }, + "Type": "AWS::EC2::RouteTable", + }, + "testvpastackvpcPublicSubnet1RouteTableAssociation74FF9906": { + "Properties": { + "RouteTableId": { + "Ref": "testvpastackvpcPublicSubnet1RouteTable8558F55A", + }, + "SubnetId": { + "Ref": "testvpastackvpcPublicSubnet1Subnet04627F09", + }, + }, + "Type": "AWS::EC2::SubnetRouteTableAssociation", + }, + "testvpastackvpcPublicSubnet1Subnet04627F09": { + "Properties": { + "AvailabilityZone": "dummy1a", + "CidrBlock": "10.0.0.0/19", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public", + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public", + }, + { + "Key": "kubernetes.io/role/elb", + "Value": "1", + }, + { + "Key": "Name", + "Value": "test-vpa-stack/test-vpa-stack-vpc/PublicSubnet1", + }, + ], + "VpcId": { + "Ref": "testvpastackvpcDE690657", + }, + }, + "Type": "AWS::EC2::Subnet", + }, + "testvpastackvpcPublicSubnet2DefaultRoute3FC28FBE": { + "DependsOn": [ + "testvpastackvpcVPCGWB95BCDC6", + ], + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "testvpastackvpcIGW626F1E20", + }, + "RouteTableId": { + "Ref": "testvpastackvpcPublicSubnet2RouteTableB217972E", + }, + }, + "Type": "AWS::EC2::Route", + }, + "testvpastackvpcPublicSubnet2EIP6732590D": { + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "kubernetes.io/role/elb", + "Value": "1", + }, + { + "Key": "Name", + "Value": "test-vpa-stack/test-vpa-stack-vpc/PublicSubnet2", + }, + ], + }, + "Type": "AWS::EC2::EIP", + }, + "testvpastackvpcPublicSubnet2NATGateway68090B44": { + "DependsOn": [ + "testvpastackvpcPublicSubnet2DefaultRoute3FC28FBE", + "testvpastackvpcPublicSubnet2RouteTableAssociationED9522C4", + ], + "Properties": { + "AllocationId": { + "Fn::GetAtt": [ + "testvpastackvpcPublicSubnet2EIP6732590D", + "AllocationId", + ], + }, + "SubnetId": { + "Ref": "testvpastackvpcPublicSubnet2SubnetA12075B4", + }, + "Tags": [ + { + "Key": "kubernetes.io/role/elb", + "Value": "1", + }, + { + "Key": "Name", + "Value": "test-vpa-stack/test-vpa-stack-vpc/PublicSubnet2", + }, + ], + }, + "Type": "AWS::EC2::NatGateway", + }, + "testvpastackvpcPublicSubnet2RouteTableAssociationED9522C4": { + "Properties": { + "RouteTableId": { + "Ref": "testvpastackvpcPublicSubnet2RouteTableB217972E", + }, + "SubnetId": { + "Ref": "testvpastackvpcPublicSubnet2SubnetA12075B4", + }, + }, + "Type": "AWS::EC2::SubnetRouteTableAssociation", + }, + "testvpastackvpcPublicSubnet2RouteTableB217972E": { + "Properties": { + "Tags": [ + { + "Key": "kubernetes.io/role/elb", + "Value": "1", + }, + { + "Key": "Name", + "Value": "test-vpa-stack/test-vpa-stack-vpc/PublicSubnet2", + }, + ], + "VpcId": { + "Ref": "testvpastackvpcDE690657", + }, + }, + "Type": "AWS::EC2::RouteTable", + }, + "testvpastackvpcPublicSubnet2SubnetA12075B4": { + "Properties": { + "AvailabilityZone": "dummy1b", + "CidrBlock": "10.0.32.0/19", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public", + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public", + }, + { + "Key": "kubernetes.io/role/elb", + "Value": "1", + }, + { + "Key": "Name", + "Value": "test-vpa-stack/test-vpa-stack-vpc/PublicSubnet2", + }, + ], + "VpcId": { + "Ref": "testvpastackvpcDE690657", + }, + }, + "Type": "AWS::EC2::Subnet", + }, + "testvpastackvpcPublicSubnet3DefaultRoute9DA5C897": { + "DependsOn": [ + "testvpastackvpcVPCGWB95BCDC6", + ], + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "testvpastackvpcIGW626F1E20", + }, + "RouteTableId": { + "Ref": "testvpastackvpcPublicSubnet3RouteTable601CC309", + }, + }, + "Type": "AWS::EC2::Route", + }, + "testvpastackvpcPublicSubnet3EIPD9E40A79": { + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "kubernetes.io/role/elb", + "Value": "1", + }, + { + "Key": "Name", + "Value": "test-vpa-stack/test-vpa-stack-vpc/PublicSubnet3", + }, + ], + }, + "Type": "AWS::EC2::EIP", + }, + "testvpastackvpcPublicSubnet3NATGateway53C95A43": { + "DependsOn": [ + "testvpastackvpcPublicSubnet3DefaultRoute9DA5C897", + "testvpastackvpcPublicSubnet3RouteTableAssociation2ADDB3AE", + ], + "Properties": { + "AllocationId": { + "Fn::GetAtt": [ + "testvpastackvpcPublicSubnet3EIPD9E40A79", + "AllocationId", + ], + }, + "SubnetId": { + "Ref": "testvpastackvpcPublicSubnet3Subnet42F4C57D", + }, + "Tags": [ + { + "Key": "kubernetes.io/role/elb", + "Value": "1", + }, + { + "Key": "Name", + "Value": "test-vpa-stack/test-vpa-stack-vpc/PublicSubnet3", + }, + ], + }, + "Type": "AWS::EC2::NatGateway", + }, + "testvpastackvpcPublicSubnet3RouteTable601CC309": { + "Properties": { + "Tags": [ + { + "Key": "kubernetes.io/role/elb", + "Value": "1", + }, + { + "Key": "Name", + "Value": "test-vpa-stack/test-vpa-stack-vpc/PublicSubnet3", + }, + ], + "VpcId": { + "Ref": "testvpastackvpcDE690657", + }, + }, + "Type": "AWS::EC2::RouteTable", + }, + "testvpastackvpcPublicSubnet3RouteTableAssociation2ADDB3AE": { + "Properties": { + "RouteTableId": { + "Ref": "testvpastackvpcPublicSubnet3RouteTable601CC309", + }, + "SubnetId": { + "Ref": "testvpastackvpcPublicSubnet3Subnet42F4C57D", + }, + }, + "Type": "AWS::EC2::SubnetRouteTableAssociation", + }, + "testvpastackvpcPublicSubnet3Subnet42F4C57D": { + "Properties": { + "AvailabilityZone": "dummy1c", + "CidrBlock": "10.0.64.0/19", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public", + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public", + }, + { + "Key": "kubernetes.io/role/elb", + "Value": "1", + }, + { + "Key": "Name", + "Value": "test-vpa-stack/test-vpa-stack-vpc/PublicSubnet3", + }, + ], + "VpcId": { + "Ref": "testvpastackvpcDE690657", + }, + }, + "Type": "AWS::EC2::Subnet", + }, + "testvpastackvpcVPCGWB95BCDC6": { + "Properties": { + "InternetGatewayId": { + "Ref": "testvpastackvpcIGW626F1E20", + }, + "VpcId": { + "Ref": "testvpastackvpcDE690657", + }, + }, + "Type": "AWS::EC2::VPCGatewayAttachment", + }, + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5", + ], + { + "Ref": "BootstrapVersion", + }, + ], + }, + ], + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI.", + }, + ], + }, + }, +} +`; diff --git a/packages/stacks/api/test/main.spec.ts b/packages/stacks/api/test/main.spec.ts index 1affccc2..e73e977e 100644 --- a/packages/stacks/api/test/main.spec.ts +++ b/packages/stacks/api/test/main.spec.ts @@ -13,7 +13,10 @@ import { KubernetesVersion } from 'aws-cdk-lib/aws-eks' import { type IConstruct } from 'constructs' import { test, expect, vi, beforeAll, afterAll } from 'vitest' import stackDefaults from '../crisiscleanup.config' -import { CrisisCleanupAddOn } from '../src/addons' +import { + CrisisCleanupAddOn, + VerticalPodAutoscalerStackAddOn, +} from '../src/addons' import { buildClusterBuilder, getCoreAddons, @@ -83,3 +86,31 @@ test('Snapshot', async () => { const template = Template.fromStack(stack) expect(template.toJSON()).toMatchSnapshot() }) + +test('VerticalPodAutoscalerAddon', async () => { + // @ts-expect-error ignore test + const config: CrisisCleanupConfig = getConfigDefaults({ + ...stackDefaults, + ...chartDefaults, + cdkEnvironment: { + account: '1234567890', + region: 'us-east-1', + }, + }) + console.log(config) + const app = new App({ + context: { + config, + 'giget-auth': 'fake-token', + }, + }) + const cluster = buildClusterBuilder(config.apiStack!.eks.k8s.version).build() + const stack = await blueprints.EksBlueprint.builder() + .version(KubernetesVersion.of(config.apiStack!.eks.k8s.version)) + .addOns(new VerticalPodAutoscalerStackAddOn()) + .clusterProvider(cluster) + .buildAsync(app, 'test-vpa-stack') + + const template = Template.fromStack(stack) + expect(template.toJSON()).toMatchSnapshot() +}) From 678ba1399e1af60ca261061c659517052a4e8eb9 Mon Sep 17 00:00:00 2001 From: Braden Mars Date: Fri, 4 Oct 2024 14:43:28 -0500 Subject: [PATCH 03/13] feat(stacks.api): add `VerticalPodAutoscalerStackAddOn` to cluster by default Signed-off-by: Braden Mars --- packages/stacks/api/src/pipeline.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/stacks/api/src/pipeline.ts b/packages/stacks/api/src/pipeline.ts index b421740b..ee240ef0 100644 --- a/packages/stacks/api/src/pipeline.ts +++ b/packages/stacks/api/src/pipeline.ts @@ -20,7 +20,7 @@ import * as lambda from 'aws-cdk-lib/aws-lambda' import { type GitHubEnvironment, StackCapabilities } from 'cdk-pipelines-github' import type { Construct } from 'constructs' -import { CrisisCleanupAddOn } from './addons' +import { CrisisCleanupAddOn, VerticalPodAutoscalerStackAddOn } from './addons' import { buildClusterBuilder, buildKarpenter, @@ -276,6 +276,7 @@ export class Pipeline { undefined, config.apiStack!.eks.instanceTypes ?? undefined, ), + new VerticalPodAutoscalerStackAddOn(), new CrisisCleanupAddOn({ config, secretsProvider, From 94e031ab3931b11e78146dd14f6e43991c34cc9e Mon Sep 17 00:00:00 2001 From: Braden Mars Date: Fri, 4 Oct 2024 14:44:21 -0500 Subject: [PATCH 04/13] feat(k8s.construct.component): implement `VerticalPodAutoscaler` resource, interfaces Signed-off-by: Braden Mars --- .../component/src/vertical-pod-autoscaler.ts | 206 ++++++++++++++++++ 1 file changed, 206 insertions(+) create mode 100644 packages/k8s/construct/component/src/vertical-pod-autoscaler.ts diff --git a/packages/k8s/construct/component/src/vertical-pod-autoscaler.ts b/packages/k8s/construct/component/src/vertical-pod-autoscaler.ts new file mode 100644 index 00000000..52ac6918 --- /dev/null +++ b/packages/k8s/construct/component/src/vertical-pod-autoscaler.ts @@ -0,0 +1,206 @@ +import { ApiObject, Lazy, type Size } from 'cdk8s' +import * as kplus from 'cdk8s-plus-27' +import { type Construct } from 'constructs' + +export interface VerticalPodAutoscalerProps extends kplus.ResourceProps { + /** + * The workload to scale up or down. + * + * Scalable workload types: + * * Deployment + * * StatefulSet + */ + readonly target: kplus.IScalable + /** + * The update mode for the VPA. + * + * Possible values are 'Off', 'Initial', 'Auto'. + * @default - 'Auto' + */ + readonly updateMode?: 'Off' | 'Initial' | 'Auto' + /** + * The resource policy for the VPA. + */ + readonly resourcePolicy?: ResourcePolicy +} + +export interface ResourcePolicy { + /** + * Container policies for resource adjustments. + */ + readonly containerPolicies: ContainerPolicy[] +} + +export interface ContainerPolicy { + /** + * The name of the container. + */ + readonly containerName: string + /** + * The minimum allowed resources. + */ + readonly minAllowed?: ResourceLimits + /** + * The maximum allowed resources. + */ + readonly maxAllowed?: ResourceLimits +} + +export interface ResourceLimits { + /** + * CPU limit. + */ + readonly cpu?: kplus.Cpu + /** + * Memory limit. + */ + readonly memory?: Size +} + +export interface ResourceLimitsSpec { + /** + * CPU limit. + */ + readonly cpu?: string + /** + * Memory limit. + */ + readonly memory?: string +} + +export interface KubeVerticalPodAutoscalerSpec { + /** + * Reference to the target resource to scale. + */ + readonly targetRef: { + apiVersion: string + kind: string + name: string + } + /** + * Update policy for the VPA. + */ + readonly updatePolicy: { + updateMode: 'Off' | 'Initial' | 'Auto' + } + /** + * Resource policy for the VPA. + */ + readonly resourcePolicy?: { + containerPolicies: { + containerName: string + minAllowed?: ResourceLimitsSpec + maxAllowed?: ResourceLimitsSpec + }[] + } +} + +/** + * Represents a Vertical Pod Autoscaler (VPA) resource in Kubernetes. + * + * The VerticalPodAutoscaler automatically adjusts the resources requested by + * a pod's containers based on historical CPU and memory usage. + * + * Depends on availability of the Vertical Pod Autoscaler API in the cluster. + * + */ +export class VerticalPodAutoscaler extends kplus.Resource { + /** + * @see base.Resource.apiObject + */ + protected readonly apiObject: ApiObject + public readonly resourceType = 'VerticalPodAutoscaler' + /** + * The workload to scale up or down. + */ + public readonly target: kplus.IScalable + /** + * The update mode for the VPA. + */ + public readonly updateMode: 'Off' | 'Initial' | 'Auto' + /** + * Container policies for the VPA. + */ + public readonly containerPolicies: ContainerPolicy[] + + constructor(scope: Construct, id: string, props: VerticalPodAutoscalerProps) { + super(scope, id) + + this.target = props.target + this.updateMode = props.updateMode ?? 'Auto' + this.containerPolicies = props.resourcePolicy?.containerPolicies ?? [] + + // this.target.markHasAutoscaler() + + this.apiObject = new ApiObject(this, 'Resource', { + apiVersion: 'autoscaling.k8s.io/v1', + kind: 'VerticalPodAutoscaler', + metadata: props.metadata, + spec: Lazy.any({ + produce: () => this._toKube(), + }) as KubeVerticalPodAutoscalerSpec, + }) + } + + /** + * Resource policy for the VPA. + */ + public get resourcePolicy(): ResourcePolicy | undefined { + return this.containerPolicies.length + ? { + containerPolicies: this.containerPolicies, + } + : undefined + } + + /** + * @internal + */ + public _toKube(): KubeVerticalPodAutoscalerSpec { + const scalingTarget = this.target.toScalingTarget() + return { + targetRef: { + apiVersion: scalingTarget.apiVersion, + kind: scalingTarget.kind, + name: scalingTarget.name, + }, + updatePolicy: { + updateMode: this.updateMode, + }, + resourcePolicy: this.resourcePolicy + ? { + containerPolicies: this.resourcePolicy.containerPolicies.map( + (policy) => ({ + containerName: policy.containerName, + minAllowed: policy.minAllowed + ? { + cpu: policy.minAllowed.cpu?.amount, + memory: policy.minAllowed.memory + ? `${policy.minAllowed.memory.toMebibytes()}Mi` + : undefined, + } + : undefined, + maxAllowed: policy.maxAllowed + ? { + cpu: policy.maxAllowed.cpu?.amount, + memory: policy.maxAllowed.memory + ? `${policy.maxAllowed.memory.toMebibytes()}Mi` + : undefined, + } + : undefined, + }), + ), + } + : undefined, + } + } + + /** + * Add a container policy to the resource policy. + * @param policy The container policy to add. + */ + public addContainerPolicy(policy: ContainerPolicy): this { + this.containerPolicies.push(policy) + return this + } +} From 899946eb81dcf9f93da92edaf3bdb349962c6ab9 Mon Sep 17 00:00:00 2001 From: Braden Mars Date: Fri, 4 Oct 2024 17:10:49 -0500 Subject: [PATCH 05/13] feat(k8s.construct.component): implement `verticalScaling` options to `ApiComponent` for deploying a VPA Signed-off-by: Braden Mars --- .../k8s/construct/component/src/component.ts | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/packages/k8s/construct/component/src/component.ts b/packages/k8s/construct/component/src/component.ts index 8576ccbd..14768290 100644 --- a/packages/k8s/construct/component/src/component.ts +++ b/packages/k8s/construct/component/src/component.ts @@ -8,6 +8,11 @@ import { ContainerImage, type ContainerImageProps } from './container-image' import { Label } from './labels' import { PodDisruptionBudget, type PodDisruptionBudgetProps } from './pdb' import { ComponentScaling, type ComponentScalingProps } from './scaling' +import { + VerticalPodAutoscaler, + type ContainerPolicy, + type ResourceLimits, +} from './vertical-pod-autoscaler' const debug = createDebug('@crisiscleanup:k8s.construct.component') @@ -27,6 +32,11 @@ export interface ContainerResourceProps { } } +export interface VerticalAutoscalingDeploymentProps { + enabled?: boolean + policies?: ContainerPolicy[] +} + const K8sMillicores = z .number() .describe('Kubernetes CPU Millicores') @@ -57,6 +67,28 @@ const resourcesSchema = z .describe('Kubernetes resource limits/requests') .partial() +/** + * @see https://github.com/colinhacks/zod/issues/384 + */ +const CpuInstanceSchema = z.custom( + (data) => data instanceof kplus.Cpu, +) +const SizeInstanceSchema = z.custom((data) => data instanceof Size) + +const resourcesRangeSchema = z + .object({ + cpu: z.union([CpuInstanceSchema, K8sMillicores]).optional(), + memory: z.union([SizeInstanceSchema, K8sMemoryMebibytes]).optional(), + }) + .describe('Resource limits for vertical scaling.') + .partial() + .pipe( + z.object({ + cpu: CpuInstanceSchema.optional(), + memory: SizeInstanceSchema.optional(), + }), + ) + export interface DeploymentProps extends kplus.WorkloadProps { replicaCount?: number image?: ContainerImageProps @@ -64,6 +96,7 @@ export interface DeploymentProps extends kplus.WorkloadProps { scaling?: ComponentScalingProps containerDefaults?: Partial resources?: ContainerResourceProps + verticalScaling?: VerticalAutoscalingDeploymentProps } export type ComponentContainerProps = Omit & { @@ -75,6 +108,7 @@ export class Component { static componentName: string = '' readonly deployment: kplus.Deployment readonly scaling?: ComponentScaling = undefined + readonly vpa?: VerticalPodAutoscaler = undefined readonly node: Node #containers: Map = new Map() @@ -109,6 +143,26 @@ export class Component { target: this.deployment, }) } + if (props.verticalScaling?.enabled) { + this.vpa = new VerticalPodAutoscaler(this.scope, this.id + '-VPA', { + target: this.deployment, + resourcePolicy: props.verticalScaling?.policies + ? { + containerPolicies: props.verticalScaling?.policies?.map?.( + ({ containerName, minAllowed, maxAllowed }) => ({ + containerName, + minAllowed: minAllowed + ? (resourcesRangeSchema.parse(minAllowed) as ResourceLimits) + : undefined, + maxAllowed: maxAllowed + ? (resourcesRangeSchema.parse(maxAllowed) as ResourceLimits) + : undefined, + }), + ), + } + : undefined, + }) + } this.node = this.deployment.node } From f8782d20841372d0884a95f14f310fed0f6af97d Mon Sep 17 00:00:00 2001 From: Braden Mars Date: Fri, 4 Oct 2024 17:11:15 -0500 Subject: [PATCH 06/13] feat(charts.crisiscleanup): add `verticalScaling` to config schema Signed-off-by: Braden Mars --- packages/charts/crisiscleanup/src/schema.ts | 51 +++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/packages/charts/crisiscleanup/src/schema.ts b/packages/charts/crisiscleanup/src/schema.ts index 8f3b378d..67bb24be 100644 --- a/packages/charts/crisiscleanup/src/schema.ts +++ b/packages/charts/crisiscleanup/src/schema.ts @@ -1,3 +1,5 @@ +import { Size } from 'cdk8s' +import * as kplus from 'cdk8s-plus-27' import { z } from 'zod' const ImagePullPolicyEnum = z.enum(['Always', 'Never', 'IfNotPresent']) @@ -12,9 +14,22 @@ const containerImageSchema = z const metricPercent = z.number().min(0).max(100) +/** + * @see https://github.com/colinhacks/zod/issues/384 + */ +const CpuInstanceSchema = z.custom( + (data) => data instanceof kplus.Cpu, +) +const SizeInstanceSchema = z.custom((data) => data instanceof Size) + const K8sMillicores = z.number().describe('Kubernetes CPU Millicores') const K8sMemoryMebibytes = z.number().describe('Kubernetes Memory Mebibytes') +const K8sMillicoresToCpu = K8sMillicores.transform((v) => kplus.Cpu.millis(v)) +const K8sMemoryMebibytesToSize = K8sMemoryMebibytes.transform((v) => + Size.mebibytes(v), +) + const resourcesSchema = z .object({ cpu: z.object({ @@ -46,10 +61,46 @@ const scalingSchema = z .describe('Horizontal Autoscaling Parameters') .passthrough() +const resourcesRangeSchema = z + .object({ + cpu: z.union([CpuInstanceSchema, K8sMillicoresToCpu]).optional(), + memory: z.union([SizeInstanceSchema, K8sMemoryMebibytesToSize]).optional(), + }) + .describe('Resource limits for vertical scaling.') + .partial() + .pipe( + z.object({ + cpu: CpuInstanceSchema.optional(), + memory: SizeInstanceSchema.optional(), + }), + ) + .describe('Resource limits for vertical scaling.') + +const verticalScalingContainerPolicySchema = z + .object({ + containerName: z + .string() + .describe('Name or pattern of containers to target.'), + minAllowed: resourcesRangeSchema.optional(), + maxAllowed: resourcesRangeSchema.optional(), + }) + .describe('Container policy for resource adjustments.') + +const verticalScalingSchema = z + .object({ + enabled: z.boolean().default(true), + policies: z + .array(verticalScalingContainerPolicySchema) + .optional() + .describe('Container policies for resource adjustments.'), + }) + .describe('Vertical Pod Autoscaler Configuration') + const deploymentSchema = z.object({ image: containerImageSchema.optional(), spread: z.boolean().default(false), resources: resourcesSchema.optional(), + verticalScaling: verticalScalingSchema.optional(), }) const withScaling = (inSchema: T) => From 87d0ed3a412d8f1166e35303943f826a9a78a6a3 Mon Sep 17 00:00:00 2001 From: Braden Mars Date: Fri, 4 Oct 2024 17:11:37 -0500 Subject: [PATCH 07/13] test(charts.crisiscleanup): add unit test with vertical scaling Signed-off-by: Braden Mars --- .../charts/crisiscleanup/test/main.spec.ts | 34 +++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/packages/charts/crisiscleanup/test/main.spec.ts b/packages/charts/crisiscleanup/test/main.spec.ts index e04d54a1..df472cf3 100644 --- a/packages/charts/crisiscleanup/test/main.spec.ts +++ b/packages/charts/crisiscleanup/test/main.spec.ts @@ -1,6 +1,6 @@ import { baseConfig } from '@crisiscleanup/config' -import { type App, Chart, Testing } from 'cdk8s' -import { ImagePullPolicy } from 'cdk8s-plus-27' +import { type App, Chart, Size, Testing } from 'cdk8s' +import { Cpu, ImagePullPolicy } from 'cdk8s-plus-27' import defu from 'defu' import { describe, expect, it } from 'vitest' import defaultChartConfig from '../crisiscleanup.config' @@ -66,6 +66,36 @@ const propCases: [ }, }, ], + [ + 'with vertical scaling', + { + asgi: { + spread: true, + replicaCount: 4, + verticalScaling: { enabled: true }, + }, + wsgi: { + spread: true, + replicaCount: 4, + verticalScaling: { + enabled: true, + policies: [ + { + containerName: '*', + minAllowed: { + cpu: Cpu.millis(500), + memory: Size.mebibytes(1200), + }, + maxAllowed: { + cpu: Cpu.units(3), + memory: Size.gibibytes(3), + }, + }, + ], + }, + }, + }, + ], ] describe.each(propCases)('CrisisCleanupChart: %o', (caseName, props, keys) => { From 795c52743305fffc0e941f2bf4ecdcd2391a3ae0 Mon Sep 17 00:00:00 2001 From: Braden Mars Date: Fri, 4 Oct 2024 17:11:48 -0500 Subject: [PATCH 08/13] test(charts.crisiscleanup): update snapshots Signed-off-by: Braden Mars --- .../test/__snapshots__/main.spec.ts.snap | 1535 +++++++++++++++++ 1 file changed, 1535 insertions(+) diff --git a/packages/charts/crisiscleanup/test/__snapshots__/main.spec.ts.snap b/packages/charts/crisiscleanup/test/__snapshots__/main.spec.ts.snap index e136425c..d27ffcc5 100644 --- a/packages/charts/crisiscleanup/test/__snapshots__/main.spec.ts.snap +++ b/packages/charts/crisiscleanup/test/__snapshots__/main.spec.ts.snap @@ -4681,3 +4681,1538 @@ exports[`CrisisCleanupChart: 'with sync' > sync matches snapshot > with sync-syn }, ] `; + +exports[`CrisisCleanupChart: 'with vertical scaling' > api matches snapshot > with vertical scaling-api 1`] = ` +[ + { + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app.kubernetes.io/component": "api", + "app.kubernetes.io/name": "wsgi", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-api-wsgi", + "namespace": "test", + }, + "spec": { + "minReadySeconds": 0, + "progressDeadlineSeconds": 600, + "replicas": 4, + "selector": { + "matchLabels": { + "cdk8s.io/metadata.addr": "crisiscleanup-api-wsgi-c83e828d", + }, + }, + "strategy": { + "rollingUpdate": { + "maxSurge": "25%", + "maxUnavailable": "25%", + }, + "type": "RollingUpdate", + }, + "template": { + "metadata": { + "labels": { + "cdk8s.io/metadata.addr": "crisiscleanup-api-wsgi-c83e828d", + }, + }, + "spec": { + "automountServiceAccountToken": false, + "containers": [ + { + "command": [ + "/serve.sh", + "wsgi", + "--workers=2", + "--threads=4", + "--worker-class=gthread", + "--worker-tmp-dir=/worker-tmp", + "--timeout=90", + ], + "envFrom": [ + { + "configMapRef": { + "name": "crisiscleanup-config-api-config", + }, + }, + ], + "image": "test-api:test", + "imagePullPolicy": "Always", + "livenessProbe": { + "failureThreshold": 30, + "httpGet": { + "path": "/health", + "port": 5000, + "scheme": "HTTP", + }, + "initialDelaySeconds": 20, + "periodSeconds": 10, + "timeoutSeconds": 8, + }, + "name": "gunicorn", + "ports": [ + { + "containerPort": 5000, + }, + ], + "readinessProbe": { + "failureThreshold": 30, + "httpGet": { + "path": "/health", + "port": 5000, + "scheme": "HTTP", + }, + "initialDelaySeconds": 20, + "periodSeconds": 10, + "timeoutSeconds": 8, + }, + "resources": { + "limits": { + "cpu": "1800m", + "memory": "1200Mi", + }, + "requests": { + "cpu": "1000m", + "memory": "1200Mi", + }, + }, + "securityContext": { + "allowPrivilegeEscalation": false, + "privileged": false, + "readOnlyRootFilesystem": false, + "runAsGroup": 1000, + "runAsNonRoot": true, + "runAsUser": 1000, + }, + "startupProbe": { + "failureThreshold": 30, + "httpGet": { + "path": "/health", + "port": 5000, + "scheme": "HTTP", + }, + "periodSeconds": 15, + }, + "volumeMounts": [ + { + "mountPath": "/app/staticfiles", + "name": "staticfiles", + }, + { + "mountPath": "/worker-tmp", + "name": "worker-tmp", + }, + ], + }, + ], + "dnsPolicy": "ClusterFirst", + "hostNetwork": false, + "restartPolicy": "Always", + "securityContext": { + "fsGroupChangePolicy": "Always", + "runAsNonRoot": true, + }, + "setHostnameAsFQDN": false, + "terminationGracePeriodSeconds": 30, + "topologySpreadConstraints": [ + { + "labelSelector": { + "matchLabels": { + "cdk8s.io/metadata.addr": "crisiscleanup-api-wsgi-c83e828d", + }, + }, + "maxSkew": 2, + "topologyKey": "topology.kubernetes.io/zone", + "whenUnsatisfiable": "ScheduleAnyway", + }, + ], + "volumes": [ + { + "emptyDir": {}, + "name": "staticfiles", + }, + { + "emptyDir": { + "medium": "Memory", + }, + "name": "worker-tmp", + }, + ], + }, + }, + }, + }, + { + "apiVersion": "batch/v1", + "kind": "Job", + "metadata": { + "labels": { + "app.kubernetes.io/component": "api", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-api-wsgi-migrate", + "namespace": "test", + }, + "spec": { + "activeDeadlineSeconds": 1800, + "template": { + "metadata": { + "labels": { + "cdk8s.io/metadata.addr": "crisiscleanup-api-wsgi-migrate-c8890c80", + "component": "api-migrate", + }, + }, + "spec": { + "automountServiceAccountToken": false, + "containers": [ + { + "command": [ + "python", + "manage.py", + "migrate", + "--noinput", + "--verbosity=1", + ], + "envFrom": [ + { + "configMapRef": { + "name": "crisiscleanup-config-api-config", + }, + }, + ], + "image": "test-api:test", + "imagePullPolicy": "Always", + "name": "migrate", + "resources": { + "limits": { + "memory": "3072Mi", + }, + "requests": { + "cpu": "100m", + "memory": "1024Mi", + }, + }, + "securityContext": { + "allowPrivilegeEscalation": false, + "privileged": false, + "readOnlyRootFilesystem": false, + "runAsGroup": 1000, + "runAsNonRoot": true, + "runAsUser": 1000, + }, + }, + ], + "dnsPolicy": "ClusterFirst", + "hostNetwork": false, + "restartPolicy": "Never", + "securityContext": { + "fsGroupChangePolicy": "Always", + "runAsGroup": 1000, + "runAsNonRoot": true, + "runAsUser": 1000, + }, + "setHostnameAsFQDN": false, + "terminationGracePeriodSeconds": 300, + }, + }, + "ttlSecondsAfterFinished": 120, + }, + }, + { + "apiVersion": "batch/v1", + "kind": "Job", + "metadata": { + "labels": { + "app.kubernetes.io/component": "api", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-api-wsgi-collectstatic", + "namespace": "test", + }, + "spec": { + "activeDeadlineSeconds": 1800, + "template": { + "metadata": { + "labels": { + "cdk8s.io/metadata.addr": "crisiscleanup-api-wsgi-collectstatic-c871685d", + "component": "api-static", + }, + }, + "spec": { + "automountServiceAccountToken": false, + "containers": [ + { + "command": [ + "python", + "manage.py", + "collectstatic", + "--no-post-process", + "--noinput", + "--verbosity=2", + ], + "envFrom": [ + { + "configMapRef": { + "name": "crisiscleanup-config-api-config", + }, + }, + ], + "image": "test-api:test", + "imagePullPolicy": "Always", + "name": "collectstatic", + "resources": { + "limits": { + "memory": "3072Mi", + }, + "requests": { + "cpu": "100m", + "memory": "1024Mi", + }, + }, + "securityContext": { + "allowPrivilegeEscalation": false, + "privileged": false, + "readOnlyRootFilesystem": false, + "runAsGroup": 1000, + "runAsNonRoot": true, + "runAsUser": 1000, + }, + "volumeMounts": [ + { + "mountPath": "/app/staticfiles", + "name": "staticfiles", + }, + ], + }, + ], + "dnsPolicy": "ClusterFirst", + "hostNetwork": false, + "restartPolicy": "Never", + "securityContext": { + "fsGroupChangePolicy": "Always", + "runAsGroup": 1000, + "runAsNonRoot": true, + "runAsUser": 1000, + }, + "setHostnameAsFQDN": false, + "terminationGracePeriodSeconds": 300, + "volumes": [ + { + "emptyDir": {}, + "name": "staticfiles", + }, + ], + }, + }, + "ttlSecondsAfterFinished": 120, + }, + }, + { + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "labels": { + "app.kubernetes.io/component": "api", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-api-wsgi-service", + "namespace": "test", + }, + "spec": { + "externalIPs": [], + "ports": [ + { + "port": 5000, + "targetPort": 5000, + }, + ], + "selector": { + "cdk8s.io/metadata.addr": "crisiscleanup-api-wsgi-c83e828d", + }, + "type": "ClusterIP", + }, + }, + { + "apiVersion": "autoscaling.k8s.io/v1", + "kind": "VerticalPodAutoscaler", + "metadata": { + "labels": { + "app.kubernetes.io/component": "api", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-api-wsgi-vpa", + "namespace": "test", + }, + "spec": { + "resourcePolicy": { + "containerPolicies": [ + { + "containerName": "*", + "maxAllowed": { + "cpu": "3", + "memory": "3072Mi", + }, + "minAllowed": { + "cpu": "500m", + "memory": "1200Mi", + }, + }, + ], + }, + "targetRef": { + "apiVersion": "apps/v1", + "kind": "Deployment", + "name": "crisiscleanup-api-wsgi", + }, + "updatePolicy": { + "updateMode": "Auto", + }, + }, + }, + { + "apiVersion": "policy/v1", + "kind": "PodDisruptionBudget", + "metadata": { + "labels": { + "app.kubernetes.io/component": "api", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "wsgipdb", + "namespace": "test", + }, + "spec": { + "minAvailable": "35%", + "selector": { + "matchLabels": { + "cdk8s.io/metadata.addr": "crisiscleanup-api-wsgi-c83e828d", + }, + }, + }, + }, + { + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app.kubernetes.io/component": "api", + "app.kubernetes.io/name": "asgi", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-api-asgi", + "namespace": "test", + }, + "spec": { + "minReadySeconds": 0, + "progressDeadlineSeconds": 600, + "replicas": 4, + "selector": { + "matchLabels": { + "cdk8s.io/metadata.addr": "crisiscleanup-api-asgi-c818ff7e", + }, + }, + "strategy": { + "rollingUpdate": { + "maxSurge": "25%", + "maxUnavailable": "25%", + }, + "type": "RollingUpdate", + }, + "template": { + "metadata": { + "labels": { + "cdk8s.io/metadata.addr": "crisiscleanup-api-asgi-c818ff7e", + }, + }, + "spec": { + "automountServiceAccountToken": false, + "containers": [ + { + "command": [ + "/serve.sh", + "asgi", + "--workers=2", + ], + "envFrom": [ + { + "configMapRef": { + "name": "crisiscleanup-config-api-config", + }, + }, + ], + "image": "test-api:test", + "imagePullPolicy": "Always", + "livenessProbe": { + "failureThreshold": 30, + "httpGet": { + "path": "/ws/health", + "port": 5000, + "scheme": "HTTP", + }, + "initialDelaySeconds": 20, + "periodSeconds": 10, + "timeoutSeconds": 8, + }, + "name": "hypercorn", + "ports": [ + { + "containerPort": 5000, + }, + ], + "readinessProbe": { + "failureThreshold": 30, + "httpGet": { + "path": "/ws/health", + "port": 5000, + "scheme": "HTTP", + }, + "initialDelaySeconds": 20, + "periodSeconds": 10, + "timeoutSeconds": 8, + }, + "resources": { + "limits": { + "cpu": "1500m", + "memory": "1024Mi", + }, + "requests": { + "cpu": "500m", + "memory": "1024Mi", + }, + }, + "securityContext": { + "allowPrivilegeEscalation": false, + "privileged": false, + "readOnlyRootFilesystem": false, + "runAsGroup": 1000, + "runAsNonRoot": true, + "runAsUser": 1000, + }, + "startupProbe": { + "failureThreshold": 30, + "httpGet": { + "path": "/ws/health", + "port": 5000, + "scheme": "HTTP", + }, + "periodSeconds": 15, + }, + }, + ], + "dnsPolicy": "ClusterFirst", + "hostNetwork": false, + "restartPolicy": "Always", + "securityContext": { + "fsGroupChangePolicy": "Always", + "runAsNonRoot": true, + }, + "setHostnameAsFQDN": false, + "terminationGracePeriodSeconds": 30, + "topologySpreadConstraints": [ + { + "labelSelector": { + "matchLabels": { + "cdk8s.io/metadata.addr": "crisiscleanup-api-asgi-c818ff7e", + }, + }, + "maxSkew": 2, + "topologyKey": "topology.kubernetes.io/zone", + "whenUnsatisfiable": "ScheduleAnyway", + }, + ], + }, + }, + }, + }, + { + "apiVersion": "storage.k8s.io/v1", + "kind": "StorageClass", + "metadata": { + "labels": { + "app.kubernetes.io/component": "api", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "rag-models", + "namespace": "test", + }, + "parameters": { + "allowAutoIOPSPerGBIncrease": "true", + "iops": "1000", + "type": "io2", + }, + "provisioner": "ebs.csi.aws.com", + "volumeBindingMode": "WaitForFirstConsumer", + }, + { + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "labels": { + "app.kubernetes.io/component": "api", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-api-asgi-asgi-rag-service", + "namespace": "test", + }, + "spec": { + "clusterIP": "None", + "externalIPs": [], + "ports": [ + { + "name": "channels", + "port": 5000, + }, + ], + "selector": { + "cdk8s.io/metadata.addr": "crisiscleanup-api-asgi-rag-c86cf6a6", + }, + "type": "ClusterIP", + }, + }, + { + "apiVersion": "apps/v1", + "kind": "StatefulSet", + "metadata": { + "labels": { + "app.kubernetes.io/component": "api", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-api-asgi-rag", + "namespace": "test", + }, + "spec": { + "minReadySeconds": 0, + "podManagementPolicy": "OrderedReady", + "selector": { + "matchLabels": { + "cdk8s.io/metadata.addr": "crisiscleanup-api-asgi-rag-c86cf6a6", + }, + }, + "serviceName": "crisiscleanup-api-asgi-asgi-rag-service", + "template": { + "metadata": { + "labels": { + "cdk8s.io/metadata.addr": "crisiscleanup-api-asgi-rag-c86cf6a6", + }, + }, + "spec": { + "affinity": { + "podAntiAffinity": { + "requiredDuringSchedulingIgnoredDuringExecution": [ + { + "labelSelector": { + "matchLabels": { + "cdk8s.io/metadata.addr": "crisiscleanup-api-asgi-rag-c86cf6a6", + }, + }, + "namespaces": [ + "test", + ], + "topologyKey": "kubernetes.io/hostname", + }, + { + "labelSelector": { + "matchLabels": { + "cdk8s.io/metadata.addr": "crisiscleanup-api-asgi-rag-c86cf6a6", + }, + }, + "namespaces": [ + "test", + ], + "topologyKey": "topology.kubernetes.io/zone", + }, + ], + }, + }, + "automountServiceAccountToken": false, + "containers": [ + { + "command": [ + "/serve.sh", + "channelsworker", + "rag-document", + ], + "envFrom": [ + { + "configMapRef": { + "name": "crisiscleanup-config-api-config", + }, + }, + ], + "image": "test-api:test", + "imagePullPolicy": "Always", + "name": "rag-channels", + "resources": { + "limits": { + "memory": "4096Mi", + }, + "requests": { + "cpu": "200m", + "memory": "1024Mi", + }, + }, + "securityContext": { + "allowPrivilegeEscalation": false, + "privileged": false, + "readOnlyRootFilesystem": false, + "runAsGroup": 1000, + "runAsNonRoot": true, + "runAsUser": 1000, + }, + "volumeMounts": [ + { + "mountPath": "/ccu/nltk_data", + "name": "rag-volume", + "subPath": "nltk_data", + }, + { + "mountPath": "/ccu/.cache/huggingface", + "name": "rag-volume", + "subPath": "hf_data", + }, + { + "mountPath": "/ccu/.cache/matplotlib", + "name": "rag-volume", + "subPath": "mp_data", + }, + ], + }, + ], + "dnsPolicy": "ClusterFirst", + "hostNetwork": false, + "initContainers": [ + { + "command": [ + "sh", + "-x", + "-c", + "mkdir -p /ccu && chown -R 1000:1000 /ccu", + ], + "image": "public.ecr.aws/docker/library/busybox:stable", + "imagePullPolicy": "IfNotPresent", + "name": "host-mounts-init", + "resources": { + "limits": { + "cpu": "30m", + "memory": "50Mi", + }, + "requests": { + "cpu": "20m", + "memory": "20Mi", + }, + }, + "securityContext": { + "allowPrivilegeEscalation": false, + "privileged": false, + "readOnlyRootFilesystem": false, + "runAsGroup": 0, + "runAsNonRoot": false, + "runAsUser": 0, + }, + "volumeMounts": [ + { + "mountPath": "/ccu/nltk_data", + "name": "rag-volume", + "subPath": "nltk_data", + }, + { + "mountPath": "/ccu/.cache/huggingface", + "name": "rag-volume", + "subPath": "hf_data", + }, + { + "mountPath": "/ccu/.cache/matplotlib", + "name": "rag-volume", + "subPath": "mp_data", + }, + ], + }, + ], + "restartPolicy": "Always", + "securityContext": { + "fsGroupChangePolicy": "Always", + "runAsNonRoot": true, + }, + "setHostnameAsFQDN": false, + "terminationGracePeriodSeconds": 30, + }, + }, + "updateStrategy": { + "rollingUpdate": { + "partition": 0, + }, + "type": "RollingUpdate", + }, + "volumeClaimTemplates": [ + { + "metadata": { + "name": "rag-volume", + }, + "spec": { + "accessModes": [ + "ReadWriteOnce", + ], + "storageClassName": "rag-models", + }, + }, + ], + }, + }, + { + "apiVersion": "autoscaling/v2", + "kind": "HorizontalPodAutoscaler", + "metadata": { + "labels": { + "app.kubernetes.io/component": "api", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-api-asgi-rag-scaling-hpa", + "namespace": "test", + }, + "spec": { + "behavior": { + "scaleDown": { + "policies": [ + { + "periodSeconds": 300, + "type": "Pods", + "value": 1, + }, + ], + "selectPolicy": "Max", + "stabilizationWindowSeconds": 300, + }, + "scaleUp": { + "policies": [ + { + "periodSeconds": 60, + "type": "Pods", + "value": 4, + }, + { + "periodSeconds": 60, + "type": "Percent", + "value": 200, + }, + ], + "selectPolicy": "Max", + "stabilizationWindowSeconds": 0, + }, + }, + "maxReplicas": 6, + "metrics": [ + { + "resource": { + "name": "cpu", + "target": { + "averageUtilization": 50, + "type": "Utilization", + }, + }, + "type": "Resource", + }, + { + "resource": { + "name": "memory", + "target": { + "averageUtilization": 80, + "type": "Utilization", + }, + }, + "type": "Resource", + }, + ], + "minReplicas": 1, + "scaleTargetRef": { + "apiVersion": "apps/v1", + "kind": "StatefulSet", + "name": "crisiscleanup-api-asgi-rag", + }, + }, + }, + { + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "labels": { + "app.kubernetes.io/component": "api", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-api-asgi-service", + "namespace": "test", + }, + "spec": { + "externalIPs": [], + "ports": [ + { + "port": 5000, + "targetPort": 5000, + }, + ], + "selector": { + "cdk8s.io/metadata.addr": "crisiscleanup-api-asgi-c818ff7e", + }, + "type": "ClusterIP", + }, + }, + { + "apiVersion": "autoscaling.k8s.io/v1", + "kind": "VerticalPodAutoscaler", + "metadata": { + "labels": { + "app.kubernetes.io/component": "api", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-api-asgi-vpa", + "namespace": "test", + }, + "spec": { + "targetRef": { + "apiVersion": "apps/v1", + "kind": "Deployment", + "name": "crisiscleanup-api-asgi", + }, + "updatePolicy": { + "updateMode": "Auto", + }, + }, + }, + { + "apiVersion": "policy/v1", + "kind": "PodDisruptionBudget", + "metadata": { + "labels": { + "app.kubernetes.io/component": "api", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "asgipdb", + "namespace": "test", + }, + "spec": { + "minAvailable": "35%", + "selector": { + "matchLabels": { + "cdk8s.io/metadata.addr": "crisiscleanup-api-asgi-c818ff7e", + }, + }, + }, + }, + { + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app.kubernetes.io/component": "api", + "app.kubernetes.io/name": "adminwebsocket", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-api-admin-websocket", + "namespace": "test", + }, + "spec": { + "minReadySeconds": 0, + "progressDeadlineSeconds": 600, + "replicas": 1, + "selector": { + "matchLabels": { + "cdk8s.io/metadata.addr": "crisiscleanup-api-admin-websocket-c879d9e4", + }, + }, + "strategy": { + "rollingUpdate": { + "maxSurge": "25%", + "maxUnavailable": "25%", + }, + "type": "RollingUpdate", + }, + "template": { + "metadata": { + "labels": { + "cdk8s.io/metadata.addr": "crisiscleanup-api-admin-websocket-c879d9e4", + }, + }, + "spec": { + "automountServiceAccountToken": false, + "containers": [ + { + "command": [ + "/serve.sh", + "adminwebsocket", + ], + "envFrom": [ + { + "configMapRef": { + "name": "crisiscleanup-config-api-config", + }, + }, + ], + "image": "test-api:test", + "imagePullPolicy": "Always", + "name": "adminwebsocket", + "resources": { + "limits": { + "memory": "250Mi", + }, + "requests": { + "cpu": "3m", + "memory": "250Mi", + }, + }, + "securityContext": { + "allowPrivilegeEscalation": false, + "privileged": false, + "readOnlyRootFilesystem": false, + "runAsGroup": 1000, + "runAsNonRoot": true, + "runAsUser": 1000, + }, + }, + ], + "dnsPolicy": "ClusterFirst", + "hostNetwork": false, + "restartPolicy": "Always", + "securityContext": { + "fsGroupChangePolicy": "Always", + "runAsNonRoot": true, + }, + "setHostnameAsFQDN": false, + "terminationGracePeriodSeconds": 30, + }, + }, + }, + }, +] +`; + +exports[`CrisisCleanupChart: 'with vertical scaling' > celery matches snapshot > with vertical scaling-celery 1`] = ` +[ + { + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app.kubernetes.io/component": "task-queue", + "app.kubernetes.io/name": "celerybeat", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-celery-celerybeat", + "namespace": "test", + }, + "spec": { + "minReadySeconds": 0, + "progressDeadlineSeconds": 600, + "replicas": 1, + "selector": { + "matchLabels": { + "cdk8s.io/metadata.addr": "crisiscleanup-celery-celerybeat-c8500419", + }, + }, + "strategy": { + "rollingUpdate": { + "maxSurge": "25%", + "maxUnavailable": "25%", + }, + "type": "RollingUpdate", + }, + "template": { + "metadata": { + "labels": { + "cdk8s.io/metadata.addr": "crisiscleanup-celery-celerybeat-c8500419", + }, + }, + "spec": { + "automountServiceAccountToken": false, + "containers": [ + { + "command": [ + "/serve.sh", + "celerybeat", + ], + "envFrom": [ + { + "configMapRef": { + "name": "crisiscleanup-config-api-config", + }, + }, + ], + "image": "test-api:test", + "imagePullPolicy": "Always", + "name": "celerybeat", + "resources": { + "limits": { + "memory": "400Mi", + }, + "requests": { + "cpu": "20m", + "memory": "400Mi", + }, + }, + "securityContext": { + "allowPrivilegeEscalation": false, + "privileged": false, + "readOnlyRootFilesystem": false, + "runAsGroup": 1000, + "runAsNonRoot": true, + "runAsUser": 1000, + }, + }, + ], + "dnsPolicy": "ClusterFirst", + "hostNetwork": false, + "restartPolicy": "Always", + "securityContext": { + "fsGroupChangePolicy": "Always", + "runAsNonRoot": true, + }, + "setHostnameAsFQDN": false, + "terminationGracePeriodSeconds": 30, + }, + }, + }, + }, + { + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app.kubernetes.io/component": "task-queue", + "app.kubernetes.io/name": "celeryworker", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-celery-celery-celery", + "namespace": "test", + }, + "spec": { + "minReadySeconds": 0, + "progressDeadlineSeconds": 600, + "selector": { + "matchLabels": { + "cdk8s.io/metadata.addr": "crisiscleanup-celery-celery-celery-c8528587", + }, + }, + "strategy": { + "rollingUpdate": { + "maxSurge": "25%", + "maxUnavailable": "25%", + }, + "type": "RollingUpdate", + }, + "template": { + "metadata": { + "labels": { + "cdk8s.io/metadata.addr": "crisiscleanup-celery-celery-celery-c8528587", + }, + }, + "spec": { + "automountServiceAccountToken": false, + "containers": [ + { + "command": [ + "/serve.sh", + "celeryworker", + "-Q", + "celery", + "--concurrency=2", + "--hostname", + "celery@%%h", + ], + "envFrom": [ + { + "configMapRef": { + "name": "crisiscleanup-config-api-config", + }, + }, + ], + "image": "test-api:test", + "imagePullPolicy": "Always", + "name": "celery", + "resources": { + "limits": { + "memory": "900Mi", + }, + "requests": { + "cpu": "100m", + "memory": "900Mi", + }, + }, + "securityContext": { + "allowPrivilegeEscalation": false, + "privileged": false, + "readOnlyRootFilesystem": false, + "runAsGroup": 1000, + "runAsNonRoot": true, + "runAsUser": 1000, + }, + }, + ], + "dnsPolicy": "ClusterFirst", + "hostNetwork": false, + "restartPolicy": "Always", + "securityContext": { + "fsGroupChangePolicy": "Always", + "runAsNonRoot": true, + }, + "setHostnameAsFQDN": false, + "terminationGracePeriodSeconds": 30, + }, + }, + }, + }, + { + "apiVersion": "autoscaling/v2", + "kind": "HorizontalPodAutoscaler", + "metadata": { + "labels": { + "app.kubernetes.io/component": "task-queue", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-celery-celery-celery-hpa", + "namespace": "test", + }, + "spec": { + "behavior": { + "scaleDown": { + "policies": [ + { + "periodSeconds": 300, + "type": "Pods", + "value": 1, + }, + ], + "selectPolicy": "Max", + "stabilizationWindowSeconds": 300, + }, + "scaleUp": { + "policies": [ + { + "periodSeconds": 60, + "type": "Pods", + "value": 4, + }, + { + "periodSeconds": 60, + "type": "Percent", + "value": 200, + }, + ], + "selectPolicy": "Max", + "stabilizationWindowSeconds": 0, + }, + }, + "maxReplicas": 2, + "metrics": [ + { + "resource": { + "name": "cpu", + "target": { + "averageUtilization": 70, + "type": "Utilization", + }, + }, + "type": "Resource", + }, + { + "resource": { + "name": "memory", + "target": { + "averageUtilization": 85, + "type": "Utilization", + }, + }, + "type": "Resource", + }, + ], + "minReplicas": 1, + "scaleTargetRef": { + "apiVersion": "apps/v1", + "kind": "Deployment", + "name": "crisiscleanup-celery-celery-celery", + }, + }, + }, + { + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app.kubernetes.io/component": "task-queue", + "app.kubernetes.io/name": "celeryworker", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-celery-celery-signal", + "namespace": "test", + }, + "spec": { + "minReadySeconds": 0, + "progressDeadlineSeconds": 600, + "selector": { + "matchLabels": { + "cdk8s.io/metadata.addr": "crisiscleanup-celery-celery-signal-c80f507d", + }, + }, + "strategy": { + "rollingUpdate": { + "maxSurge": "25%", + "maxUnavailable": "25%", + }, + "type": "RollingUpdate", + }, + "template": { + "metadata": { + "labels": { + "cdk8s.io/metadata.addr": "crisiscleanup-celery-celery-signal-c80f507d", + }, + }, + "spec": { + "automountServiceAccountToken": false, + "containers": [ + { + "command": [ + "/serve.sh", + "celeryworker", + "-Q", + "signal,phone,metrics", + "--concurrency=2", + "--hostname", + "signal@%%h", + ], + "envFrom": [ + { + "configMapRef": { + "name": "crisiscleanup-config-api-config", + }, + }, + ], + "image": "test-api:test", + "imagePullPolicy": "Always", + "name": "signal", + "resources": { + "limits": { + "memory": "900Mi", + }, + "requests": { + "cpu": "100m", + "memory": "900Mi", + }, + }, + "securityContext": { + "allowPrivilegeEscalation": false, + "privileged": false, + "readOnlyRootFilesystem": false, + "runAsGroup": 1000, + "runAsNonRoot": true, + "runAsUser": 1000, + }, + }, + ], + "dnsPolicy": "ClusterFirst", + "hostNetwork": false, + "restartPolicy": "Always", + "securityContext": { + "fsGroupChangePolicy": "Always", + "runAsNonRoot": true, + }, + "setHostnameAsFQDN": false, + "terminationGracePeriodSeconds": 30, + }, + }, + }, + }, + { + "apiVersion": "autoscaling/v2", + "kind": "HorizontalPodAutoscaler", + "metadata": { + "labels": { + "app.kubernetes.io/component": "task-queue", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-celery-celery-signal-hpa", + "namespace": "test", + }, + "spec": { + "behavior": { + "scaleDown": { + "policies": [ + { + "periodSeconds": 300, + "type": "Pods", + "value": 1, + }, + ], + "selectPolicy": "Max", + "stabilizationWindowSeconds": 300, + }, + "scaleUp": { + "policies": [ + { + "periodSeconds": 60, + "type": "Pods", + "value": 4, + }, + { + "periodSeconds": 60, + "type": "Percent", + "value": 200, + }, + ], + "selectPolicy": "Max", + "stabilizationWindowSeconds": 0, + }, + }, + "maxReplicas": 2, + "metrics": [ + { + "resource": { + "name": "cpu", + "target": { + "averageUtilization": 70, + "type": "Utilization", + }, + }, + "type": "Resource", + }, + { + "resource": { + "name": "memory", + "target": { + "averageUtilization": 85, + "type": "Utilization", + }, + }, + "type": "Resource", + }, + ], + "minReplicas": 1, + "scaleTargetRef": { + "apiVersion": "apps/v1", + "kind": "Deployment", + "name": "crisiscleanup-celery-celery-signal", + }, + }, + }, +] +`; + +exports[`CrisisCleanupChart: 'with vertical scaling' > config matches snapshot > with vertical scaling-config 1`] = ` +[ + { + "apiVersion": "v1", + "data": { + "CCU_API_URL": "https://api.local.crisiscleanup.io", + "CCU_FORCE_DOCKER": "true", + "CCU_NEWRELIC_DISABLE": "true", + "CCU_WEB_URL": "https://local.crisiscleanup.io", + "CELERY_ALWAYS_EAGER": "false", + "CONNECT_INSTANCE_ID": "", + "DJANGO_ACCOUNT_ALLOW_REGISTRATION": "true", + "DJANGO_ALLOWED_HOSTS": "*", + "DJANGO_CORS_ORIGIN_WHITELIST": "https://local.crisiscleanup.io,https://app.local.crisiscleanup.io", + "DJANGO_CSRF_COOKIE_SECURE": "true", + "DJANGO_CSRF_TRUSTED_ORIGINS": "https://local.crisiscleanup.io,https://app.local.crisiscleanup.io", + "DJANGO_EMAIL_BACKEND": "django.core.mail.backends.dummy.EmailBackend", + "DJANGO_SECURE_SSL_REDIRECT": "false", + "DJANGO_SESSION_COOKIE_SECURE": "true", + "DJANGO_SETTINGS_MODULE": "config.settings.local", + "ELASTIC_SEARCH_HOST": "", + "LANGCHAIN_ENDPOINT": "https://api.smith.langchain.com", + "LANGCHAIN_PROJECT": "crisiscleanup-3-api", + "LANGCHAIN_TRACING_V2": "false", + "NEW_RELIC_CONFIG_FILE": "/app/newrelic.ini", + "PHONE_CHECK_TIMEZONE": "true", + "RAG_CHAT_MODEL": "gpt-4o", + "RAG_DOCUMENT_EMBED_MODEL": "text-embedding-3-large", + "RAG_QUERY_EMBED_MODEL": "text-embedding-3-small", + "SENTRY_TRACE_EXCLUDE_URLS": "/,/health,/health/,/ws/health,/ws/health/,/version,/version/,/{var}health/,/{var}version/", + }, + "immutable": false, + "kind": "ConfigMap", + "metadata": { + "labels": { + "app.kubernetes.io/component": "config", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-config-api-config", + "namespace": "test", + }, + }, +] +`; + +exports[`CrisisCleanupChart: 'with vertical scaling' > crisiscleanup matches snapshot > with vertical scaling-crisiscleanup 1`] = ` +[ + { + "apiVersion": "networking.k8s.io/v1", + "kind": "Ingress", + "metadata": { + "annotations": { + "alb.ingress.kubernetes.io/healthcheck-path": "/health", + "alb.ingress.kubernetes.io/listen-ports": "[{\\"HTTP\\": 80}, {\\"HTTPS\\":443}]", + "alb.ingress.kubernetes.io/load-balancer-attributes": "idle_timeout.timeout_seconds=120", + "alb.ingress.kubernetes.io/scheme": "internet-facing", + "alb.ingress.kubernetes.io/ssl-redirect": "443", + "alb.ingress.kubernetes.io/target-group-attributes": "load_balancing.algorithm.type=least_outstanding_requests", + "alb.ingress.kubernetes.io/target-type": "ip", + }, + "labels": { + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-ingress-c8203526", + "namespace": "test", + }, + "spec": { + "rules": [ + { + "host": "api.test.crisiscleanup.io", + "http": { + "paths": [ + { + "backend": { + "service": { + "name": "crisiscleanup-api-wsgi-service", + "port": { + "number": 5000, + }, + }, + }, + "path": "/", + "pathType": "Prefix", + }, + { + "backend": { + "service": { + "name": "crisiscleanup-api-asgi-service", + "port": { + "number": 5000, + }, + }, + }, + "path": "/ws/", + "pathType": "Prefix", + }, + ], + }, + }, + ], + }, + }, +] +`; + +exports[`CrisisCleanupChart: 'with vertical scaling' > namespace matches snapshot > with vertical scaling-namespace 1`] = ` +[ + { + "apiVersion": "v1", + "kind": "Namespace", + "metadata": { + "labels": { + "app.kubernetes.io/part-of": "crisiscleanup", + "elbv2.k8s.aws/pod-readiness-gate-inject": "enabled", + }, + "name": "test", + "namespace": "test", + }, + "spec": {}, + }, +] +`; From 2bb54c0d50b288854a23fcde99e5a512e16c957d Mon Sep 17 00:00:00 2001 From: Braden Mars Date: Fri, 4 Oct 2024 17:21:35 -0500 Subject: [PATCH 09/13] fix(stacks.api): make `CrisisCleanupAddOn` depend on `VerticalPodAutoscalerAddon` Signed-off-by: Braden Mars --- packages/stacks/api/src/addons/crisiscleanup.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/stacks/api/src/addons/crisiscleanup.ts b/packages/stacks/api/src/addons/crisiscleanup.ts index 8926a0d8..3c142a09 100644 --- a/packages/stacks/api/src/addons/crisiscleanup.ts +++ b/packages/stacks/api/src/addons/crisiscleanup.ts @@ -16,6 +16,7 @@ import { App, type Chart } from 'cdk8s' import * as kplus from 'cdk8s-plus-27' import type { Construct } from 'constructs' import defu from 'defu' +import { VerticalPodAutoscalerStackAddOn } from './vertical-pod-autoscaler' import { type NamedSecretsProvider } from '../secrets' import { getRequiredResource } from '../util' @@ -38,6 +39,7 @@ export class CrisisCleanupAddOn implements blueprints.ClusterAddOn { // TODO: resolve esbuild transform error that is occurring with tsx/esbuild. const newDeploy = blueprints.utils.dependable( blueprints.addons.SecretsStoreAddOn.name, + VerticalPodAutoscalerStackAddOn.name, )( // eslint-disable-next-line @typescript-eslint/no-unsafe-argument Object.getPrototypeOf(this), From 3f7491af5dcb8de2055a115974b41234911d90e7 Mon Sep 17 00:00:00 2001 From: Braden Mars Date: Fri, 4 Oct 2024 17:23:40 -0500 Subject: [PATCH 10/13] refactor(stacks.api): correct name for `VerticalPodAutoscalerAddon` Signed-off-by: Braden Mars --- packages/stacks/api/src/addons/crisiscleanup.ts | 4 ++-- .../stacks/api/src/addons/vertical-pod-autoscaler.ts | 12 ++++++------ packages/stacks/api/src/pipeline.ts | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/stacks/api/src/addons/crisiscleanup.ts b/packages/stacks/api/src/addons/crisiscleanup.ts index 3c142a09..83c4d749 100644 --- a/packages/stacks/api/src/addons/crisiscleanup.ts +++ b/packages/stacks/api/src/addons/crisiscleanup.ts @@ -16,7 +16,7 @@ import { App, type Chart } from 'cdk8s' import * as kplus from 'cdk8s-plus-27' import type { Construct } from 'constructs' import defu from 'defu' -import { VerticalPodAutoscalerStackAddOn } from './vertical-pod-autoscaler' +import { VerticalPodAutoscalerAddOn } from './vertical-pod-autoscaler' import { type NamedSecretsProvider } from '../secrets' import { getRequiredResource } from '../util' @@ -39,7 +39,7 @@ export class CrisisCleanupAddOn implements blueprints.ClusterAddOn { // TODO: resolve esbuild transform error that is occurring with tsx/esbuild. const newDeploy = blueprints.utils.dependable( blueprints.addons.SecretsStoreAddOn.name, - VerticalPodAutoscalerStackAddOn.name, + VerticalPodAutoscalerAddOn.name, )( // eslint-disable-next-line @typescript-eslint/no-unsafe-argument Object.getPrototypeOf(this), diff --git a/packages/stacks/api/src/addons/vertical-pod-autoscaler.ts b/packages/stacks/api/src/addons/vertical-pod-autoscaler.ts index 7dd0a8d0..cd9be115 100644 --- a/packages/stacks/api/src/addons/vertical-pod-autoscaler.ts +++ b/packages/stacks/api/src/addons/vertical-pod-autoscaler.ts @@ -2,10 +2,10 @@ import * as blueprints from '@aws-quickstart/eks-blueprints' import { type Construct } from 'constructs' import defu from 'defu' -export interface VerticalPodAutoscalerStackAddOnProps +export interface VerticalPodAutoscalerAddOnProps extends blueprints.HelmAddOnProps {} -const vpaStackDefaults: VerticalPodAutoscalerStackAddOnProps = { +const vpaStackDefaults: VerticalPodAutoscalerAddOnProps = { name: 'vertical-pod-autoscaler', version: '9.9.0', chart: 'vertical-pod-autoscaler', @@ -14,14 +14,14 @@ const vpaStackDefaults: VerticalPodAutoscalerStackAddOnProps = { repository: 'https://cowboysysop.github.io/charts', } -export class VerticalPodAutoscalerStackAddOn extends blueprints.HelmAddOn { - readonly props: VerticalPodAutoscalerStackAddOnProps +export class VerticalPodAutoscalerAddOn extends blueprints.HelmAddOn { + readonly props: VerticalPodAutoscalerAddOnProps - constructor(props?: Partial) { + constructor(props?: Partial) { const withDefaults = defu( props ?? {}, vpaStackDefaults, - ) as VerticalPodAutoscalerStackAddOnProps + ) as VerticalPodAutoscalerAddOnProps super(withDefaults) this.props = withDefaults } diff --git a/packages/stacks/api/src/pipeline.ts b/packages/stacks/api/src/pipeline.ts index ee240ef0..44590ec5 100644 --- a/packages/stacks/api/src/pipeline.ts +++ b/packages/stacks/api/src/pipeline.ts @@ -20,7 +20,7 @@ import * as lambda from 'aws-cdk-lib/aws-lambda' import { type GitHubEnvironment, StackCapabilities } from 'cdk-pipelines-github' import type { Construct } from 'constructs' -import { CrisisCleanupAddOn, VerticalPodAutoscalerStackAddOn } from './addons' +import { CrisisCleanupAddOn, VerticalPodAutoscalerAddOn } from './addons' import { buildClusterBuilder, buildKarpenter, @@ -276,7 +276,7 @@ export class Pipeline { undefined, config.apiStack!.eks.instanceTypes ?? undefined, ), - new VerticalPodAutoscalerStackAddOn(), + new VerticalPodAutoscalerAddOn(), new CrisisCleanupAddOn({ config, secretsProvider, From c7744a5c59fc53ea417fee47bf106775e0bf0a8c Mon Sep 17 00:00:00 2001 From: Braden Mars Date: Fri, 4 Oct 2024 17:23:59 -0500 Subject: [PATCH 11/13] test(stacks.api): add dependant addon to unit test, update snapshots Signed-off-by: Braden Mars --- .../api/test/__snapshots__/main.spec.ts.snap | 66 +++++++++++++++++++ packages/stacks/api/test/main.spec.ts | 8 +-- 2 files changed, 69 insertions(+), 5 deletions(-) diff --git a/packages/stacks/api/test/__snapshots__/main.spec.ts.snap b/packages/stacks/api/test/__snapshots__/main.spec.ts.snap index 62d6ec91..baabb458 100644 --- a/packages/stacks/api/test/__snapshots__/main.spec.ts.snap +++ b/packages/stacks/api/test/__snapshots__/main.spec.ts.snap @@ -2534,6 +2534,71 @@ exports[`Snapshot 1`] = ` "Type": "Custom::AWSCDK-EKS-HelmChart", "UpdateReplacePolicy": "Delete", }, + "teststackchartverticalpodautoscaler6D637854": { + "DeletionPolicy": "Delete", + "DependsOn": [ + "teststackvpcIGW03B105E6", + "teststackvpcPrivateSubnet1DefaultRouteD98CD628", + "teststackvpcPrivateSubnet1RouteTable73100B52", + "teststackvpcPrivateSubnet1RouteTableAssociation3900E69F", + "teststackvpcPrivateSubnet1SubnetF0331D8A", + "teststackvpcPrivateSubnet2DefaultRoute134E1612", + "teststackvpcPrivateSubnet2RouteTable3A43C01B", + "teststackvpcPrivateSubnet2RouteTableAssociation425F10F9", + "teststackvpcPrivateSubnet2Subnet3D907BDE", + "teststackvpcPrivateSubnet3DefaultRoute9B3E87CD", + "teststackvpcPrivateSubnet3RouteTableEE6C9D04", + "teststackvpcPrivateSubnet3RouteTableAssociation9E2AFFF0", + "teststackvpcPrivateSubnet3Subnet04F192E1", + "teststackvpcPublicSubnet1DefaultRoute559FCEC5", + "teststackvpcPublicSubnet1EIPD9571571", + "teststackvpcPublicSubnet1NATGateway69A82078", + "teststackvpcPublicSubnet1RouteTable4A6F7D68", + "teststackvpcPublicSubnet1RouteTableAssociation6F4CDBB8", + "teststackvpcPublicSubnet1Subnet98CD6475", + "teststackvpcPublicSubnet2DefaultRoute6D4EE093", + "teststackvpcPublicSubnet2EIP2A9F3E46", + "teststackvpcPublicSubnet2NATGateway03687D6F", + "teststackvpcPublicSubnet2RouteTable58C7856E", + "teststackvpcPublicSubnet2RouteTableAssociationE029BF04", + "teststackvpcPublicSubnet2SubnetDEE0C8F7", + "teststackvpcPublicSubnet3DefaultRoute7B38571F", + "teststackvpcPublicSubnet3EIP67D3B36B", + "teststackvpcPublicSubnet3NATGateway47881F6D", + "teststackvpcPublicSubnet3RouteTable5DB46CC9", + "teststackvpcPublicSubnet3RouteTableAssociation24AA1DD0", + "teststackvpcPublicSubnet3Subnet37390ED3", + "teststackvpcAF2EB73C", + "teststackvpcVPCGW05B02F5B", + "teststackchartawsloadbalancercontrollerF71AE295", + "teststackKubectlReadyBarrier041D6F85", + ], + "Properties": { + "Chart": "vertical-pod-autoscaler", + "ClusterName": { + "Ref": "teststackF0A1F222", + }, + "Namespace": "kube-system", + "Release": "vertical-pod-autoscaler", + "Repository": "https://cowboysysop.github.io/charts", + "RoleArn": { + "Fn::GetAtt": [ + "teststackCreationRole2F53ED2E", + "Arn", + ], + }, + "ServiceToken": { + "Fn::GetAtt": [ + "awscdkawseksKubectlProviderNestedStackawscdkawseksKubectlProviderNestedStackResourceA7AEBA6B", + "Outputs.teststackawscdkawseksKubectlProviderframeworkonEventA7D3599FArn", + ], + }, + "Values": "{}", + "Version": "9.9.0", + }, + "Type": "Custom::AWSCDK-EKS-HelmChart", + "UpdateReplacePolicy": "Delete", + }, "teststackconfig269E4FBB": { "DeletionPolicy": "Delete", "DependsOn": [ @@ -2634,6 +2699,7 @@ exports[`Snapshot 1`] = ` "teststackvpcVPCGW05B02F5B", "teststackapi7BAC5B30", "teststackchartawsloadbalancercontrollerF71AE295", + "teststackchartverticalpodautoscaler6D637854", "teststackKubectlReadyBarrier041D6F85", "teststackmanifestSecretsStoreCsiDriverProviderAws9B659B7C", ], diff --git a/packages/stacks/api/test/main.spec.ts b/packages/stacks/api/test/main.spec.ts index e73e977e..60b4c72f 100644 --- a/packages/stacks/api/test/main.spec.ts +++ b/packages/stacks/api/test/main.spec.ts @@ -13,10 +13,7 @@ import { KubernetesVersion } from 'aws-cdk-lib/aws-eks' import { type IConstruct } from 'constructs' import { test, expect, vi, beforeAll, afterAll } from 'vitest' import stackDefaults from '../crisiscleanup.config' -import { - CrisisCleanupAddOn, - VerticalPodAutoscalerStackAddOn, -} from '../src/addons' +import { CrisisCleanupAddOn, VerticalPodAutoscalerAddOn } from '../src/addons' import { buildClusterBuilder, getCoreAddons, @@ -72,6 +69,7 @@ test('Snapshot', async () => { }, }) .addOns( + new VerticalPodAutoscalerAddOn(), new CrisisCleanupAddOn({ config, databaseResourceName: '', @@ -107,7 +105,7 @@ test('VerticalPodAutoscalerAddon', async () => { const cluster = buildClusterBuilder(config.apiStack!.eks.k8s.version).build() const stack = await blueprints.EksBlueprint.builder() .version(KubernetesVersion.of(config.apiStack!.eks.k8s.version)) - .addOns(new VerticalPodAutoscalerStackAddOn()) + .addOns(new VerticalPodAutoscalerAddOn()) .clusterProvider(cluster) .buildAsync(app, 'test-vpa-stack') From 2e754764fa844e533b6170d83ad492755682377c Mon Sep 17 00:00:00 2001 From: Braden Mars Date: Fri, 4 Oct 2024 17:40:07 -0500 Subject: [PATCH 12/13] feat(charts.crisiscleanup): enable vertical pod autoscaling for deployments by default Signed-off-by: Braden Mars --- packages/charts/crisiscleanup/src/schema.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/charts/crisiscleanup/src/schema.ts b/packages/charts/crisiscleanup/src/schema.ts index 67bb24be..b541f5f0 100644 --- a/packages/charts/crisiscleanup/src/schema.ts +++ b/packages/charts/crisiscleanup/src/schema.ts @@ -100,7 +100,7 @@ const deploymentSchema = z.object({ image: containerImageSchema.optional(), spread: z.boolean().default(false), resources: resourcesSchema.optional(), - verticalScaling: verticalScalingSchema.optional(), + verticalScaling: verticalScalingSchema.optional().default({ enabled: true }), }) const withScaling = (inSchema: T) => From 58f5fe1e81b6dd04877fd183697d5dbd1279d411 Mon Sep 17 00:00:00 2001 From: Braden Mars Date: Fri, 4 Oct 2024 17:40:14 -0500 Subject: [PATCH 13/13] test: update snapshots Signed-off-by: Braden Mars --- .../test/__snapshots__/main.spec.ts.snap | 484 ++++++++++++++++++ .../api/test/__snapshots__/main.spec.ts.snap | 4 +- 2 files changed, 486 insertions(+), 2 deletions(-) diff --git a/packages/charts/crisiscleanup/test/__snapshots__/main.spec.ts.snap b/packages/charts/crisiscleanup/test/__snapshots__/main.spec.ts.snap index d27ffcc5..114610a4 100644 --- a/packages/charts/crisiscleanup/test/__snapshots__/main.spec.ts.snap +++ b/packages/charts/crisiscleanup/test/__snapshots__/main.spec.ts.snap @@ -411,6 +411,28 @@ exports[`CrisisCleanupChart: 'defaults' > api matches snapshot > defaults-api 1` }, }, }, + { + "apiVersion": "autoscaling.k8s.io/v1", + "kind": "VerticalPodAutoscaler", + "metadata": { + "labels": { + "app.kubernetes.io/component": "api", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-api-wsgi-vpa", + "namespace": "test", + }, + "spec": { + "targetRef": { + "apiVersion": "apps/v1", + "kind": "Deployment", + "name": "crisiscleanup-api-wsgi", + }, + "updatePolicy": { + "updateMode": "Auto", + }, + }, + }, { "apiVersion": "apps/v1", "kind": "Deployment", @@ -935,6 +957,28 @@ exports[`CrisisCleanupChart: 'defaults' > api matches snapshot > defaults-api 1` }, }, }, + { + "apiVersion": "autoscaling.k8s.io/v1", + "kind": "VerticalPodAutoscaler", + "metadata": { + "labels": { + "app.kubernetes.io/component": "api", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-api-asgi-vpa", + "namespace": "test", + }, + "spec": { + "targetRef": { + "apiVersion": "apps/v1", + "kind": "Deployment", + "name": "crisiscleanup-api-asgi", + }, + "updatePolicy": { + "updateMode": "Auto", + }, + }, + }, { "apiVersion": "apps/v1", "kind": "Deployment", @@ -1019,6 +1063,28 @@ exports[`CrisisCleanupChart: 'defaults' > api matches snapshot > defaults-api 1` }, }, }, + { + "apiVersion": "autoscaling.k8s.io/v1", + "kind": "VerticalPodAutoscaler", + "metadata": { + "labels": { + "app.kubernetes.io/component": "api", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-api-admin-websocket-vpa", + "namespace": "test", + }, + "spec": { + "targetRef": { + "apiVersion": "apps/v1", + "kind": "Deployment", + "name": "crisiscleanup-api-admin-websocket", + }, + "updatePolicy": { + "updateMode": "Auto", + }, + }, + }, ] `; @@ -1108,6 +1174,28 @@ exports[`CrisisCleanupChart: 'defaults' > celery matches snapshot > defaults-cel }, }, }, + { + "apiVersion": "autoscaling.k8s.io/v1", + "kind": "VerticalPodAutoscaler", + "metadata": { + "labels": { + "app.kubernetes.io/component": "task-queue", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-celery-celerybeat-vpa", + "namespace": "test", + }, + "spec": { + "targetRef": { + "apiVersion": "apps/v1", + "kind": "Deployment", + "name": "crisiscleanup-celery-celerybeat", + }, + "updatePolicy": { + "updateMode": "Auto", + }, + }, + }, { "apiVersion": "apps/v1", "kind": "Deployment", @@ -1268,6 +1356,28 @@ exports[`CrisisCleanupChart: 'defaults' > celery matches snapshot > defaults-cel }, }, }, + { + "apiVersion": "autoscaling.k8s.io/v1", + "kind": "VerticalPodAutoscaler", + "metadata": { + "labels": { + "app.kubernetes.io/component": "task-queue", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-celery-celery-celery-vpa", + "namespace": "test", + }, + "spec": { + "targetRef": { + "apiVersion": "apps/v1", + "kind": "Deployment", + "name": "crisiscleanup-celery-celery-celery", + }, + "updatePolicy": { + "updateMode": "Auto", + }, + }, + }, { "apiVersion": "apps/v1", "kind": "Deployment", @@ -1428,6 +1538,28 @@ exports[`CrisisCleanupChart: 'defaults' > celery matches snapshot > defaults-cel }, }, }, + { + "apiVersion": "autoscaling.k8s.io/v1", + "kind": "VerticalPodAutoscaler", + "metadata": { + "labels": { + "app.kubernetes.io/component": "task-queue", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-celery-celery-signal-vpa", + "namespace": "test", + }, + "spec": { + "targetRef": { + "apiVersion": "apps/v1", + "kind": "Deployment", + "name": "crisiscleanup-celery-celery-signal", + }, + "updatePolicy": { + "updateMode": "Auto", + }, + }, + }, ] `; @@ -1906,6 +2038,28 @@ exports[`CrisisCleanupChart: 'with spread' > api matches snapshot > with spread- "type": "ClusterIP", }, }, + { + "apiVersion": "autoscaling.k8s.io/v1", + "kind": "VerticalPodAutoscaler", + "metadata": { + "labels": { + "app.kubernetes.io/component": "api", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-api-wsgi-vpa", + "namespace": "test", + }, + "spec": { + "targetRef": { + "apiVersion": "apps/v1", + "kind": "Deployment", + "name": "crisiscleanup-api-wsgi", + }, + "updatePolicy": { + "updateMode": "Auto", + }, + }, + }, { "apiVersion": "policy/v1", "kind": "PodDisruptionBudget", @@ -2391,6 +2545,28 @@ exports[`CrisisCleanupChart: 'with spread' > api matches snapshot > with spread- "type": "ClusterIP", }, }, + { + "apiVersion": "autoscaling.k8s.io/v1", + "kind": "VerticalPodAutoscaler", + "metadata": { + "labels": { + "app.kubernetes.io/component": "api", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-api-asgi-vpa", + "namespace": "test", + }, + "spec": { + "targetRef": { + "apiVersion": "apps/v1", + "kind": "Deployment", + "name": "crisiscleanup-api-asgi", + }, + "updatePolicy": { + "updateMode": "Auto", + }, + }, + }, { "apiVersion": "policy/v1", "kind": "PodDisruptionBudget", @@ -2495,6 +2671,28 @@ exports[`CrisisCleanupChart: 'with spread' > api matches snapshot > with spread- }, }, }, + { + "apiVersion": "autoscaling.k8s.io/v1", + "kind": "VerticalPodAutoscaler", + "metadata": { + "labels": { + "app.kubernetes.io/component": "api", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-api-admin-websocket-vpa", + "namespace": "test", + }, + "spec": { + "targetRef": { + "apiVersion": "apps/v1", + "kind": "Deployment", + "name": "crisiscleanup-api-admin-websocket", + }, + "updatePolicy": { + "updateMode": "Auto", + }, + }, + }, ] `; @@ -2584,6 +2782,28 @@ exports[`CrisisCleanupChart: 'with spread' > celery matches snapshot > with spre }, }, }, + { + "apiVersion": "autoscaling.k8s.io/v1", + "kind": "VerticalPodAutoscaler", + "metadata": { + "labels": { + "app.kubernetes.io/component": "task-queue", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-celery-celerybeat-vpa", + "namespace": "test", + }, + "spec": { + "targetRef": { + "apiVersion": "apps/v1", + "kind": "Deployment", + "name": "crisiscleanup-celery-celerybeat", + }, + "updatePolicy": { + "updateMode": "Auto", + }, + }, + }, { "apiVersion": "apps/v1", "kind": "Deployment", @@ -2744,6 +2964,28 @@ exports[`CrisisCleanupChart: 'with spread' > celery matches snapshot > with spre }, }, }, + { + "apiVersion": "autoscaling.k8s.io/v1", + "kind": "VerticalPodAutoscaler", + "metadata": { + "labels": { + "app.kubernetes.io/component": "task-queue", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-celery-celery-celery-vpa", + "namespace": "test", + }, + "spec": { + "targetRef": { + "apiVersion": "apps/v1", + "kind": "Deployment", + "name": "crisiscleanup-celery-celery-celery", + }, + "updatePolicy": { + "updateMode": "Auto", + }, + }, + }, { "apiVersion": "apps/v1", "kind": "Deployment", @@ -2904,6 +3146,28 @@ exports[`CrisisCleanupChart: 'with spread' > celery matches snapshot > with spre }, }, }, + { + "apiVersion": "autoscaling.k8s.io/v1", + "kind": "VerticalPodAutoscaler", + "metadata": { + "labels": { + "app.kubernetes.io/component": "task-queue", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-celery-celery-signal-vpa", + "namespace": "test", + }, + "spec": { + "targetRef": { + "apiVersion": "apps/v1", + "kind": "Deployment", + "name": "crisiscleanup-celery-celery-signal", + }, + "updatePolicy": { + "updateMode": "Auto", + }, + }, + }, ] `; @@ -3441,6 +3705,28 @@ exports[`CrisisCleanupChart: 'with sync' > api matches snapshot > with sync-api }, }, }, + { + "apiVersion": "autoscaling.k8s.io/v1", + "kind": "VerticalPodAutoscaler", + "metadata": { + "labels": { + "app.kubernetes.io/component": "api", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-api-wsgi-vpa", + "namespace": "test", + }, + "spec": { + "targetRef": { + "apiVersion": "apps/v1", + "kind": "Deployment", + "name": "crisiscleanup-api-wsgi", + }, + "updatePolicy": { + "updateMode": "Auto", + }, + }, + }, { "apiVersion": "apps/v1", "kind": "Deployment", @@ -3965,6 +4251,28 @@ exports[`CrisisCleanupChart: 'with sync' > api matches snapshot > with sync-api }, }, }, + { + "apiVersion": "autoscaling.k8s.io/v1", + "kind": "VerticalPodAutoscaler", + "metadata": { + "labels": { + "app.kubernetes.io/component": "api", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-api-asgi-vpa", + "namespace": "test", + }, + "spec": { + "targetRef": { + "apiVersion": "apps/v1", + "kind": "Deployment", + "name": "crisiscleanup-api-asgi", + }, + "updatePolicy": { + "updateMode": "Auto", + }, + }, + }, { "apiVersion": "apps/v1", "kind": "Deployment", @@ -4049,6 +4357,28 @@ exports[`CrisisCleanupChart: 'with sync' > api matches snapshot > with sync-api }, }, }, + { + "apiVersion": "autoscaling.k8s.io/v1", + "kind": "VerticalPodAutoscaler", + "metadata": { + "labels": { + "app.kubernetes.io/component": "api", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-api-admin-websocket-vpa", + "namespace": "test", + }, + "spec": { + "targetRef": { + "apiVersion": "apps/v1", + "kind": "Deployment", + "name": "crisiscleanup-api-admin-websocket", + }, + "updatePolicy": { + "updateMode": "Auto", + }, + }, + }, ] `; @@ -4138,6 +4468,28 @@ exports[`CrisisCleanupChart: 'with sync' > celery matches snapshot > with sync-c }, }, }, + { + "apiVersion": "autoscaling.k8s.io/v1", + "kind": "VerticalPodAutoscaler", + "metadata": { + "labels": { + "app.kubernetes.io/component": "task-queue", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-celery-celerybeat-vpa", + "namespace": "test", + }, + "spec": { + "targetRef": { + "apiVersion": "apps/v1", + "kind": "Deployment", + "name": "crisiscleanup-celery-celerybeat", + }, + "updatePolicy": { + "updateMode": "Auto", + }, + }, + }, { "apiVersion": "apps/v1", "kind": "Deployment", @@ -4298,6 +4650,28 @@ exports[`CrisisCleanupChart: 'with sync' > celery matches snapshot > with sync-c }, }, }, + { + "apiVersion": "autoscaling.k8s.io/v1", + "kind": "VerticalPodAutoscaler", + "metadata": { + "labels": { + "app.kubernetes.io/component": "task-queue", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-celery-celery-celery-vpa", + "namespace": "test", + }, + "spec": { + "targetRef": { + "apiVersion": "apps/v1", + "kind": "Deployment", + "name": "crisiscleanup-celery-celery-celery", + }, + "updatePolicy": { + "updateMode": "Auto", + }, + }, + }, { "apiVersion": "apps/v1", "kind": "Deployment", @@ -4458,6 +4832,28 @@ exports[`CrisisCleanupChart: 'with sync' > celery matches snapshot > with sync-c }, }, }, + { + "apiVersion": "autoscaling.k8s.io/v1", + "kind": "VerticalPodAutoscaler", + "metadata": { + "labels": { + "app.kubernetes.io/component": "task-queue", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-celery-celery-signal-vpa", + "namespace": "test", + }, + "spec": { + "targetRef": { + "apiVersion": "apps/v1", + "kind": "Deployment", + "name": "crisiscleanup-celery-celery-signal", + }, + "updatePolicy": { + "updateMode": "Auto", + }, + }, + }, ] `; @@ -5682,6 +6078,28 @@ exports[`CrisisCleanupChart: 'with vertical scaling' > api matches snapshot > wi }, }, }, + { + "apiVersion": "autoscaling.k8s.io/v1", + "kind": "VerticalPodAutoscaler", + "metadata": { + "labels": { + "app.kubernetes.io/component": "api", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-api-admin-websocket-vpa", + "namespace": "test", + }, + "spec": { + "targetRef": { + "apiVersion": "apps/v1", + "kind": "Deployment", + "name": "crisiscleanup-api-admin-websocket", + }, + "updatePolicy": { + "updateMode": "Auto", + }, + }, + }, ] `; @@ -5771,6 +6189,28 @@ exports[`CrisisCleanupChart: 'with vertical scaling' > celery matches snapshot > }, }, }, + { + "apiVersion": "autoscaling.k8s.io/v1", + "kind": "VerticalPodAutoscaler", + "metadata": { + "labels": { + "app.kubernetes.io/component": "task-queue", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-celery-celerybeat-vpa", + "namespace": "test", + }, + "spec": { + "targetRef": { + "apiVersion": "apps/v1", + "kind": "Deployment", + "name": "crisiscleanup-celery-celerybeat", + }, + "updatePolicy": { + "updateMode": "Auto", + }, + }, + }, { "apiVersion": "apps/v1", "kind": "Deployment", @@ -5931,6 +6371,28 @@ exports[`CrisisCleanupChart: 'with vertical scaling' > celery matches snapshot > }, }, }, + { + "apiVersion": "autoscaling.k8s.io/v1", + "kind": "VerticalPodAutoscaler", + "metadata": { + "labels": { + "app.kubernetes.io/component": "task-queue", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-celery-celery-celery-vpa", + "namespace": "test", + }, + "spec": { + "targetRef": { + "apiVersion": "apps/v1", + "kind": "Deployment", + "name": "crisiscleanup-celery-celery-celery", + }, + "updatePolicy": { + "updateMode": "Auto", + }, + }, + }, { "apiVersion": "apps/v1", "kind": "Deployment", @@ -6091,6 +6553,28 @@ exports[`CrisisCleanupChart: 'with vertical scaling' > celery matches snapshot > }, }, }, + { + "apiVersion": "autoscaling.k8s.io/v1", + "kind": "VerticalPodAutoscaler", + "metadata": { + "labels": { + "app.kubernetes.io/component": "task-queue", + "app.kubernetes.io/part-of": "crisiscleanup", + }, + "name": "crisiscleanup-celery-celery-signal-vpa", + "namespace": "test", + }, + "spec": { + "targetRef": { + "apiVersion": "apps/v1", + "kind": "Deployment", + "name": "crisiscleanup-celery-celery-signal", + }, + "updatePolicy": { + "updateMode": "Auto", + }, + }, + }, ] `; diff --git a/packages/stacks/api/test/__snapshots__/main.spec.ts.snap b/packages/stacks/api/test/__snapshots__/main.spec.ts.snap index baabb458..66614424 100644 --- a/packages/stacks/api/test/__snapshots__/main.spec.ts.snap +++ b/packages/stacks/api/test/__snapshots__/main.spec.ts.snap @@ -1283,7 +1283,7 @@ exports[`Snapshot 1`] = ` "ClusterName": { "Ref": "teststackF0A1F222", }, - "Manifest": "[{\\"apiVersion\\":\\"apps/v1\\",\\"kind\\":\\"Deployment\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c82f78fa5f1261be46ff61475603c88ab5fa680f3b\\":\\"\\",\\"app.kubernetes.io/component\\":\\"api\\",\\"app.kubernetes.io/name\\":\\"wsgi\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-api-wsgi\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"minReadySeconds\\":0,\\"progressDeadlineSeconds\\":600,\\"selector\\":{\\"matchLabels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-api-wsgi-c83e828d\\"}},\\"strategy\\":{\\"rollingUpdate\\":{\\"maxSurge\\":\\"25%\\",\\"maxUnavailable\\":\\"25%\\"},\\"type\\":\\"RollingUpdate\\"},\\"template\\":{\\"metadata\\":{\\"labels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-api-wsgi-c83e828d\\"}},\\"spec\\":{\\"automountServiceAccountToken\\":false,\\"containers\\":[{\\"command\\":[\\"/serve.sh\\",\\"wsgi\\",\\"--workers=2\\",\\"--threads=4\\",\\"--worker-class=gthread\\",\\"--worker-tmp-dir=/worker-tmp\\",\\"--timeout=90\\"],\\"env\\":[{\\"name\\":\\"POSTGRES_USER\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_USER\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_PASSWORD\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_PASSWORD\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_HOST\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_HOST\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}}],\\"envFrom\\":[{\\"configMapRef\\":{\\"name\\":\\"crisiscleanup-config-api-config\\"}}],\\"image\\":\\"crisiscleanup-api:latest\\",\\"imagePullPolicy\\":\\"IfNotPresent\\",\\"livenessProbe\\":{\\"failureThreshold\\":30,\\"httpGet\\":{\\"path\\":\\"/health\\",\\"port\\":5000,\\"scheme\\":\\"HTTP\\"},\\"initialDelaySeconds\\":20,\\"periodSeconds\\":10,\\"timeoutSeconds\\":8},\\"name\\":\\"gunicorn\\",\\"ports\\":[{\\"containerPort\\":5000}],\\"readinessProbe\\":{\\"failureThreshold\\":30,\\"httpGet\\":{\\"path\\":\\"/health\\",\\"port\\":5000,\\"scheme\\":\\"HTTP\\"},\\"initialDelaySeconds\\":20,\\"periodSeconds\\":10,\\"timeoutSeconds\\":8},\\"resources\\":{\\"limits\\":{\\"cpu\\":\\"1800m\\",\\"memory\\":\\"1200Mi\\"},\\"requests\\":{\\"cpu\\":\\"1000m\\",\\"memory\\":\\"1200Mi\\"}},\\"securityContext\\":{\\"allowPrivilegeEscalation\\":false,\\"privileged\\":false,\\"readOnlyRootFilesystem\\":false,\\"runAsGroup\\":1000,\\"runAsNonRoot\\":true,\\"runAsUser\\":1000},\\"startupProbe\\":{\\"failureThreshold\\":30,\\"httpGet\\":{\\"path\\":\\"/health\\",\\"port\\":5000,\\"scheme\\":\\"HTTP\\"},\\"periodSeconds\\":15},\\"volumeMounts\\":[{\\"mountPath\\":\\"/app/staticfiles\\",\\"name\\":\\"staticfiles\\"},{\\"mountPath\\":\\"/worker-tmp\\",\\"name\\":\\"worker-tmp\\"},{\\"mountPath\\":\\"/mnt/secrets-store\\",\\"name\\":\\"secrets-store-inline\\",\\"readOnly\\":true}]}],\\"dnsPolicy\\":\\"ClusterFirst\\",\\"hostNetwork\\":false,\\"restartPolicy\\":\\"Always\\",\\"securityContext\\":{\\"fsGroupChangePolicy\\":\\"Always\\",\\"runAsNonRoot\\":true},\\"serviceAccountName\\":\\"crisiscleanup-api\\",\\"setHostnameAsFQDN\\":false,\\"terminationGracePeriodSeconds\\":30,\\"volumes\\":[{\\"emptyDir\\":{},\\"name\\":\\"staticfiles\\"},{\\"emptyDir\\":{\\"medium\\":\\"Memory\\"},\\"name\\":\\"worker-tmp\\"},{\\"csi\\":{\\"driver\\":\\"secrets-store.csi.k8s.io\\",\\"readOnly\\":true,\\"volumeAttributes\\":{\\"secretProviderClass\\":\\"crisiscleanup-api\\"}},\\"name\\":\\"secrets-store-inline\\"}]}}}},{\\"apiVersion\\":\\"batch/v1\\",\\"kind\\":\\"Job\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c82f78fa5f1261be46ff61475603c88ab5fa680f3b\\":\\"\\",\\"app.kubernetes.io/component\\":\\"api\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-api-wsgi-migrate\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"activeDeadlineSeconds\\":1800,\\"template\\":{\\"metadata\\":{\\"labels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-api-wsgi-migrate-c8890c80\\",\\"component\\":\\"api-migrate\\"}},\\"spec\\":{\\"automountServiceAccountToken\\":false,\\"containers\\":[{\\"command\\":[\\"python\\",\\"manage.py\\",\\"migrate\\",\\"--noinput\\",\\"--verbosity=1\\"],\\"env\\":[{\\"name\\":\\"POSTGRES_USER\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_USER\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_PASSWORD\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_PASSWORD\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_HOST\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_HOST\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}}],\\"envFrom\\":[{\\"configMapRef\\":{\\"name\\":\\"crisiscleanup-config-api-config\\"}}],\\"image\\":\\"crisiscleanup-api:latest\\",\\"imagePullPolicy\\":\\"IfNotPresent\\",\\"name\\":\\"migrate\\",\\"resources\\":{\\"limits\\":{\\"memory\\":\\"3072Mi\\"},\\"requests\\":{\\"cpu\\":\\"100m\\",\\"memory\\":\\"1024Mi\\"}},\\"securityContext\\":{\\"allowPrivilegeEscalation\\":false,\\"privileged\\":false,\\"readOnlyRootFilesystem\\":false,\\"runAsGroup\\":1000,\\"runAsNonRoot\\":true,\\"runAsUser\\":1000},\\"volumeMounts\\":[{\\"mountPath\\":\\"/mnt/secrets-store\\",\\"name\\":\\"secrets-store-inline\\",\\"readOnly\\":true}]}],\\"dnsPolicy\\":\\"ClusterFirst\\",\\"hostNetwork\\":false,\\"restartPolicy\\":\\"Never\\",\\"securityContext\\":{\\"fsGroupChangePolicy\\":\\"Always\\",\\"runAsGroup\\":1000,\\"runAsNonRoot\\":true,\\"runAsUser\\":1000},\\"serviceAccountName\\":\\"crisiscleanup-api\\",\\"setHostnameAsFQDN\\":false,\\"terminationGracePeriodSeconds\\":300,\\"volumes\\":[{\\"csi\\":{\\"driver\\":\\"secrets-store.csi.k8s.io\\",\\"readOnly\\":true,\\"volumeAttributes\\":{\\"secretProviderClass\\":\\"crisiscleanup-api\\"}},\\"name\\":\\"secrets-store-inline\\"}]}},\\"ttlSecondsAfterFinished\\":120}},{\\"apiVersion\\":\\"batch/v1\\",\\"kind\\":\\"Job\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c82f78fa5f1261be46ff61475603c88ab5fa680f3b\\":\\"\\",\\"app.kubernetes.io/component\\":\\"api\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-api-wsgi-collectstatic\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"activeDeadlineSeconds\\":1800,\\"template\\":{\\"metadata\\":{\\"labels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-api-wsgi-collectstatic-c871685d\\",\\"component\\":\\"api-static\\"}},\\"spec\\":{\\"automountServiceAccountToken\\":false,\\"containers\\":[{\\"command\\":[\\"python\\",\\"manage.py\\",\\"collectstatic\\",\\"--no-post-process\\",\\"--noinput\\",\\"--verbosity=2\\"],\\"env\\":[{\\"name\\":\\"POSTGRES_USER\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_USER\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_PASSWORD\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_PASSWORD\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_HOST\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_HOST\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}}],\\"envFrom\\":[{\\"configMapRef\\":{\\"name\\":\\"crisiscleanup-config-api-config\\"}}],\\"image\\":\\"crisiscleanup-api:latest\\",\\"imagePullPolicy\\":\\"IfNotPresent\\",\\"name\\":\\"collectstatic\\",\\"resources\\":{\\"limits\\":{\\"memory\\":\\"3072Mi\\"},\\"requests\\":{\\"cpu\\":\\"100m\\",\\"memory\\":\\"1024Mi\\"}},\\"securityContext\\":{\\"allowPrivilegeEscalation\\":false,\\"privileged\\":false,\\"readOnlyRootFilesystem\\":false,\\"runAsGroup\\":1000,\\"runAsNonRoot\\":true,\\"runAsUser\\":1000},\\"volumeMounts\\":[{\\"mountPath\\":\\"/app/staticfiles\\",\\"name\\":\\"staticfiles\\"},{\\"mountPath\\":\\"/mnt/secrets-store\\",\\"name\\":\\"secrets-store-inline\\",\\"readOnly\\":true}]}],\\"dnsPolicy\\":\\"ClusterFirst\\",\\"hostNetwork\\":false,\\"restartPolicy\\":\\"Never\\",\\"securityContext\\":{\\"fsGroupChangePolicy\\":\\"Always\\",\\"runAsGroup\\":1000,\\"runAsNonRoot\\":true,\\"runAsUser\\":1000},\\"serviceAccountName\\":\\"crisiscleanup-api\\",\\"setHostnameAsFQDN\\":false,\\"terminationGracePeriodSeconds\\":300,\\"volumes\\":[{\\"emptyDir\\":{},\\"name\\":\\"staticfiles\\"},{\\"csi\\":{\\"driver\\":\\"secrets-store.csi.k8s.io\\",\\"readOnly\\":true,\\"volumeAttributes\\":{\\"secretProviderClass\\":\\"crisiscleanup-api\\"}},\\"name\\":\\"secrets-store-inline\\"}]}},\\"ttlSecondsAfterFinished\\":120}},{\\"apiVersion\\":\\"v1\\",\\"kind\\":\\"Service\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c82f78fa5f1261be46ff61475603c88ab5fa680f3b\\":\\"\\",\\"app.kubernetes.io/component\\":\\"api\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-api-wsgi-service\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"externalIPs\\":[],\\"ports\\":[{\\"port\\":5000,\\"targetPort\\":5000}],\\"selector\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-api-wsgi-c83e828d\\"},\\"type\\":\\"ClusterIP\\"}},{\\"apiVersion\\":\\"autoscaling/v2\\",\\"kind\\":\\"HorizontalPodAutoscaler\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c82f78fa5f1261be46ff61475603c88ab5fa680f3b\\":\\"\\",\\"app.kubernetes.io/component\\":\\"api\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-api-wsgi-hpa\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"behavior\\":{\\"scaleDown\\":{\\"policies\\":[{\\"periodSeconds\\":300,\\"type\\":\\"Pods\\",\\"value\\":1}],\\"selectPolicy\\":\\"Max\\",\\"stabilizationWindowSeconds\\":300},\\"scaleUp\\":{\\"policies\\":[{\\"periodSeconds\\":60,\\"type\\":\\"Pods\\",\\"value\\":4},{\\"periodSeconds\\":60,\\"type\\":\\"Percent\\",\\"value\\":200}],\\"selectPolicy\\":\\"Max\\",\\"stabilizationWindowSeconds\\":0}},\\"maxReplicas\\":3,\\"metrics\\":[{\\"resource\\":{\\"name\\":\\"cpu\\",\\"target\\":{\\"averageUtilization\\":70,\\"type\\":\\"Utilization\\"}},\\"type\\":\\"Resource\\"},{\\"resource\\":{\\"name\\":\\"memory\\",\\"target\\":{\\"averageUtilization\\":85,\\"type\\":\\"Utilization\\"}},\\"type\\":\\"Resource\\"}],\\"minReplicas\\":1,\\"scaleTargetRef\\":{\\"apiVersion\\":\\"apps/v1\\",\\"kind\\":\\"Deployment\\",\\"name\\":\\"crisiscleanup-api-wsgi\\"}}},{\\"apiVersion\\":\\"apps/v1\\",\\"kind\\":\\"Deployment\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c82f78fa5f1261be46ff61475603c88ab5fa680f3b\\":\\"\\",\\"app.kubernetes.io/component\\":\\"api\\",\\"app.kubernetes.io/name\\":\\"asgi\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-api-asgi\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"minReadySeconds\\":0,\\"progressDeadlineSeconds\\":600,\\"selector\\":{\\"matchLabels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-api-asgi-c818ff7e\\"}},\\"strategy\\":{\\"rollingUpdate\\":{\\"maxSurge\\":\\"25%\\",\\"maxUnavailable\\":\\"25%\\"},\\"type\\":\\"RollingUpdate\\"},\\"template\\":{\\"metadata\\":{\\"labels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-api-asgi-c818ff7e\\"}},\\"spec\\":{\\"automountServiceAccountToken\\":false,\\"containers\\":[{\\"command\\":[\\"/serve.sh\\",\\"asgi\\",\\"--workers=2\\"],\\"env\\":[{\\"name\\":\\"POSTGRES_USER\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_USER\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_PASSWORD\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_PASSWORD\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_HOST\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_HOST\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}}],\\"envFrom\\":[{\\"configMapRef\\":{\\"name\\":\\"crisiscleanup-config-api-config\\"}}],\\"image\\":\\"crisiscleanup-api:latest\\",\\"imagePullPolicy\\":\\"IfNotPresent\\",\\"livenessProbe\\":{\\"failureThreshold\\":30,\\"httpGet\\":{\\"path\\":\\"/ws/health\\",\\"port\\":5000,\\"scheme\\":\\"HTTP\\"},\\"initialDelaySeconds\\":20,\\"periodSeconds\\":10,\\"timeoutSeconds\\":8},\\"name\\":\\"hypercorn\\",\\"ports\\":[{\\"containerPort\\":5000}],\\"readinessProbe\\":{\\"failureThreshold\\":30,\\"httpGet\\":{\\"path\\":\\"/ws/health\\",\\"port\\":5000,\\"scheme\\":\\"HTTP\\"},\\"initialDelaySeconds\\":20,\\"periodSeconds\\":10,\\"timeoutSeconds\\":8},\\"resources\\":{\\"limits\\":{\\"cpu\\":\\"1500m\\",\\"memory\\":\\"1024Mi\\"},\\"requests\\":{\\"cpu\\":\\"500m\\",\\"memory\\":\\"1024Mi\\"}},\\"securityContext\\":{\\"allowPrivilegeEscalation\\":false,\\"privileged\\":false,\\"readOnlyRootFilesystem\\":false,\\"runAsGroup\\":1000,\\"runAsNonRoot\\":true,\\"runAsUser\\":1000},\\"startupProbe\\":{\\"failureThreshold\\":30,\\"httpGet\\":{\\"path\\":\\"/ws/health\\",\\"port\\":5000,\\"scheme\\":\\"HTTP\\"},\\"periodSeconds\\":15},\\"volumeMounts\\":[{\\"mountPath\\":\\"/mnt/secrets-store\\",\\"name\\":\\"secrets-store-inline\\",\\"readOnly\\":true}]}],\\"dnsPolicy\\":\\"ClusterFirst\\",\\"hostNetwork\\":false,\\"restartPolicy\\":\\"Always\\",\\"securityContext\\":{\\"fsGroupChangePolicy\\":\\"Always\\",\\"runAsNonRoot\\":true},\\"serviceAccountName\\":\\"crisiscleanup-api\\",\\"setHostnameAsFQDN\\":false,\\"terminationGracePeriodSeconds\\":30,\\"volumes\\":[{\\"csi\\":{\\"driver\\":\\"secrets-store.csi.k8s.io\\",\\"readOnly\\":true,\\"volumeAttributes\\":{\\"secretProviderClass\\":\\"crisiscleanup-api\\"}},\\"name\\":\\"secrets-store-inline\\"}]}}}},{\\"apiVersion\\":\\"storage.k8s.io/v1\\",\\"kind\\":\\"StorageClass\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c82f78fa5f1261be46ff61475603c88ab5fa680f3b\\":\\"\\",\\"app.kubernetes.io/component\\":\\"api\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"rag-models\\",\\"namespace\\":\\"local\\"},\\"parameters\\":{\\"allowAutoIOPSPerGBIncrease\\":\\"true\\",\\"iops\\":\\"1000\\",\\"type\\":\\"io2\\"},\\"provisioner\\":\\"ebs.csi.aws.com\\",\\"volumeBindingMode\\":\\"WaitForFirstConsumer\\"},{\\"apiVersion\\":\\"v1\\",\\"kind\\":\\"Service\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c82f78fa5f1261be46ff61475603c88ab5fa680f3b\\":\\"\\",\\"app.kubernetes.io/component\\":\\"api\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-api-asgi-asgi-rag-service\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"clusterIP\\":\\"None\\",\\"externalIPs\\":[],\\"ports\\":[{\\"name\\":\\"channels\\",\\"port\\":5000}],\\"selector\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-api-asgi-rag-c86cf6a6\\"},\\"type\\":\\"ClusterIP\\"}},{\\"apiVersion\\":\\"apps/v1\\",\\"kind\\":\\"StatefulSet\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c82f78fa5f1261be46ff61475603c88ab5fa680f3b\\":\\"\\",\\"app.kubernetes.io/component\\":\\"api\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-api-asgi-rag\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"minReadySeconds\\":0,\\"podManagementPolicy\\":\\"OrderedReady\\",\\"selector\\":{\\"matchLabels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-api-asgi-rag-c86cf6a6\\"}},\\"serviceName\\":\\"crisiscleanup-api-asgi-asgi-rag-service\\",\\"template\\":{\\"metadata\\":{\\"labels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-api-asgi-rag-c86cf6a6\\"}},\\"spec\\":{\\"affinity\\":{\\"podAntiAffinity\\":{\\"requiredDuringSchedulingIgnoredDuringExecution\\":[{\\"labelSelector\\":{\\"matchLabels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-api-asgi-rag-c86cf6a6\\"}},\\"namespaces\\":[\\"local\\"],\\"topologyKey\\":\\"kubernetes.io/hostname\\"},{\\"labelSelector\\":{\\"matchLabels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-api-asgi-rag-c86cf6a6\\"}},\\"namespaces\\":[\\"local\\"],\\"topologyKey\\":\\"topology.kubernetes.io/zone\\"}]}},\\"automountServiceAccountToken\\":false,\\"containers\\":[{\\"command\\":[\\"/serve.sh\\",\\"channelsworker\\",\\"rag-document\\"],\\"env\\":[{\\"name\\":\\"POSTGRES_USER\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_USER\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_PASSWORD\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_PASSWORD\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_HOST\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_HOST\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}}],\\"envFrom\\":[{\\"configMapRef\\":{\\"name\\":\\"crisiscleanup-config-api-config\\"}}],\\"image\\":\\"crisiscleanup-api:latest\\",\\"imagePullPolicy\\":\\"IfNotPresent\\",\\"name\\":\\"rag-channels\\",\\"resources\\":{\\"limits\\":{\\"memory\\":\\"4096Mi\\"},\\"requests\\":{\\"cpu\\":\\"200m\\",\\"memory\\":\\"1024Mi\\"}},\\"securityContext\\":{\\"allowPrivilegeEscalation\\":false,\\"privileged\\":false,\\"readOnlyRootFilesystem\\":false,\\"runAsGroup\\":1000,\\"runAsNonRoot\\":true,\\"runAsUser\\":1000},\\"volumeMounts\\":[{\\"mountPath\\":\\"/ccu/nltk_data\\",\\"name\\":\\"rag-volume\\",\\"subPath\\":\\"nltk_data\\"},{\\"mountPath\\":\\"/ccu/.cache/huggingface\\",\\"name\\":\\"rag-volume\\",\\"subPath\\":\\"hf_data\\"},{\\"mountPath\\":\\"/ccu/.cache/matplotlib\\",\\"name\\":\\"rag-volume\\",\\"subPath\\":\\"mp_data\\"}]}],\\"dnsPolicy\\":\\"ClusterFirst\\",\\"hostNetwork\\":false,\\"initContainers\\":[{\\"command\\":[\\"sh\\",\\"-x\\",\\"-c\\",\\"mkdir -p /ccu && chown -R 1000:1000 /ccu\\"],\\"image\\":\\"public.ecr.aws/docker/library/busybox:stable\\",\\"imagePullPolicy\\":\\"IfNotPresent\\",\\"name\\":\\"host-mounts-init\\",\\"resources\\":{\\"limits\\":{\\"cpu\\":\\"30m\\",\\"memory\\":\\"50Mi\\"},\\"requests\\":{\\"cpu\\":\\"20m\\",\\"memory\\":\\"20Mi\\"}},\\"securityContext\\":{\\"allowPrivilegeEscalation\\":false,\\"privileged\\":false,\\"readOnlyRootFilesystem\\":false,\\"runAsGroup\\":0,\\"runAsNonRoot\\":false,\\"runAsUser\\":0},\\"volumeMounts\\":[{\\"mountPath\\":\\"/ccu/nltk_data\\",\\"name\\":\\"rag-volume\\",\\"subPath\\":\\"nltk_data\\"},{\\"mountPath\\":\\"/ccu/.cache/huggingface\\",\\"name\\":\\"rag-volume\\",\\"subPath\\":\\"hf_data\\"},{\\"mountPath\\":\\"/ccu/.cache/matplotlib\\",\\"name\\":\\"rag-volume\\",\\"subPath\\":\\"mp_data\\"}]}],\\"restartPolicy\\":\\"Always\\",\\"securityContext\\":{\\"fsGroupChangePolicy\\":\\"Always\\",\\"runAsNonRoot\\":true},\\"serviceAccountName\\":\\"crisiscleanup-api\\",\\"setHostnameAsFQDN\\":false,\\"terminationGracePeriodSeconds\\":30,\\"volumes\\":[{\\"csi\\":{\\"driver\\":\\"secrets-store.csi.k8s.io\\",\\"readOnly\\":true,\\"volumeAttributes\\":{\\"secretProviderClass\\":\\"crisiscleanup-api\\"}},\\"name\\":\\"secrets-store-inline\\"}]}},\\"updateStrategy\\":{\\"rollingUpdate\\":{\\"partition\\":0},\\"type\\":\\"RollingUpdate\\"},\\"volumeClaimTemplates\\":[{\\"metadata\\":{\\"name\\":\\"rag-volume\\"},\\"spec\\":{\\"accessModes\\":[\\"ReadWriteOnce\\"],\\"storageClassName\\":\\"rag-models\\",\\"resources\\":{\\"requests\\":{\\"storage\\":\\"10Gi\\"}}}}]}},{\\"apiVersion\\":\\"autoscaling/v2\\",\\"kind\\":\\"HorizontalPodAutoscaler\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c82f78fa5f1261be46ff61475603c88ab5fa680f3b\\":\\"\\",\\"app.kubernetes.io/component\\":\\"api\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-api-asgi-rag-scaling-hpa\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"behavior\\":{\\"scaleDown\\":{\\"policies\\":[{\\"periodSeconds\\":300,\\"type\\":\\"Pods\\",\\"value\\":1}],\\"selectPolicy\\":\\"Max\\",\\"stabilizationWindowSeconds\\":300},\\"scaleUp\\":{\\"policies\\":[{\\"periodSeconds\\":60,\\"type\\":\\"Pods\\",\\"value\\":4},{\\"periodSeconds\\":60,\\"type\\":\\"Percent\\",\\"value\\":200}],\\"selectPolicy\\":\\"Max\\",\\"stabilizationWindowSeconds\\":0}},\\"maxReplicas\\":6,\\"metrics\\":[{\\"resource\\":{\\"name\\":\\"cpu\\",\\"target\\":{\\"averageUtilization\\":50,\\"type\\":\\"Utilization\\"}},\\"type\\":\\"Resource\\"},{\\"resource\\":{\\"name\\":\\"memory\\",\\"target\\":{\\"averageUtilization\\":80,\\"type\\":\\"Utilization\\"}},\\"type\\":\\"Resource\\"}],\\"minReplicas\\":1,\\"scaleTargetRef\\":{\\"apiVersion\\":\\"apps/v1\\",\\"kind\\":\\"StatefulSet\\",\\"name\\":\\"crisiscleanup-api-asgi-rag\\"}}},{\\"apiVersion\\":\\"v1\\",\\"kind\\":\\"Service\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c82f78fa5f1261be46ff61475603c88ab5fa680f3b\\":\\"\\",\\"app.kubernetes.io/component\\":\\"api\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-api-asgi-service\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"externalIPs\\":[],\\"ports\\":[{\\"port\\":5000,\\"targetPort\\":5000}],\\"selector\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-api-asgi-c818ff7e\\"},\\"type\\":\\"ClusterIP\\"}},{\\"apiVersion\\":\\"autoscaling/v2\\",\\"kind\\":\\"HorizontalPodAutoscaler\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c82f78fa5f1261be46ff61475603c88ab5fa680f3b\\":\\"\\",\\"app.kubernetes.io/component\\":\\"api\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-api-asgi-hpa\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"behavior\\":{\\"scaleDown\\":{\\"policies\\":[{\\"periodSeconds\\":300,\\"type\\":\\"Pods\\",\\"value\\":1}],\\"selectPolicy\\":\\"Max\\",\\"stabilizationWindowSeconds\\":300},\\"scaleUp\\":{\\"policies\\":[{\\"periodSeconds\\":60,\\"type\\":\\"Pods\\",\\"value\\":4},{\\"periodSeconds\\":60,\\"type\\":\\"Percent\\",\\"value\\":200}],\\"selectPolicy\\":\\"Max\\",\\"stabilizationWindowSeconds\\":0}},\\"maxReplicas\\":2,\\"metrics\\":[{\\"resource\\":{\\"name\\":\\"cpu\\",\\"target\\":{\\"averageUtilization\\":70,\\"type\\":\\"Utilization\\"}},\\"type\\":\\"Resource\\"},{\\"resource\\":{\\"name\\":\\"memory\\",\\"target\\":{\\"averageUtilization\\":85,\\"type\\":\\"Utilization\\"}},\\"type\\":\\"Resource\\"}],\\"minReplicas\\":1,\\"scaleTargetRef\\":{\\"apiVersion\\":\\"apps/v1\\",\\"kind\\":\\"Deployment\\",\\"name\\":\\"crisiscleanup-api-asgi\\"}}},{\\"apiVersion\\":\\"apps/v1\\",\\"kind\\":\\"Deployment\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c82f78fa5f1261be46ff61475603c88ab5fa680f3b\\":\\"\\",\\"app.kubernetes.io/component\\":\\"api\\",\\"app.kubernetes.io/name\\":\\"adminwebsocket\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-api-admin-websocket\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"minReadySeconds\\":0,\\"progressDeadlineSeconds\\":600,\\"replicas\\":1,\\"selector\\":{\\"matchLabels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-api-admin-websocket-c879d9e4\\"}},\\"strategy\\":{\\"rollingUpdate\\":{\\"maxSurge\\":\\"25%\\",\\"maxUnavailable\\":\\"25%\\"},\\"type\\":\\"RollingUpdate\\"},\\"template\\":{\\"metadata\\":{\\"labels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-api-admin-websocket-c879d9e4\\"}},\\"spec\\":{\\"automountServiceAccountToken\\":false,\\"containers\\":[{\\"command\\":[\\"/serve.sh\\",\\"adminwebsocket\\"],\\"env\\":[{\\"name\\":\\"POSTGRES_USER\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_USER\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_PASSWORD\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_PASSWORD\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_HOST\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_HOST\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}}],\\"envFrom\\":[{\\"configMapRef\\":{\\"name\\":\\"crisiscleanup-config-api-config\\"}}],\\"image\\":\\"crisiscleanup-api:latest\\",\\"imagePullPolicy\\":\\"IfNotPresent\\",\\"name\\":\\"adminwebsocket\\",\\"resources\\":{\\"limits\\":{\\"memory\\":\\"250Mi\\"},\\"requests\\":{\\"cpu\\":\\"3m\\",\\"memory\\":\\"250Mi\\"}},\\"securityContext\\":{\\"allowPrivilegeEscalation\\":false,\\"privileged\\":false,\\"readOnlyRootFilesystem\\":false,\\"runAsGroup\\":1000,\\"runAsNonRoot\\":true,\\"runAsUser\\":1000},\\"volumeMounts\\":[{\\"mountPath\\":\\"/mnt/secrets-store\\",\\"name\\":\\"secrets-store-inline\\",\\"readOnly\\":true}]}],\\"dnsPolicy\\":\\"ClusterFirst\\",\\"hostNetwork\\":false,\\"restartPolicy\\":\\"Always\\",\\"securityContext\\":{\\"fsGroupChangePolicy\\":\\"Always\\",\\"runAsNonRoot\\":true},\\"serviceAccountName\\":\\"crisiscleanup-api\\",\\"setHostnameAsFQDN\\":false,\\"terminationGracePeriodSeconds\\":30,\\"volumes\\":[{\\"csi\\":{\\"driver\\":\\"secrets-store.csi.k8s.io\\",\\"readOnly\\":true,\\"volumeAttributes\\":{\\"secretProviderClass\\":\\"crisiscleanup-api\\"}},\\"name\\":\\"secrets-store-inline\\"}]}}}}]", + "Manifest": "[{\\"apiVersion\\":\\"apps/v1\\",\\"kind\\":\\"Deployment\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c82f78fa5f1261be46ff61475603c88ab5fa680f3b\\":\\"\\",\\"app.kubernetes.io/component\\":\\"api\\",\\"app.kubernetes.io/name\\":\\"wsgi\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-api-wsgi\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"minReadySeconds\\":0,\\"progressDeadlineSeconds\\":600,\\"selector\\":{\\"matchLabels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-api-wsgi-c83e828d\\"}},\\"strategy\\":{\\"rollingUpdate\\":{\\"maxSurge\\":\\"25%\\",\\"maxUnavailable\\":\\"25%\\"},\\"type\\":\\"RollingUpdate\\"},\\"template\\":{\\"metadata\\":{\\"labels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-api-wsgi-c83e828d\\"}},\\"spec\\":{\\"automountServiceAccountToken\\":false,\\"containers\\":[{\\"command\\":[\\"/serve.sh\\",\\"wsgi\\",\\"--workers=2\\",\\"--threads=4\\",\\"--worker-class=gthread\\",\\"--worker-tmp-dir=/worker-tmp\\",\\"--timeout=90\\"],\\"env\\":[{\\"name\\":\\"POSTGRES_USER\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_USER\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_PASSWORD\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_PASSWORD\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_HOST\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_HOST\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}}],\\"envFrom\\":[{\\"configMapRef\\":{\\"name\\":\\"crisiscleanup-config-api-config\\"}}],\\"image\\":\\"crisiscleanup-api:latest\\",\\"imagePullPolicy\\":\\"IfNotPresent\\",\\"livenessProbe\\":{\\"failureThreshold\\":30,\\"httpGet\\":{\\"path\\":\\"/health\\",\\"port\\":5000,\\"scheme\\":\\"HTTP\\"},\\"initialDelaySeconds\\":20,\\"periodSeconds\\":10,\\"timeoutSeconds\\":8},\\"name\\":\\"gunicorn\\",\\"ports\\":[{\\"containerPort\\":5000}],\\"readinessProbe\\":{\\"failureThreshold\\":30,\\"httpGet\\":{\\"path\\":\\"/health\\",\\"port\\":5000,\\"scheme\\":\\"HTTP\\"},\\"initialDelaySeconds\\":20,\\"periodSeconds\\":10,\\"timeoutSeconds\\":8},\\"resources\\":{\\"limits\\":{\\"cpu\\":\\"1800m\\",\\"memory\\":\\"1200Mi\\"},\\"requests\\":{\\"cpu\\":\\"1000m\\",\\"memory\\":\\"1200Mi\\"}},\\"securityContext\\":{\\"allowPrivilegeEscalation\\":false,\\"privileged\\":false,\\"readOnlyRootFilesystem\\":false,\\"runAsGroup\\":1000,\\"runAsNonRoot\\":true,\\"runAsUser\\":1000},\\"startupProbe\\":{\\"failureThreshold\\":30,\\"httpGet\\":{\\"path\\":\\"/health\\",\\"port\\":5000,\\"scheme\\":\\"HTTP\\"},\\"periodSeconds\\":15},\\"volumeMounts\\":[{\\"mountPath\\":\\"/app/staticfiles\\",\\"name\\":\\"staticfiles\\"},{\\"mountPath\\":\\"/worker-tmp\\",\\"name\\":\\"worker-tmp\\"},{\\"mountPath\\":\\"/mnt/secrets-store\\",\\"name\\":\\"secrets-store-inline\\",\\"readOnly\\":true}]}],\\"dnsPolicy\\":\\"ClusterFirst\\",\\"hostNetwork\\":false,\\"restartPolicy\\":\\"Always\\",\\"securityContext\\":{\\"fsGroupChangePolicy\\":\\"Always\\",\\"runAsNonRoot\\":true},\\"serviceAccountName\\":\\"crisiscleanup-api\\",\\"setHostnameAsFQDN\\":false,\\"terminationGracePeriodSeconds\\":30,\\"volumes\\":[{\\"emptyDir\\":{},\\"name\\":\\"staticfiles\\"},{\\"emptyDir\\":{\\"medium\\":\\"Memory\\"},\\"name\\":\\"worker-tmp\\"},{\\"csi\\":{\\"driver\\":\\"secrets-store.csi.k8s.io\\",\\"readOnly\\":true,\\"volumeAttributes\\":{\\"secretProviderClass\\":\\"crisiscleanup-api\\"}},\\"name\\":\\"secrets-store-inline\\"}]}}}},{\\"apiVersion\\":\\"batch/v1\\",\\"kind\\":\\"Job\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c82f78fa5f1261be46ff61475603c88ab5fa680f3b\\":\\"\\",\\"app.kubernetes.io/component\\":\\"api\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-api-wsgi-migrate\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"activeDeadlineSeconds\\":1800,\\"template\\":{\\"metadata\\":{\\"labels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-api-wsgi-migrate-c8890c80\\",\\"component\\":\\"api-migrate\\"}},\\"spec\\":{\\"automountServiceAccountToken\\":false,\\"containers\\":[{\\"command\\":[\\"python\\",\\"manage.py\\",\\"migrate\\",\\"--noinput\\",\\"--verbosity=1\\"],\\"env\\":[{\\"name\\":\\"POSTGRES_USER\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_USER\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_PASSWORD\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_PASSWORD\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_HOST\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_HOST\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}}],\\"envFrom\\":[{\\"configMapRef\\":{\\"name\\":\\"crisiscleanup-config-api-config\\"}}],\\"image\\":\\"crisiscleanup-api:latest\\",\\"imagePullPolicy\\":\\"IfNotPresent\\",\\"name\\":\\"migrate\\",\\"resources\\":{\\"limits\\":{\\"memory\\":\\"3072Mi\\"},\\"requests\\":{\\"cpu\\":\\"100m\\",\\"memory\\":\\"1024Mi\\"}},\\"securityContext\\":{\\"allowPrivilegeEscalation\\":false,\\"privileged\\":false,\\"readOnlyRootFilesystem\\":false,\\"runAsGroup\\":1000,\\"runAsNonRoot\\":true,\\"runAsUser\\":1000},\\"volumeMounts\\":[{\\"mountPath\\":\\"/mnt/secrets-store\\",\\"name\\":\\"secrets-store-inline\\",\\"readOnly\\":true}]}],\\"dnsPolicy\\":\\"ClusterFirst\\",\\"hostNetwork\\":false,\\"restartPolicy\\":\\"Never\\",\\"securityContext\\":{\\"fsGroupChangePolicy\\":\\"Always\\",\\"runAsGroup\\":1000,\\"runAsNonRoot\\":true,\\"runAsUser\\":1000},\\"serviceAccountName\\":\\"crisiscleanup-api\\",\\"setHostnameAsFQDN\\":false,\\"terminationGracePeriodSeconds\\":300,\\"volumes\\":[{\\"csi\\":{\\"driver\\":\\"secrets-store.csi.k8s.io\\",\\"readOnly\\":true,\\"volumeAttributes\\":{\\"secretProviderClass\\":\\"crisiscleanup-api\\"}},\\"name\\":\\"secrets-store-inline\\"}]}},\\"ttlSecondsAfterFinished\\":120}},{\\"apiVersion\\":\\"batch/v1\\",\\"kind\\":\\"Job\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c82f78fa5f1261be46ff61475603c88ab5fa680f3b\\":\\"\\",\\"app.kubernetes.io/component\\":\\"api\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-api-wsgi-collectstatic\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"activeDeadlineSeconds\\":1800,\\"template\\":{\\"metadata\\":{\\"labels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-api-wsgi-collectstatic-c871685d\\",\\"component\\":\\"api-static\\"}},\\"spec\\":{\\"automountServiceAccountToken\\":false,\\"containers\\":[{\\"command\\":[\\"python\\",\\"manage.py\\",\\"collectstatic\\",\\"--no-post-process\\",\\"--noinput\\",\\"--verbosity=2\\"],\\"env\\":[{\\"name\\":\\"POSTGRES_USER\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_USER\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_PASSWORD\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_PASSWORD\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_HOST\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_HOST\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}}],\\"envFrom\\":[{\\"configMapRef\\":{\\"name\\":\\"crisiscleanup-config-api-config\\"}}],\\"image\\":\\"crisiscleanup-api:latest\\",\\"imagePullPolicy\\":\\"IfNotPresent\\",\\"name\\":\\"collectstatic\\",\\"resources\\":{\\"limits\\":{\\"memory\\":\\"3072Mi\\"},\\"requests\\":{\\"cpu\\":\\"100m\\",\\"memory\\":\\"1024Mi\\"}},\\"securityContext\\":{\\"allowPrivilegeEscalation\\":false,\\"privileged\\":false,\\"readOnlyRootFilesystem\\":false,\\"runAsGroup\\":1000,\\"runAsNonRoot\\":true,\\"runAsUser\\":1000},\\"volumeMounts\\":[{\\"mountPath\\":\\"/app/staticfiles\\",\\"name\\":\\"staticfiles\\"},{\\"mountPath\\":\\"/mnt/secrets-store\\",\\"name\\":\\"secrets-store-inline\\",\\"readOnly\\":true}]}],\\"dnsPolicy\\":\\"ClusterFirst\\",\\"hostNetwork\\":false,\\"restartPolicy\\":\\"Never\\",\\"securityContext\\":{\\"fsGroupChangePolicy\\":\\"Always\\",\\"runAsGroup\\":1000,\\"runAsNonRoot\\":true,\\"runAsUser\\":1000},\\"serviceAccountName\\":\\"crisiscleanup-api\\",\\"setHostnameAsFQDN\\":false,\\"terminationGracePeriodSeconds\\":300,\\"volumes\\":[{\\"emptyDir\\":{},\\"name\\":\\"staticfiles\\"},{\\"csi\\":{\\"driver\\":\\"secrets-store.csi.k8s.io\\",\\"readOnly\\":true,\\"volumeAttributes\\":{\\"secretProviderClass\\":\\"crisiscleanup-api\\"}},\\"name\\":\\"secrets-store-inline\\"}]}},\\"ttlSecondsAfterFinished\\":120}},{\\"apiVersion\\":\\"v1\\",\\"kind\\":\\"Service\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c82f78fa5f1261be46ff61475603c88ab5fa680f3b\\":\\"\\",\\"app.kubernetes.io/component\\":\\"api\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-api-wsgi-service\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"externalIPs\\":[],\\"ports\\":[{\\"port\\":5000,\\"targetPort\\":5000}],\\"selector\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-api-wsgi-c83e828d\\"},\\"type\\":\\"ClusterIP\\"}},{\\"apiVersion\\":\\"autoscaling/v2\\",\\"kind\\":\\"HorizontalPodAutoscaler\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c82f78fa5f1261be46ff61475603c88ab5fa680f3b\\":\\"\\",\\"app.kubernetes.io/component\\":\\"api\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-api-wsgi-hpa\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"behavior\\":{\\"scaleDown\\":{\\"policies\\":[{\\"periodSeconds\\":300,\\"type\\":\\"Pods\\",\\"value\\":1}],\\"selectPolicy\\":\\"Max\\",\\"stabilizationWindowSeconds\\":300},\\"scaleUp\\":{\\"policies\\":[{\\"periodSeconds\\":60,\\"type\\":\\"Pods\\",\\"value\\":4},{\\"periodSeconds\\":60,\\"type\\":\\"Percent\\",\\"value\\":200}],\\"selectPolicy\\":\\"Max\\",\\"stabilizationWindowSeconds\\":0}},\\"maxReplicas\\":3,\\"metrics\\":[{\\"resource\\":{\\"name\\":\\"cpu\\",\\"target\\":{\\"averageUtilization\\":70,\\"type\\":\\"Utilization\\"}},\\"type\\":\\"Resource\\"},{\\"resource\\":{\\"name\\":\\"memory\\",\\"target\\":{\\"averageUtilization\\":85,\\"type\\":\\"Utilization\\"}},\\"type\\":\\"Resource\\"}],\\"minReplicas\\":1,\\"scaleTargetRef\\":{\\"apiVersion\\":\\"apps/v1\\",\\"kind\\":\\"Deployment\\",\\"name\\":\\"crisiscleanup-api-wsgi\\"}}},{\\"apiVersion\\":\\"autoscaling.k8s.io/v1\\",\\"kind\\":\\"VerticalPodAutoscaler\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c82f78fa5f1261be46ff61475603c88ab5fa680f3b\\":\\"\\",\\"app.kubernetes.io/component\\":\\"api\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-api-wsgi-vpa\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"targetRef\\":{\\"apiVersion\\":\\"apps/v1\\",\\"kind\\":\\"Deployment\\",\\"name\\":\\"crisiscleanup-api-wsgi\\"},\\"updatePolicy\\":{\\"updateMode\\":\\"Auto\\"}}},{\\"apiVersion\\":\\"apps/v1\\",\\"kind\\":\\"Deployment\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c82f78fa5f1261be46ff61475603c88ab5fa680f3b\\":\\"\\",\\"app.kubernetes.io/component\\":\\"api\\",\\"app.kubernetes.io/name\\":\\"asgi\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-api-asgi\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"minReadySeconds\\":0,\\"progressDeadlineSeconds\\":600,\\"selector\\":{\\"matchLabels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-api-asgi-c818ff7e\\"}},\\"strategy\\":{\\"rollingUpdate\\":{\\"maxSurge\\":\\"25%\\",\\"maxUnavailable\\":\\"25%\\"},\\"type\\":\\"RollingUpdate\\"},\\"template\\":{\\"metadata\\":{\\"labels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-api-asgi-c818ff7e\\"}},\\"spec\\":{\\"automountServiceAccountToken\\":false,\\"containers\\":[{\\"command\\":[\\"/serve.sh\\",\\"asgi\\",\\"--workers=2\\"],\\"env\\":[{\\"name\\":\\"POSTGRES_USER\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_USER\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_PASSWORD\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_PASSWORD\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_HOST\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_HOST\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}}],\\"envFrom\\":[{\\"configMapRef\\":{\\"name\\":\\"crisiscleanup-config-api-config\\"}}],\\"image\\":\\"crisiscleanup-api:latest\\",\\"imagePullPolicy\\":\\"IfNotPresent\\",\\"livenessProbe\\":{\\"failureThreshold\\":30,\\"httpGet\\":{\\"path\\":\\"/ws/health\\",\\"port\\":5000,\\"scheme\\":\\"HTTP\\"},\\"initialDelaySeconds\\":20,\\"periodSeconds\\":10,\\"timeoutSeconds\\":8},\\"name\\":\\"hypercorn\\",\\"ports\\":[{\\"containerPort\\":5000}],\\"readinessProbe\\":{\\"failureThreshold\\":30,\\"httpGet\\":{\\"path\\":\\"/ws/health\\",\\"port\\":5000,\\"scheme\\":\\"HTTP\\"},\\"initialDelaySeconds\\":20,\\"periodSeconds\\":10,\\"timeoutSeconds\\":8},\\"resources\\":{\\"limits\\":{\\"cpu\\":\\"1500m\\",\\"memory\\":\\"1024Mi\\"},\\"requests\\":{\\"cpu\\":\\"500m\\",\\"memory\\":\\"1024Mi\\"}},\\"securityContext\\":{\\"allowPrivilegeEscalation\\":false,\\"privileged\\":false,\\"readOnlyRootFilesystem\\":false,\\"runAsGroup\\":1000,\\"runAsNonRoot\\":true,\\"runAsUser\\":1000},\\"startupProbe\\":{\\"failureThreshold\\":30,\\"httpGet\\":{\\"path\\":\\"/ws/health\\",\\"port\\":5000,\\"scheme\\":\\"HTTP\\"},\\"periodSeconds\\":15},\\"volumeMounts\\":[{\\"mountPath\\":\\"/mnt/secrets-store\\",\\"name\\":\\"secrets-store-inline\\",\\"readOnly\\":true}]}],\\"dnsPolicy\\":\\"ClusterFirst\\",\\"hostNetwork\\":false,\\"restartPolicy\\":\\"Always\\",\\"securityContext\\":{\\"fsGroupChangePolicy\\":\\"Always\\",\\"runAsNonRoot\\":true},\\"serviceAccountName\\":\\"crisiscleanup-api\\",\\"setHostnameAsFQDN\\":false,\\"terminationGracePeriodSeconds\\":30,\\"volumes\\":[{\\"csi\\":{\\"driver\\":\\"secrets-store.csi.k8s.io\\",\\"readOnly\\":true,\\"volumeAttributes\\":{\\"secretProviderClass\\":\\"crisiscleanup-api\\"}},\\"name\\":\\"secrets-store-inline\\"}]}}}},{\\"apiVersion\\":\\"storage.k8s.io/v1\\",\\"kind\\":\\"StorageClass\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c82f78fa5f1261be46ff61475603c88ab5fa680f3b\\":\\"\\",\\"app.kubernetes.io/component\\":\\"api\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"rag-models\\",\\"namespace\\":\\"local\\"},\\"parameters\\":{\\"allowAutoIOPSPerGBIncrease\\":\\"true\\",\\"iops\\":\\"1000\\",\\"type\\":\\"io2\\"},\\"provisioner\\":\\"ebs.csi.aws.com\\",\\"volumeBindingMode\\":\\"WaitForFirstConsumer\\"},{\\"apiVersion\\":\\"v1\\",\\"kind\\":\\"Service\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c82f78fa5f1261be46ff61475603c88ab5fa680f3b\\":\\"\\",\\"app.kubernetes.io/component\\":\\"api\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-api-asgi-asgi-rag-service\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"clusterIP\\":\\"None\\",\\"externalIPs\\":[],\\"ports\\":[{\\"name\\":\\"channels\\",\\"port\\":5000}],\\"selector\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-api-asgi-rag-c86cf6a6\\"},\\"type\\":\\"ClusterIP\\"}},{\\"apiVersion\\":\\"apps/v1\\",\\"kind\\":\\"StatefulSet\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c82f78fa5f1261be46ff61475603c88ab5fa680f3b\\":\\"\\",\\"app.kubernetes.io/component\\":\\"api\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-api-asgi-rag\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"minReadySeconds\\":0,\\"podManagementPolicy\\":\\"OrderedReady\\",\\"selector\\":{\\"matchLabels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-api-asgi-rag-c86cf6a6\\"}},\\"serviceName\\":\\"crisiscleanup-api-asgi-asgi-rag-service\\",\\"template\\":{\\"metadata\\":{\\"labels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-api-asgi-rag-c86cf6a6\\"}},\\"spec\\":{\\"affinity\\":{\\"podAntiAffinity\\":{\\"requiredDuringSchedulingIgnoredDuringExecution\\":[{\\"labelSelector\\":{\\"matchLabels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-api-asgi-rag-c86cf6a6\\"}},\\"namespaces\\":[\\"local\\"],\\"topologyKey\\":\\"kubernetes.io/hostname\\"},{\\"labelSelector\\":{\\"matchLabels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-api-asgi-rag-c86cf6a6\\"}},\\"namespaces\\":[\\"local\\"],\\"topologyKey\\":\\"topology.kubernetes.io/zone\\"}]}},\\"automountServiceAccountToken\\":false,\\"containers\\":[{\\"command\\":[\\"/serve.sh\\",\\"channelsworker\\",\\"rag-document\\"],\\"env\\":[{\\"name\\":\\"POSTGRES_USER\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_USER\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_PASSWORD\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_PASSWORD\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_HOST\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_HOST\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}}],\\"envFrom\\":[{\\"configMapRef\\":{\\"name\\":\\"crisiscleanup-config-api-config\\"}}],\\"image\\":\\"crisiscleanup-api:latest\\",\\"imagePullPolicy\\":\\"IfNotPresent\\",\\"name\\":\\"rag-channels\\",\\"resources\\":{\\"limits\\":{\\"memory\\":\\"4096Mi\\"},\\"requests\\":{\\"cpu\\":\\"200m\\",\\"memory\\":\\"1024Mi\\"}},\\"securityContext\\":{\\"allowPrivilegeEscalation\\":false,\\"privileged\\":false,\\"readOnlyRootFilesystem\\":false,\\"runAsGroup\\":1000,\\"runAsNonRoot\\":true,\\"runAsUser\\":1000},\\"volumeMounts\\":[{\\"mountPath\\":\\"/ccu/nltk_data\\",\\"name\\":\\"rag-volume\\",\\"subPath\\":\\"nltk_data\\"},{\\"mountPath\\":\\"/ccu/.cache/huggingface\\",\\"name\\":\\"rag-volume\\",\\"subPath\\":\\"hf_data\\"},{\\"mountPath\\":\\"/ccu/.cache/matplotlib\\",\\"name\\":\\"rag-volume\\",\\"subPath\\":\\"mp_data\\"}]}],\\"dnsPolicy\\":\\"ClusterFirst\\",\\"hostNetwork\\":false,\\"initContainers\\":[{\\"command\\":[\\"sh\\",\\"-x\\",\\"-c\\",\\"mkdir -p /ccu && chown -R 1000:1000 /ccu\\"],\\"image\\":\\"public.ecr.aws/docker/library/busybox:stable\\",\\"imagePullPolicy\\":\\"IfNotPresent\\",\\"name\\":\\"host-mounts-init\\",\\"resources\\":{\\"limits\\":{\\"cpu\\":\\"30m\\",\\"memory\\":\\"50Mi\\"},\\"requests\\":{\\"cpu\\":\\"20m\\",\\"memory\\":\\"20Mi\\"}},\\"securityContext\\":{\\"allowPrivilegeEscalation\\":false,\\"privileged\\":false,\\"readOnlyRootFilesystem\\":false,\\"runAsGroup\\":0,\\"runAsNonRoot\\":false,\\"runAsUser\\":0},\\"volumeMounts\\":[{\\"mountPath\\":\\"/ccu/nltk_data\\",\\"name\\":\\"rag-volume\\",\\"subPath\\":\\"nltk_data\\"},{\\"mountPath\\":\\"/ccu/.cache/huggingface\\",\\"name\\":\\"rag-volume\\",\\"subPath\\":\\"hf_data\\"},{\\"mountPath\\":\\"/ccu/.cache/matplotlib\\",\\"name\\":\\"rag-volume\\",\\"subPath\\":\\"mp_data\\"}]}],\\"restartPolicy\\":\\"Always\\",\\"securityContext\\":{\\"fsGroupChangePolicy\\":\\"Always\\",\\"runAsNonRoot\\":true},\\"serviceAccountName\\":\\"crisiscleanup-api\\",\\"setHostnameAsFQDN\\":false,\\"terminationGracePeriodSeconds\\":30,\\"volumes\\":[{\\"csi\\":{\\"driver\\":\\"secrets-store.csi.k8s.io\\",\\"readOnly\\":true,\\"volumeAttributes\\":{\\"secretProviderClass\\":\\"crisiscleanup-api\\"}},\\"name\\":\\"secrets-store-inline\\"}]}},\\"updateStrategy\\":{\\"rollingUpdate\\":{\\"partition\\":0},\\"type\\":\\"RollingUpdate\\"},\\"volumeClaimTemplates\\":[{\\"metadata\\":{\\"name\\":\\"rag-volume\\"},\\"spec\\":{\\"accessModes\\":[\\"ReadWriteOnce\\"],\\"storageClassName\\":\\"rag-models\\",\\"resources\\":{\\"requests\\":{\\"storage\\":\\"10Gi\\"}}}}]}},{\\"apiVersion\\":\\"autoscaling/v2\\",\\"kind\\":\\"HorizontalPodAutoscaler\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c82f78fa5f1261be46ff61475603c88ab5fa680f3b\\":\\"\\",\\"app.kubernetes.io/component\\":\\"api\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-api-asgi-rag-scaling-hpa\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"behavior\\":{\\"scaleDown\\":{\\"policies\\":[{\\"periodSeconds\\":300,\\"type\\":\\"Pods\\",\\"value\\":1}],\\"selectPolicy\\":\\"Max\\",\\"stabilizationWindowSeconds\\":300},\\"scaleUp\\":{\\"policies\\":[{\\"periodSeconds\\":60,\\"type\\":\\"Pods\\",\\"value\\":4},{\\"periodSeconds\\":60,\\"type\\":\\"Percent\\",\\"value\\":200}],\\"selectPolicy\\":\\"Max\\",\\"stabilizationWindowSeconds\\":0}},\\"maxReplicas\\":6,\\"metrics\\":[{\\"resource\\":{\\"name\\":\\"cpu\\",\\"target\\":{\\"averageUtilization\\":50,\\"type\\":\\"Utilization\\"}},\\"type\\":\\"Resource\\"},{\\"resource\\":{\\"name\\":\\"memory\\",\\"target\\":{\\"averageUtilization\\":80,\\"type\\":\\"Utilization\\"}},\\"type\\":\\"Resource\\"}],\\"minReplicas\\":1,\\"scaleTargetRef\\":{\\"apiVersion\\":\\"apps/v1\\",\\"kind\\":\\"StatefulSet\\",\\"name\\":\\"crisiscleanup-api-asgi-rag\\"}}},{\\"apiVersion\\":\\"v1\\",\\"kind\\":\\"Service\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c82f78fa5f1261be46ff61475603c88ab5fa680f3b\\":\\"\\",\\"app.kubernetes.io/component\\":\\"api\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-api-asgi-service\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"externalIPs\\":[],\\"ports\\":[{\\"port\\":5000,\\"targetPort\\":5000}],\\"selector\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-api-asgi-c818ff7e\\"},\\"type\\":\\"ClusterIP\\"}},{\\"apiVersion\\":\\"autoscaling/v2\\",\\"kind\\":\\"HorizontalPodAutoscaler\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c82f78fa5f1261be46ff61475603c88ab5fa680f3b\\":\\"\\",\\"app.kubernetes.io/component\\":\\"api\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-api-asgi-hpa\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"behavior\\":{\\"scaleDown\\":{\\"policies\\":[{\\"periodSeconds\\":300,\\"type\\":\\"Pods\\",\\"value\\":1}],\\"selectPolicy\\":\\"Max\\",\\"stabilizationWindowSeconds\\":300},\\"scaleUp\\":{\\"policies\\":[{\\"periodSeconds\\":60,\\"type\\":\\"Pods\\",\\"value\\":4},{\\"periodSeconds\\":60,\\"type\\":\\"Percent\\",\\"value\\":200}],\\"selectPolicy\\":\\"Max\\",\\"stabilizationWindowSeconds\\":0}},\\"maxReplicas\\":2,\\"metrics\\":[{\\"resource\\":{\\"name\\":\\"cpu\\",\\"target\\":{\\"averageUtilization\\":70,\\"type\\":\\"Utilization\\"}},\\"type\\":\\"Resource\\"},{\\"resource\\":{\\"name\\":\\"memory\\",\\"target\\":{\\"averageUtilization\\":85,\\"type\\":\\"Utilization\\"}},\\"type\\":\\"Resource\\"}],\\"minReplicas\\":1,\\"scaleTargetRef\\":{\\"apiVersion\\":\\"apps/v1\\",\\"kind\\":\\"Deployment\\",\\"name\\":\\"crisiscleanup-api-asgi\\"}}},{\\"apiVersion\\":\\"autoscaling.k8s.io/v1\\",\\"kind\\":\\"VerticalPodAutoscaler\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c82f78fa5f1261be46ff61475603c88ab5fa680f3b\\":\\"\\",\\"app.kubernetes.io/component\\":\\"api\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-api-asgi-vpa\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"targetRef\\":{\\"apiVersion\\":\\"apps/v1\\",\\"kind\\":\\"Deployment\\",\\"name\\":\\"crisiscleanup-api-asgi\\"},\\"updatePolicy\\":{\\"updateMode\\":\\"Auto\\"}}},{\\"apiVersion\\":\\"apps/v1\\",\\"kind\\":\\"Deployment\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c82f78fa5f1261be46ff61475603c88ab5fa680f3b\\":\\"\\",\\"app.kubernetes.io/component\\":\\"api\\",\\"app.kubernetes.io/name\\":\\"adminwebsocket\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-api-admin-websocket\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"minReadySeconds\\":0,\\"progressDeadlineSeconds\\":600,\\"replicas\\":1,\\"selector\\":{\\"matchLabels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-api-admin-websocket-c879d9e4\\"}},\\"strategy\\":{\\"rollingUpdate\\":{\\"maxSurge\\":\\"25%\\",\\"maxUnavailable\\":\\"25%\\"},\\"type\\":\\"RollingUpdate\\"},\\"template\\":{\\"metadata\\":{\\"labels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-api-admin-websocket-c879d9e4\\"}},\\"spec\\":{\\"automountServiceAccountToken\\":false,\\"containers\\":[{\\"command\\":[\\"/serve.sh\\",\\"adminwebsocket\\"],\\"env\\":[{\\"name\\":\\"POSTGRES_USER\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_USER\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_PASSWORD\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_PASSWORD\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_HOST\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_HOST\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}}],\\"envFrom\\":[{\\"configMapRef\\":{\\"name\\":\\"crisiscleanup-config-api-config\\"}}],\\"image\\":\\"crisiscleanup-api:latest\\",\\"imagePullPolicy\\":\\"IfNotPresent\\",\\"name\\":\\"adminwebsocket\\",\\"resources\\":{\\"limits\\":{\\"memory\\":\\"250Mi\\"},\\"requests\\":{\\"cpu\\":\\"3m\\",\\"memory\\":\\"250Mi\\"}},\\"securityContext\\":{\\"allowPrivilegeEscalation\\":false,\\"privileged\\":false,\\"readOnlyRootFilesystem\\":false,\\"runAsGroup\\":1000,\\"runAsNonRoot\\":true,\\"runAsUser\\":1000},\\"volumeMounts\\":[{\\"mountPath\\":\\"/mnt/secrets-store\\",\\"name\\":\\"secrets-store-inline\\",\\"readOnly\\":true}]}],\\"dnsPolicy\\":\\"ClusterFirst\\",\\"hostNetwork\\":false,\\"restartPolicy\\":\\"Always\\",\\"securityContext\\":{\\"fsGroupChangePolicy\\":\\"Always\\",\\"runAsNonRoot\\":true},\\"serviceAccountName\\":\\"crisiscleanup-api\\",\\"setHostnameAsFQDN\\":false,\\"terminationGracePeriodSeconds\\":30,\\"volumes\\":[{\\"csi\\":{\\"driver\\":\\"secrets-store.csi.k8s.io\\",\\"readOnly\\":true,\\"volumeAttributes\\":{\\"secretProviderClass\\":\\"crisiscleanup-api\\"}},\\"name\\":\\"secrets-store-inline\\"}]}}}},{\\"apiVersion\\":\\"autoscaling.k8s.io/v1\\",\\"kind\\":\\"VerticalPodAutoscaler\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c82f78fa5f1261be46ff61475603c88ab5fa680f3b\\":\\"\\",\\"app.kubernetes.io/component\\":\\"api\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-api-admin-websocket-vpa\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"targetRef\\":{\\"apiVersion\\":\\"apps/v1\\",\\"kind\\":\\"Deployment\\",\\"name\\":\\"crisiscleanup-api-admin-websocket\\"},\\"updatePolicy\\":{\\"updateMode\\":\\"Auto\\"}}}]", "PruneLabel": "aws.cdk.eks/prune-c82f78fa5f1261be46ff61475603c88ab5fa680f3b", "RoleArn": { "Fn::GetAtt": [ @@ -2232,7 +2232,7 @@ exports[`Snapshot 1`] = ` "ClusterName": { "Ref": "teststackF0A1F222", }, - "Manifest": "[{\\"apiVersion\\":\\"apps/v1\\",\\"kind\\":\\"Deployment\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c8018c2be8cb5160e18a226ae9045eb81abe0e66ee\\":\\"\\",\\"app.kubernetes.io/component\\":\\"task-queue\\",\\"app.kubernetes.io/name\\":\\"celerybeat\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-celery-celerybeat\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"minReadySeconds\\":0,\\"progressDeadlineSeconds\\":600,\\"replicas\\":1,\\"selector\\":{\\"matchLabels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-celery-celerybeat-c8500419\\"}},\\"strategy\\":{\\"rollingUpdate\\":{\\"maxSurge\\":\\"25%\\",\\"maxUnavailable\\":\\"25%\\"},\\"type\\":\\"RollingUpdate\\"},\\"template\\":{\\"metadata\\":{\\"labels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-celery-celerybeat-c8500419\\"}},\\"spec\\":{\\"automountServiceAccountToken\\":false,\\"containers\\":[{\\"command\\":[\\"/serve.sh\\",\\"celerybeat\\"],\\"env\\":[{\\"name\\":\\"POSTGRES_USER\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_USER\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_PASSWORD\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_PASSWORD\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_HOST\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_HOST\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}}],\\"envFrom\\":[{\\"configMapRef\\":{\\"name\\":\\"crisiscleanup-config-api-config\\"}}],\\"image\\":\\"crisiscleanup-api:latest\\",\\"imagePullPolicy\\":\\"IfNotPresent\\",\\"name\\":\\"celerybeat\\",\\"resources\\":{\\"limits\\":{\\"memory\\":\\"400Mi\\"},\\"requests\\":{\\"cpu\\":\\"20m\\",\\"memory\\":\\"400Mi\\"}},\\"securityContext\\":{\\"allowPrivilegeEscalation\\":false,\\"privileged\\":false,\\"readOnlyRootFilesystem\\":false,\\"runAsGroup\\":1000,\\"runAsNonRoot\\":true,\\"runAsUser\\":1000},\\"volumeMounts\\":[{\\"mountPath\\":\\"/mnt/secrets-store\\",\\"name\\":\\"secrets-store-inline\\",\\"readOnly\\":true}]}],\\"dnsPolicy\\":\\"ClusterFirst\\",\\"hostNetwork\\":false,\\"restartPolicy\\":\\"Always\\",\\"securityContext\\":{\\"fsGroupChangePolicy\\":\\"Always\\",\\"runAsNonRoot\\":true},\\"serviceAccountName\\":\\"crisiscleanup-api\\",\\"setHostnameAsFQDN\\":false,\\"terminationGracePeriodSeconds\\":30,\\"volumes\\":[{\\"csi\\":{\\"driver\\":\\"secrets-store.csi.k8s.io\\",\\"readOnly\\":true,\\"volumeAttributes\\":{\\"secretProviderClass\\":\\"crisiscleanup-api\\"}},\\"name\\":\\"secrets-store-inline\\"}]}}}},{\\"apiVersion\\":\\"apps/v1\\",\\"kind\\":\\"Deployment\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c8018c2be8cb5160e18a226ae9045eb81abe0e66ee\\":\\"\\",\\"app.kubernetes.io/component\\":\\"task-queue\\",\\"app.kubernetes.io/name\\":\\"celeryworker\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-celery-celery-celery\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"minReadySeconds\\":0,\\"progressDeadlineSeconds\\":600,\\"selector\\":{\\"matchLabels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-celery-celery-celery-c8528587\\"}},\\"strategy\\":{\\"rollingUpdate\\":{\\"maxSurge\\":\\"25%\\",\\"maxUnavailable\\":\\"25%\\"},\\"type\\":\\"RollingUpdate\\"},\\"template\\":{\\"metadata\\":{\\"labels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-celery-celery-celery-c8528587\\"}},\\"spec\\":{\\"automountServiceAccountToken\\":false,\\"containers\\":[{\\"command\\":[\\"/serve.sh\\",\\"celeryworker\\",\\"-Q\\",\\"celery\\",\\"--concurrency=2\\",\\"--hostname\\",\\"celery@%%h\\"],\\"env\\":[{\\"name\\":\\"POSTGRES_USER\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_USER\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_PASSWORD\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_PASSWORD\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_HOST\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_HOST\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}}],\\"envFrom\\":[{\\"configMapRef\\":{\\"name\\":\\"crisiscleanup-config-api-config\\"}}],\\"image\\":\\"crisiscleanup-api:latest\\",\\"imagePullPolicy\\":\\"IfNotPresent\\",\\"name\\":\\"celery\\",\\"resources\\":{\\"limits\\":{\\"memory\\":\\"900Mi\\"},\\"requests\\":{\\"cpu\\":\\"100m\\",\\"memory\\":\\"900Mi\\"}},\\"securityContext\\":{\\"allowPrivilegeEscalation\\":false,\\"privileged\\":false,\\"readOnlyRootFilesystem\\":false,\\"runAsGroup\\":1000,\\"runAsNonRoot\\":true,\\"runAsUser\\":1000},\\"volumeMounts\\":[{\\"mountPath\\":\\"/mnt/secrets-store\\",\\"name\\":\\"secrets-store-inline\\",\\"readOnly\\":true}]}],\\"dnsPolicy\\":\\"ClusterFirst\\",\\"hostNetwork\\":false,\\"restartPolicy\\":\\"Always\\",\\"securityContext\\":{\\"fsGroupChangePolicy\\":\\"Always\\",\\"runAsNonRoot\\":true},\\"serviceAccountName\\":\\"crisiscleanup-api\\",\\"setHostnameAsFQDN\\":false,\\"terminationGracePeriodSeconds\\":30,\\"volumes\\":[{\\"csi\\":{\\"driver\\":\\"secrets-store.csi.k8s.io\\",\\"readOnly\\":true,\\"volumeAttributes\\":{\\"secretProviderClass\\":\\"crisiscleanup-api\\"}},\\"name\\":\\"secrets-store-inline\\"}]}}}},{\\"apiVersion\\":\\"autoscaling/v2\\",\\"kind\\":\\"HorizontalPodAutoscaler\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c8018c2be8cb5160e18a226ae9045eb81abe0e66ee\\":\\"\\",\\"app.kubernetes.io/component\\":\\"task-queue\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-celery-celery-celery-hpa\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"behavior\\":{\\"scaleDown\\":{\\"policies\\":[{\\"periodSeconds\\":300,\\"type\\":\\"Pods\\",\\"value\\":1}],\\"selectPolicy\\":\\"Max\\",\\"stabilizationWindowSeconds\\":300},\\"scaleUp\\":{\\"policies\\":[{\\"periodSeconds\\":60,\\"type\\":\\"Pods\\",\\"value\\":4},{\\"periodSeconds\\":60,\\"type\\":\\"Percent\\",\\"value\\":200}],\\"selectPolicy\\":\\"Max\\",\\"stabilizationWindowSeconds\\":0}},\\"maxReplicas\\":2,\\"metrics\\":[{\\"resource\\":{\\"name\\":\\"cpu\\",\\"target\\":{\\"averageUtilization\\":70,\\"type\\":\\"Utilization\\"}},\\"type\\":\\"Resource\\"},{\\"resource\\":{\\"name\\":\\"memory\\",\\"target\\":{\\"averageUtilization\\":85,\\"type\\":\\"Utilization\\"}},\\"type\\":\\"Resource\\"}],\\"minReplicas\\":1,\\"scaleTargetRef\\":{\\"apiVersion\\":\\"apps/v1\\",\\"kind\\":\\"Deployment\\",\\"name\\":\\"crisiscleanup-celery-celery-celery\\"}}},{\\"apiVersion\\":\\"apps/v1\\",\\"kind\\":\\"Deployment\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c8018c2be8cb5160e18a226ae9045eb81abe0e66ee\\":\\"\\",\\"app.kubernetes.io/component\\":\\"task-queue\\",\\"app.kubernetes.io/name\\":\\"celeryworker\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-celery-celery-signal\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"minReadySeconds\\":0,\\"progressDeadlineSeconds\\":600,\\"selector\\":{\\"matchLabels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-celery-celery-signal-c80f507d\\"}},\\"strategy\\":{\\"rollingUpdate\\":{\\"maxSurge\\":\\"25%\\",\\"maxUnavailable\\":\\"25%\\"},\\"type\\":\\"RollingUpdate\\"},\\"template\\":{\\"metadata\\":{\\"labels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-celery-celery-signal-c80f507d\\"}},\\"spec\\":{\\"automountServiceAccountToken\\":false,\\"containers\\":[{\\"command\\":[\\"/serve.sh\\",\\"celeryworker\\",\\"-Q\\",\\"signal,phone,metrics\\",\\"--concurrency=2\\",\\"--hostname\\",\\"signal@%%h\\"],\\"env\\":[{\\"name\\":\\"POSTGRES_USER\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_USER\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_PASSWORD\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_PASSWORD\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_HOST\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_HOST\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}}],\\"envFrom\\":[{\\"configMapRef\\":{\\"name\\":\\"crisiscleanup-config-api-config\\"}}],\\"image\\":\\"crisiscleanup-api:latest\\",\\"imagePullPolicy\\":\\"IfNotPresent\\",\\"name\\":\\"signal\\",\\"resources\\":{\\"limits\\":{\\"memory\\":\\"900Mi\\"},\\"requests\\":{\\"cpu\\":\\"100m\\",\\"memory\\":\\"900Mi\\"}},\\"securityContext\\":{\\"allowPrivilegeEscalation\\":false,\\"privileged\\":false,\\"readOnlyRootFilesystem\\":false,\\"runAsGroup\\":1000,\\"runAsNonRoot\\":true,\\"runAsUser\\":1000},\\"volumeMounts\\":[{\\"mountPath\\":\\"/mnt/secrets-store\\",\\"name\\":\\"secrets-store-inline\\",\\"readOnly\\":true}]}],\\"dnsPolicy\\":\\"ClusterFirst\\",\\"hostNetwork\\":false,\\"restartPolicy\\":\\"Always\\",\\"securityContext\\":{\\"fsGroupChangePolicy\\":\\"Always\\",\\"runAsNonRoot\\":true},\\"serviceAccountName\\":\\"crisiscleanup-api\\",\\"setHostnameAsFQDN\\":false,\\"terminationGracePeriodSeconds\\":30,\\"volumes\\":[{\\"csi\\":{\\"driver\\":\\"secrets-store.csi.k8s.io\\",\\"readOnly\\":true,\\"volumeAttributes\\":{\\"secretProviderClass\\":\\"crisiscleanup-api\\"}},\\"name\\":\\"secrets-store-inline\\"}]}}}},{\\"apiVersion\\":\\"autoscaling/v2\\",\\"kind\\":\\"HorizontalPodAutoscaler\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c8018c2be8cb5160e18a226ae9045eb81abe0e66ee\\":\\"\\",\\"app.kubernetes.io/component\\":\\"task-queue\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-celery-celery-signal-hpa\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"behavior\\":{\\"scaleDown\\":{\\"policies\\":[{\\"periodSeconds\\":300,\\"type\\":\\"Pods\\",\\"value\\":1}],\\"selectPolicy\\":\\"Max\\",\\"stabilizationWindowSeconds\\":300},\\"scaleUp\\":{\\"policies\\":[{\\"periodSeconds\\":60,\\"type\\":\\"Pods\\",\\"value\\":4},{\\"periodSeconds\\":60,\\"type\\":\\"Percent\\",\\"value\\":200}],\\"selectPolicy\\":\\"Max\\",\\"stabilizationWindowSeconds\\":0}},\\"maxReplicas\\":2,\\"metrics\\":[{\\"resource\\":{\\"name\\":\\"cpu\\",\\"target\\":{\\"averageUtilization\\":70,\\"type\\":\\"Utilization\\"}},\\"type\\":\\"Resource\\"},{\\"resource\\":{\\"name\\":\\"memory\\",\\"target\\":{\\"averageUtilization\\":85,\\"type\\":\\"Utilization\\"}},\\"type\\":\\"Resource\\"}],\\"minReplicas\\":1,\\"scaleTargetRef\\":{\\"apiVersion\\":\\"apps/v1\\",\\"kind\\":\\"Deployment\\",\\"name\\":\\"crisiscleanup-celery-celery-signal\\"}}}]", + "Manifest": "[{\\"apiVersion\\":\\"apps/v1\\",\\"kind\\":\\"Deployment\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c8018c2be8cb5160e18a226ae9045eb81abe0e66ee\\":\\"\\",\\"app.kubernetes.io/component\\":\\"task-queue\\",\\"app.kubernetes.io/name\\":\\"celerybeat\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-celery-celerybeat\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"minReadySeconds\\":0,\\"progressDeadlineSeconds\\":600,\\"replicas\\":1,\\"selector\\":{\\"matchLabels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-celery-celerybeat-c8500419\\"}},\\"strategy\\":{\\"rollingUpdate\\":{\\"maxSurge\\":\\"25%\\",\\"maxUnavailable\\":\\"25%\\"},\\"type\\":\\"RollingUpdate\\"},\\"template\\":{\\"metadata\\":{\\"labels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-celery-celerybeat-c8500419\\"}},\\"spec\\":{\\"automountServiceAccountToken\\":false,\\"containers\\":[{\\"command\\":[\\"/serve.sh\\",\\"celerybeat\\"],\\"env\\":[{\\"name\\":\\"POSTGRES_USER\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_USER\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_PASSWORD\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_PASSWORD\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_HOST\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_HOST\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}}],\\"envFrom\\":[{\\"configMapRef\\":{\\"name\\":\\"crisiscleanup-config-api-config\\"}}],\\"image\\":\\"crisiscleanup-api:latest\\",\\"imagePullPolicy\\":\\"IfNotPresent\\",\\"name\\":\\"celerybeat\\",\\"resources\\":{\\"limits\\":{\\"memory\\":\\"400Mi\\"},\\"requests\\":{\\"cpu\\":\\"20m\\",\\"memory\\":\\"400Mi\\"}},\\"securityContext\\":{\\"allowPrivilegeEscalation\\":false,\\"privileged\\":false,\\"readOnlyRootFilesystem\\":false,\\"runAsGroup\\":1000,\\"runAsNonRoot\\":true,\\"runAsUser\\":1000},\\"volumeMounts\\":[{\\"mountPath\\":\\"/mnt/secrets-store\\",\\"name\\":\\"secrets-store-inline\\",\\"readOnly\\":true}]}],\\"dnsPolicy\\":\\"ClusterFirst\\",\\"hostNetwork\\":false,\\"restartPolicy\\":\\"Always\\",\\"securityContext\\":{\\"fsGroupChangePolicy\\":\\"Always\\",\\"runAsNonRoot\\":true},\\"serviceAccountName\\":\\"crisiscleanup-api\\",\\"setHostnameAsFQDN\\":false,\\"terminationGracePeriodSeconds\\":30,\\"volumes\\":[{\\"csi\\":{\\"driver\\":\\"secrets-store.csi.k8s.io\\",\\"readOnly\\":true,\\"volumeAttributes\\":{\\"secretProviderClass\\":\\"crisiscleanup-api\\"}},\\"name\\":\\"secrets-store-inline\\"}]}}}},{\\"apiVersion\\":\\"autoscaling.k8s.io/v1\\",\\"kind\\":\\"VerticalPodAutoscaler\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c8018c2be8cb5160e18a226ae9045eb81abe0e66ee\\":\\"\\",\\"app.kubernetes.io/component\\":\\"task-queue\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-celery-celerybeat-vpa\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"targetRef\\":{\\"apiVersion\\":\\"apps/v1\\",\\"kind\\":\\"Deployment\\",\\"name\\":\\"crisiscleanup-celery-celerybeat\\"},\\"updatePolicy\\":{\\"updateMode\\":\\"Auto\\"}}},{\\"apiVersion\\":\\"apps/v1\\",\\"kind\\":\\"Deployment\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c8018c2be8cb5160e18a226ae9045eb81abe0e66ee\\":\\"\\",\\"app.kubernetes.io/component\\":\\"task-queue\\",\\"app.kubernetes.io/name\\":\\"celeryworker\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-celery-celery-celery\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"minReadySeconds\\":0,\\"progressDeadlineSeconds\\":600,\\"selector\\":{\\"matchLabels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-celery-celery-celery-c8528587\\"}},\\"strategy\\":{\\"rollingUpdate\\":{\\"maxSurge\\":\\"25%\\",\\"maxUnavailable\\":\\"25%\\"},\\"type\\":\\"RollingUpdate\\"},\\"template\\":{\\"metadata\\":{\\"labels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-celery-celery-celery-c8528587\\"}},\\"spec\\":{\\"automountServiceAccountToken\\":false,\\"containers\\":[{\\"command\\":[\\"/serve.sh\\",\\"celeryworker\\",\\"-Q\\",\\"celery\\",\\"--concurrency=2\\",\\"--hostname\\",\\"celery@%%h\\"],\\"env\\":[{\\"name\\":\\"POSTGRES_USER\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_USER\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_PASSWORD\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_PASSWORD\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_HOST\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_HOST\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}}],\\"envFrom\\":[{\\"configMapRef\\":{\\"name\\":\\"crisiscleanup-config-api-config\\"}}],\\"image\\":\\"crisiscleanup-api:latest\\",\\"imagePullPolicy\\":\\"IfNotPresent\\",\\"name\\":\\"celery\\",\\"resources\\":{\\"limits\\":{\\"memory\\":\\"900Mi\\"},\\"requests\\":{\\"cpu\\":\\"100m\\",\\"memory\\":\\"900Mi\\"}},\\"securityContext\\":{\\"allowPrivilegeEscalation\\":false,\\"privileged\\":false,\\"readOnlyRootFilesystem\\":false,\\"runAsGroup\\":1000,\\"runAsNonRoot\\":true,\\"runAsUser\\":1000},\\"volumeMounts\\":[{\\"mountPath\\":\\"/mnt/secrets-store\\",\\"name\\":\\"secrets-store-inline\\",\\"readOnly\\":true}]}],\\"dnsPolicy\\":\\"ClusterFirst\\",\\"hostNetwork\\":false,\\"restartPolicy\\":\\"Always\\",\\"securityContext\\":{\\"fsGroupChangePolicy\\":\\"Always\\",\\"runAsNonRoot\\":true},\\"serviceAccountName\\":\\"crisiscleanup-api\\",\\"setHostnameAsFQDN\\":false,\\"terminationGracePeriodSeconds\\":30,\\"volumes\\":[{\\"csi\\":{\\"driver\\":\\"secrets-store.csi.k8s.io\\",\\"readOnly\\":true,\\"volumeAttributes\\":{\\"secretProviderClass\\":\\"crisiscleanup-api\\"}},\\"name\\":\\"secrets-store-inline\\"}]}}}},{\\"apiVersion\\":\\"autoscaling/v2\\",\\"kind\\":\\"HorizontalPodAutoscaler\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c8018c2be8cb5160e18a226ae9045eb81abe0e66ee\\":\\"\\",\\"app.kubernetes.io/component\\":\\"task-queue\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-celery-celery-celery-hpa\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"behavior\\":{\\"scaleDown\\":{\\"policies\\":[{\\"periodSeconds\\":300,\\"type\\":\\"Pods\\",\\"value\\":1}],\\"selectPolicy\\":\\"Max\\",\\"stabilizationWindowSeconds\\":300},\\"scaleUp\\":{\\"policies\\":[{\\"periodSeconds\\":60,\\"type\\":\\"Pods\\",\\"value\\":4},{\\"periodSeconds\\":60,\\"type\\":\\"Percent\\",\\"value\\":200}],\\"selectPolicy\\":\\"Max\\",\\"stabilizationWindowSeconds\\":0}},\\"maxReplicas\\":2,\\"metrics\\":[{\\"resource\\":{\\"name\\":\\"cpu\\",\\"target\\":{\\"averageUtilization\\":70,\\"type\\":\\"Utilization\\"}},\\"type\\":\\"Resource\\"},{\\"resource\\":{\\"name\\":\\"memory\\",\\"target\\":{\\"averageUtilization\\":85,\\"type\\":\\"Utilization\\"}},\\"type\\":\\"Resource\\"}],\\"minReplicas\\":1,\\"scaleTargetRef\\":{\\"apiVersion\\":\\"apps/v1\\",\\"kind\\":\\"Deployment\\",\\"name\\":\\"crisiscleanup-celery-celery-celery\\"}}},{\\"apiVersion\\":\\"autoscaling.k8s.io/v1\\",\\"kind\\":\\"VerticalPodAutoscaler\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c8018c2be8cb5160e18a226ae9045eb81abe0e66ee\\":\\"\\",\\"app.kubernetes.io/component\\":\\"task-queue\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-celery-celery-celery-vpa\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"targetRef\\":{\\"apiVersion\\":\\"apps/v1\\",\\"kind\\":\\"Deployment\\",\\"name\\":\\"crisiscleanup-celery-celery-celery\\"},\\"updatePolicy\\":{\\"updateMode\\":\\"Auto\\"}}},{\\"apiVersion\\":\\"apps/v1\\",\\"kind\\":\\"Deployment\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c8018c2be8cb5160e18a226ae9045eb81abe0e66ee\\":\\"\\",\\"app.kubernetes.io/component\\":\\"task-queue\\",\\"app.kubernetes.io/name\\":\\"celeryworker\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-celery-celery-signal\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"minReadySeconds\\":0,\\"progressDeadlineSeconds\\":600,\\"selector\\":{\\"matchLabels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-celery-celery-signal-c80f507d\\"}},\\"strategy\\":{\\"rollingUpdate\\":{\\"maxSurge\\":\\"25%\\",\\"maxUnavailable\\":\\"25%\\"},\\"type\\":\\"RollingUpdate\\"},\\"template\\":{\\"metadata\\":{\\"labels\\":{\\"cdk8s.io/metadata.addr\\":\\"crisiscleanup-celery-celery-signal-c80f507d\\"}},\\"spec\\":{\\"automountServiceAccountToken\\":false,\\"containers\\":[{\\"command\\":[\\"/serve.sh\\",\\"celeryworker\\",\\"-Q\\",\\"signal,phone,metrics\\",\\"--concurrency=2\\",\\"--hostname\\",\\"signal@%%h\\"],\\"env\\":[{\\"name\\":\\"POSTGRES_USER\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_USER\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_PASSWORD\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_PASSWORD\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}},{\\"name\\":\\"POSTGRES_HOST\\",\\"valueFrom\\":{\\"secretKeyRef\\":{\\"key\\":\\"POSTGRES_HOST\\",\\"name\\":\\"crisiscleanup-db-secrets\\"}}}],\\"envFrom\\":[{\\"configMapRef\\":{\\"name\\":\\"crisiscleanup-config-api-config\\"}}],\\"image\\":\\"crisiscleanup-api:latest\\",\\"imagePullPolicy\\":\\"IfNotPresent\\",\\"name\\":\\"signal\\",\\"resources\\":{\\"limits\\":{\\"memory\\":\\"900Mi\\"},\\"requests\\":{\\"cpu\\":\\"100m\\",\\"memory\\":\\"900Mi\\"}},\\"securityContext\\":{\\"allowPrivilegeEscalation\\":false,\\"privileged\\":false,\\"readOnlyRootFilesystem\\":false,\\"runAsGroup\\":1000,\\"runAsNonRoot\\":true,\\"runAsUser\\":1000},\\"volumeMounts\\":[{\\"mountPath\\":\\"/mnt/secrets-store\\",\\"name\\":\\"secrets-store-inline\\",\\"readOnly\\":true}]}],\\"dnsPolicy\\":\\"ClusterFirst\\",\\"hostNetwork\\":false,\\"restartPolicy\\":\\"Always\\",\\"securityContext\\":{\\"fsGroupChangePolicy\\":\\"Always\\",\\"runAsNonRoot\\":true},\\"serviceAccountName\\":\\"crisiscleanup-api\\",\\"setHostnameAsFQDN\\":false,\\"terminationGracePeriodSeconds\\":30,\\"volumes\\":[{\\"csi\\":{\\"driver\\":\\"secrets-store.csi.k8s.io\\",\\"readOnly\\":true,\\"volumeAttributes\\":{\\"secretProviderClass\\":\\"crisiscleanup-api\\"}},\\"name\\":\\"secrets-store-inline\\"}]}}}},{\\"apiVersion\\":\\"autoscaling/v2\\",\\"kind\\":\\"HorizontalPodAutoscaler\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c8018c2be8cb5160e18a226ae9045eb81abe0e66ee\\":\\"\\",\\"app.kubernetes.io/component\\":\\"task-queue\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-celery-celery-signal-hpa\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"behavior\\":{\\"scaleDown\\":{\\"policies\\":[{\\"periodSeconds\\":300,\\"type\\":\\"Pods\\",\\"value\\":1}],\\"selectPolicy\\":\\"Max\\",\\"stabilizationWindowSeconds\\":300},\\"scaleUp\\":{\\"policies\\":[{\\"periodSeconds\\":60,\\"type\\":\\"Pods\\",\\"value\\":4},{\\"periodSeconds\\":60,\\"type\\":\\"Percent\\",\\"value\\":200}],\\"selectPolicy\\":\\"Max\\",\\"stabilizationWindowSeconds\\":0}},\\"maxReplicas\\":2,\\"metrics\\":[{\\"resource\\":{\\"name\\":\\"cpu\\",\\"target\\":{\\"averageUtilization\\":70,\\"type\\":\\"Utilization\\"}},\\"type\\":\\"Resource\\"},{\\"resource\\":{\\"name\\":\\"memory\\",\\"target\\":{\\"averageUtilization\\":85,\\"type\\":\\"Utilization\\"}},\\"type\\":\\"Resource\\"}],\\"minReplicas\\":1,\\"scaleTargetRef\\":{\\"apiVersion\\":\\"apps/v1\\",\\"kind\\":\\"Deployment\\",\\"name\\":\\"crisiscleanup-celery-celery-signal\\"}}},{\\"apiVersion\\":\\"autoscaling.k8s.io/v1\\",\\"kind\\":\\"VerticalPodAutoscaler\\",\\"metadata\\":{\\"labels\\":{\\"aws.cdk.eks/prune-c8018c2be8cb5160e18a226ae9045eb81abe0e66ee\\":\\"\\",\\"app.kubernetes.io/component\\":\\"task-queue\\",\\"app.kubernetes.io/part-of\\":\\"crisiscleanup\\"},\\"name\\":\\"crisiscleanup-celery-celery-signal-vpa\\",\\"namespace\\":\\"local\\"},\\"spec\\":{\\"targetRef\\":{\\"apiVersion\\":\\"apps/v1\\",\\"kind\\":\\"Deployment\\",\\"name\\":\\"crisiscleanup-celery-celery-signal\\"},\\"updatePolicy\\":{\\"updateMode\\":\\"Auto\\"}}}]", "PruneLabel": "aws.cdk.eks/prune-c8018c2be8cb5160e18a226ae9045eb81abe0e66ee", "RoleArn": { "Fn::GetAtt": [