konokenj.cdk-api-mcp-server 0.47.0__py3-none-any.whl → 0.49.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of konokenj.cdk-api-mcp-server might be problematic. Click here for more details.
- cdk_api_mcp_server/__about__.py +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/@aws-cdk/aws-amplify-alpha/README.md +12 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/README.md/README.md +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-batch/README.md +15 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-batch/integ.managed-compute-environment-default-instance-class.ts +20 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-cloudfront-origins/README.md +33 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-cloudfront-origins/integ.function-url-origin-ip-address-type.ts +84 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-cloudwatch/README.md +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-cloudwatch/integ.anomaly-detection-alarm.ts +44 -2
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-codebuild/README.md +76 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-codebuild/integ.project-fleet-attribute-based-compute.ts +59 -7
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-codebuild/integ.project-fleet-custom-instance-type.ts +130 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-codebuild/integ.project-fleet-overflow-behavior.ts +61 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ec2/README.md +15 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ec2/integ.client-vpn-endpoint-disconnect-on-session-timeout.ts +65 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ecs/README.md +101 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ecs/integ.managedinstances-capacity-provider.ts +112 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-eks/README.md +20 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-eks/integ.eks-cluster-removal-policy.ts +31 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-kinesis/README.md +42 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-kinesis/integ.stream-shard-level-monitoring.ts +47 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-lambda/README.md +9 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-logs/README.md +4 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-logs/integ.metricfilter-apply-on-transformed-logs.ts +29 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-opensearchservice/integ.opensearch.min.ts +1 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-route53/README.md +12 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-route53/integ.private-hosted-zone-from-attributes.ts +41 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-synthetics/README.md +17 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-synthetics/integ.canary-runtime-validation.ts +43 -0
- {konokenj_cdk_api_mcp_server-0.47.0.dist-info → konokenj_cdk_api_mcp_server-0.49.0.dist-info}/METADATA +2 -2
- {konokenj_cdk_api_mcp_server-0.47.0.dist-info → konokenj_cdk_api_mcp_server-0.49.0.dist-info}/RECORD +34 -23
- {konokenj_cdk_api_mcp_server-0.47.0.dist-info → konokenj_cdk_api_mcp_server-0.49.0.dist-info}/WHEEL +0 -0
- {konokenj_cdk_api_mcp_server-0.47.0.dist-info → konokenj_cdk_api_mcp_server-0.49.0.dist-info}/entry_points.txt +0 -0
- {konokenj_cdk_api_mcp_server-0.47.0.dist-info → konokenj_cdk_api_mcp_server-0.49.0.dist-info}/licenses/LICENSE.txt +0 -0
|
@@ -1306,6 +1306,21 @@ const endpoint = vpc.addClientVpnEndpoint('Endpoint', {
|
|
|
1306
1306
|
});
|
|
1307
1307
|
```
|
|
1308
1308
|
|
|
1309
|
+
To control whether clients are automatically disconnected when the maximum session duration is reached, use the `disconnectOnSessionTimeout` prop.
|
|
1310
|
+
By default (`true`), clients are disconnected and must manually reconnect.
|
|
1311
|
+
Set to `false` to allow automatic reconnection attempts:
|
|
1312
|
+
|
|
1313
|
+
```ts fixture=client-vpn
|
|
1314
|
+
const endpoint = vpc.addClientVpnEndpoint('Endpoint', {
|
|
1315
|
+
cidr: '10.100.0.0/16',
|
|
1316
|
+
serverCertificateArn: 'arn:aws:acm:us-east-1:123456789012:certificate/server-certificate-id',
|
|
1317
|
+
clientCertificateArn: 'arn:aws:acm:us-east-1:123456789012:certificate/client-certificate-id',
|
|
1318
|
+
disconnectOnSessionTimeout: false, // Allow automatic reconnection attempts
|
|
1319
|
+
});
|
|
1320
|
+
```
|
|
1321
|
+
|
|
1322
|
+
Detail information about maximum VPN session duration timeout can be found in the [AWS documentation](https://docs.aws.amazon.com/vpn/latest/clientvpn-admin/cvpn-working-max-duration.html).
|
|
1323
|
+
|
|
1309
1324
|
## Instances
|
|
1310
1325
|
|
|
1311
1326
|
You can use the `Instance` class to start up a single EC2 instance. For production setups, we recommend
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { App, RemovalPolicy, Stack, StackProps, UnscopedValidationError } from 'aws-cdk-lib';
|
|
2
|
+
import * as acm from 'aws-cdk-lib/aws-certificatemanager';
|
|
3
|
+
import * as ec2 from 'aws-cdk-lib/aws-ec2';
|
|
4
|
+
import * as logs from 'aws-cdk-lib/aws-logs';
|
|
5
|
+
import * as route53 from 'aws-cdk-lib/aws-route53';
|
|
6
|
+
import { IntegTest } from '@aws-cdk/integ-tests-alpha';
|
|
7
|
+
import { Construct } from 'constructs';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* In order to test this you need to have a valid public hosted zone that you can use
|
|
11
|
+
* to validate the domain identity.
|
|
12
|
+
*/
|
|
13
|
+
const hostedZoneId = process.env.CDK_INTEG_HOSTED_ZONE_ID ?? process.env.HOSTED_ZONE_ID;
|
|
14
|
+
if (!hostedZoneId) throw new UnscopedValidationError('For this test you must provide your own HostedZoneId as an env var "HOSTED_ZONE_ID". See framework-integ/README.md for details.');
|
|
15
|
+
const hostedZoneName = process.env.CDK_INTEG_HOSTED_ZONE_NAME ?? process.env.HOSTED_ZONE_NAME;
|
|
16
|
+
if (!hostedZoneName) throw new UnscopedValidationError('For this test you must provide your own HostedZoneName as an env var "HOSTED_ZONE_NAME". See framework-integ/README.md for details.');
|
|
17
|
+
|
|
18
|
+
interface TestStackProps extends StackProps {
|
|
19
|
+
hostedZoneId: string;
|
|
20
|
+
hostedZoneName: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
class TestStack extends Stack {
|
|
24
|
+
constructor(scope: Construct, id: string, props: TestStackProps) {
|
|
25
|
+
super(scope, id, props);
|
|
26
|
+
|
|
27
|
+
const hostedZone = route53.PublicHostedZone.fromHostedZoneAttributes(this, 'HostedZone', {
|
|
28
|
+
hostedZoneId: props.hostedZoneId,
|
|
29
|
+
zoneName: props.hostedZoneName,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const serverCertificate = new acm.Certificate(this, 'Certificate', {
|
|
33
|
+
domainName: `server.${props.hostedZoneName}`,
|
|
34
|
+
validation: acm.CertificateValidation.fromDns(hostedZone),
|
|
35
|
+
});
|
|
36
|
+
const clientCertificate = new acm.Certificate(this, 'ClientCertificate', {
|
|
37
|
+
domainName: `client.${props.hostedZoneName}`,
|
|
38
|
+
validation: acm.CertificateValidation.fromDns(hostedZone),
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const vpc = new ec2.Vpc(this, 'Vpc', { maxAzs: 2, natGateways: 0 });
|
|
42
|
+
|
|
43
|
+
const logGroup = new logs.LogGroup(this, 'LogGroup', {
|
|
44
|
+
removalPolicy: RemovalPolicy.DESTROY,
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
vpc.addClientVpnEndpoint('Endpoint', {
|
|
48
|
+
cidr: '10.100.0.0/16',
|
|
49
|
+
serverCertificateArn: serverCertificate.certificateArn,
|
|
50
|
+
clientCertificateArn: clientCertificate.certificateArn,
|
|
51
|
+
logGroup,
|
|
52
|
+
disconnectOnSessionTimeout: false,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const app = new App();
|
|
58
|
+
new IntegTest(app, 'client-vpn-endpoint-integ', {
|
|
59
|
+
testCases: [
|
|
60
|
+
new TestStack(app, 'client-vpn-endpoint-stack', {
|
|
61
|
+
hostedZoneId,
|
|
62
|
+
hostedZoneName,
|
|
63
|
+
}),
|
|
64
|
+
],
|
|
65
|
+
});
|
|
@@ -1659,6 +1659,107 @@ new ecs.Ec2Service(this, 'EC2Service', {
|
|
|
1659
1659
|
});
|
|
1660
1660
|
```
|
|
1661
1661
|
|
|
1662
|
+
### Managed Instances Capacity Providers
|
|
1663
|
+
|
|
1664
|
+
Managed Instances Capacity Providers allow you to use AWS-managed EC2 instances for your ECS tasks while providing more control over instance selection than standard Fargate. AWS handles the instance lifecycle, patching, and maintenance while you can specify detailed instance requirements.
|
|
1665
|
+
|
|
1666
|
+
To create a Managed Instances Capacity Provider, you need to specify the required EC2 instance profile, and networking configuration. You can also define detailed instance requirements to control which types of instances are used for your workloads.
|
|
1667
|
+
|
|
1668
|
+
```ts
|
|
1669
|
+
declare const vpc: ec2.Vpc;
|
|
1670
|
+
declare const infrastructureRole: iam.Role;
|
|
1671
|
+
declare const instanceProfile: iam.InstanceProfile;
|
|
1672
|
+
|
|
1673
|
+
const cluster = new ecs.Cluster(this, 'Cluster', { vpc });
|
|
1674
|
+
|
|
1675
|
+
// Create a Managed Instances Capacity Provider
|
|
1676
|
+
const miCapacityProvider = new ecs.ManagedInstancesCapacityProvider(this, 'MICapacityProvider', {
|
|
1677
|
+
infrastructureRole,
|
|
1678
|
+
ec2InstanceProfile: instanceProfile,
|
|
1679
|
+
subnets: vpc.privateSubnets,
|
|
1680
|
+
securityGroups: [new ec2.SecurityGroup(this, 'MISecurityGroup', { vpc })],
|
|
1681
|
+
instanceRequirements: {
|
|
1682
|
+
vCpuCountMin: 1,
|
|
1683
|
+
memoryMin: Size.gibibytes(2),
|
|
1684
|
+
cpuManufacturers: [ec2.CpuManufacturer.INTEL],
|
|
1685
|
+
acceleratorManufacturers: [ec2.AcceleratorManufacturer.NVIDIA],
|
|
1686
|
+
},
|
|
1687
|
+
propagateTags: ecs.PropagateManagedInstancesTags.CAPACITY_PROVIDER,
|
|
1688
|
+
});
|
|
1689
|
+
|
|
1690
|
+
// Add the capacity provider to the cluster
|
|
1691
|
+
cluster.addManagedInstancesCapacityProvider(miCapacityProvider);
|
|
1692
|
+
|
|
1693
|
+
const taskDefinition = new ecs.Ec2TaskDefinition(this, 'TaskDef');
|
|
1694
|
+
|
|
1695
|
+
taskDefinition.addContainer('web', {
|
|
1696
|
+
image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'),
|
|
1697
|
+
memoryReservationMiB: 256,
|
|
1698
|
+
});
|
|
1699
|
+
|
|
1700
|
+
new ecs.Ec2Service(this, 'EC2Service', {
|
|
1701
|
+
cluster,
|
|
1702
|
+
taskDefinition,
|
|
1703
|
+
minHealthyPercent: 100,
|
|
1704
|
+
capacityProviderStrategies: [
|
|
1705
|
+
{
|
|
1706
|
+
capacityProvider: miCapacityProvider.capacityProviderName,
|
|
1707
|
+
weight: 1,
|
|
1708
|
+
},
|
|
1709
|
+
],
|
|
1710
|
+
});
|
|
1711
|
+
```
|
|
1712
|
+
|
|
1713
|
+
You can specify detailed instance requirements to control which types of instances are used:
|
|
1714
|
+
|
|
1715
|
+
```ts
|
|
1716
|
+
declare const infrastructureRole: iam.Role;
|
|
1717
|
+
declare const instanceProfile: iam.InstanceProfile;
|
|
1718
|
+
declare const vpc: ec2.Vpc;
|
|
1719
|
+
|
|
1720
|
+
const miCapacityProvider = new ecs.ManagedInstancesCapacityProvider(this, 'MICapacityProvider', {
|
|
1721
|
+
infrastructureRole,
|
|
1722
|
+
ec2InstanceProfile: instanceProfile,
|
|
1723
|
+
subnets: vpc.privateSubnets,
|
|
1724
|
+
instanceRequirements: {
|
|
1725
|
+
// Required: CPU and memory constraints
|
|
1726
|
+
vCpuCountMin: 2,
|
|
1727
|
+
vCpuCountMax: 8,
|
|
1728
|
+
memoryMin: Size.gibibytes(4),
|
|
1729
|
+
memoryMax: Size.gibibytes(32),
|
|
1730
|
+
|
|
1731
|
+
// CPU preferences
|
|
1732
|
+
cpuManufacturers: [ec2.CpuManufacturer.INTEL, ec2.CpuManufacturer.AMD],
|
|
1733
|
+
instanceGenerations: [ec2.InstanceGeneration.CURRENT],
|
|
1734
|
+
|
|
1735
|
+
// Instance type filtering
|
|
1736
|
+
allowedInstanceTypes: ['m5.*', 'c5.*'],
|
|
1737
|
+
|
|
1738
|
+
// Performance characteristics
|
|
1739
|
+
burstablePerformance: ec2.BurstablePerformance.EXCLUDED,
|
|
1740
|
+
bareMetal: ec2.BareMetal.EXCLUDED,
|
|
1741
|
+
|
|
1742
|
+
// Accelerator requirements (for ML/AI workloads)
|
|
1743
|
+
acceleratorTypes: [ec2.AcceleratorType.GPU],
|
|
1744
|
+
acceleratorManufacturers: [ec2.AcceleratorManufacturer.NVIDIA],
|
|
1745
|
+
acceleratorNames: [ec2.AcceleratorName.T4, ec2.AcceleratorName.V100],
|
|
1746
|
+
acceleratorCountMin: 1,
|
|
1747
|
+
|
|
1748
|
+
// Storage requirements
|
|
1749
|
+
localStorage: ec2.LocalStorage.REQUIRED,
|
|
1750
|
+
localStorageTypes: [ec2.LocalStorageType.SSD],
|
|
1751
|
+
totalLocalStorageGBMin: 100,
|
|
1752
|
+
|
|
1753
|
+
// Network requirements
|
|
1754
|
+
networkInterfaceCountMin: 2,
|
|
1755
|
+
networkBandwidthGbpsMin: 10,
|
|
1756
|
+
|
|
1757
|
+
// Cost optimization
|
|
1758
|
+
onDemandMaxPricePercentageOverLowestPrice: 10,
|
|
1759
|
+
},
|
|
1760
|
+
});
|
|
1761
|
+
```
|
|
1762
|
+
|
|
1662
1763
|
### Cluster Default Provider Strategy
|
|
1663
1764
|
|
|
1664
1765
|
A capacity provider strategy determines whether ECS tasks are launched on EC2 instances or Fargate/Fargate Spot. It can be specified at the cluster, service, or task level, and consists of one or more capacity providers. You can specify an optional base and weight value for finer control of how tasks are launched. The `base` specifies a minimum number of tasks on one capacity provider, and the `weight`s of each capacity provider determine how tasks are distributed after `base` is satisfied.
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import * as ec2 from 'aws-cdk-lib/aws-ec2';
|
|
2
|
+
import * as iam from 'aws-cdk-lib/aws-iam';
|
|
3
|
+
import * as cdk from 'aws-cdk-lib';
|
|
4
|
+
import * as ecs from 'aws-cdk-lib/aws-ecs';
|
|
5
|
+
import * as integ from '@aws-cdk/integ-tests-alpha';
|
|
6
|
+
|
|
7
|
+
const app = new cdk.App({
|
|
8
|
+
postCliContext: {
|
|
9
|
+
'@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm': true,
|
|
10
|
+
'@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false,
|
|
11
|
+
'@aws-cdk/aws-ecs:disableEcsImdsBlocking': false,
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
const stack = new cdk.Stack(app, 'integ-managedinstances-capacity-provider');
|
|
15
|
+
|
|
16
|
+
const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 2, restrictDefaultSecurityGroup: false });
|
|
17
|
+
const cluster = new ecs.Cluster(stack, 'ManagedInstancesCluster', {
|
|
18
|
+
vpc,
|
|
19
|
+
enableFargateCapacityProviders: true,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// Create IAM roles required for FMI following Omakase specifications
|
|
23
|
+
const infrastructureRole = new iam.Role(stack, 'InfrastructureRole', {
|
|
24
|
+
roleName: 'AmazonECSInfrastructureRoleForOmakase',
|
|
25
|
+
assumedBy: new iam.ServicePrincipal('ecs.amazonaws.com'),
|
|
26
|
+
managedPolicies: [
|
|
27
|
+
iam.ManagedPolicy.fromAwsManagedPolicyName('AdministratorAccess'),
|
|
28
|
+
],
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const instanceRole = new iam.Role(stack, 'InstanceRole', {
|
|
32
|
+
roleName: 'AmazonECSInstanceRoleForOmakase',
|
|
33
|
+
assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'),
|
|
34
|
+
managedPolicies: [
|
|
35
|
+
iam.ManagedPolicy.fromAwsManagedPolicyName('AdministratorAccess'),
|
|
36
|
+
],
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const instanceProfile = new iam.InstanceProfile(stack, 'InstanceProfile', {
|
|
40
|
+
instanceProfileName: 'AmazonECSInstanceRoleForOmakase',
|
|
41
|
+
role: instanceRole,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// Create a security group for FMI instances
|
|
45
|
+
const fmiSecurityGroup = new ec2.SecurityGroup(stack, 'ManagedInstancesSecurityGroup', {
|
|
46
|
+
vpc,
|
|
47
|
+
description: 'Security group for ManagedInstances capacity provider instances',
|
|
48
|
+
allowAllOutbound: true,
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// Create MI Capacity Provider
|
|
52
|
+
const miCapacityProvider = new ecs.ManagedInstancesCapacityProvider(stack, 'ManagedInstancesCapacityProvider', {
|
|
53
|
+
infrastructureRole: infrastructureRole,
|
|
54
|
+
ec2InstanceProfile: instanceProfile,
|
|
55
|
+
subnets: vpc.privateSubnets,
|
|
56
|
+
securityGroups: [fmiSecurityGroup],
|
|
57
|
+
propagateTags: ecs.PropagateManagedInstancesTags.CAPACITY_PROVIDER,
|
|
58
|
+
instanceRequirements: {
|
|
59
|
+
vCpuCountMin: 1,
|
|
60
|
+
memoryMin: cdk.Size.gibibytes(2),
|
|
61
|
+
cpuManufacturers: [ec2.CpuManufacturer.INTEL],
|
|
62
|
+
acceleratorManufacturers: [ec2.AcceleratorManufacturer.NVIDIA],
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Add FMI capacity provider to cluster
|
|
67
|
+
cluster.addManagedInstancesCapacityProvider(miCapacityProvider);
|
|
68
|
+
cluster.addDefaultCapacityProviderStrategy([
|
|
69
|
+
{
|
|
70
|
+
capacityProvider: miCapacityProvider.capacityProviderName,
|
|
71
|
+
weight: 1,
|
|
72
|
+
},
|
|
73
|
+
]);
|
|
74
|
+
|
|
75
|
+
// Create a task definition compatible with Managed Instances and Fargate
|
|
76
|
+
const taskDefinition = new ecs.TaskDefinition(stack, 'TaskDef', {
|
|
77
|
+
compatibility: ecs.Compatibility.FARGATE_AND_MANAGED_INSTANCES,
|
|
78
|
+
cpu: '256',
|
|
79
|
+
memoryMiB: '512',
|
|
80
|
+
networkMode: ecs.NetworkMode.AWS_VPC,
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
taskDefinition.addContainer('web', {
|
|
84
|
+
image: ecs.ContainerImage.fromRegistry('public.ecr.aws/docker/library/httpd:2.4'),
|
|
85
|
+
memoryLimitMiB: 512,
|
|
86
|
+
portMappings: [
|
|
87
|
+
{
|
|
88
|
+
containerPort: 80,
|
|
89
|
+
protocol: ecs.Protocol.TCP,
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// Create a service using the MI capacity provider
|
|
95
|
+
new ecs.FargateService(stack, 'ManagedInstancesService', {
|
|
96
|
+
cluster,
|
|
97
|
+
taskDefinition,
|
|
98
|
+
capacityProviderStrategies: [
|
|
99
|
+
{
|
|
100
|
+
capacityProvider: miCapacityProvider.capacityProviderName,
|
|
101
|
+
weight: 1,
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
desiredCount: 1,
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
new integ.IntegTest(app, 'ManagedInstancesCapacityProviders', {
|
|
108
|
+
testCases: [stack],
|
|
109
|
+
regions: ['us-west-2'],
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
app.synth();
|
|
@@ -147,6 +147,26 @@ new eks.Cluster(this, 'HelloEKS', {
|
|
|
147
147
|
});
|
|
148
148
|
```
|
|
149
149
|
|
|
150
|
+
You can control what happens to the resources created by the cluster construct when they are no longer managed by CloudFormation by specifying a `removalPolicy`.
|
|
151
|
+
|
|
152
|
+
This can happen in one of three situations:
|
|
153
|
+
- The resource is removed from the template, so CloudFormation stops managing it;
|
|
154
|
+
- A change to the resource is made that requires it to be replaced, so CloudFormation stops managing it;
|
|
155
|
+
- The stack is deleted, so CloudFormation stops managing all resources in it.
|
|
156
|
+
|
|
157
|
+
This affects the EKS cluster itself, the custom resource that created the cluster, associated IAM roles, node groups, security groups, VPC and any other CloudFormation resources managed by this construct.
|
|
158
|
+
|
|
159
|
+
```ts
|
|
160
|
+
import { KubectlV33Layer } from '@aws-cdk/lambda-layer-kubectl-v33';
|
|
161
|
+
import * as core from 'aws-cdk-lib/core';
|
|
162
|
+
|
|
163
|
+
new eks.Cluster(this, 'HelloEKS', {
|
|
164
|
+
version: eks.KubernetesVersion.V1_33,
|
|
165
|
+
kubectlLayer: new KubectlV33Layer(this, 'kubectl'),
|
|
166
|
+
removalPolicy: core.RemovalPolicy.RETAIN, // Keep all resources created by the construct.
|
|
167
|
+
});
|
|
168
|
+
```
|
|
169
|
+
|
|
150
170
|
You can also use `FargateCluster` to provision a cluster that uses only fargate workers.
|
|
151
171
|
|
|
152
172
|
```ts
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/// !cdk-integ pragma:disable-update-workflow
|
|
2
|
+
import { App, RemovalPolicy, Stack, StackProps } from 'aws-cdk-lib';
|
|
3
|
+
import * as integ from '@aws-cdk/integ-tests-alpha';
|
|
4
|
+
import { getClusterVersionConfig } from './integ-tests-kubernetes-version';
|
|
5
|
+
import * as eks from 'aws-cdk-lib/aws-eks';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* This test just checks that all resources can be deployed with a removal policy.
|
|
9
|
+
* We use the DESTROY policy here to avoid leaving orphaned resources behind, but if it works for DESTROY, it should work for other values as well.
|
|
10
|
+
*/
|
|
11
|
+
class EksClusterRemovalPolicyStack extends Stack {
|
|
12
|
+
constructor(scope: App, id: string, props?: StackProps) {
|
|
13
|
+
super(scope, id, props);
|
|
14
|
+
|
|
15
|
+
new eks.Cluster(this, 'Cluster', {
|
|
16
|
+
...getClusterVersionConfig(this, eks.KubernetesVersion.V1_32),
|
|
17
|
+
removalPolicy: RemovalPolicy.DESTROY,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const app = new App();
|
|
23
|
+
|
|
24
|
+
const stack = new EksClusterRemovalPolicyStack(app, 'EksClusterRemovalPolicyStack');
|
|
25
|
+
|
|
26
|
+
new integ.IntegTest(app, 'eks-cluster-removal-policy-integ', {
|
|
27
|
+
testCases: [stack],
|
|
28
|
+
diffAssets: false,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
app.synth();
|
|
@@ -15,6 +15,7 @@ intake and aggregation.
|
|
|
15
15
|
- [Write Permissions](#write-permissions)
|
|
16
16
|
- [Custom Permissions](#custom-permissions)
|
|
17
17
|
- [Metrics](#metrics)
|
|
18
|
+
- [Shard-level Metrics](#shard-level-metrics)
|
|
18
19
|
- [Stream Consumers](#stream-consumers)
|
|
19
20
|
- [Read Permissions](#read-permissions-1)
|
|
20
21
|
- [Resource Policy](#resource-policy)
|
|
@@ -191,6 +192,47 @@ stream.metricGetRecordsSuccess();
|
|
|
191
192
|
stream.metricGetRecordsSuccess({ statistic: 'Maximum' });
|
|
192
193
|
```
|
|
193
194
|
|
|
195
|
+
#### Shard-level Metrics
|
|
196
|
+
|
|
197
|
+
You can enable enhanced shard-level metrics for your Kinesis stream to get detailed monitoring of individual shards. Shard-level metrics provide more granular insights into the performance and health of your stream.
|
|
198
|
+
|
|
199
|
+
```ts
|
|
200
|
+
const stream = new kinesis.Stream(this, 'MyStream', {
|
|
201
|
+
shardLevelMetrics: [kinesis.ShardLevelMetrics.ALL],
|
|
202
|
+
});
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
You can also specify individual metrics that you want to monitor:
|
|
206
|
+
|
|
207
|
+
```ts
|
|
208
|
+
const stream = new kinesis.Stream(this, 'MyStream', {
|
|
209
|
+
shardLevelMetrics: [
|
|
210
|
+
kinesis.ShardLevelMetrics.INCOMING_BYTES,
|
|
211
|
+
kinesis.ShardLevelMetrics.INCOMING_RECORDS,
|
|
212
|
+
kinesis.ShardLevelMetrics.ITERATOR_AGE_MILLISECONDS,
|
|
213
|
+
kinesis.ShardLevelMetrics.OUTGOING_BYTES,
|
|
214
|
+
kinesis.ShardLevelMetrics.OUTGOING_RECORDS,
|
|
215
|
+
kinesis.ShardLevelMetrics.READ_PROVISIONED_THROUGHPUT_EXCEEDED,
|
|
216
|
+
kinesis.ShardLevelMetrics.WRITE_PROVISIONED_THROUGHPUT_EXCEEDED,
|
|
217
|
+
],
|
|
218
|
+
});
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Available shard-level metrics include:
|
|
222
|
+
|
|
223
|
+
- `INCOMING_BYTES` - The number of bytes successfully put to the shard
|
|
224
|
+
- `INCOMING_RECORDS` - The number of records successfully put to the shard
|
|
225
|
+
- `ITERATOR_AGE_MILLISECONDS` - The age of the last record in all GetRecords calls made against a shard
|
|
226
|
+
- `OUTGOING_BYTES` - The number of bytes retrieved from the shard
|
|
227
|
+
- `OUTGOING_RECORDS` - The number of records retrieved from the shard
|
|
228
|
+
- `READ_PROVISIONED_THROUGHPUT_EXCEEDED` - The number of GetRecords calls throttled for the shard
|
|
229
|
+
- `WRITE_PROVISIONED_THROUGHPUT_EXCEEDED` - The number of records rejected due to throttling for the shard
|
|
230
|
+
- `ALL` - All available metrics
|
|
231
|
+
|
|
232
|
+
Note: You cannot specify `ALL` together with other individual metrics. If you want all metrics, use `ALL` alone.
|
|
233
|
+
|
|
234
|
+
For more information about shard-level metrics, see [Monitoring the Amazon Kinesis Data Streams Service with Amazon CloudWatch](https://docs.aws.amazon.com/streams/latest/dev/monitoring-with-cloudwatch.html#kinesis-metrics-shard).
|
|
235
|
+
|
|
194
236
|
## Stream Consumers
|
|
195
237
|
|
|
196
238
|
Creating stream consumers allow consumers to receive data from the stream using enhanced fan-out at a rate of up to 2 MiB per second for every shard.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { App, Stack, RemovalPolicies } from 'aws-cdk-lib';
|
|
2
|
+
import * as kinesis from 'aws-cdk-lib/aws-kinesis';
|
|
3
|
+
import { ExpectedResult, IntegTest } from '@aws-cdk/integ-tests-alpha';
|
|
4
|
+
|
|
5
|
+
const app = new App();
|
|
6
|
+
const stack = new Stack(app, 'kinesis-stream-shard-level-monitoring-stack');
|
|
7
|
+
|
|
8
|
+
const explicitStream = new kinesis.Stream(stack, 'ExplicitStream', {
|
|
9
|
+
shardLevelMetrics: [
|
|
10
|
+
kinesis.ShardLevelMetrics.INCOMING_BYTES,
|
|
11
|
+
kinesis.ShardLevelMetrics.INCOMING_RECORDS,
|
|
12
|
+
kinesis.ShardLevelMetrics.ITERATOR_AGE_MILLISECONDS,
|
|
13
|
+
kinesis.ShardLevelMetrics.OUTGOING_BYTES,
|
|
14
|
+
kinesis.ShardLevelMetrics.OUTGOING_RECORDS,
|
|
15
|
+
kinesis.ShardLevelMetrics.WRITE_PROVISIONED_THROUGHPUT_EXCEEDED,
|
|
16
|
+
kinesis.ShardLevelMetrics.READ_PROVISIONED_THROUGHPUT_EXCEEDED,
|
|
17
|
+
],
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const allStream = new kinesis.Stream(stack, 'AllStream', {
|
|
21
|
+
shardLevelMetrics: [kinesis.ShardLevelMetrics.ALL],
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
RemovalPolicies.of(stack).destroy();
|
|
25
|
+
|
|
26
|
+
const integ = new IntegTest(app, 'integ-kinesis-stream-consumer', {
|
|
27
|
+
testCases: [stack],
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const streams = [explicitStream, allStream];
|
|
31
|
+
streams.forEach((stream) => {
|
|
32
|
+
integ.assertions.awsApiCall('Kinesis', 'describeStream', {
|
|
33
|
+
StreamName: stream.streamName,
|
|
34
|
+
}).expect(ExpectedResult.objectLike({
|
|
35
|
+
StreamDescription: {
|
|
36
|
+
ShardLevelMetrics: [
|
|
37
|
+
'IncomingBytes',
|
|
38
|
+
'IncomingRecords',
|
|
39
|
+
'IteratorAgeMilliseconds',
|
|
40
|
+
'OutgoingBytes',
|
|
41
|
+
'OutgoingRecords',
|
|
42
|
+
'WriteProvisionedThroughputExceeded',
|
|
43
|
+
'ReadProvisionedThroughputExceeded',
|
|
44
|
+
],
|
|
45
|
+
},
|
|
46
|
+
}));
|
|
47
|
+
});
|
|
@@ -642,6 +642,15 @@ new CfnOutput(this, 'TheUrl', {
|
|
|
642
642
|
});
|
|
643
643
|
```
|
|
644
644
|
|
|
645
|
+
### Important Function URL Permission Update - Oct 2025
|
|
646
|
+
Starting Oct 2025, Function URL invocation will require two permissions
|
|
647
|
+
- lambda:InvokeFunctionUrl
|
|
648
|
+
- lambda:InvokeFunction (New)
|
|
649
|
+
|
|
650
|
+
CDK has updated `grantInvokeUrl` and `addFunctionUrl` to add both permission above.
|
|
651
|
+
|
|
652
|
+
If your existing CDK stack uses `grantInvokeUrl` or `addFunctionUrl`, your next deployment will automatically add the `lambda:InvokeFunction` permission without requiring any code changes. This ensures your Function URLs continue working seamlessly. No additional actions are needed.
|
|
653
|
+
|
|
645
654
|
### CORS configuration for Function URLs
|
|
646
655
|
|
|
647
656
|
If you want your Function URLs to be invokable from a web page in browser, you
|
|
@@ -545,6 +545,10 @@ new logs.Transformer(this, 'Transformer', {
|
|
|
545
545
|
|
|
546
546
|
For more details on CloudWatch Logs transformation processors, refer to the [AWS documentation](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/CloudWatch-Logs-Transformation-Processors.html).
|
|
547
547
|
|
|
548
|
+
### Usage of metric filters on transformed logs
|
|
549
|
+
|
|
550
|
+
In order to use the transformed logs as search pattern, set the parameter `applyOnTransformedLogs: true` in the MetricFilterProps.
|
|
551
|
+
|
|
548
552
|
## Notes
|
|
549
553
|
|
|
550
554
|
Be aware that Log Group ARNs will always have the string `:*` appended to
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { App, RemovalPolicy, Stack, StackProps } from 'aws-cdk-lib';
|
|
2
|
+
import { IntegTest } from '@aws-cdk/integ-tests-alpha';
|
|
3
|
+
import { FilterPattern, LogGroup, MetricFilter } from 'aws-cdk-lib/aws-logs';
|
|
4
|
+
|
|
5
|
+
class TestStack extends Stack {
|
|
6
|
+
constructor(scope: App, id: string, props?: StackProps) {
|
|
7
|
+
super(scope, id, props);
|
|
8
|
+
|
|
9
|
+
const logGroup = new LogGroup(this, 'LogGroup', {
|
|
10
|
+
removalPolicy: RemovalPolicy.DESTROY,
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
new MetricFilter(this, 'MetricFilter', {
|
|
14
|
+
logGroup,
|
|
15
|
+
metricNamespace: 'MyApp',
|
|
16
|
+
metricName: 'Latency',
|
|
17
|
+
filterPattern: FilterPattern.exists('$.latency'),
|
|
18
|
+
applyOnTransformedLogs: true,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const app = new App();
|
|
24
|
+
const testCase = new TestStack(app, 'aws-cdk-metricfilter-apply-on-transformed-logs-integ');
|
|
25
|
+
|
|
26
|
+
new IntegTest(app, 'metricfilter-apply-on-transformed-logs', {
|
|
27
|
+
testCases: [testCase],
|
|
28
|
+
});
|
|
29
|
+
app.synth();
|
|
@@ -11,6 +11,7 @@ class TestStack extends Stack {
|
|
|
11
11
|
opensearch.EngineVersion.OPENSEARCH_2_13,
|
|
12
12
|
opensearch.EngineVersion.OPENSEARCH_2_15,
|
|
13
13
|
opensearch.EngineVersion.OPENSEARCH_2_17,
|
|
14
|
+
opensearch.EngineVersion.OPENSEARCH_3_1,
|
|
14
15
|
];
|
|
15
16
|
|
|
16
17
|
// deploy opensearch domain with minimal configuration
|
|
@@ -558,6 +558,18 @@ const zoneFromAttributes = route53.PublicHostedZone.fromPublicHostedZoneAttribut
|
|
|
558
558
|
const zoneFromId = route53.PublicHostedZone.fromPublicHostedZoneId(this, 'MyZone', 'ZOJJZC49E0EPZ');
|
|
559
559
|
```
|
|
560
560
|
|
|
561
|
+
You can import a Private Hosted Zone with `PrivateHostedZone.fromPrivateHostedZoneId` and `PrivateHostedZone.fromPrivateHostedZoneAttributes` methods:
|
|
562
|
+
|
|
563
|
+
```ts
|
|
564
|
+
const privateZoneFromAttributes = route53.PrivateHostedZone.fromPrivateHostedZoneAttributes(this, 'MyPrivateZone', {
|
|
565
|
+
zoneName: 'example.local',
|
|
566
|
+
hostedZoneId: 'ZOJJZC49E0EPZ',
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
// Does not know zoneName
|
|
570
|
+
const privateZoneFromId = route53.PrivateHostedZone.fromPrivateHostedZoneId(this, 'MyPrivateZone', 'ZOJJZC49E0EPZ');
|
|
571
|
+
```
|
|
572
|
+
|
|
561
573
|
You can use `CrossAccountZoneDelegationRecord` on imported Hosted Zones with the `grantDelegation` method:
|
|
562
574
|
|
|
563
575
|
```ts
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import * as ec2 from 'aws-cdk-lib/aws-ec2';
|
|
2
|
+
import * as cdk from 'aws-cdk-lib';
|
|
3
|
+
import * as route53 from 'aws-cdk-lib/aws-route53';
|
|
4
|
+
import { PrivateHostedZone } from 'aws-cdk-lib/aws-route53';
|
|
5
|
+
import { ExpectedResult, IntegTest } from '@aws-cdk/integ-tests-alpha';
|
|
6
|
+
|
|
7
|
+
const app = new cdk.App();
|
|
8
|
+
|
|
9
|
+
const stack = new cdk.Stack(app, 'aws-cdk-route53-integ');
|
|
10
|
+
|
|
11
|
+
const vpc = new ec2.Vpc(stack, 'VPC', { maxAzs: 1, restrictDefaultSecurityGroup: false });
|
|
12
|
+
|
|
13
|
+
const privateZone = new PrivateHostedZone(stack, 'PrivateZone', {
|
|
14
|
+
zoneName: 'aws-cdk.dev', vpc,
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const expectPrivateHostedZone = route53.PrivateHostedZone.fromHostedZoneAttributes(stack, 'ExpectPrivateHostedZone', {
|
|
18
|
+
hostedZoneId: privateZone.hostedZoneId,
|
|
19
|
+
zoneName: privateZone.zoneName,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const integTest = new IntegTest(app, 'AwsCdkRoute53IntegTest', {
|
|
23
|
+
testCases: [stack],
|
|
24
|
+
diffAssets: false,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const hostedZoneApiCall = integTest.assertions.awsApiCall('Route53', 'getHostedZone', {
|
|
28
|
+
Id: expectPrivateHostedZone.hostedZoneId,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
hostedZoneApiCall.expect(
|
|
32
|
+
ExpectedResult.objectLike({
|
|
33
|
+
HostedZone: {
|
|
34
|
+
Id: expectPrivateHostedZone.hostedZoneId,
|
|
35
|
+
Name: expectPrivateHostedZone.zoneName,
|
|
36
|
+
},
|
|
37
|
+
}),
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
app.synth();
|
|
41
|
+
|
|
@@ -267,7 +267,7 @@ new synthetics.Canary(this, 'Bucket Canary', {
|
|
|
267
267
|
```
|
|
268
268
|
|
|
269
269
|
> **Note:** Synthetics have a specified folder structure for canaries.
|
|
270
|
-
> For Node with puppeteer scripts supplied via `code.fromAsset()` or `code.fromBucket()`, the canary resource requires the following folder structure
|
|
270
|
+
> For Node with puppeteer scripts supplied via `code.fromAsset()` or `code.fromBucket()`, the canary resource requires the following folder structure for runtime versions older than `syn-nodejs-puppeteer-11.0`:
|
|
271
271
|
>
|
|
272
272
|
> ```plaintext
|
|
273
273
|
> canary/
|
|
@@ -276,6 +276,22 @@ new synthetics.Canary(this, 'Bucket Canary', {
|
|
|
276
276
|
> ├── <filename>.js
|
|
277
277
|
> ```
|
|
278
278
|
>
|
|
279
|
+
> For puppeteer based runtime versions newer than or equal to `syn-nodejs-puppeteer-11.0`, `nodjs/node_modules` is not necessary but supported.
|
|
280
|
+
>
|
|
281
|
+
> Both
|
|
282
|
+
> ```plaintext
|
|
283
|
+
> canary/
|
|
284
|
+
> ├── nodejs/
|
|
285
|
+
> ├── node_modules/
|
|
286
|
+
> ├── <filename>.js
|
|
287
|
+
> ```
|
|
288
|
+
> And
|
|
289
|
+
> ```plaintext
|
|
290
|
+
> canary/
|
|
291
|
+
> ├── <filename>.js
|
|
292
|
+
> ```
|
|
293
|
+
> are supported.
|
|
294
|
+
>
|
|
279
295
|
> For Node with playwright scripts supplied via `code.fromAsset()` or `code.fromBucket()`, the canary resource requires the following folder structure:
|
|
280
296
|
>
|
|
281
297
|
> ```plaintext
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as path from 'node:path';
|
|
2
|
+
import { App, Duration, Size, Stack, StackProps } from 'aws-cdk-lib/core';
|
|
3
|
+
import { IntegTest } from '@aws-cdk/integ-tests-alpha';
|
|
4
|
+
import { Construct } from 'constructs';
|
|
5
|
+
import * as synthetics from 'aws-cdk-lib/aws-synthetics';
|
|
6
|
+
|
|
7
|
+
class TestStack extends Stack {
|
|
8
|
+
public puppeteer11RootCanary: synthetics.Canary;
|
|
9
|
+
public puppeteer11NodeModulesCanary: synthetics.Canary;
|
|
10
|
+
|
|
11
|
+
constructor(scope: Construct, id: string, props?: StackProps) {
|
|
12
|
+
super(scope, id, props);
|
|
13
|
+
|
|
14
|
+
// Test puppeteer 11.0+ with root-level files only
|
|
15
|
+
this.puppeteer11RootCanary = new synthetics.Canary(this, 'Puppeteer11RootCanary', {
|
|
16
|
+
runtime: synthetics.Runtime.SYNTHETICS_NODEJS_PUPPETEER_11_0,
|
|
17
|
+
test: synthetics.Test.custom({
|
|
18
|
+
handler: 'canary.handler',
|
|
19
|
+
code: synthetics.Code.fromAsset(path.join(__dirname, 'canaries-runtime-validation', 'root-only')),
|
|
20
|
+
}),
|
|
21
|
+
memory: Size.mebibytes(1024),
|
|
22
|
+
timeout: Duration.minutes(2),
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// Test puppeteer 11.0+ also supports nodejs/node_modules structure
|
|
26
|
+
this.puppeteer11NodeModulesCanary = new synthetics.Canary(this, 'Puppeteer11NodeModulesCanary', {
|
|
27
|
+
runtime: synthetics.Runtime.SYNTHETICS_NODEJS_PUPPETEER_11_0,
|
|
28
|
+
test: synthetics.Test.custom({
|
|
29
|
+
handler: 'canary.handler',
|
|
30
|
+
code: synthetics.Code.fromAsset(path.join(__dirname, 'canaries')),
|
|
31
|
+
}),
|
|
32
|
+
memory: Size.mebibytes(1024),
|
|
33
|
+
timeout: Duration.minutes(2),
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const app = new App();
|
|
39
|
+
const testStack = new TestStack(app, 'SyntheticsCanaryRuntimeValidationStack');
|
|
40
|
+
|
|
41
|
+
new IntegTest(app, 'SyntheticsCanaryRuntimeValidation', {
|
|
42
|
+
testCases: [testStack],
|
|
43
|
+
});
|