@aws-cdk/aws-neptune-alpha 2.0.0-alpha.3 → 2.0.0-alpha.4

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.
package/.jsii CHANGED
@@ -8,7 +8,7 @@
8
8
  "url": "https://aws.amazon.com"
9
9
  },
10
10
  "dependencies": {
11
- "aws-cdk-lib": "^2.0.0-rc.26",
11
+ "aws-cdk-lib": "^2.0.0-rc.27",
12
12
  "constructs": "^10.0.0"
13
13
  },
14
14
  "dependencyClosure": {
@@ -1326,7 +1326,7 @@
1326
1326
  "line": 66
1327
1327
  },
1328
1328
  "readme": {
1329
- "markdown": "# Amazon EC2 Construct Library\n\n\n\nThe `@aws-cdk/aws-ec2` package contains primitives for setting up networking and\ninstances.\n\n```ts nofixture\nimport { aws_ec2 as ec2 } from 'aws-cdk-lib';\n```\n\n## VPC\n\nMost projects need a Virtual Private Cloud to provide security by means of\nnetwork partitioning. This is achieved by creating an instance of\n`Vpc`:\n\n```ts\nconst vpc = new ec2.Vpc(this, 'VPC');\n```\n\nAll default constructs require EC2 instances to be launched inside a VPC, so\nyou should generally start by defining a VPC whenever you need to launch\ninstances for your project.\n\n### Subnet Types\n\nA VPC consists of one or more subnets that instances can be placed into. CDK\ndistinguishes three different subnet types:\n\n* **Public (`SubnetType.PUBLIC`)** - public subnets connect directly to the Internet using an\n Internet Gateway. If you want your instances to have a public IP address\n and be directly reachable from the Internet, you must place them in a\n public subnet.\n* **Private with Internet Access (`SubnetType.PRIVATE_WITH_NAT`)** - instances in private subnets are not directly routable from the\n Internet, and connect out to the Internet via a NAT gateway. By default, a\n NAT gateway is created in every public subnet for maximum availability. Be\n aware that you will be charged for NAT gateways.\n* **Isolated (`SubnetType.PRIVATE_ISOLATED`)** - isolated subnets do not route from or to the Internet, and\n as such do not require NAT gateways. They can only connect to or be\n connected to from other instances in the same VPC. A default VPC configuration\n will not include isolated subnets,\n\nA default VPC configuration will create public and **private** subnets. However, if\n`natGateways:0` **and** `subnetConfiguration` is undefined, default VPC configuration\nwill create public and **isolated** subnets. See [*Advanced Subnet Configuration*](#advanced-subnet-configuration)\nbelow for information on how to change the default subnet configuration.\n\nConstructs using the VPC will \"launch instances\" (or more accurately, create\nElastic Network Interfaces) into one or more of the subnets. They all accept\na property called `subnetSelection` (sometimes called `vpcSubnets`) to allow\nyou to select in what subnet to place the ENIs, usually defaulting to\n*private* subnets if the property is omitted.\n\nIf you would like to save on the cost of NAT gateways, you can use\n*isolated* subnets instead of *private* subnets (as described in Advanced\n*Subnet Configuration*). If you need private instances to have\ninternet connectivity, another option is to reduce the number of NAT gateways\ncreated by setting the `natGateways` property to a lower value (the default\nis one NAT gateway per availability zone). Be aware that this may have\navailability implications for your application.\n\n[Read more about\nsubnets](https://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Subnets.html).\n\n### Control over availability zones\n\nBy default, a VPC will spread over at most 3 Availability Zones available to\nit. To change the number of Availability Zones that the VPC will spread over,\nspecify the `maxAzs` property when defining it.\n\nThe number of Availability Zones that are available depends on the *region*\nand *account* of the Stack containing the VPC. If the [region and account are\nspecified](https://docs.aws.amazon.com/cdk/latest/guide/environments.html) on\nthe Stack, the CLI will [look up the existing Availability\nZones](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#using-regions-availability-zones-describe)\nand get an accurate count. If region and account are not specified, the stack\ncould be deployed anywhere and it will have to make a safe choice, limiting\nitself to 2 Availability Zones.\n\nTherefore, to get the VPC to spread over 3 or more availability zones, you\nmust specify the environment where the stack will be deployed.\n\nYou can gain full control over the availability zones selection strategy by overriding the Stack's [`get availabilityZones()`](https://github.com/aws/aws-cdk/blob/master/packages/@aws-cdk/core/lib/stack.ts) method:\n\n```ts\nclass MyStack extends Stack {\n\n get availabilityZones(): string[] {\n return ['us-west-2a', 'us-west-2b'];\n }\n\n constructor(scope: Construct, id: string, props?: StackProps) {\n super(scope, id, props);\n ...\n }\n}\n```\n\nNote that overriding the `get availabilityZones()` method will override the default behavior for all constructs defined within the Stack.\n\n### Choosing subnets for resources\n\nWhen creating resources that create Elastic Network Interfaces (such as\ndatabases or instances), there is an option to choose which subnets to place\nthem in. For example, a VPC endpoint by default is placed into a subnet in\nevery availability zone, but you can override which subnets to use. The property\nis typically called one of `subnets`, `vpcSubnets` or `subnetSelection`.\n\nThe example below will place the endpoint into two AZs (`us-east-1a` and `us-east-1c`),\nin Isolated subnets:\n\n```ts\nnew InterfaceVpcEndpoint(stack, 'VPC Endpoint', {\n vpc,\n service: new InterfaceVpcEndpointService('com.amazonaws.vpce.us-east-1.vpce-svc-uuddlrlrbastrtsvc', 443),\n subnets: {\n subnetType: SubnetType.ISOLATED,\n availabilityZones: ['us-east-1a', 'us-east-1c']\n }\n});\n```\n\nYou can also specify specific subnet objects for granular control:\n\n```ts\nnew InterfaceVpcEndpoint(stack, 'VPC Endpoint', {\n vpc,\n service: new InterfaceVpcEndpointService('com.amazonaws.vpce.us-east-1.vpce-svc-uuddlrlrbastrtsvc', 443),\n subnets: {\n subnets: [subnet1, subnet2]\n }\n});\n```\n\nWhich subnets are selected is evaluated as follows:\n\n* `subnets`: if specific subnet objects are supplied, these are selected, and no other\n logic is used.\n* `subnetType`/`subnetGroupName`: otherwise, a set of subnets is selected by\n supplying either type or name:\n * `subnetType` will select all subnets of the given type.\n * `subnetGroupName` should be used to distinguish between multiple groups of subnets of\n the same type (for example, you may want to separate your application instances and your\n RDS instances into two distinct groups of Isolated subnets).\n * If neither are given, the first available subnet group of a given type that\n exists in the VPC will be used, in this order: Private, then Isolated, then Public.\n In short: by default ENIs will preferentially be placed in subnets not connected to\n the Internet.\n* `availabilityZones`/`onePerAz`: finally, some availability-zone based filtering may be done.\n This filtering by availability zones will only be possible if the VPC has been created or\n looked up in a non-environment agnostic stack (so account and region have been set and\n availability zones have been looked up).\n * `availabilityZones`: only the specific subnets from the selected subnet groups that are\n in the given availability zones will be returned.\n * `onePerAz`: per availability zone, a maximum of one subnet will be returned (Useful for resource\n types that do not allow creating two ENIs in the same availability zone).\n* `subnetFilters`: additional filtering on subnets using any number of user-provided filters which\n extend `SubnetFilter`. The following methods on the `SubnetFilter` class can be used to create\n a filter:\n * `byIds`: chooses subnets from a list of ids\n * `availabilityZones`: chooses subnets in the provided list of availability zones\n * `onePerAz`: chooses at most one subnet per availability zone\n * `containsIpAddresses`: chooses a subnet which contains *any* of the listed ip addresses\n * `byCidrMask`: chooses subnets that have the provided CIDR netmask\n\n### Using NAT instances\n\nBy default, the `Vpc` construct will create NAT *gateways* for you, which\nare managed by AWS. If you would prefer to use your own managed NAT\n*instances* instead, specify a different value for the `natGatewayProvider`\nproperty, as follows:\n\n[using NAT instances](test/integ.nat-instances.lit.ts)\n\nThe construct will automatically search for the most recent NAT gateway AMI.\nIf you prefer to use a custom AMI, use `machineImage:\nMachineImage.genericLinux({ ... })` and configure the right AMI ID for the\nregions you want to deploy to.\n\nBy default, the NAT instances will route all traffic. To control what traffic\ngets routed, pass `allowAllTraffic: false` and access the\n`NatInstanceProvider.connections` member after having passed it to the VPC:\n\n```ts\nconst provider = NatProvider.instance({\n instanceType: /* ... */,\n allowAllTraffic: false,\n});\nnew Vpc(stack, 'TheVPC', {\n natGatewayProvider: provider,\n});\nprovider.connections.allowFrom(Peer.ipv4('1.2.3.4/8'), Port.tcp(80));\n```\n\n### Advanced Subnet Configuration\n\nIf the default VPC configuration (public and private subnets spanning the\nsize of the VPC) don't suffice for you, you can configure what subnets to\ncreate by specifying the `subnetConfiguration` property. It allows you\nto configure the number and size of all subnets. Specifying an advanced\nsubnet configuration could look like this:\n\n```ts\nconst vpc = new ec2.Vpc(this, 'TheVPC', {\n // 'cidr' configures the IP range and size of the entire VPC.\n // The IP space will be divided over the configured subnets.\n cidr: '10.0.0.0/21',\n\n // 'maxAzs' configures the maximum number of availability zones to use\n maxAzs: 3,\n\n // 'subnetConfiguration' specifies the \"subnet groups\" to create.\n // Every subnet group will have a subnet for each AZ, so this\n // configuration will create `3 groups × 3 AZs = 9` subnets.\n subnetConfiguration: [\n {\n // 'subnetType' controls Internet access, as described above.\n subnetType: ec2.SubnetType.PUBLIC,\n\n // 'name' is used to name this particular subnet group. You will have to\n // use the name for subnet selection if you have more than one subnet\n // group of the same type.\n name: 'Ingress',\n\n // 'cidrMask' specifies the IP addresses in the range of of individual\n // subnets in the group. Each of the subnets in this group will contain\n // `2^(32 address bits - 24 subnet bits) - 2 reserved addresses = 254`\n // usable IP addresses.\n //\n // If 'cidrMask' is left out the available address space is evenly\n // divided across the remaining subnet groups.\n cidrMask: 24,\n },\n {\n cidrMask: 24,\n name: 'Application',\n subnetType: ec2.SubnetType.PRIVATE_WITH_NAT,\n },\n {\n cidrMask: 28,\n name: 'Database',\n subnetType: ec2.SubnetType.PRIVATE_ISOLATED,\n\n // 'reserved' can be used to reserve IP address space. No resources will\n // be created for this subnet, but the IP range will be kept available for\n // future creation of this subnet, or even for future subdivision.\n reserved: true\n }\n ],\n});\n```\n\nThe example above is one possible configuration, but the user can use the\nconstructs above to implement many other network configurations.\n\nThe `Vpc` from the above configuration in a Region with three\navailability zones will be the following:\n\nSubnet Name |Type |IP Block |AZ|Features\n------------------|----------|--------------|--|--------\nIngressSubnet1 |`PUBLIC` |`10.0.0.0/24` |#1|NAT Gateway\nIngressSubnet2 |`PUBLIC` |`10.0.1.0/24` |#2|NAT Gateway\nIngressSubnet3 |`PUBLIC` |`10.0.2.0/24` |#3|NAT Gateway\nApplicationSubnet1|`PRIVATE` |`10.0.3.0/24` |#1|Route to NAT in IngressSubnet1\nApplicationSubnet2|`PRIVATE` |`10.0.4.0/24` |#2|Route to NAT in IngressSubnet2\nApplicationSubnet3|`PRIVATE` |`10.0.5.0/24` |#3|Route to NAT in IngressSubnet3\nDatabaseSubnet1 |`ISOLATED`|`10.0.6.0/28` |#1|Only routes within the VPC\nDatabaseSubnet2 |`ISOLATED`|`10.0.6.16/28`|#2|Only routes within the VPC\nDatabaseSubnet3 |`ISOLATED`|`10.0.6.32/28`|#3|Only routes within the VPC\n\n### Accessing the Internet Gateway\n\nIf you need access to the internet gateway, you can get its ID like so:\n\n```ts\nconst igwId = vpc.internetGatewayId;\n```\n\nFor a VPC with only `ISOLATED` subnets, this value will be undefined.\n\nThis is only supported for VPCs created in the stack - currently you're\nunable to get the ID for imported VPCs. To do that you'd have to specifically\nlook up the Internet Gateway by name, which would require knowing the name\nbeforehand.\n\nThis can be useful for configuring routing using a combination of gateways:\nfor more information see [Routing](#routing) below.\n\n#### Routing\n\nIt's possible to add routes to any subnets using the `addRoute()` method. If for\nexample you want an isolated subnet to have a static route via the default\nInternet Gateway created for the public subnet - perhaps for routing a VPN\nconnection - you can do so like this:\n\n```ts\nconst vpc = ec2.Vpc(this, \"VPC\", {\n subnetConfiguration: [{\n subnetType: SubnetType.PUBLIC,\n name: 'Public',\n },{\n subnetType: SubnetType.ISOLATED,\n name: 'Isolated',\n }]\n})\n(vpc.isolatedSubnets[0] as Subnet).addRoute(\"StaticRoute\", {\n routerId: vpc.internetGatewayId,\n routerType: RouterType.GATEWAY,\n destinationCidrBlock: \"8.8.8.8/32\",\n})\n```\n\n*Note that we cast to `Subnet` here because the list of subnets only returns an\n`ISubnet`.*\n\n### Reserving subnet IP space\n\nThere are situations where the IP space for a subnet or number of subnets\nwill need to be reserved. This is useful in situations where subnets would\nneed to be added after the vpc is originally deployed, without causing IP\nrenumbering for existing subnets. The IP space for a subnet may be reserved\nby setting the `reserved` subnetConfiguration property to true, as shown\nbelow:\n\n```ts\nconst vpc = new ec2.Vpc(this, 'TheVPC', {\n natGateways: 1,\n subnetConfiguration: [\n {\n cidrMask: 26,\n name: 'Public',\n subnetType: ec2.SubnetType.PUBLIC,\n },\n {\n cidrMask: 26,\n name: 'Application1',\n subnetType: ec2.SubnetType.PRIVATE_WITH_NAT,\n },\n {\n cidrMask: 26,\n name: 'Application2',\n subnetType: ec2.SubnetType.PRIVATE_WITH_NAT,\n reserved: true, // <---- This subnet group is reserved\n },\n {\n cidrMask: 27,\n name: 'Database',\n subnetType: ec2.SubnetType.ISOLATED,\n }\n ],\n});\n```\n\nIn the example above, the subnet for Application2 is not actually provisioned\nbut its IP space is still reserved. If in the future this subnet needs to be\nprovisioned, then the `reserved: true` property should be removed. Reserving\nparts of the IP space prevents the other subnets from getting renumbered.\n\n### Sharing VPCs between stacks\n\nIf you are creating multiple `Stack`s inside the same CDK application, you\ncan reuse a VPC defined in one Stack in another by simply passing the VPC\ninstance around:\n\n[sharing VPCs between stacks](test/integ.share-vpcs.lit.ts)\n\n### Importing an existing VPC\n\nIf your VPC is created outside your CDK app, you can use `Vpc.fromLookup()`.\nThe CDK CLI will search for the specified VPC in the the stack's region and\naccount, and import the subnet configuration. Looking up can be done by VPC\nID, but more flexibly by searching for a specific tag on the VPC.\n\nSubnet types will be determined from the `aws-cdk:subnet-type` tag on the\nsubnet if it exists, or the presence of a route to an Internet Gateway\notherwise. Subnet names will be determined from the `aws-cdk:subnet-name` tag\non the subnet if it exists, or will mirror the subnet type otherwise (i.e.\na public subnet will have the name `\"Public\"`).\n\nThe result of the `Vpc.fromLookup()` operation will be written to a file\ncalled `cdk.context.json`. You must commit this file to source control so\nthat the lookup values are available in non-privileged environments such\nas CI build steps, and to ensure your template builds are repeatable.\n\nHere's how `Vpc.fromLookup()` can be used:\n\n[importing existing VPCs](test/integ.import-default-vpc.lit.ts)\n\n`Vpc.fromLookup` is the recommended way to import VPCs. If for whatever\nreason you do not want to use the context mechanism to look up a VPC at\nsynthesis time, you can also use `Vpc.fromVpcAttributes`. This has the\nfollowing limitations:\n\n* Every subnet group in the VPC must have a subnet in each availability zone\n (for example, each AZ must have both a public and private subnet). Asymmetric\n VPCs are not supported.\n* All VpcId, SubnetId, RouteTableId, ... parameters must either be known at\n synthesis time, or they must come from deploy-time list parameters whose\n deploy-time lengths are known at synthesis time.\n\nUsing `Vpc.fromVpcAttributes()` looks like this:\n\n```ts\nconst vpc = ec2.Vpc.fromVpcAttributes(stack, 'VPC', {\n vpcId: 'vpc-1234',\n availabilityZones: ['us-east-1a', 'us-east-1b'],\n\n // Either pass literals for all IDs\n publicSubnetIds: ['s-12345', 's-67890'],\n\n // OR: import a list of known length\n privateSubnetIds: Fn.importListValue('PrivateSubnetIds', 2),\n\n // OR: split an imported string to a list of known length\n isolatedSubnetIds: Fn.split(',', ssm.StringParameter.valueForStringParameter(stack, `MyParameter`), 2),\n});\n```\n\n## Allowing Connections\n\nIn AWS, all network traffic in and out of **Elastic Network Interfaces** (ENIs)\nis controlled by **Security Groups**. You can think of Security Groups as a\nfirewall with a set of rules. By default, Security Groups allow no incoming\n(ingress) traffic and all outgoing (egress) traffic. You can add ingress rules\nto them to allow incoming traffic streams. To exert fine-grained control over\negress traffic, set `allowAllOutbound: false` on the `SecurityGroup`, after\nwhich you can add egress traffic rules.\n\nYou can manipulate Security Groups directly:\n\n```ts fixture=with-vpc\nconst mySecurityGroup = new ec2.SecurityGroup(this, 'SecurityGroup', {\n vpc,\n description: 'Allow ssh access to ec2 instances',\n allowAllOutbound: true // Can be set to false\n});\nmySecurityGroup.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(22), 'allow ssh access from the world');\n```\n\nAll constructs that create ENIs on your behalf (typically constructs that create\nEC2 instances or other VPC-connected resources) will all have security groups\nautomatically assigned. Those constructs have an attribute called\n**connections**, which is an object that makes it convenient to update the\nsecurity groups. If you want to allow connections between two constructs that\nhave security groups, you have to add an **Egress** rule to one Security Group,\nand an **Ingress** rule to the other. The connections object will automatically\ntake care of this for you:\n\n```ts fixture=conns\n// Allow connections from anywhere\nloadBalancer.connections.allowFromAnyIpv4(ec2.Port.tcp(443), 'Allow inbound HTTPS');\n\n// The same, but an explicit IP address\nloadBalancer.connections.allowFrom(ec2.Peer.ipv4('1.2.3.4/32'), ec2.Port.tcp(443), 'Allow inbound HTTPS');\n\n// Allow connection between AutoScalingGroups\nappFleet.connections.allowTo(dbFleet, ec2.Port.tcp(443), 'App can call database');\n```\n\n### Connection Peers\n\nThere are various classes that implement the connection peer part:\n\n```ts fixture=conns\n// Simple connection peers\nlet peer = ec2.Peer.ipv4('10.0.0.0/16');\npeer = ec2.Peer.anyIpv4();\npeer = ec2.Peer.ipv6('::0/0');\npeer = ec2.Peer.anyIpv6();\npeer = ec2.Peer.prefixList('pl-12345');\nappFleet.connections.allowTo(peer, ec2.Port.tcp(443), 'Allow outbound HTTPS');\n```\n\nAny object that has a security group can itself be used as a connection peer:\n\n```ts fixture=conns\n// These automatically create appropriate ingress and egress rules in both security groups\nfleet1.connections.allowTo(fleet2, ec2.Port.tcp(80), 'Allow between fleets');\n\nappFleet.connections.allowFromAnyIpv4(ec2.Port.tcp(80), 'Allow from load balancer');\n```\n\n### Port Ranges\n\nThe connections that are allowed are specified by port ranges. A number of classes provide\nthe connection specifier:\n\n```ts\nec2.Port.tcp(80)\nec2.Port.tcpRange(60000, 65535)\nec2.Port.allTcp()\nec2.Port.allTraffic()\n```\n\n> NOTE: This set is not complete yet; for example, there is no library support for ICMP at the moment.\n> However, you can write your own classes to implement those.\n\n### Default Ports\n\nSome Constructs have default ports associated with them. For example, the\nlistener of a load balancer does (it's the public port), or instances of an\nRDS database (it's the port the database is accepting connections on).\n\nIf the object you're calling the peering method on has a default port associated with it, you can call\n`allowDefaultPortFrom()` and omit the port specifier. If the argument has an associated default port, call\n`allowDefaultPortTo()`.\n\nFor example:\n\n```ts fixture=conns\n// Port implicit in listener\nlistener.connections.allowDefaultPortFromAnyIpv4('Allow public');\n\n// Port implicit in peer\nappFleet.connections.allowDefaultPortTo(rdsDatabase, 'Fleet can access database');\n```\n\n### Security group rules\n\nBy default, security group wills be added inline to the security group in the output cloud formation\ntemplate, if applicable. This includes any static rules by ip address and port range. This\noptimization helps to minimize the size of the template.\n\nIn some environments this is not desirable, for example if your security group access is controlled\nvia tags. You can disable inline rules per security group or globally via the context key\n`@aws-cdk/aws-ec2.securityGroupDisableInlineRules`.\n\n```ts fixture=with-vpc\nconst mySecurityGroupWithoutInlineRules = new ec2.SecurityGroup(this, 'SecurityGroup', {\n vpc,\n description: 'Allow ssh access to ec2 instances',\n allowAllOutbound: true,\n disableInlineRules: true\n});\n//This will add the rule as an external cloud formation construct\nmySecurityGroupWithoutInlineRules.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(22), 'allow ssh access from the world');\n```\n\n## Machine Images (AMIs)\n\nAMIs control the OS that gets launched when you start your EC2 instance. The EC2\nlibrary contains constructs to select the AMI you want to use.\n\nDepending on the type of AMI, you select it a different way. Here are some\nexamples of things you might want to use:\n\n[example of creating images](test/example.images.lit.ts)\n\n> NOTE: The AMIs selected by `MachineImage.lookup()` will be cached in\n> `cdk.context.json`, so that your AutoScalingGroup instances aren't replaced while\n> you are making unrelated changes to your CDK app.\n>\n> To query for the latest AMI again, remove the relevant cache entry from\n> `cdk.context.json`, or use the `cdk context` command. For more information, see\n> [Runtime Context](https://docs.aws.amazon.com/cdk/latest/guide/context.html) in the CDK\n> developer guide.\n>\n> `MachineImage.genericLinux()`, `MachineImage.genericWindows()` will use `CfnMapping` in\n> an agnostic stack.\n\n## Special VPC configurations\n\n### VPN connections to a VPC\n\nCreate your VPC with VPN connections by specifying the `vpnConnections` props (keys are construct `id`s):\n\n```ts\nconst vpc = new ec2.Vpc(this, 'MyVpc', {\n vpnConnections: {\n dynamic: { // Dynamic routing (BGP)\n ip: '1.2.3.4'\n },\n static: { // Static routing\n ip: '4.5.6.7',\n staticRoutes: [\n '192.168.10.0/24',\n '192.168.20.0/24'\n ]\n }\n }\n});\n```\n\nTo create a VPC that can accept VPN connections, set `vpnGateway` to `true`:\n\n```ts\nconst vpc = new ec2.Vpc(this, 'MyVpc', {\n vpnGateway: true\n});\n```\n\nVPN connections can then be added:\n\n```ts fixture=with-vpc\nvpc.addVpnConnection('Dynamic', {\n ip: '1.2.3.4'\n});\n```\n\nBy default, routes will be propagated on the route tables associated with the private subnets. If no\nprivate subnets exists, isolated subnets are used. If no isolated subnets exists, public subnets are\nused. Use the `Vpc` property `vpnRoutePropagation` to customize this behavior.\n\nVPN connections expose [metrics (cloudwatch.Metric)](https://github.com/aws/aws-cdk/blob/master/packages/%40aws-cdk/aws-cloudwatch/README.md) across all tunnels in the account/region and per connection:\n\n```ts fixture=with-vpc\n// Across all tunnels in the account/region\nconst allDataOut = ec2.VpnConnection.metricAllTunnelDataOut();\n\n// For a specific vpn connection\nconst vpnConnection = vpc.addVpnConnection('Dynamic', {\n ip: '1.2.3.4'\n});\nconst state = vpnConnection.metricTunnelState();\n```\n\n### VPC endpoints\n\nA VPC endpoint enables you to privately connect your VPC to supported AWS services and VPC endpoint services powered by PrivateLink without requiring an internet gateway, NAT device, VPN connection, or AWS Direct Connect connection. Instances in your VPC do not require public IP addresses to communicate with resources in the service. Traffic between your VPC and the other service does not leave the Amazon network.\n\nEndpoints are virtual devices. They are horizontally scaled, redundant, and highly available VPC components that allow communication between instances in your VPC and services without imposing availability risks or bandwidth constraints on your network traffic.\n\n[example of setting up VPC endpoints](test/integ.vpc-endpoint.lit.ts)\n\nBy default, CDK will place a VPC endpoint in one subnet per AZ. If you wish to override the AZs CDK places the VPC endpoint in,\nuse the `subnets` parameter as follows:\n\n```ts\nnew InterfaceVpcEndpoint(stack, 'VPC Endpoint', {\n vpc,\n service: new InterfaceVpcEndpointService('com.amazonaws.vpce.us-east-1.vpce-svc-uuddlrlrbastrtsvc', 443),\n // Choose which availability zones to place the VPC endpoint in, based on\n // available AZs\n subnets: {\n availabilityZones: ['us-east-1a', 'us-east-1c']\n }\n});\n```\n\nPer the [AWS documentation](https://aws.amazon.com/premiumsupport/knowledge-center/interface-endpoint-availability-zone/), not all\nVPC endpoint services are available in all AZs. If you specify the parameter `lookupSupportedAzs`, CDK attempts to discover which\nAZs an endpoint service is available in, and will ensure the VPC endpoint is not placed in a subnet that doesn't match those AZs.\nThese AZs will be stored in cdk.context.json.\n\n```ts\nnew InterfaceVpcEndpoint(stack, 'VPC Endpoint', {\n vpc,\n service: new InterfaceVpcEndpointService('com.amazonaws.vpce.us-east-1.vpce-svc-uuddlrlrbastrtsvc', 443),\n // Choose which availability zones to place the VPC endpoint in, based on\n // available AZs\n lookupSupportedAzs: true\n});\n```\n\nPre-defined AWS services are defined in the [InterfaceVpcEndpointAwsService](lib/vpc-endpoint.ts) class, and can be used to\ncreate VPC endpoints without having to configure name, ports, etc. For example, a Keyspaces endpoint can be created for\nuse in your VPC:\n\n``` ts\nnew InterfaceVpcEndpoint(stack, 'VPC Endpoint', { vpc, service: InterfaceVpcEndpointAwsService.KEYSPACES });\n```\n\n#### Security groups for interface VPC endpoints\n\nBy default, interface VPC endpoints create a new security group and traffic is **not**\nautomatically allowed from the VPC CIDR.\n\nUse the `connections` object to allow traffic to flow to the endpoint:\n\n```ts fixture=conns\nmyEndpoint.connections.allowDefaultPortFromAnyIpv4();\n```\n\nAlternatively, existing security groups can be used by specifying the `securityGroups` prop.\n\n### VPC endpoint services\n\nA VPC endpoint service enables you to expose a Network Load Balancer(s) as a provider service to consumers, who connect to your service over a VPC endpoint. You can restrict access to your service via allowed principals (anything that extends ArnPrincipal), and require that new connections be manually accepted.\n\n```ts\nnew VpcEndpointService(this, 'EndpointService', {\n vpcEndpointServiceLoadBalancers: [networkLoadBalancer1, networkLoadBalancer2],\n acceptanceRequired: true,\n allowedPrincipals: [new ArnPrincipal('arn:aws:iam::123456789012:root')]\n});\n```\n\nEndpoint services support private DNS, which makes it easier for clients to connect to your service by automatically setting up DNS in their VPC.\nYou can enable private DNS on an endpoint service like so:\n\n```ts\nimport { VpcEndpointServiceDomainName } from 'aws-cdk-lib/aws-route53';\n\nnew VpcEndpointServiceDomainName(stack, 'EndpointDomain', {\n endpointService: vpces,\n domainName: 'my-stuff.aws-cdk.dev',\n publicHostedZone: zone,\n});\n```\n\nNote: The domain name must be owned (registered through Route53) by the account the endpoint service is in, or delegated to the account.\nThe VpcEndpointServiceDomainName will handle the AWS side of domain verification, the process for which can be found\n[here](https://docs.aws.amazon.com/vpc/latest/userguide/endpoint-services-dns-validation.html)\n\n### Client VPN endpoint\n\nAWS Client VPN is a managed client-based VPN service that enables you to securely access your AWS\nresources and resources in your on-premises network. With Client VPN, you can access your resources\nfrom any location using an OpenVPN-based VPN client.\n\nUse the `addClientVpnEndpoint()` method to add a client VPN endpoint to a VPC:\n\n```ts fixture=client-vpn\nvpc.addClientVpnEndpoint('Endpoint', {\n cidr: '10.100.0.0/16',\n serverCertificateArn: 'arn:aws:acm:us-east-1:123456789012:certificate/server-certificate-id',\n // Mutual authentication\n clientCertificateArn: 'arn:aws:acm:us-east-1:123456789012:certificate/client-certificate-id',\n // User-based authentication\n userBasedAuthentication: ec2.ClientVpnUserBasedAuthentication.federated(samlProvider),\n});\n```\n\nThe endpoint must use at least one [authentication method](https://docs.aws.amazon.com/vpn/latest/clientvpn-admin/client-authentication.html):\n\n* Mutual authentication with a client certificate\n* User-based authentication (directory or federated)\n\nIf user-based authentication is used, the [self-service portal URL](https://docs.aws.amazon.com/vpn/latest/clientvpn-user/self-service-portal.html)\nis made available via a CloudFormation output.\n\nBy default, a new security group is created and logging is enabled. Moreover, a rule to\nauthorize all users to the VPC CIDR is created.\n\nTo customize authorization rules, set the `authorizeAllUsersToVpcCidr` prop to `false`\nand use `addaddAuthorizationRule()`:\n\n```ts fixture=client-vpn\nconst endpoint = vpc.addClientVpnEndpoint('Endpoint', {\n cidr: '10.100.0.0/16',\n serverCertificateArn: 'arn:aws:acm:us-east-1:123456789012:certificate/server-certificate-id',\n userBasedAuthentication: ec2.ClientVpnUserBasedAuthentication.federated(samlProvider),\n authorizeAllUsersToVpcCidr: false,\n});\n\nendpoint.addAuthorizationRule('Rule', {\n cidr: '10.0.10.0/32',\n groupId: 'group-id',\n});\n```\n\nUse `addRoute()` to configure network routes:\n\n```ts fixture=client-vpn\nconst endpoint = vpc.addClientVpnEndpoint('Endpoint', {\n cidr: '10.100.0.0/16',\n serverCertificateArn: 'arn:aws:acm:us-east-1:123456789012:certificate/server-certificate-id',\n userBasedAuthentication: ec2.ClientVpnUserBasedAuthentication.federated(samlProvider),\n});\n\n// Client-to-client access\nendpoint.addRoute('Route', {\n cidr: '10.100.0.0/16',\n target: ec2.ClientVpnRouteTarget.local(),\n});\n```\n\nUse the `connections` object of the endpoint to allow traffic to other security groups.\n\n## Instances\n\nYou can use the `Instance` class to start up a single EC2 instance. For production setups, we recommend\nyou use an `AutoScalingGroup` from the `aws-autoscaling` module instead, as AutoScalingGroups will take\ncare of restarting your instance if it ever fails.\n\n### Configuring Instances using CloudFormation Init (cfn-init)\n\nCloudFormation Init allows you to configure your instances by writing files to them, installing software\npackages, starting services and running arbitrary commands. By default, if any of the instance setup\ncommands throw an error, the deployment will fail and roll back to the previously known good state.\nThe following documentation also applies to `AutoScalingGroup`s.\n\nFor the full set of capabilities of this system, see the documentation for\n[`AWS::CloudFormation::Init`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-init.html).\nHere is an example of applying some configuration to an instance:\n\n```ts\nnew ec2.Instance(this, 'Instance', {\n // Showing the most complex setup, if you have simpler requirements\n // you can use `CloudFormationInit.fromElements()`.\n init: ec2.CloudFormationInit.fromConfigSets({\n configSets: {\n // Applies the configs below in this order\n default: ['yumPreinstall', 'config'],\n },\n configs: {\n yumPreinstall: new ec2.InitConfig([\n // Install an Amazon Linux package using yum\n ec2.InitPackage.yum('git'),\n ]),\n config: new ec2.InitConfig([\n // Create a JSON file from tokens (can also create other files)\n ec2.InitFile.fromObject('/etc/stack.json', {\n stackId: stack.stackId,\n stackName: stack.stackName,\n region: stack.region,\n }),\n\n // Create a group and user\n ec2.InitGroup.fromName('my-group'),\n ec2.InitUser.fromName('my-user'),\n\n // Install an RPM from the internet\n ec2.InitPackage.rpm('http://mirrors.ukfast.co.uk/sites/dl.fedoraproject.org/pub/epel/8/Everything/x86_64/Packages/r/rubygem-git-1.5.0-2.el8.noarch.rpm'),\n ]),\n },\n }),\n initOptions: {\n // Optional, which configsets to activate (['default'] by default)\n configSets: ['default'],\n\n // Optional, how long the installation is expected to take (5 minutes by default)\n timeout: Duration.minutes(30),\n\n // Optional, whether to include the --url argument when running cfn-init and cfn-signal commands (false by default)\n includeUrl: true\n\n // Optional, whether to include the --role argument when running cfn-init and cfn-signal commands (false by default)\n includeRole: true\n },\n});\n```\n\nYou can have services restarted after the init process has made changes to the system.\nTo do that, instantiate an `InitServiceRestartHandle` and pass it to the config elements\nthat need to trigger the restart and the service itself. For example, the following\nconfig writes a config file for nginx, extracts an archive to the root directory, and then\nrestarts nginx so that it picks up the new config and files:\n\n```ts\nconst handle = new ec2.InitServiceRestartHandle();\n\nec2.CloudFormationInit.fromElements(\n ec2.InitFile.fromString('/etc/nginx/nginx.conf', '...', { serviceRestartHandles: [handle] }),\n ec2.InitSource.fromBucket('/var/www/html', myBucket, 'html.zip', { serviceRestartHandles: [handle] }),\n ec2.InitService.enable('nginx', {\n serviceRestartHandle: handle,\n })\n);\n```\n\n### Bastion Hosts\n\nA bastion host functions as an instance used to access servers and resources in a VPC without open up the complete VPC on a network level.\nYou can use bastion hosts using a standard SSH connection targeting port 22 on the host. As an alternative, you can connect the SSH connection\nfeature of AWS Systems Manager Session Manager, which does not need an opened security group. (https://aws.amazon.com/about-aws/whats-new/2019/07/session-manager-launches-tunneling-support-for-ssh-and-scp/)\n\nA default bastion host for use via SSM can be configured like:\n\n```ts fixture=with-vpc\nconst host = new ec2.BastionHostLinux(this, 'BastionHost', { vpc });\n```\n\nIf you want to connect from the internet using SSH, you need to place the host into a public subnet. You can then configure allowed source hosts.\n\n```ts fixture=with-vpc\nconst host = new ec2.BastionHostLinux(this, 'BastionHost', {\n vpc,\n subnetSelection: { subnetType: ec2.SubnetType.PUBLIC },\n});\nhost.allowSshAccessFrom(ec2.Peer.ipv4('1.2.3.4/32'));\n```\n\nAs there are no SSH public keys deployed on this machine, you need to use [EC2 Instance Connect](https://aws.amazon.com/de/blogs/compute/new-using-amazon-ec2-instance-connect-for-ssh-access-to-your-ec2-instances/)\nwith the command `aws ec2-instance-connect send-ssh-public-key` to provide your SSH public key.\n\nEBS volume for the bastion host can be encrypted like:\n\n```ts\n const host = new ec2.BastionHostLinux(stack, 'BastionHost', {\n vpc,\n blockDevices: [{\n deviceName: 'EBSBastionHost',\n volume: BlockDeviceVolume.ebs(10, {\n encrypted: true,\n }),\n }],\n });\n```\n\n### Block Devices\n\nTo add EBS block device mappings, specify the `blockDevices` property. The following example sets the EBS-backed\nroot device (`/dev/sda1`) size to 50 GiB, and adds another EBS-backed device mapped to `/dev/sdm` that is 100 GiB in\nsize:\n\n```ts\nnew ec2.Instance(this, 'Instance', {\n // ...\n blockDevices: [\n {\n deviceName: '/dev/sda1',\n volume: ec2.BlockDeviceVolume.ebs(50),\n },\n {\n deviceName: '/dev/sdm',\n volume: ec2.BlockDeviceVolume.ebs(100),\n },\n ],\n});\n\n```\n\n### Volumes\n\nWhereas a `BlockDeviceVolume` is an EBS volume that is created and destroyed as part of the creation and destruction of a specific instance. A `Volume` is for when you want an EBS volume separate from any particular instance. A `Volume` is an EBS block device that can be attached to, or detached from, any instance at any time. Some types of `Volume`s can also be attached to multiple instances at the same time to allow you to have shared storage between those instances.\n\nA notable restriction is that a Volume can only be attached to instances in the same availability zone as the Volume itself.\n\nThe following demonstrates how to create a 500 GiB encrypted Volume in the `us-west-2a` availability zone, and give a role the ability to attach that Volume to a specific instance:\n\n```ts\nconst instance = new ec2.Instance(this, 'Instance', {\n // ...\n});\nconst role = new iam.Role(stack, 'SomeRole', {\n assumedBy: new iam.AccountRootPrincipal(),\n});\nconst volume = new ec2.Volume(this, 'Volume', {\n availabilityZone: 'us-west-2a',\n size: cdk.Size.gibibytes(500),\n encrypted: true,\n});\n\nvolume.grantAttachVolume(role, [instance]);\n```\n\n#### Instances Attaching Volumes to Themselves\n\nIf you need to grant an instance the ability to attach/detach an EBS volume to/from itself, then using `grantAttachVolume` and `grantDetachVolume` as outlined above\nwill lead to an unresolvable circular reference between the instance role and the instance. In this case, use `grantAttachVolumeByResourceTag` and `grantDetachVolumeByResourceTag` as follows:\n\n```ts\nconst instance = new ec2.Instance(this, 'Instance', {\n // ...\n});\nconst volume = new ec2.Volume(this, 'Volume', {\n // ...\n});\n\nconst attachGrant = volume.grantAttachVolumeByResourceTag(instance.grantPrincipal, [instance]);\nconst detachGrant = volume.grantDetachVolumeByResourceTag(instance.grantPrincipal, [instance]);\n```\n\n#### Attaching Volumes\n\nThe Amazon EC2 documentation for\n[Linux Instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AmazonEBS.html) and\n[Windows Instances](https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/ebs-volumes.html) contains information on how\nto attach and detach your Volumes to/from instances, and how to format them for use.\n\nThe following is a sample skeleton of EC2 UserData that can be used to attach a Volume to the Linux instance that it is running on:\n\n```ts\nconst volume = new ec2.Volume(this, 'Volume', {\n // ...\n});\nconst instance = new ec2.Instance(this, 'Instance', {\n // ...\n});\nvolume.grantAttachVolumeByResourceTag(instance.grantPrincipal, [instance]);\nconst targetDevice = '/dev/xvdz';\ninstance.userData.addCommands(\n // Retrieve token for accessing EC2 instance metadata (https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html)\n `TOKEN=$(curl -SsfX PUT \"http://169.254.169.254/latest/api/token\" -H \"X-aws-ec2-metadata-token-ttl-seconds: 21600\")`,\n // Retrieve the instance Id of the current EC2 instance\n `INSTANCE_ID=$(curl -SsfH \"X-aws-ec2-metadata-token: $TOKEN\" http://169.254.169.254/latest/meta-data/instance-id)`,\n // Attach the volume to /dev/xvdz\n `aws --region ${Stack.of(this).region} ec2 attach-volume --volume-id ${volume.volumeId} --instance-id $INSTANCE_ID --device ${targetDevice}`,\n // Wait until the volume has attached\n `while ! test -e ${targetDevice}; do sleep 1; done`\n // The volume will now be mounted. You may have to add additional code to format the volume if it has not been prepared.\n);\n```\n\n### Configuring Instance Metadata Service (IMDS)\n\n#### Toggling IMDSv1\n\nYou can configure [EC2 Instance Metadata Service](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html) options to either\nallow both IMDSv1 and IMDSv2 or enforce IMDSv2 when interacting with the IMDS.\n\nTo do this for a single `Instance`, you can use the `requireImdsv2` property.\nThe example below demonstrates IMDSv2 being required on a single `Instance`:\n\n```ts\nnew ec2.Instance(this, 'Instance', {\n requireImdsv2: true,\n // ...\n});\n```\n\nYou can also use the either the `InstanceRequireImdsv2Aspect` for EC2 instances or the `LaunchTemplateRequireImdsv2Aspect` for EC2 launch templates\nto apply the operation to multiple instances or launch templates, respectively.\n\nThe following example demonstrates how to use the `InstanceRequireImdsv2Aspect` to require IMDSv2 for all EC2 instances in a stack:\n\n```ts\nconst aspect = new ec2.InstanceRequireImdsv2Aspect();\nAspects.of(stack).add(aspect);\n```\n\n## VPC Flow Logs\n\nVPC Flow Logs is a feature that enables you to capture information about the IP traffic going to and from network interfaces in your VPC. Flow log data can be published to Amazon CloudWatch Logs and Amazon S3. After you've created a flow log, you can retrieve and view its data in the chosen destination. (<https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html>).\n\nBy default a flow log will be created with CloudWatch Logs as the destination.\n\nYou can create a flow log like this:\n\n```ts\nnew ec2.FlowLog(this, 'FlowLog', {\n resourceType: ec2.FlowLogResourceType.fromVpc(vpc)\n})\n```\n\nOr you can add a Flow Log to a VPC by using the addFlowLog method like this:\n\n```ts\nconst vpc = new ec2.Vpc(this, 'Vpc');\n\nvpc.addFlowLog('FlowLog');\n```\n\nYou can also add multiple flow logs with different destinations.\n\n```ts\nconst vpc = new ec2.Vpc(this, 'Vpc');\n\nvpc.addFlowLog('FlowLogS3', {\n destination: ec2.FlowLogDestination.toS3()\n});\n\nvpc.addFlowLog('FlowLogCloudWatch', {\n trafficType: ec2.FlowLogTrafficType.REJECT\n});\n```\n\nBy default the CDK will create the necessary resources for the destination. For the CloudWatch Logs destination\nit will create a CloudWatch Logs Log Group as well as the IAM role with the necessary permissions to publish to\nthe log group. In the case of an S3 destination, it will create the S3 bucket.\n\nIf you want to customize any of the destination resources you can provide your own as part of the `destination`.\n\n*CloudWatch Logs*\n\n```ts\nconst logGroup = new logs.LogGroup(this, 'MyCustomLogGroup');\n\nconst role = new iam.Role(this, 'MyCustomRole', {\n assumedBy: new iam.ServicePrincipal('vpc-flow-logs.amazonaws.com')\n});\n\nnew ec2.FlowLog(this, 'FlowLog', {\n resourceType: ec2.FlowLogResourceType.fromVpc(vpc),\n destination: ec2.FlowLogDestination.toCloudWatchLogs(logGroup, role)\n});\n```\n\n*S3*\n\n```ts\n\nconst bucket = new s3.Bucket(this, 'MyCustomBucket');\n\nnew ec2.FlowLog(this, 'FlowLog', {\n resourceType: ec2.FlowLogResourceType.fromVpc(vpc),\n destination: ec2.FlowLogDestination.toS3(bucket)\n});\n\nnew ec2.FlowLog(this, 'FlowLogWithKeyPrefix', {\n resourceType: ec2.FlowLogResourceType.fromVpc(vpc),\n destination: ec2.FlowLogDestination.toS3(bucket, 'prefix/')\n});\n```\n\n## User Data\n\nUser data enables you to run a script when your instances start up. In order to configure these scripts you can add commands directly to the script\n or you can use the UserData's convenience functions to aid in the creation of your script.\n\nA user data could be configured to run a script found in an asset through the following:\n\n```ts\nconst asset = new Asset(this, 'Asset', {path: path.join(__dirname, 'configure.sh')});\nconst instance = new ec2.Instance(this, 'Instance', {\n // ...\n });\nconst localPath = instance.userData.addS3DownloadCommand({\n bucket:asset.bucket,\n bucketKey:asset.s3ObjectKey,\n});\ninstance.userData.addExecuteFileCommand({\n filePath:localPath,\n arguments: '--verbose -y'\n});\nasset.grantRead( instance.role );\n```\n\n### Multipart user data\n\nIn addition, to above the `MultipartUserData` can be used to change instance startup behavior. Multipart user data are composed\nfrom separate parts forming archive. The most common parts are scripts executed during instance set-up. However, there are other\nkinds, too.\n\nThe advantage of multipart archive is in flexibility when it's needed to add additional parts or to use specialized parts to\nfine tune instance startup. Some services (like AWS Batch) supports only `MultipartUserData`.\n\nThe parts can be executed at different moment of instance start-up and can serve a different purposes. This is controlled by `contentType` property.\nFor common scripts, `text/x-shellscript; charset=\"utf-8\"` can be used as content type.\n\nIn order to create archive the `MultipartUserData` has to be instantiated. Than, user can add parts to multipart archive using `addPart`. The `MultipartBody` contains methods supporting creation of body parts.\n\nIf the very custom part is required, it can be created using `MultipartUserData.fromRawBody`, in this case full control over content type,\ntransfer encoding, and body properties is given to the user.\n\nBelow is an example for creating multipart user data with single body part responsible for installing `awscli` and configuring maximum size\nof storage used by Docker containers:\n\n```ts\nconst bootHookConf = ec2.UserData.forLinux();\nbootHookConf.addCommands('cloud-init-per once docker_options echo \\'OPTIONS=\"${OPTIONS} --storage-opt dm.basesize=40G\"\\' >> /etc/sysconfig/docker');\n\nconst setupCommands = ec2.UserData.forLinux();\nsetupCommands.addCommands('sudo yum install awscli && echo Packages installed らと > /var/tmp/setup');\n\nconst multipartUserData = new ec2.MultipartUserData();\n// The docker has to be configured at early stage, so content type is overridden to boothook\nmultipartUserData.addPart(ec2.MultipartBody.fromUserData(bootHookConf, 'text/cloud-boothook; charset=\"us-ascii\"'));\n// Execute the rest of setup\nmultipartUserData.addPart(ec2.MultipartBody.fromUserData(setupCommands));\n\nnew ec2.LaunchTemplate(stack, '', {\n userData: multipartUserData,\n blockDevices: [\n // Block device configuration rest\n ]\n});\n```\n\nFor more information see\n[Specifying Multiple User Data Blocks Using a MIME Multi Part Archive](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/bootstrap_container_instance.html#multi-part_user_data)\n\n#### Using add*Command on MultipartUserData\n\nTo use the `add*Command` methods, that are inherited from the `UserData` interface, on `MultipartUserData` you must add a part\nto the `MultipartUserData` and designate it as the reciever for these methods. This is accomplished by using the `addUserDataPart()`\nmethod on `MultipartUserData` with the `makeDefault` argument set to `true`:\n\n```ts\nconst multipartUserData = new ec2.MultipartUserData();\nconst commandsUserData = ec2.UserData.forLinux();\nmultipartUserData.addUserDataPart(commandsUserData, MultipartBody.SHELL_SCRIPT, true);\n\n// Adding commands to the multipartUserData adds them to commandsUserData, and vice-versa.\nmultipartUserData.addCommands('touch /root/multi.txt');\ncommandsUserData.addCommands('touch /root/userdata.txt');\n```\n\nWhen used on an EC2 instance, the above `multipartUserData` will create both `multi.txt` and `userdata.txt` in `/root`.\n\n## Importing existing subnet\n\nTo import an existing Subnet, call `Subnet.fromSubnetAttributes()` or\n`Subnet.fromSubnetId()`. Only if you supply the subnet's Availability Zone\nand Route Table Ids when calling `Subnet.fromSubnetAttributes()` will you be\nable to use the CDK features that use these values (such as selecting one\nsubnet per AZ).\n\nImporting an existing subnet looks like this:\n\n```ts\n// Supply all properties\nconst subnet = Subnet.fromSubnetAttributes(this, 'SubnetFromAttributes', {\n subnetId: 's-1234',\n availabilityZone: 'pub-az-4465',\n routeTableId: 'rt-145'\n});\n\n// Supply only subnet id\nconst subnet = Subnet.fromSubnetId(this, 'SubnetFromId', 's-1234');\n```\n\n## Launch Templates\n\nA Launch Template is a standardized template that contains the configuration information to launch an instance.\nThey can be used when launching instances on their own, through Amazon EC2 Auto Scaling, EC2 Fleet, and Spot Fleet.\nLaunch templates enable you to store launch parameters so that you do not have to specify them every time you launch\nan instance. For information on Launch Templates please see the\n[official documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-launch-templates.html).\n\nThe following demonstrates how to create a launch template with an Amazon Machine Image, and security group.\n\n```ts\nconst vpc = new ec2.Vpc(...);\n// ...\nconst template = new ec2.LaunchTemplate(this, 'LaunchTemplate', {\n machineImage: new ec2.AmazonMachineImage(),\n securityGroup: new ec2.SecurityGroup(this, 'LaunchTemplateSG', {\n vpc: vpc,\n }),\n});\n```\n"
1329
+ "markdown": "# Amazon EC2 Construct Library\n\n\n\nThe `@aws-cdk/aws-ec2` package contains primitives for setting up networking and\ninstances.\n\n```ts nofixture\nimport { aws_ec2 as ec2 } from 'aws-cdk-lib';\n```\n\n## VPC\n\nMost projects need a Virtual Private Cloud to provide security by means of\nnetwork partitioning. This is achieved by creating an instance of\n`Vpc`:\n\n```ts\nconst vpc = new ec2.Vpc(this, 'VPC');\n```\n\nAll default constructs require EC2 instances to be launched inside a VPC, so\nyou should generally start by defining a VPC whenever you need to launch\ninstances for your project.\n\n### Subnet Types\n\nA VPC consists of one or more subnets that instances can be placed into. CDK\ndistinguishes three different subnet types:\n\n* **Public (`SubnetType.PUBLIC`)** - public subnets connect directly to the Internet using an\n Internet Gateway. If you want your instances to have a public IP address\n and be directly reachable from the Internet, you must place them in a\n public subnet.\n* **Private with Internet Access (`SubnetType.PRIVATE_WITH_NAT`)** - instances in private subnets are not directly routable from the\n Internet, and connect out to the Internet via a NAT gateway. By default, a\n NAT gateway is created in every public subnet for maximum availability. Be\n aware that you will be charged for NAT gateways.\n* **Isolated (`SubnetType.PRIVATE_ISOLATED`)** - isolated subnets do not route from or to the Internet, and\n as such do not require NAT gateways. They can only connect to or be\n connected to from other instances in the same VPC. A default VPC configuration\n will not include isolated subnets,\n\nA default VPC configuration will create public and **private** subnets. However, if\n`natGateways:0` **and** `subnetConfiguration` is undefined, default VPC configuration\nwill create public and **isolated** subnets. See [*Advanced Subnet Configuration*](#advanced-subnet-configuration)\nbelow for information on how to change the default subnet configuration.\n\nConstructs using the VPC will \"launch instances\" (or more accurately, create\nElastic Network Interfaces) into one or more of the subnets. They all accept\na property called `subnetSelection` (sometimes called `vpcSubnets`) to allow\nyou to select in what subnet to place the ENIs, usually defaulting to\n*private* subnets if the property is omitted.\n\nIf you would like to save on the cost of NAT gateways, you can use\n*isolated* subnets instead of *private* subnets (as described in Advanced\n*Subnet Configuration*). If you need private instances to have\ninternet connectivity, another option is to reduce the number of NAT gateways\ncreated by setting the `natGateways` property to a lower value (the default\nis one NAT gateway per availability zone). Be aware that this may have\navailability implications for your application.\n\n[Read more about\nsubnets](https://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Subnets.html).\n\n### Control over availability zones\n\nBy default, a VPC will spread over at most 3 Availability Zones available to\nit. To change the number of Availability Zones that the VPC will spread over,\nspecify the `maxAzs` property when defining it.\n\nThe number of Availability Zones that are available depends on the *region*\nand *account* of the Stack containing the VPC. If the [region and account are\nspecified](https://docs.aws.amazon.com/cdk/latest/guide/environments.html) on\nthe Stack, the CLI will [look up the existing Availability\nZones](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#using-regions-availability-zones-describe)\nand get an accurate count. If region and account are not specified, the stack\ncould be deployed anywhere and it will have to make a safe choice, limiting\nitself to 2 Availability Zones.\n\nTherefore, to get the VPC to spread over 3 or more availability zones, you\nmust specify the environment where the stack will be deployed.\n\nYou can gain full control over the availability zones selection strategy by overriding the Stack's [`get availabilityZones()`](https://github.com/aws/aws-cdk/blob/master/packages/@aws-cdk/core/lib/stack.ts) method:\n\n```ts\nclass MyStack extends Stack {\n\n get availabilityZones(): string[] {\n return ['us-west-2a', 'us-west-2b'];\n }\n\n constructor(scope: Construct, id: string, props?: StackProps) {\n super(scope, id, props);\n ...\n }\n}\n```\n\nNote that overriding the `get availabilityZones()` method will override the default behavior for all constructs defined within the Stack.\n\n### Choosing subnets for resources\n\nWhen creating resources that create Elastic Network Interfaces (such as\ndatabases or instances), there is an option to choose which subnets to place\nthem in. For example, a VPC endpoint by default is placed into a subnet in\nevery availability zone, but you can override which subnets to use. The property\nis typically called one of `subnets`, `vpcSubnets` or `subnetSelection`.\n\nThe example below will place the endpoint into two AZs (`us-east-1a` and `us-east-1c`),\nin Isolated subnets:\n\n```ts\nnew InterfaceVpcEndpoint(stack, 'VPC Endpoint', {\n vpc,\n service: new InterfaceVpcEndpointService('com.amazonaws.vpce.us-east-1.vpce-svc-uuddlrlrbastrtsvc', 443),\n subnets: {\n subnetType: SubnetType.ISOLATED,\n availabilityZones: ['us-east-1a', 'us-east-1c']\n }\n});\n```\n\nYou can also specify specific subnet objects for granular control:\n\n```ts\nnew InterfaceVpcEndpoint(stack, 'VPC Endpoint', {\n vpc,\n service: new InterfaceVpcEndpointService('com.amazonaws.vpce.us-east-1.vpce-svc-uuddlrlrbastrtsvc', 443),\n subnets: {\n subnets: [subnet1, subnet2]\n }\n});\n```\n\nWhich subnets are selected is evaluated as follows:\n\n* `subnets`: if specific subnet objects are supplied, these are selected, and no other\n logic is used.\n* `subnetType`/`subnetGroupName`: otherwise, a set of subnets is selected by\n supplying either type or name:\n * `subnetType` will select all subnets of the given type.\n * `subnetGroupName` should be used to distinguish between multiple groups of subnets of\n the same type (for example, you may want to separate your application instances and your\n RDS instances into two distinct groups of Isolated subnets).\n * If neither are given, the first available subnet group of a given type that\n exists in the VPC will be used, in this order: Private, then Isolated, then Public.\n In short: by default ENIs will preferentially be placed in subnets not connected to\n the Internet.\n* `availabilityZones`/`onePerAz`: finally, some availability-zone based filtering may be done.\n This filtering by availability zones will only be possible if the VPC has been created or\n looked up in a non-environment agnostic stack (so account and region have been set and\n availability zones have been looked up).\n * `availabilityZones`: only the specific subnets from the selected subnet groups that are\n in the given availability zones will be returned.\n * `onePerAz`: per availability zone, a maximum of one subnet will be returned (Useful for resource\n types that do not allow creating two ENIs in the same availability zone).\n* `subnetFilters`: additional filtering on subnets using any number of user-provided filters which\n extend `SubnetFilter`. The following methods on the `SubnetFilter` class can be used to create\n a filter:\n * `byIds`: chooses subnets from a list of ids\n * `availabilityZones`: chooses subnets in the provided list of availability zones\n * `onePerAz`: chooses at most one subnet per availability zone\n * `containsIpAddresses`: chooses a subnet which contains *any* of the listed ip addresses\n * `byCidrMask`: chooses subnets that have the provided CIDR netmask\n\n### Using NAT instances\n\nBy default, the `Vpc` construct will create NAT *gateways* for you, which\nare managed by AWS. If you would prefer to use your own managed NAT\n*instances* instead, specify a different value for the `natGatewayProvider`\nproperty, as follows:\n\n[using NAT instances](test/integ.nat-instances.lit.ts)\n\nThe construct will automatically search for the most recent NAT gateway AMI.\nIf you prefer to use a custom AMI, use `machineImage:\nMachineImage.genericLinux({ ... })` and configure the right AMI ID for the\nregions you want to deploy to.\n\nBy default, the NAT instances will route all traffic. To control what traffic\ngets routed, pass `allowAllTraffic: false` and access the\n`NatInstanceProvider.connections` member after having passed it to the VPC:\n\n```ts\nconst provider = NatProvider.instance({\n instanceType: /* ... */,\n allowAllTraffic: false,\n});\nnew Vpc(stack, 'TheVPC', {\n natGatewayProvider: provider,\n});\nprovider.connections.allowFrom(Peer.ipv4('1.2.3.4/8'), Port.tcp(80));\n```\n\n### Advanced Subnet Configuration\n\nIf the default VPC configuration (public and private subnets spanning the\nsize of the VPC) don't suffice for you, you can configure what subnets to\ncreate by specifying the `subnetConfiguration` property. It allows you\nto configure the number and size of all subnets. Specifying an advanced\nsubnet configuration could look like this:\n\n```ts\nconst vpc = new ec2.Vpc(this, 'TheVPC', {\n // 'cidr' configures the IP range and size of the entire VPC.\n // The IP space will be divided over the configured subnets.\n cidr: '10.0.0.0/21',\n\n // 'maxAzs' configures the maximum number of availability zones to use\n maxAzs: 3,\n\n // 'subnetConfiguration' specifies the \"subnet groups\" to create.\n // Every subnet group will have a subnet for each AZ, so this\n // configuration will create `3 groups × 3 AZs = 9` subnets.\n subnetConfiguration: [\n {\n // 'subnetType' controls Internet access, as described above.\n subnetType: ec2.SubnetType.PUBLIC,\n\n // 'name' is used to name this particular subnet group. You will have to\n // use the name for subnet selection if you have more than one subnet\n // group of the same type.\n name: 'Ingress',\n\n // 'cidrMask' specifies the IP addresses in the range of of individual\n // subnets in the group. Each of the subnets in this group will contain\n // `2^(32 address bits - 24 subnet bits) - 2 reserved addresses = 254`\n // usable IP addresses.\n //\n // If 'cidrMask' is left out the available address space is evenly\n // divided across the remaining subnet groups.\n cidrMask: 24,\n },\n {\n cidrMask: 24,\n name: 'Application',\n subnetType: ec2.SubnetType.PRIVATE_WITH_NAT,\n },\n {\n cidrMask: 28,\n name: 'Database',\n subnetType: ec2.SubnetType.PRIVATE_ISOLATED,\n\n // 'reserved' can be used to reserve IP address space. No resources will\n // be created for this subnet, but the IP range will be kept available for\n // future creation of this subnet, or even for future subdivision.\n reserved: true\n }\n ],\n});\n```\n\nThe example above is one possible configuration, but the user can use the\nconstructs above to implement many other network configurations.\n\nThe `Vpc` from the above configuration in a Region with three\navailability zones will be the following:\n\nSubnet Name |Type |IP Block |AZ|Features\n------------------|----------|--------------|--|--------\nIngressSubnet1 |`PUBLIC` |`10.0.0.0/24` |#1|NAT Gateway\nIngressSubnet2 |`PUBLIC` |`10.0.1.0/24` |#2|NAT Gateway\nIngressSubnet3 |`PUBLIC` |`10.0.2.0/24` |#3|NAT Gateway\nApplicationSubnet1|`PRIVATE` |`10.0.3.0/24` |#1|Route to NAT in IngressSubnet1\nApplicationSubnet2|`PRIVATE` |`10.0.4.0/24` |#2|Route to NAT in IngressSubnet2\nApplicationSubnet3|`PRIVATE` |`10.0.5.0/24` |#3|Route to NAT in IngressSubnet3\nDatabaseSubnet1 |`ISOLATED`|`10.0.6.0/28` |#1|Only routes within the VPC\nDatabaseSubnet2 |`ISOLATED`|`10.0.6.16/28`|#2|Only routes within the VPC\nDatabaseSubnet3 |`ISOLATED`|`10.0.6.32/28`|#3|Only routes within the VPC\n\n### Accessing the Internet Gateway\n\nIf you need access to the internet gateway, you can get its ID like so:\n\n```ts\nconst igwId = vpc.internetGatewayId;\n```\n\nFor a VPC with only `ISOLATED` subnets, this value will be undefined.\n\nThis is only supported for VPCs created in the stack - currently you're\nunable to get the ID for imported VPCs. To do that you'd have to specifically\nlook up the Internet Gateway by name, which would require knowing the name\nbeforehand.\n\nThis can be useful for configuring routing using a combination of gateways:\nfor more information see [Routing](#routing) below.\n\n#### Routing\n\nIt's possible to add routes to any subnets using the `addRoute()` method. If for\nexample you want an isolated subnet to have a static route via the default\nInternet Gateway created for the public subnet - perhaps for routing a VPN\nconnection - you can do so like this:\n\n```ts\nconst vpc = ec2.Vpc(this, \"VPC\", {\n subnetConfiguration: [{\n subnetType: SubnetType.PUBLIC,\n name: 'Public',\n },{\n subnetType: SubnetType.ISOLATED,\n name: 'Isolated',\n }]\n})\n(vpc.isolatedSubnets[0] as Subnet).addRoute(\"StaticRoute\", {\n routerId: vpc.internetGatewayId,\n routerType: RouterType.GATEWAY,\n destinationCidrBlock: \"8.8.8.8/32\",\n})\n```\n\n*Note that we cast to `Subnet` here because the list of subnets only returns an\n`ISubnet`.*\n\n### Reserving subnet IP space\n\nThere are situations where the IP space for a subnet or number of subnets\nwill need to be reserved. This is useful in situations where subnets would\nneed to be added after the vpc is originally deployed, without causing IP\nrenumbering for existing subnets. The IP space for a subnet may be reserved\nby setting the `reserved` subnetConfiguration property to true, as shown\nbelow:\n\n```ts\nconst vpc = new ec2.Vpc(this, 'TheVPC', {\n natGateways: 1,\n subnetConfiguration: [\n {\n cidrMask: 26,\n name: 'Public',\n subnetType: ec2.SubnetType.PUBLIC,\n },\n {\n cidrMask: 26,\n name: 'Application1',\n subnetType: ec2.SubnetType.PRIVATE_WITH_NAT,\n },\n {\n cidrMask: 26,\n name: 'Application2',\n subnetType: ec2.SubnetType.PRIVATE_WITH_NAT,\n reserved: true, // <---- This subnet group is reserved\n },\n {\n cidrMask: 27,\n name: 'Database',\n subnetType: ec2.SubnetType.ISOLATED,\n }\n ],\n});\n```\n\nIn the example above, the subnet for Application2 is not actually provisioned\nbut its IP space is still reserved. If in the future this subnet needs to be\nprovisioned, then the `reserved: true` property should be removed. Reserving\nparts of the IP space prevents the other subnets from getting renumbered.\n\n### Sharing VPCs between stacks\n\nIf you are creating multiple `Stack`s inside the same CDK application, you\ncan reuse a VPC defined in one Stack in another by simply passing the VPC\ninstance around:\n\n[sharing VPCs between stacks](test/integ.share-vpcs.lit.ts)\n\n### Importing an existing VPC\n\nIf your VPC is created outside your CDK app, you can use `Vpc.fromLookup()`.\nThe CDK CLI will search for the specified VPC in the the stack's region and\naccount, and import the subnet configuration. Looking up can be done by VPC\nID, but more flexibly by searching for a specific tag on the VPC.\n\nSubnet types will be determined from the `aws-cdk:subnet-type` tag on the\nsubnet if it exists, or the presence of a route to an Internet Gateway\notherwise. Subnet names will be determined from the `aws-cdk:subnet-name` tag\non the subnet if it exists, or will mirror the subnet type otherwise (i.e.\na public subnet will have the name `\"Public\"`).\n\nThe result of the `Vpc.fromLookup()` operation will be written to a file\ncalled `cdk.context.json`. You must commit this file to source control so\nthat the lookup values are available in non-privileged environments such\nas CI build steps, and to ensure your template builds are repeatable.\n\nHere's how `Vpc.fromLookup()` can be used:\n\n[importing existing VPCs](test/integ.import-default-vpc.lit.ts)\n\n`Vpc.fromLookup` is the recommended way to import VPCs. If for whatever\nreason you do not want to use the context mechanism to look up a VPC at\nsynthesis time, you can also use `Vpc.fromVpcAttributes`. This has the\nfollowing limitations:\n\n* Every subnet group in the VPC must have a subnet in each availability zone\n (for example, each AZ must have both a public and private subnet). Asymmetric\n VPCs are not supported.\n* All VpcId, SubnetId, RouteTableId, ... parameters must either be known at\n synthesis time, or they must come from deploy-time list parameters whose\n deploy-time lengths are known at synthesis time.\n\nUsing `Vpc.fromVpcAttributes()` looks like this:\n\n```ts\nconst vpc = ec2.Vpc.fromVpcAttributes(stack, 'VPC', {\n vpcId: 'vpc-1234',\n availabilityZones: ['us-east-1a', 'us-east-1b'],\n\n // Either pass literals for all IDs\n publicSubnetIds: ['s-12345', 's-67890'],\n\n // OR: import a list of known length\n privateSubnetIds: Fn.importListValue('PrivateSubnetIds', 2),\n\n // OR: split an imported string to a list of known length\n isolatedSubnetIds: Fn.split(',', ssm.StringParameter.valueForStringParameter(stack, `MyParameter`), 2),\n});\n```\n\n## Allowing Connections\n\nIn AWS, all network traffic in and out of **Elastic Network Interfaces** (ENIs)\nis controlled by **Security Groups**. You can think of Security Groups as a\nfirewall with a set of rules. By default, Security Groups allow no incoming\n(ingress) traffic and all outgoing (egress) traffic. You can add ingress rules\nto them to allow incoming traffic streams. To exert fine-grained control over\negress traffic, set `allowAllOutbound: false` on the `SecurityGroup`, after\nwhich you can add egress traffic rules.\n\nYou can manipulate Security Groups directly:\n\n```ts fixture=with-vpc\nconst mySecurityGroup = new ec2.SecurityGroup(this, 'SecurityGroup', {\n vpc,\n description: 'Allow ssh access to ec2 instances',\n allowAllOutbound: true // Can be set to false\n});\nmySecurityGroup.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(22), 'allow ssh access from the world');\n```\n\nAll constructs that create ENIs on your behalf (typically constructs that create\nEC2 instances or other VPC-connected resources) will all have security groups\nautomatically assigned. Those constructs have an attribute called\n**connections**, which is an object that makes it convenient to update the\nsecurity groups. If you want to allow connections between two constructs that\nhave security groups, you have to add an **Egress** rule to one Security Group,\nand an **Ingress** rule to the other. The connections object will automatically\ntake care of this for you:\n\n```ts fixture=conns\n// Allow connections from anywhere\nloadBalancer.connections.allowFromAnyIpv4(ec2.Port.tcp(443), 'Allow inbound HTTPS');\n\n// The same, but an explicit IP address\nloadBalancer.connections.allowFrom(ec2.Peer.ipv4('1.2.3.4/32'), ec2.Port.tcp(443), 'Allow inbound HTTPS');\n\n// Allow connection between AutoScalingGroups\nappFleet.connections.allowTo(dbFleet, ec2.Port.tcp(443), 'App can call database');\n```\n\n### Connection Peers\n\nThere are various classes that implement the connection peer part:\n\n```ts fixture=conns\n// Simple connection peers\nlet peer = ec2.Peer.ipv4('10.0.0.0/16');\npeer = ec2.Peer.anyIpv4();\npeer = ec2.Peer.ipv6('::0/0');\npeer = ec2.Peer.anyIpv6();\npeer = ec2.Peer.prefixList('pl-12345');\nappFleet.connections.allowTo(peer, ec2.Port.tcp(443), 'Allow outbound HTTPS');\n```\n\nAny object that has a security group can itself be used as a connection peer:\n\n```ts fixture=conns\n// These automatically create appropriate ingress and egress rules in both security groups\nfleet1.connections.allowTo(fleet2, ec2.Port.tcp(80), 'Allow between fleets');\n\nappFleet.connections.allowFromAnyIpv4(ec2.Port.tcp(80), 'Allow from load balancer');\n```\n\n### Port Ranges\n\nThe connections that are allowed are specified by port ranges. A number of classes provide\nthe connection specifier:\n\n```ts\nec2.Port.tcp(80)\nec2.Port.tcpRange(60000, 65535)\nec2.Port.allTcp()\nec2.Port.allTraffic()\n```\n\n> NOTE: This set is not complete yet; for example, there is no library support for ICMP at the moment.\n> However, you can write your own classes to implement those.\n\n### Default Ports\n\nSome Constructs have default ports associated with them. For example, the\nlistener of a load balancer does (it's the public port), or instances of an\nRDS database (it's the port the database is accepting connections on).\n\nIf the object you're calling the peering method on has a default port associated with it, you can call\n`allowDefaultPortFrom()` and omit the port specifier. If the argument has an associated default port, call\n`allowDefaultPortTo()`.\n\nFor example:\n\n```ts fixture=conns\n// Port implicit in listener\nlistener.connections.allowDefaultPortFromAnyIpv4('Allow public');\n\n// Port implicit in peer\nappFleet.connections.allowDefaultPortTo(rdsDatabase, 'Fleet can access database');\n```\n\n### Security group rules\n\nBy default, security group wills be added inline to the security group in the output cloud formation\ntemplate, if applicable. This includes any static rules by ip address and port range. This\noptimization helps to minimize the size of the template.\n\nIn some environments this is not desirable, for example if your security group access is controlled\nvia tags. You can disable inline rules per security group or globally via the context key\n`@aws-cdk/aws-ec2.securityGroupDisableInlineRules`.\n\n```ts fixture=with-vpc\nconst mySecurityGroupWithoutInlineRules = new ec2.SecurityGroup(this, 'SecurityGroup', {\n vpc,\n description: 'Allow ssh access to ec2 instances',\n allowAllOutbound: true,\n disableInlineRules: true\n});\n//This will add the rule as an external cloud formation construct\nmySecurityGroupWithoutInlineRules.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(22), 'allow ssh access from the world');\n```\n\n## Machine Images (AMIs)\n\nAMIs control the OS that gets launched when you start your EC2 instance. The EC2\nlibrary contains constructs to select the AMI you want to use.\n\nDepending on the type of AMI, you select it a different way. Here are some\nexamples of things you might want to use:\n\n[example of creating images](test/example.images.lit.ts)\n\n> NOTE: The AMIs selected by `MachineImage.lookup()` will be cached in\n> `cdk.context.json`, so that your AutoScalingGroup instances aren't replaced while\n> you are making unrelated changes to your CDK app.\n>\n> To query for the latest AMI again, remove the relevant cache entry from\n> `cdk.context.json`, or use the `cdk context` command. For more information, see\n> [Runtime Context](https://docs.aws.amazon.com/cdk/latest/guide/context.html) in the CDK\n> developer guide.\n>\n> `MachineImage.genericLinux()`, `MachineImage.genericWindows()` will use `CfnMapping` in\n> an agnostic stack.\n\n## Special VPC configurations\n\n### VPN connections to a VPC\n\nCreate your VPC with VPN connections by specifying the `vpnConnections` props (keys are construct `id`s):\n\n```ts\nconst vpc = new ec2.Vpc(this, 'MyVpc', {\n vpnConnections: {\n dynamic: { // Dynamic routing (BGP)\n ip: '1.2.3.4'\n },\n static: { // Static routing\n ip: '4.5.6.7',\n staticRoutes: [\n '192.168.10.0/24',\n '192.168.20.0/24'\n ]\n }\n }\n});\n```\n\nTo create a VPC that can accept VPN connections, set `vpnGateway` to `true`:\n\n```ts\nconst vpc = new ec2.Vpc(this, 'MyVpc', {\n vpnGateway: true\n});\n```\n\nVPN connections can then be added:\n\n```ts fixture=with-vpc\nvpc.addVpnConnection('Dynamic', {\n ip: '1.2.3.4'\n});\n```\n\nBy default, routes will be propagated on the route tables associated with the private subnets. If no\nprivate subnets exists, isolated subnets are used. If no isolated subnets exists, public subnets are\nused. Use the `Vpc` property `vpnRoutePropagation` to customize this behavior.\n\nVPN connections expose [metrics (cloudwatch.Metric)](https://github.com/aws/aws-cdk/blob/master/packages/%40aws-cdk/aws-cloudwatch/README.md) across all tunnels in the account/region and per connection:\n\n```ts fixture=with-vpc\n// Across all tunnels in the account/region\nconst allDataOut = ec2.VpnConnection.metricAllTunnelDataOut();\n\n// For a specific vpn connection\nconst vpnConnection = vpc.addVpnConnection('Dynamic', {\n ip: '1.2.3.4'\n});\nconst state = vpnConnection.metricTunnelState();\n```\n\n### VPC endpoints\n\nA VPC endpoint enables you to privately connect your VPC to supported AWS services and VPC endpoint services powered by PrivateLink without requiring an internet gateway, NAT device, VPN connection, or AWS Direct Connect connection. Instances in your VPC do not require public IP addresses to communicate with resources in the service. Traffic between your VPC and the other service does not leave the Amazon network.\n\nEndpoints are virtual devices. They are horizontally scaled, redundant, and highly available VPC components that allow communication between instances in your VPC and services without imposing availability risks or bandwidth constraints on your network traffic.\n\n[example of setting up VPC endpoints](test/integ.vpc-endpoint.lit.ts)\n\nBy default, CDK will place a VPC endpoint in one subnet per AZ. If you wish to override the AZs CDK places the VPC endpoint in,\nuse the `subnets` parameter as follows:\n\n```ts\nnew InterfaceVpcEndpoint(stack, 'VPC Endpoint', {\n vpc,\n service: new InterfaceVpcEndpointService('com.amazonaws.vpce.us-east-1.vpce-svc-uuddlrlrbastrtsvc', 443),\n // Choose which availability zones to place the VPC endpoint in, based on\n // available AZs\n subnets: {\n availabilityZones: ['us-east-1a', 'us-east-1c']\n }\n});\n```\n\nPer the [AWS documentation](https://aws.amazon.com/premiumsupport/knowledge-center/interface-endpoint-availability-zone/), not all\nVPC endpoint services are available in all AZs. If you specify the parameter `lookupSupportedAzs`, CDK attempts to discover which\nAZs an endpoint service is available in, and will ensure the VPC endpoint is not placed in a subnet that doesn't match those AZs.\nThese AZs will be stored in cdk.context.json.\n\n```ts\nnew InterfaceVpcEndpoint(stack, 'VPC Endpoint', {\n vpc,\n service: new InterfaceVpcEndpointService('com.amazonaws.vpce.us-east-1.vpce-svc-uuddlrlrbastrtsvc', 443),\n // Choose which availability zones to place the VPC endpoint in, based on\n // available AZs\n lookupSupportedAzs: true\n});\n```\n\nPre-defined AWS services are defined in the [InterfaceVpcEndpointAwsService](lib/vpc-endpoint.ts) class, and can be used to\ncreate VPC endpoints without having to configure name, ports, etc. For example, a Keyspaces endpoint can be created for\nuse in your VPC:\n\n``` ts\nnew InterfaceVpcEndpoint(stack, 'VPC Endpoint', { vpc, service: InterfaceVpcEndpointAwsService.KEYSPACES });\n```\n\n#### Security groups for interface VPC endpoints\n\nBy default, interface VPC endpoints create a new security group and traffic is **not**\nautomatically allowed from the VPC CIDR.\n\nUse the `connections` object to allow traffic to flow to the endpoint:\n\n```ts fixture=conns\nmyEndpoint.connections.allowDefaultPortFromAnyIpv4();\n```\n\nAlternatively, existing security groups can be used by specifying the `securityGroups` prop.\n\n### VPC endpoint services\n\nA VPC endpoint service enables you to expose a Network Load Balancer(s) as a provider service to consumers, who connect to your service over a VPC endpoint. You can restrict access to your service via allowed principals (anything that extends ArnPrincipal), and require that new connections be manually accepted.\n\n```ts\nnew VpcEndpointService(this, 'EndpointService', {\n vpcEndpointServiceLoadBalancers: [networkLoadBalancer1, networkLoadBalancer2],\n acceptanceRequired: true,\n allowedPrincipals: [new ArnPrincipal('arn:aws:iam::123456789012:root')]\n});\n```\n\nEndpoint services support private DNS, which makes it easier for clients to connect to your service by automatically setting up DNS in their VPC.\nYou can enable private DNS on an endpoint service like so:\n\n```ts\nimport { VpcEndpointServiceDomainName } from 'aws-cdk-lib/aws-route53';\n\nnew VpcEndpointServiceDomainName(stack, 'EndpointDomain', {\n endpointService: vpces,\n domainName: 'my-stuff.aws-cdk.dev',\n publicHostedZone: zone,\n});\n```\n\nNote: The domain name must be owned (registered through Route53) by the account the endpoint service is in, or delegated to the account.\nThe VpcEndpointServiceDomainName will handle the AWS side of domain verification, the process for which can be found\n[here](https://docs.aws.amazon.com/vpc/latest/userguide/endpoint-services-dns-validation.html)\n\n### Client VPN endpoint\n\nAWS Client VPN is a managed client-based VPN service that enables you to securely access your AWS\nresources and resources in your on-premises network. With Client VPN, you can access your resources\nfrom any location using an OpenVPN-based VPN client.\n\nUse the `addClientVpnEndpoint()` method to add a client VPN endpoint to a VPC:\n\n```ts fixture=client-vpn\nvpc.addClientVpnEndpoint('Endpoint', {\n cidr: '10.100.0.0/16',\n serverCertificateArn: 'arn:aws:acm:us-east-1:123456789012:certificate/server-certificate-id',\n // Mutual authentication\n clientCertificateArn: 'arn:aws:acm:us-east-1:123456789012:certificate/client-certificate-id',\n // User-based authentication\n userBasedAuthentication: ec2.ClientVpnUserBasedAuthentication.federated(samlProvider),\n});\n```\n\nThe endpoint must use at least one [authentication method](https://docs.aws.amazon.com/vpn/latest/clientvpn-admin/client-authentication.html):\n\n* Mutual authentication with a client certificate\n* User-based authentication (directory or federated)\n\nIf user-based authentication is used, the [self-service portal URL](https://docs.aws.amazon.com/vpn/latest/clientvpn-user/self-service-portal.html)\nis made available via a CloudFormation output.\n\nBy default, a new security group is created and logging is enabled. Moreover, a rule to\nauthorize all users to the VPC CIDR is created.\n\nTo customize authorization rules, set the `authorizeAllUsersToVpcCidr` prop to `false`\nand use `addAuthorizationRule()`:\n\n```ts fixture=client-vpn\nconst endpoint = vpc.addClientVpnEndpoint('Endpoint', {\n cidr: '10.100.0.0/16',\n serverCertificateArn: 'arn:aws:acm:us-east-1:123456789012:certificate/server-certificate-id',\n userBasedAuthentication: ec2.ClientVpnUserBasedAuthentication.federated(samlProvider),\n authorizeAllUsersToVpcCidr: false,\n});\n\nendpoint.addAuthorizationRule('Rule', {\n cidr: '10.0.10.0/32',\n groupId: 'group-id',\n});\n```\n\nUse `addRoute()` to configure network routes:\n\n```ts fixture=client-vpn\nconst endpoint = vpc.addClientVpnEndpoint('Endpoint', {\n cidr: '10.100.0.0/16',\n serverCertificateArn: 'arn:aws:acm:us-east-1:123456789012:certificate/server-certificate-id',\n userBasedAuthentication: ec2.ClientVpnUserBasedAuthentication.federated(samlProvider),\n});\n\n// Client-to-client access\nendpoint.addRoute('Route', {\n cidr: '10.100.0.0/16',\n target: ec2.ClientVpnRouteTarget.local(),\n});\n```\n\nUse the `connections` object of the endpoint to allow traffic to other security groups.\n\n## Instances\n\nYou can use the `Instance` class to start up a single EC2 instance. For production setups, we recommend\nyou use an `AutoScalingGroup` from the `aws-autoscaling` module instead, as AutoScalingGroups will take\ncare of restarting your instance if it ever fails.\n\n### Configuring Instances using CloudFormation Init (cfn-init)\n\nCloudFormation Init allows you to configure your instances by writing files to them, installing software\npackages, starting services and running arbitrary commands. By default, if any of the instance setup\ncommands throw an error, the deployment will fail and roll back to the previously known good state.\nThe following documentation also applies to `AutoScalingGroup`s.\n\nFor the full set of capabilities of this system, see the documentation for\n[`AWS::CloudFormation::Init`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-init.html).\nHere is an example of applying some configuration to an instance:\n\n```ts\nnew ec2.Instance(this, 'Instance', {\n // Showing the most complex setup, if you have simpler requirements\n // you can use `CloudFormationInit.fromElements()`.\n init: ec2.CloudFormationInit.fromConfigSets({\n configSets: {\n // Applies the configs below in this order\n default: ['yumPreinstall', 'config'],\n },\n configs: {\n yumPreinstall: new ec2.InitConfig([\n // Install an Amazon Linux package using yum\n ec2.InitPackage.yum('git'),\n ]),\n config: new ec2.InitConfig([\n // Create a JSON file from tokens (can also create other files)\n ec2.InitFile.fromObject('/etc/stack.json', {\n stackId: stack.stackId,\n stackName: stack.stackName,\n region: stack.region,\n }),\n\n // Create a group and user\n ec2.InitGroup.fromName('my-group'),\n ec2.InitUser.fromName('my-user'),\n\n // Install an RPM from the internet\n ec2.InitPackage.rpm('http://mirrors.ukfast.co.uk/sites/dl.fedoraproject.org/pub/epel/8/Everything/x86_64/Packages/r/rubygem-git-1.5.0-2.el8.noarch.rpm'),\n ]),\n },\n }),\n initOptions: {\n // Optional, which configsets to activate (['default'] by default)\n configSets: ['default'],\n\n // Optional, how long the installation is expected to take (5 minutes by default)\n timeout: Duration.minutes(30),\n\n // Optional, whether to include the --url argument when running cfn-init and cfn-signal commands (false by default)\n includeUrl: true\n\n // Optional, whether to include the --role argument when running cfn-init and cfn-signal commands (false by default)\n includeRole: true\n },\n});\n```\n\nYou can have services restarted after the init process has made changes to the system.\nTo do that, instantiate an `InitServiceRestartHandle` and pass it to the config elements\nthat need to trigger the restart and the service itself. For example, the following\nconfig writes a config file for nginx, extracts an archive to the root directory, and then\nrestarts nginx so that it picks up the new config and files:\n\n```ts\nconst handle = new ec2.InitServiceRestartHandle();\n\nec2.CloudFormationInit.fromElements(\n ec2.InitFile.fromString('/etc/nginx/nginx.conf', '...', { serviceRestartHandles: [handle] }),\n ec2.InitSource.fromBucket('/var/www/html', myBucket, 'html.zip', { serviceRestartHandles: [handle] }),\n ec2.InitService.enable('nginx', {\n serviceRestartHandle: handle,\n })\n);\n```\n\n### Bastion Hosts\n\nA bastion host functions as an instance used to access servers and resources in a VPC without open up the complete VPC on a network level.\nYou can use bastion hosts using a standard SSH connection targeting port 22 on the host. As an alternative, you can connect the SSH connection\nfeature of AWS Systems Manager Session Manager, which does not need an opened security group. (https://aws.amazon.com/about-aws/whats-new/2019/07/session-manager-launches-tunneling-support-for-ssh-and-scp/)\n\nA default bastion host for use via SSM can be configured like:\n\n```ts fixture=with-vpc\nconst host = new ec2.BastionHostLinux(this, 'BastionHost', { vpc });\n```\n\nIf you want to connect from the internet using SSH, you need to place the host into a public subnet. You can then configure allowed source hosts.\n\n```ts fixture=with-vpc\nconst host = new ec2.BastionHostLinux(this, 'BastionHost', {\n vpc,\n subnetSelection: { subnetType: ec2.SubnetType.PUBLIC },\n});\nhost.allowSshAccessFrom(ec2.Peer.ipv4('1.2.3.4/32'));\n```\n\nAs there are no SSH public keys deployed on this machine, you need to use [EC2 Instance Connect](https://aws.amazon.com/de/blogs/compute/new-using-amazon-ec2-instance-connect-for-ssh-access-to-your-ec2-instances/)\nwith the command `aws ec2-instance-connect send-ssh-public-key` to provide your SSH public key.\n\nEBS volume for the bastion host can be encrypted like:\n\n```ts\n const host = new ec2.BastionHostLinux(stack, 'BastionHost', {\n vpc,\n blockDevices: [{\n deviceName: 'EBSBastionHost',\n volume: BlockDeviceVolume.ebs(10, {\n encrypted: true,\n }),\n }],\n });\n```\n\n### Block Devices\n\nTo add EBS block device mappings, specify the `blockDevices` property. The following example sets the EBS-backed\nroot device (`/dev/sda1`) size to 50 GiB, and adds another EBS-backed device mapped to `/dev/sdm` that is 100 GiB in\nsize:\n\n```ts\nnew ec2.Instance(this, 'Instance', {\n // ...\n blockDevices: [\n {\n deviceName: '/dev/sda1',\n volume: ec2.BlockDeviceVolume.ebs(50),\n },\n {\n deviceName: '/dev/sdm',\n volume: ec2.BlockDeviceVolume.ebs(100),\n },\n ],\n});\n\n```\n\n### Volumes\n\nWhereas a `BlockDeviceVolume` is an EBS volume that is created and destroyed as part of the creation and destruction of a specific instance. A `Volume` is for when you want an EBS volume separate from any particular instance. A `Volume` is an EBS block device that can be attached to, or detached from, any instance at any time. Some types of `Volume`s can also be attached to multiple instances at the same time to allow you to have shared storage between those instances.\n\nA notable restriction is that a Volume can only be attached to instances in the same availability zone as the Volume itself.\n\nThe following demonstrates how to create a 500 GiB encrypted Volume in the `us-west-2a` availability zone, and give a role the ability to attach that Volume to a specific instance:\n\n```ts\nconst instance = new ec2.Instance(this, 'Instance', {\n // ...\n});\nconst role = new iam.Role(stack, 'SomeRole', {\n assumedBy: new iam.AccountRootPrincipal(),\n});\nconst volume = new ec2.Volume(this, 'Volume', {\n availabilityZone: 'us-west-2a',\n size: cdk.Size.gibibytes(500),\n encrypted: true,\n});\n\nvolume.grantAttachVolume(role, [instance]);\n```\n\n#### Instances Attaching Volumes to Themselves\n\nIf you need to grant an instance the ability to attach/detach an EBS volume to/from itself, then using `grantAttachVolume` and `grantDetachVolume` as outlined above\nwill lead to an unresolvable circular reference between the instance role and the instance. In this case, use `grantAttachVolumeByResourceTag` and `grantDetachVolumeByResourceTag` as follows:\n\n```ts\nconst instance = new ec2.Instance(this, 'Instance', {\n // ...\n});\nconst volume = new ec2.Volume(this, 'Volume', {\n // ...\n});\n\nconst attachGrant = volume.grantAttachVolumeByResourceTag(instance.grantPrincipal, [instance]);\nconst detachGrant = volume.grantDetachVolumeByResourceTag(instance.grantPrincipal, [instance]);\n```\n\n#### Attaching Volumes\n\nThe Amazon EC2 documentation for\n[Linux Instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AmazonEBS.html) and\n[Windows Instances](https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/ebs-volumes.html) contains information on how\nto attach and detach your Volumes to/from instances, and how to format them for use.\n\nThe following is a sample skeleton of EC2 UserData that can be used to attach a Volume to the Linux instance that it is running on:\n\n```ts\nconst volume = new ec2.Volume(this, 'Volume', {\n // ...\n});\nconst instance = new ec2.Instance(this, 'Instance', {\n // ...\n});\nvolume.grantAttachVolumeByResourceTag(instance.grantPrincipal, [instance]);\nconst targetDevice = '/dev/xvdz';\ninstance.userData.addCommands(\n // Retrieve token for accessing EC2 instance metadata (https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html)\n `TOKEN=$(curl -SsfX PUT \"http://169.254.169.254/latest/api/token\" -H \"X-aws-ec2-metadata-token-ttl-seconds: 21600\")`,\n // Retrieve the instance Id of the current EC2 instance\n `INSTANCE_ID=$(curl -SsfH \"X-aws-ec2-metadata-token: $TOKEN\" http://169.254.169.254/latest/meta-data/instance-id)`,\n // Attach the volume to /dev/xvdz\n `aws --region ${Stack.of(this).region} ec2 attach-volume --volume-id ${volume.volumeId} --instance-id $INSTANCE_ID --device ${targetDevice}`,\n // Wait until the volume has attached\n `while ! test -e ${targetDevice}; do sleep 1; done`\n // The volume will now be mounted. You may have to add additional code to format the volume if it has not been prepared.\n);\n```\n\n### Configuring Instance Metadata Service (IMDS)\n\n#### Toggling IMDSv1\n\nYou can configure [EC2 Instance Metadata Service](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html) options to either\nallow both IMDSv1 and IMDSv2 or enforce IMDSv2 when interacting with the IMDS.\n\nTo do this for a single `Instance`, you can use the `requireImdsv2` property.\nThe example below demonstrates IMDSv2 being required on a single `Instance`:\n\n```ts\nnew ec2.Instance(this, 'Instance', {\n requireImdsv2: true,\n // ...\n});\n```\n\nYou can also use the either the `InstanceRequireImdsv2Aspect` for EC2 instances or the `LaunchTemplateRequireImdsv2Aspect` for EC2 launch templates\nto apply the operation to multiple instances or launch templates, respectively.\n\nThe following example demonstrates how to use the `InstanceRequireImdsv2Aspect` to require IMDSv2 for all EC2 instances in a stack:\n\n```ts\nconst aspect = new ec2.InstanceRequireImdsv2Aspect();\nAspects.of(stack).add(aspect);\n```\n\n## VPC Flow Logs\n\nVPC Flow Logs is a feature that enables you to capture information about the IP traffic going to and from network interfaces in your VPC. Flow log data can be published to Amazon CloudWatch Logs and Amazon S3. After you've created a flow log, you can retrieve and view its data in the chosen destination. (<https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html>).\n\nBy default a flow log will be created with CloudWatch Logs as the destination.\n\nYou can create a flow log like this:\n\n```ts\nnew ec2.FlowLog(this, 'FlowLog', {\n resourceType: ec2.FlowLogResourceType.fromVpc(vpc)\n})\n```\n\nOr you can add a Flow Log to a VPC by using the addFlowLog method like this:\n\n```ts\nconst vpc = new ec2.Vpc(this, 'Vpc');\n\nvpc.addFlowLog('FlowLog');\n```\n\nYou can also add multiple flow logs with different destinations.\n\n```ts\nconst vpc = new ec2.Vpc(this, 'Vpc');\n\nvpc.addFlowLog('FlowLogS3', {\n destination: ec2.FlowLogDestination.toS3()\n});\n\nvpc.addFlowLog('FlowLogCloudWatch', {\n trafficType: ec2.FlowLogTrafficType.REJECT\n});\n```\n\nBy default the CDK will create the necessary resources for the destination. For the CloudWatch Logs destination\nit will create a CloudWatch Logs Log Group as well as the IAM role with the necessary permissions to publish to\nthe log group. In the case of an S3 destination, it will create the S3 bucket.\n\nIf you want to customize any of the destination resources you can provide your own as part of the `destination`.\n\n*CloudWatch Logs*\n\n```ts\nconst logGroup = new logs.LogGroup(this, 'MyCustomLogGroup');\n\nconst role = new iam.Role(this, 'MyCustomRole', {\n assumedBy: new iam.ServicePrincipal('vpc-flow-logs.amazonaws.com')\n});\n\nnew ec2.FlowLog(this, 'FlowLog', {\n resourceType: ec2.FlowLogResourceType.fromVpc(vpc),\n destination: ec2.FlowLogDestination.toCloudWatchLogs(logGroup, role)\n});\n```\n\n*S3*\n\n```ts\n\nconst bucket = new s3.Bucket(this, 'MyCustomBucket');\n\nnew ec2.FlowLog(this, 'FlowLog', {\n resourceType: ec2.FlowLogResourceType.fromVpc(vpc),\n destination: ec2.FlowLogDestination.toS3(bucket)\n});\n\nnew ec2.FlowLog(this, 'FlowLogWithKeyPrefix', {\n resourceType: ec2.FlowLogResourceType.fromVpc(vpc),\n destination: ec2.FlowLogDestination.toS3(bucket, 'prefix/')\n});\n```\n\n## User Data\n\nUser data enables you to run a script when your instances start up. In order to configure these scripts you can add commands directly to the script\n or you can use the UserData's convenience functions to aid in the creation of your script.\n\nA user data could be configured to run a script found in an asset through the following:\n\n```ts\nconst asset = new Asset(this, 'Asset', {path: path.join(__dirname, 'configure.sh')});\nconst instance = new ec2.Instance(this, 'Instance', {\n // ...\n });\nconst localPath = instance.userData.addS3DownloadCommand({\n bucket:asset.bucket,\n bucketKey:asset.s3ObjectKey,\n region: 'us-east-1', // Optional\n});\ninstance.userData.addExecuteFileCommand({\n filePath:localPath,\n arguments: '--verbose -y'\n});\nasset.grantRead( instance.role );\n```\n\n### Multipart user data\n\nIn addition, to above the `MultipartUserData` can be used to change instance startup behavior. Multipart user data are composed\nfrom separate parts forming archive. The most common parts are scripts executed during instance set-up. However, there are other\nkinds, too.\n\nThe advantage of multipart archive is in flexibility when it's needed to add additional parts or to use specialized parts to\nfine tune instance startup. Some services (like AWS Batch) supports only `MultipartUserData`.\n\nThe parts can be executed at different moment of instance start-up and can serve a different purposes. This is controlled by `contentType` property.\nFor common scripts, `text/x-shellscript; charset=\"utf-8\"` can be used as content type.\n\nIn order to create archive the `MultipartUserData` has to be instantiated. Than, user can add parts to multipart archive using `addPart`. The `MultipartBody` contains methods supporting creation of body parts.\n\nIf the very custom part is required, it can be created using `MultipartUserData.fromRawBody`, in this case full control over content type,\ntransfer encoding, and body properties is given to the user.\n\nBelow is an example for creating multipart user data with single body part responsible for installing `awscli` and configuring maximum size\nof storage used by Docker containers:\n\n```ts\nconst bootHookConf = ec2.UserData.forLinux();\nbootHookConf.addCommands('cloud-init-per once docker_options echo \\'OPTIONS=\"${OPTIONS} --storage-opt dm.basesize=40G\"\\' >> /etc/sysconfig/docker');\n\nconst setupCommands = ec2.UserData.forLinux();\nsetupCommands.addCommands('sudo yum install awscli && echo Packages installed らと > /var/tmp/setup');\n\nconst multipartUserData = new ec2.MultipartUserData();\n// The docker has to be configured at early stage, so content type is overridden to boothook\nmultipartUserData.addPart(ec2.MultipartBody.fromUserData(bootHookConf, 'text/cloud-boothook; charset=\"us-ascii\"'));\n// Execute the rest of setup\nmultipartUserData.addPart(ec2.MultipartBody.fromUserData(setupCommands));\n\nnew ec2.LaunchTemplate(stack, '', {\n userData: multipartUserData,\n blockDevices: [\n // Block device configuration rest\n ]\n});\n```\n\nFor more information see\n[Specifying Multiple User Data Blocks Using a MIME Multi Part Archive](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/bootstrap_container_instance.html#multi-part_user_data)\n\n#### Using add*Command on MultipartUserData\n\nTo use the `add*Command` methods, that are inherited from the `UserData` interface, on `MultipartUserData` you must add a part\nto the `MultipartUserData` and designate it as the reciever for these methods. This is accomplished by using the `addUserDataPart()`\nmethod on `MultipartUserData` with the `makeDefault` argument set to `true`:\n\n```ts\nconst multipartUserData = new ec2.MultipartUserData();\nconst commandsUserData = ec2.UserData.forLinux();\nmultipartUserData.addUserDataPart(commandsUserData, MultipartBody.SHELL_SCRIPT, true);\n\n// Adding commands to the multipartUserData adds them to commandsUserData, and vice-versa.\nmultipartUserData.addCommands('touch /root/multi.txt');\ncommandsUserData.addCommands('touch /root/userdata.txt');\n```\n\nWhen used on an EC2 instance, the above `multipartUserData` will create both `multi.txt` and `userdata.txt` in `/root`.\n\n## Importing existing subnet\n\nTo import an existing Subnet, call `Subnet.fromSubnetAttributes()` or\n`Subnet.fromSubnetId()`. Only if you supply the subnet's Availability Zone\nand Route Table Ids when calling `Subnet.fromSubnetAttributes()` will you be\nable to use the CDK features that use these values (such as selecting one\nsubnet per AZ).\n\nImporting an existing subnet looks like this:\n\n```ts\n// Supply all properties\nconst subnet = Subnet.fromSubnetAttributes(this, 'SubnetFromAttributes', {\n subnetId: 's-1234',\n availabilityZone: 'pub-az-4465',\n routeTableId: 'rt-145'\n});\n\n// Supply only subnet id\nconst subnet = Subnet.fromSubnetId(this, 'SubnetFromId', 's-1234');\n```\n\n## Launch Templates\n\nA Launch Template is a standardized template that contains the configuration information to launch an instance.\nThey can be used when launching instances on their own, through Amazon EC2 Auto Scaling, EC2 Fleet, and Spot Fleet.\nLaunch templates enable you to store launch parameters so that you do not have to specify them every time you launch\nan instance. For information on Launch Templates please see the\n[official documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-launch-templates.html).\n\nThe following demonstrates how to create a launch template with an Amazon Machine Image, and security group.\n\n```ts\nconst vpc = new ec2.Vpc(...);\n// ...\nconst template = new ec2.LaunchTemplate(this, 'LaunchTemplate', {\n machineImage: new ec2.AmazonMachineImage(),\n securityGroup: new ec2.SecurityGroup(this, 'LaunchTemplateSG', {\n vpc: vpc,\n }),\n});\n```\n"
1330
1330
  },
1331
1331
  "targets": {
1332
1332
  "dotnet": {
@@ -3726,7 +3726,7 @@
3726
3726
  "line": 186
3727
3727
  },
3728
3728
  "readme": {
3729
- "markdown": "# AWS Step Functions Construct Library\n\n\nThe `@aws-cdk/aws-stepfunctions` package contains constructs for building\nserverless workflows using objects. Use this in conjunction with the\n`@aws-cdk/aws-stepfunctions-tasks` package, which contains classes used\nto call other AWS services.\n\nDefining a workflow looks like this (for the [Step Functions Job Poller\nexample](https://docs.aws.amazon.com/step-functions/latest/dg/job-status-poller-sample.html)):\n\n## Example\n\n```ts\nimport * as cdk from 'aws-cdk-lib';\nimport { aws_stepfunctions as sfn } from 'aws-cdk-lib';\nimport { aws_stepfunctions_tasks as tasks } from 'aws-cdk-lib';\nimport { aws_lambda as lambda } from 'aws-cdk-lib';\n\nconst submitLambda = new lambda.Function(this, 'SubmitLambda', { ... });\nconst getStatusLambda = new lambda.Function(this, 'CheckLambda', { ... });\n\nconst submitJob = new tasks.LambdaInvoke(this, 'Submit Job', {\n lambdaFunction: submitLambda,\n // Lambda's result is in the attribute `Payload`\n outputPath: '$.Payload',\n});\n\nconst waitX = new sfn.Wait(this, 'Wait X Seconds', {\n time: sfn.WaitTime.secondsPath('$.waitSeconds'),\n});\n\nconst getStatus = new tasks.LambdaInvoke(this, 'Get Job Status', {\n lambdaFunction: getStatusLambda,\n // Pass just the field named \"guid\" into the Lambda, put the\n // Lambda's result in a field called \"status\" in the response\n inputPath: '$.guid',\n outputPath: '$.Payload',\n});\n\nconst jobFailed = new sfn.Fail(this, 'Job Failed', {\n cause: 'AWS Batch Job Failed',\n error: 'DescribeJob returned FAILED',\n});\n\nconst finalStatus = new tasks.LambdaInvoke(this, 'Get Final Job Status', {\n lambdaFunction: getStatusLambda,\n // Use \"guid\" field as input\n inputPath: '$.guid',\n outputPath: '$.Payload',\n});\n\nconst definition = submitJob\n .next(waitX)\n .next(getStatus)\n .next(new sfn.Choice(this, 'Job Complete?')\n // Look at the \"status\" field\n .when(sfn.Condition.stringEquals('$.status', 'FAILED'), jobFailed)\n .when(sfn.Condition.stringEquals('$.status', 'SUCCEEDED'), finalStatus)\n .otherwise(waitX));\n\nnew sfn.StateMachine(this, 'StateMachine', {\n definition,\n timeout: cdk.Duration.minutes(5),\n});\n```\n\nYou can find more sample snippets and learn more about the service integrations\nin the `@aws-cdk/aws-stepfunctions-tasks` package.\n\n## State Machine\n\nA `stepfunctions.StateMachine` is a resource that takes a state machine\ndefinition. The definition is specified by its start state, and encompasses\nall states reachable from the start state:\n\n```ts\nconst startState = new sfn.Pass(this, 'StartState');\n\nnew sfn.StateMachine(this, 'StateMachine', {\n definition: startState,\n});\n```\n\nState machines execute using an IAM Role, which will automatically have all\npermissions added that are required to make all state machine tasks execute\nproperly (for example, permissions to invoke any Lambda functions you add to\nyour workflow). A role will be created by default, but you can supply an\nexisting one as well.\n\n## Amazon States Language\n\nThis library comes with a set of classes that model the [Amazon States\nLanguage](https://states-language.net/spec.html). The following State classes\nare supported:\n\n* [`Task`](#task)\n* [`Pass`](#pass)\n* [`Wait`](#wait)\n* [`Choice`](#choice)\n* [`Parallel`](#parallel)\n* [`Succeed`](#succeed)\n* [`Fail`](#fail)\n* [`Map`](#map)\n* [`Custom State`](#custom-state)\n\nAn arbitrary JSON object (specified at execution start) is passed from state to\nstate and transformed during the execution of the workflow. For more\ninformation, see the States Language spec.\n\n### Task\n\nA `Task` represents some work that needs to be done. The exact work to be\ndone is determine by a class that implements `IStepFunctionsTask`, a collection\nof which can be found in the `@aws-cdk/aws-stepfunctions-tasks` module.\n\nThe tasks in the `@aws-cdk/aws-stepfunctions-tasks` module support the\n[service integration pattern](https://docs.aws.amazon.com/step-functions/latest/dg/connect-to-resource.html) that integrates Step Functions with services\ndirectly in the Amazon States language.\n\n### Pass\n\nA `Pass` state passes its input to its output, without performing work.\nPass states are useful when constructing and debugging state machines.\n\nThe following example injects some fixed data into the state machine through\nthe `result` field. The `result` field will be added to the input and the result\nwill be passed as the state's output.\n\n```ts\n// Makes the current JSON state { ..., \"subObject\": { \"hello\": \"world\" } }\nconst pass = new sfn.Pass(this, 'Add Hello World', {\n result: sfn.Result.fromObject({ hello: 'world' }),\n resultPath: '$.subObject',\n});\n\n// Set the next state\npass.next(nextState);\n```\n\nThe `Pass` state also supports passing key-value pairs as input. Values can\nbe static, or selected from the input with a path.\n\nThe following example filters the `greeting` field from the state input\nand also injects a field called `otherData`.\n\n```ts\nconst pass = new sfn.Pass(this, 'Filter input and inject data', {\n parameters: { // input to the pass state\n input: sfn.JsonPath.stringAt('$.input.greeting'),\n otherData: 'some-extra-stuff',\n },\n});\n```\n\nThe object specified in `parameters` will be the input of the `Pass` state.\nSince neither `Result` nor `ResultPath` are supplied, the `Pass` state copies\nits input through to its output.\n\nLearn more about the [Pass state](https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-pass-state.html)\n\n### Wait\n\nA `Wait` state waits for a given number of seconds, or until the current time\nhits a particular time. The time to wait may be taken from the execution's JSON\nstate.\n\n```ts\n// Wait until it's the time mentioned in the the state object's \"triggerTime\"\n// field.\nconst wait = new sfn.Wait(this, 'Wait For Trigger Time', {\n time: sfn.WaitTime.timestampPath('$.triggerTime'),\n});\n\n// Set the next state\nwait.next(startTheWork);\n```\n\n### Choice\n\nA `Choice` state can take a different path through the workflow based on the\nvalues in the execution's JSON state:\n\n```ts\nconst choice = new sfn.Choice(this, 'Did it work?');\n\n// Add conditions with .when()\nchoice.when(sfn.Condition.stringEquals('$.status', 'SUCCESS'), successState);\nchoice.when(sfn.Condition.numberGreaterThan('$.attempts', 5), failureState);\n\n// Use .otherwise() to indicate what should be done if none of the conditions match\nchoice.otherwise(tryAgainState);\n```\n\nIf you want to temporarily branch your workflow based on a condition, but have\nall branches come together and continuing as one (similar to how an `if ...\nthen ... else` works in a programming language), use the `.afterwards()` method:\n\n```ts\nconst choice = new sfn.Choice(this, 'What color is it?');\nchoice.when(sfn.Condition.stringEquals('$.color', 'BLUE'), handleBlueItem);\nchoice.when(sfn.Condition.stringEquals('$.color', 'RED'), handleRedItem);\nchoice.otherwise(handleOtherItemColor);\n\n// Use .afterwards() to join all possible paths back together and continue\nchoice.afterwards().next(shipTheItem);\n```\n\nIf your `Choice` doesn't have an `otherwise()` and none of the conditions match\nthe JSON state, a `NoChoiceMatched` error will be thrown. Wrap the state machine\nin a `Parallel` state if you want to catch and recover from this.\n\n#### Available Conditions\n\nsee [step function comparison operators](https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-choice-state.html#amazon-states-language-choice-state-rules)\n\n* `Condition.isPresent` - matches if a json path is present\n* `Condition.isNotPresent` - matches if a json path is not present\n* `Condition.isString` - matches if a json path contains a string\n* `Condition.isNotString` - matches if a json path is not a string\n* `Condition.isNumeric` - matches if a json path is numeric\n* `Condition.isNotNumeric` - matches if a json path is not numeric\n* `Condition.isBoolean` - matches if a json path is boolean\n* `Condition.isNotBoolean` - matches if a json path is not boolean\n* `Condition.isTimestamp` - matches if a json path is a timestamp\n* `Condition.isNotTimestamp` - matches if a json path is not a timestamp\n* `Condition.isNotNull` - matches if a json path is not null\n* `Condition.isNull` - matches if a json path is null\n* `Condition.booleanEquals` - matches if a boolean field has a given value\n* `Condition.booleanEqualsJsonPath` - matches if a boolean field equals a value in a given mapping path\n* `Condition.stringEqualsJsonPath` - matches if a string field equals a given mapping path\n* `Condition.stringEquals` - matches if a field equals a string value\n* `Condition.stringLessThan` - matches if a string field sorts before a given value\n* `Condition.stringLessThanJsonPath` - matches if a string field sorts before a value at given mapping path\n* `Condition.stringLessThanEquals` - matches if a string field sorts equal to or before a given value\n* `Condition.stringLessThanEqualsJsonPath` - matches if a string field sorts equal to or before a given mapping\n* `Condition.stringGreaterThan` - matches if a string field sorts after a given value\n* `Condition.stringGreaterThanJsonPath` - matches if a string field sorts after a value at a given mapping path\n* `Condition.stringGreaterThanEqualsJsonPath` - matches if a string field sorts after or equal to value at a given mapping path\n* `Condition.stringGreaterThanEquals` - matches if a string field sorts after or equal to a given value\n* `Condition.numberEquals` - matches if a numeric field has the given value\n* `Condition.numberEqualsJsonPath` - matches if a numeric field has the value in a given mapping path\n* `Condition.numberLessThan` - matches if a numeric field is less than the given value\n* `Condition.numberLessThanJsonPath` - matches if a numeric field is less than the value at the given mapping path\n* `Condition.numberLessThanEquals` - matches if a numeric field is less than or equal to the given value\n* `Condition.numberLessThanEqualsJsonPath` - matches if a numeric field is less than or equal to the numeric value at given mapping path\n* `Condition.numberGreaterThan` - matches if a numeric field is greater than the given value\n* `Condition.numberGreaterThanJsonPath` - matches if a numeric field is greater than the value at a given mapping path\n* `Condition.numberGreaterThanEquals` - matches if a numeric field is greater than or equal to the given value\n* `Condition.numberGreaterThanEqualsJsonPath` - matches if a numeric field is greater than or equal to the value at a given mapping path\n* `Condition.timestampEquals` - matches if a timestamp field is the same time as the given timestamp\n* `Condition.timestampEqualsJsonPath` - matches if a timestamp field is the same time as the timestamp at a given mapping path\n* `Condition.timestampLessThan` - matches if a timestamp field is before the given timestamp\n* `Condition.timestampLessThanJsonPath` - matches if a timestamp field is before the timestamp at a given mapping path\n* `Condition.timestampLessThanEquals` - matches if a timestamp field is before or equal to the given timestamp\n* `Condition.timestampLessThanEqualsJsonPath` - matches if a timestamp field is before or equal to the timestamp at a given mapping path\n* `Condition.timestampGreaterThan` - matches if a timestamp field is after the timestamp at a given mapping path\n* `Condition.timestampGreaterThanJsonPath` - matches if a timestamp field is after the timestamp at a given mapping path\n* `Condition.timestampGreaterThanEquals` - matches if a timestamp field is after or equal to the given timestamp\n* `Condition.timestampGreaterThanEqualsJsonPath` - matches if a timestamp field is after or equal to the timestamp at a given mapping path\n* `Condition.stringMatches` - matches if a field matches a string pattern that can contain a wild card (\\*) e.g: log-\\*.txt or \\*LATEST\\*. No other characters other than \"\\*\" have any special meaning - \\* can be escaped: \\\\\\\\*\n\n### Parallel\n\nA `Parallel` state executes one or more subworkflows in parallel. It can also\nbe used to catch and recover from errors in subworkflows.\n\n```ts\nconst parallel = new sfn.Parallel(this, 'Do the work in parallel');\n\n// Add branches to be executed in parallel\nparallel.branch(shipItem);\nparallel.branch(sendInvoice);\nparallel.branch(restock);\n\n// Retry the whole workflow if something goes wrong\nparallel.addRetry({ maxAttempts: 1 });\n\n// How to recover from errors\nparallel.addCatch(sendFailureNotification);\n\n// What to do in case everything succeeded\nparallel.next(closeOrder);\n```\n\n### Succeed\n\nReaching a `Succeed` state terminates the state machine execution with a\nsuccessful status.\n\n```ts\nconst success = new sfn.Succeed(this, 'We did it!');\n```\n\n### Fail\n\nReaching a `Fail` state terminates the state machine execution with a\nfailure status. The fail state should report the reason for the failure.\nFailures can be caught by encompassing `Parallel` states.\n\n```ts\nconst success = new sfn.Fail(this, 'Fail', {\n error: 'WorkflowFailure',\n cause: \"Something went wrong\",\n});\n```\n\n### Map\n\nA `Map` state can be used to run a set of steps for each element of an input array.\nA `Map` state will execute the same steps for multiple entries of an array in the state input.\n\nWhile the `Parallel` state executes multiple branches of steps using the same input, a `Map` state will\nexecute the same steps for multiple entries of an array in the state input.\n\n```ts\nconst map = new sfn.Map(this, 'Map State', {\n maxConcurrency: 1,\n itemsPath: sfn.JsonPath.stringAt('$.inputForMap'),\n});\nmap.iterator(new sfn.Pass(this, 'Pass State'));\n```\n\n### Custom State\n\nIt's possible that the high-level constructs for the states or `stepfunctions-tasks` do not have\nthe states or service integrations you are looking for. The primary reasons for this lack of\nfunctionality are:\n\n* A [service integration](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-service-integrations.html) is available through Amazon States Langauge, but not available as construct\n classes in the CDK.\n* The state or state properties are available through Step Functions, but are not configurable\n through constructs\n\nIf a feature is not available, a `CustomState` can be used to supply any Amazon States Language\nJSON-based object as the state definition.\n\n[Code Snippets](https://docs.aws.amazon.com/step-functions/latest/dg/tutorial-code-snippet.html#tutorial-code-snippet-1) are available and can be plugged in as the state definition.\n\nCustom states can be chained together with any of the other states to create your state machine\ndefinition. You will also need to provide any permissions that are required to the `role` that\nthe State Machine uses.\n\nThe following example uses the `DynamoDB` service integration to insert data into a DynamoDB table.\n\n```ts\nimport * as cdk from 'aws-cdk-lib';\nimport { aws_dynamodb as ddb } from 'aws-cdk-lib';\nimport { aws_stepfunctions as sfn } from 'aws-cdk-lib';\n\n// create a table\nconst table = new ddb.Table(this, 'montable', {\n partitionKey: {\n name: 'id',\n type: ddb.AttributeType.STRING,\n },\n});\n\nconst finalStatus = new sfn.Pass(stack, 'final step');\n\n// States language JSON to put an item into DynamoDB\n// snippet generated from https://docs.aws.amazon.com/step-functions/latest/dg/tutorial-code-snippet.html#tutorial-code-snippet-1\nconst stateJson = {\n Type: 'Task',\n Resource: 'arn:aws:states:::dynamodb:putItem',\n Parameters: {\n TableName: table.tableName,\n Item: {\n id: {\n S: 'MyEntry',\n },\n },\n },\n ResultPath: null,\n};\n\n// custom state which represents a task to insert data into DynamoDB\nconst custom = new sfn.CustomState(this, 'my custom task', {\n stateJson,\n});\n\nconst chain = sfn.Chain.start(custom)\n .next(finalStatus);\n\nconst sm = new sfn.StateMachine(this, 'StateMachine', {\n definition: chain,\n timeout: cdk.Duration.seconds(30),\n});\n\n// don't forget permissions. You need to assign them\ntable.grantWriteData(sm);\n```\n\n## Task Chaining\n\nTo make defining work flows as convenient (and readable in a top-to-bottom way)\nas writing regular programs, it is possible to chain most methods invocations.\nIn particular, the `.next()` method can be repeated. The result of a series of\n`.next()` calls is called a **Chain**, and can be used when defining the jump\ntargets of `Choice.on` or `Parallel.branch`:\n\n```ts\nconst definition = step1\n .next(step2)\n .next(choice\n .when(condition1, step3.next(step4).next(step5))\n .otherwise(step6)\n .afterwards())\n .next(parallel\n .branch(step7.next(step8))\n .branch(step9.next(step10)))\n .next(finish);\n\nnew sfn.StateMachine(this, 'StateMachine', {\n definition,\n});\n```\n\nIf you don't like the visual look of starting a chain directly off the first\nstep, you can use `Chain.start`:\n\n```ts\nconst definition = sfn.Chain\n .start(step1)\n .next(step2)\n .next(step3)\n // ...\n```\n\n## State Machine Fragments\n\nIt is possible to define reusable (or abstracted) mini-state machines by\ndefining a construct that implements `IChainable`, which requires you to define\ntwo fields:\n\n* `startState: State`, representing the entry point into this state machine.\n* `endStates: INextable[]`, representing the (one or more) states that outgoing\n transitions will be added to if you chain onto the fragment.\n\nSince states will be named after their construct IDs, you may need to prefix the\nIDs of states if you plan to instantiate the same state machine fragment\nmultiples times (otherwise all states in every instantiation would have the same\nname).\n\nThe class `StateMachineFragment` contains some helper functions (like\n`prefixStates()`) to make it easier for you to do this. If you define your state\nmachine as a subclass of this, it will be convenient to use:\n\n```ts\ninterface MyJobProps {\n jobFlavor: string;\n}\n\nclass MyJob extends sfn.StateMachineFragment {\n public readonly startState: sfn.State;\n public readonly endStates: sfn.INextable[];\n\n constructor(parent: cdk.Construct, id: string, props: MyJobProps) {\n super(parent, id);\n\n const first = new sfn.Task(this, 'First', { ... });\n // ...\n const last = new sfn.Task(this, 'Last', { ... });\n\n this.startState = first;\n this.endStates = [last];\n }\n}\n\n// Do 3 different variants of MyJob in parallel\nnew sfn.Parallel(this, 'All jobs')\n .branch(new MyJob(this, 'Quick', { jobFlavor: 'quick' }).prefixStates())\n .branch(new MyJob(this, 'Medium', { jobFlavor: 'medium' }).prefixStates())\n .branch(new MyJob(this, 'Slow', { jobFlavor: 'slow' }).prefixStates());\n```\n\nA few utility functions are available to parse state machine fragments.\n\n* `State.findReachableStates`: Retrieve the list of states reachable from a given state.\n* `State.findReachableEndStates`: Retrieve the list of end or terminal states reachable from a given state.\n\n## Activity\n\n**Activities** represent work that is done on some non-Lambda worker pool. The\nStep Functions workflow will submit work to this Activity, and a worker pool\nthat you run yourself, probably on EC2, will pull jobs from the Activity and\nsubmit the results of individual jobs back.\n\nYou need the ARN to do so, so if you use Activities be sure to pass the Activity\nARN into your worker pool:\n\n```ts\nconst activity = new sfn.Activity(this, 'Activity');\n\n// Read this CloudFormation Output from your application and use it to poll for work on\n// the activity.\nnew cdk.CfnOutput(this, 'ActivityArn', { value: activity.activityArn });\n```\n\n### Activity-Level Permissions\n\nGranting IAM permissions to an activity can be achieved by calling the `grant(principal, actions)` API:\n\n```ts\nconst activity = new sfn.Activity(this, 'Activity');\n\nconst role = new iam.Role(stack, 'Role', {\n assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),\n});\n\nactivity.grant(role, 'states:SendTaskSuccess');\n```\n\nThis will grant the IAM principal the specified actions onto the activity.\n\n## Metrics\n\n`Task` object expose various metrics on the execution of that particular task. For example,\nto create an alarm on a particular task failing:\n\n```ts\nnew cloudwatch.Alarm(this, 'TaskAlarm', {\n metric: task.metricFailed(),\n threshold: 1,\n evaluationPeriods: 1,\n});\n```\n\nThere are also metrics on the complete state machine:\n\n```ts\nnew cloudwatch.Alarm(this, 'StateMachineAlarm', {\n metric: stateMachine.metricFailed(),\n threshold: 1,\n evaluationPeriods: 1,\n});\n```\n\nAnd there are metrics on the capacity of all state machines in your account:\n\n```ts\nnew cloudwatch.Alarm(this, 'ThrottledAlarm', {\n metric: StateTransitionMetrics.metricThrottledEvents(),\n threshold: 10,\n evaluationPeriods: 2,\n});\n```\n\n## Error names\n\nStep Functions identifies errors in the Amazon States Language using case-sensitive strings, known as error names. \nThe Amazon States Language defines a set of built-in strings that name well-known errors, all beginning with the `States.` prefix. \n\n* `States.ALL` - A wildcard that matches any known error name.\n* `States.Runtime` - An execution failed due to some exception that could not be processed. Often these are caused by errors at runtime, such as attempting to apply InputPath or OutputPath on a null JSON payload. A `States.Runtime` error is not retriable, and will always cause the execution to fail. A retry or catch on `States.ALL` will NOT catch States.Runtime errors.\n* `States.DataLimitExceeded` - A States.DataLimitExceeded exception will be thrown for the following:\n * When the output of a connector is larger than payload size quota.\n * When the output of a state is larger than payload size quota.\n * When, after Parameters processing, the input of a state is larger than the payload size quota.\n * See [the AWS documentation](https://docs.aws.amazon.com/step-functions/latest/dg/limits-overview.html) to learn more about AWS Step Functions Quotas.\n* `States.HeartbeatTimeout` - A Task state failed to send a heartbeat for a period longer than the HeartbeatSeconds value.\n* `States.Timeout` - A Task state either ran longer than the TimeoutSeconds value, or failed to send a heartbeat for a period longer than the HeartbeatSeconds value.\n* `States.TaskFailed`- A Task state failed during the execution. When used in a retry or catch, `States.TaskFailed` acts as a wildcard that matches any known error name except for `States.Timeout`.\n\n## Logging\n\nEnable logging to CloudWatch by passing a logging configuration with a\ndestination LogGroup:\n\n```ts\nconst logGroup = new logs.LogGroup(stack, 'MyLogGroup');\n\nnew sfn.StateMachine(stack, 'MyStateMachine', {\n definition: sfn.Chain.start(new sfn.Pass(stack, 'Pass')),\n logs: {\n destination: logGroup,\n level: sfn.LogLevel.ALL,\n },\n});\n```\n\n## X-Ray tracing\n\nEnable X-Ray tracing for StateMachine:\n\n```ts\nnew sfn.StateMachine(stack, 'MyStateMachine', {\n definition: sfn.Chain.start(new sfn.Pass(stack, 'Pass')),\n tracingEnabled: true,\n});\n```\n\nSee [the AWS documentation](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-xray-tracing.html)\nto learn more about AWS Step Functions's X-Ray support.\n\n## State Machine Permission Grants\n\nIAM roles, users, or groups which need to be able to work with a State Machine should be granted IAM permissions.\n\nAny object that implements the `IGrantable` interface (has an associated principal) can be granted permissions by calling:\n\n* `stateMachine.grantStartExecution(principal)` - grants the principal the ability to execute the state machine\n* `stateMachine.grantRead(principal)` - grants the principal read access\n* `stateMachine.grantTaskResponse(principal)` - grants the principal the ability to send task tokens to the state machine\n* `stateMachine.grantExecution(principal, actions)` - grants the principal execution-level permissions for the IAM actions specified\n* `stateMachine.grant(principal, actions)` - grants the principal state-machine-level permissions for the IAM actions specified\n\n### Start Execution Permission\n\nGrant permission to start an execution of a state machine by calling the `grantStartExecution()` API.\n\n```ts\nconst role = new iam.Role(stack, 'Role', {\n assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),\n});\n\nconst stateMachine = new stepfunction.StateMachine(stack, 'StateMachine', {\n definition,\n});\n\n// Give role permission to start execution of state machine\nstateMachine.grantStartExecution(role);\n```\n\nThe following permission is provided to a service principal by the `grantStartExecution()` API:\n\n* `states:StartExecution` - to state machine\n\n### Read Permissions\n\nGrant `read` access to a state machine by calling the `grantRead()` API.\n\n```ts\nconst role = new iam.Role(stack, 'Role', {\n assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),\n});\n\nconst stateMachine = new stepfunction.StateMachine(stack, 'StateMachine', {\n definition,\n});\n\n// Give role read access to state machine\nstateMachine.grantRead(role);\n```\n\nThe following read permissions are provided to a service principal by the `grantRead()` API:\n\n* `states:ListExecutions` - to state machine\n* `states:ListStateMachines` - to state machine\n* `states:DescribeExecution` - to executions\n* `states:DescribeStateMachineForExecution` - to executions\n* `states:GetExecutionHistory` - to executions\n* `states:ListActivities` - to `*`\n* `states:DescribeStateMachine` - to `*`\n* `states:DescribeActivity` - to `*`\n\n### Task Response Permissions\n\nGrant permission to allow task responses to a state machine by calling the `grantTaskResponse()` API:\n\n```ts\nconst role = new iam.Role(stack, 'Role', {\n assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),\n});\n\nconst stateMachine = new stepfunction.StateMachine(stack, 'StateMachine', {\n definition,\n});\n\n// Give role task response permissions to the state machine\nstateMachine.grantTaskResponse(role);\n```\n\nThe following read permissions are provided to a service principal by the `grantRead()` API:\n\n* `states:SendTaskSuccess` - to state machine\n* `states:SendTaskFailure` - to state machine\n* `states:SendTaskHeartbeat` - to state machine\n\n### Execution-level Permissions\n\nGrant execution-level permissions to a state machine by calling the `grantExecution()` API:\n\n```ts\nconst role = new iam.Role(stack, 'Role', {\n assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),\n});\n\nconst stateMachine = new stepfunction.StateMachine(stack, 'StateMachine', {\n definition,\n});\n\n// Give role permission to get execution history of ALL executions for the state machine\nstateMachine.grantExecution(role, 'states:GetExecutionHistory');\n```\n\n### Custom Permissions\n\nYou can add any set of permissions to a state machine by calling the `grant()` API.\n\n```ts\nconst user = new iam.User(stack, 'MyUser');\n\nconst stateMachine = new stepfunction.StateMachine(stack, 'StateMachine', {\n definition,\n});\n\n//give user permission to send task success to the state machine\nstateMachine.grant(user, 'states:SendTaskSuccess');\n```\n\n## Import\n\nAny Step Functions state machine that has been created outside the stack can be imported\ninto your CDK stack.\n\nState machines can be imported by their ARN via the `StateMachine.fromStateMachineArn()` API\n\n```ts\nimport * as sfn from 'aws-stepfunctions';\n\nconst stack = new Stack(app, 'MyStack');\nsfn.StateMachine.fromStateMachineArn(\n stack,\n 'ImportedStateMachine',\n 'arn:aws:states:us-east-1:123456789012:stateMachine:StateMachine2E01A3A5-N5TJppzoevKQ',\n);\n```\n"
3729
+ "markdown": "# AWS Step Functions Construct Library\n\n\nThe `@aws-cdk/aws-stepfunctions` package contains constructs for building\nserverless workflows using objects. Use this in conjunction with the\n`@aws-cdk/aws-stepfunctions-tasks` package, which contains classes used\nto call other AWS services.\n\nDefining a workflow looks like this (for the [Step Functions Job Poller\nexample](https://docs.aws.amazon.com/step-functions/latest/dg/job-status-poller-sample.html)):\n\n## Example\n\n```ts\nimport { aws_lambda as lambda } from 'aws-cdk-lib';\n\ndeclare const submitLambda: lambda.Function;\ndeclare const getStatusLambda: lambda.Function;\n\nconst submitJob = new tasks.LambdaInvoke(this, 'Submit Job', {\n lambdaFunction: submitLambda,\n // Lambda's result is in the attribute `Payload`\n outputPath: '$.Payload',\n});\n\nconst waitX = new sfn.Wait(this, 'Wait X Seconds', {\n time: sfn.WaitTime.secondsPath('$.waitSeconds'),\n});\n\nconst getStatus = new tasks.LambdaInvoke(this, 'Get Job Status', {\n lambdaFunction: getStatusLambda,\n // Pass just the field named \"guid\" into the Lambda, put the\n // Lambda's result in a field called \"status\" in the response\n inputPath: '$.guid',\n outputPath: '$.Payload',\n});\n\nconst jobFailed = new sfn.Fail(this, 'Job Failed', {\n cause: 'AWS Batch Job Failed',\n error: 'DescribeJob returned FAILED',\n});\n\nconst finalStatus = new tasks.LambdaInvoke(this, 'Get Final Job Status', {\n lambdaFunction: getStatusLambda,\n // Use \"guid\" field as input\n inputPath: '$.guid',\n outputPath: '$.Payload',\n});\n\nconst definition = submitJob\n .next(waitX)\n .next(getStatus)\n .next(new sfn.Choice(this, 'Job Complete?')\n // Look at the \"status\" field\n .when(sfn.Condition.stringEquals('$.status', 'FAILED'), jobFailed)\n .when(sfn.Condition.stringEquals('$.status', 'SUCCEEDED'), finalStatus)\n .otherwise(waitX));\n\nnew sfn.StateMachine(this, 'StateMachine', {\n definition,\n timeout: Duration.minutes(5),\n});\n```\n\nYou can find more sample snippets and learn more about the service integrations\nin the `@aws-cdk/aws-stepfunctions-tasks` package.\n\n## State Machine\n\nA `stepfunctions.StateMachine` is a resource that takes a state machine\ndefinition. The definition is specified by its start state, and encompasses\nall states reachable from the start state:\n\n```ts\nconst startState = new sfn.Pass(this, 'StartState');\n\nnew sfn.StateMachine(this, 'StateMachine', {\n definition: startState,\n});\n```\n\nState machines execute using an IAM Role, which will automatically have all\npermissions added that are required to make all state machine tasks execute\nproperly (for example, permissions to invoke any Lambda functions you add to\nyour workflow). A role will be created by default, but you can supply an\nexisting one as well.\n\n## Amazon States Language\n\nThis library comes with a set of classes that model the [Amazon States\nLanguage](https://states-language.net/spec.html). The following State classes\nare supported:\n\n* [`Task`](#task)\n* [`Pass`](#pass)\n* [`Wait`](#wait)\n* [`Choice`](#choice)\n* [`Parallel`](#parallel)\n* [`Succeed`](#succeed)\n* [`Fail`](#fail)\n* [`Map`](#map)\n* [`Custom State`](#custom-state)\n\nAn arbitrary JSON object (specified at execution start) is passed from state to\nstate and transformed during the execution of the workflow. For more\ninformation, see the States Language spec.\n\n### Task\n\nA `Task` represents some work that needs to be done. The exact work to be\ndone is determine by a class that implements `IStepFunctionsTask`, a collection\nof which can be found in the `@aws-cdk/aws-stepfunctions-tasks` module.\n\nThe tasks in the `@aws-cdk/aws-stepfunctions-tasks` module support the\n[service integration pattern](https://docs.aws.amazon.com/step-functions/latest/dg/connect-to-resource.html) that integrates Step Functions with services\ndirectly in the Amazon States language.\n\n### Pass\n\nA `Pass` state passes its input to its output, without performing work.\nPass states are useful when constructing and debugging state machines.\n\nThe following example injects some fixed data into the state machine through\nthe `result` field. The `result` field will be added to the input and the result\nwill be passed as the state's output.\n\n```ts\n// Makes the current JSON state { ..., \"subObject\": { \"hello\": \"world\" } }\nconst pass = new sfn.Pass(this, 'Add Hello World', {\n result: sfn.Result.fromObject({ hello: 'world' }),\n resultPath: '$.subObject',\n});\n\n// Set the next state\nconst nextState = new sfn.Pass(this, 'NextState');\npass.next(nextState);\n```\n\nThe `Pass` state also supports passing key-value pairs as input. Values can\nbe static, or selected from the input with a path.\n\nThe following example filters the `greeting` field from the state input\nand also injects a field called `otherData`.\n\n```ts\nconst pass = new sfn.Pass(this, 'Filter input and inject data', {\n parameters: { // input to the pass state\n input: sfn.JsonPath.stringAt('$.input.greeting'),\n otherData: 'some-extra-stuff',\n },\n});\n```\n\nThe object specified in `parameters` will be the input of the `Pass` state.\nSince neither `Result` nor `ResultPath` are supplied, the `Pass` state copies\nits input through to its output.\n\nLearn more about the [Pass state](https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-pass-state.html)\n\n### Wait\n\nA `Wait` state waits for a given number of seconds, or until the current time\nhits a particular time. The time to wait may be taken from the execution's JSON\nstate.\n\n```ts\n// Wait until it's the time mentioned in the the state object's \"triggerTime\"\n// field.\nconst wait = new sfn.Wait(this, 'Wait For Trigger Time', {\n time: sfn.WaitTime.timestampPath('$.triggerTime'),\n});\n\n// Set the next state\nconst startTheWork = new sfn.Pass(this, 'StartTheWork');\nwait.next(startTheWork);\n```\n\n### Choice\n\nA `Choice` state can take a different path through the workflow based on the\nvalues in the execution's JSON state:\n\n```ts\nconst choice = new sfn.Choice(this, 'Did it work?');\n\n// Add conditions with .when()\nconst successState = new sfn.Pass(this, 'SuccessState');\nconst failureState = new sfn.Pass(this, 'FailureState');\nchoice.when(sfn.Condition.stringEquals('$.status', 'SUCCESS'), successState);\nchoice.when(sfn.Condition.numberGreaterThan('$.attempts', 5), failureState);\n\n// Use .otherwise() to indicate what should be done if none of the conditions match\nconst tryAgainState = new sfn.Pass(this, 'TryAgainState');\nchoice.otherwise(tryAgainState);\n```\n\nIf you want to temporarily branch your workflow based on a condition, but have\nall branches come together and continuing as one (similar to how an `if ...\nthen ... else` works in a programming language), use the `.afterwards()` method:\n\n```ts\nconst choice = new sfn.Choice(this, 'What color is it?');\nconst handleBlueItem = new sfn.Pass(this, 'HandleBlueItem');\nconst handleRedItem = new sfn.Pass(this, 'HandleRedItem');\nconst handleOtherItemColor = new sfn.Pass(this, 'HanldeOtherItemColor');\nchoice.when(sfn.Condition.stringEquals('$.color', 'BLUE'), handleBlueItem);\nchoice.when(sfn.Condition.stringEquals('$.color', 'RED'), handleRedItem);\nchoice.otherwise(handleOtherItemColor);\n\n// Use .afterwards() to join all possible paths back together and continue\nconst shipTheItem = new sfn.Pass(this, 'ShipTheItem');\nchoice.afterwards().next(shipTheItem);\n```\n\nIf your `Choice` doesn't have an `otherwise()` and none of the conditions match\nthe JSON state, a `NoChoiceMatched` error will be thrown. Wrap the state machine\nin a `Parallel` state if you want to catch and recover from this.\n\n#### Available Conditions\n\nsee [step function comparison operators](https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-choice-state.html#amazon-states-language-choice-state-rules)\n\n* `Condition.isPresent` - matches if a json path is present\n* `Condition.isNotPresent` - matches if a json path is not present\n* `Condition.isString` - matches if a json path contains a string\n* `Condition.isNotString` - matches if a json path is not a string\n* `Condition.isNumeric` - matches if a json path is numeric\n* `Condition.isNotNumeric` - matches if a json path is not numeric\n* `Condition.isBoolean` - matches if a json path is boolean\n* `Condition.isNotBoolean` - matches if a json path is not boolean\n* `Condition.isTimestamp` - matches if a json path is a timestamp\n* `Condition.isNotTimestamp` - matches if a json path is not a timestamp\n* `Condition.isNotNull` - matches if a json path is not null\n* `Condition.isNull` - matches if a json path is null\n* `Condition.booleanEquals` - matches if a boolean field has a given value\n* `Condition.booleanEqualsJsonPath` - matches if a boolean field equals a value in a given mapping path\n* `Condition.stringEqualsJsonPath` - matches if a string field equals a given mapping path\n* `Condition.stringEquals` - matches if a field equals a string value\n* `Condition.stringLessThan` - matches if a string field sorts before a given value\n* `Condition.stringLessThanJsonPath` - matches if a string field sorts before a value at given mapping path\n* `Condition.stringLessThanEquals` - matches if a string field sorts equal to or before a given value\n* `Condition.stringLessThanEqualsJsonPath` - matches if a string field sorts equal to or before a given mapping\n* `Condition.stringGreaterThan` - matches if a string field sorts after a given value\n* `Condition.stringGreaterThanJsonPath` - matches if a string field sorts after a value at a given mapping path\n* `Condition.stringGreaterThanEqualsJsonPath` - matches if a string field sorts after or equal to value at a given mapping path\n* `Condition.stringGreaterThanEquals` - matches if a string field sorts after or equal to a given value\n* `Condition.numberEquals` - matches if a numeric field has the given value\n* `Condition.numberEqualsJsonPath` - matches if a numeric field has the value in a given mapping path\n* `Condition.numberLessThan` - matches if a numeric field is less than the given value\n* `Condition.numberLessThanJsonPath` - matches if a numeric field is less than the value at the given mapping path\n* `Condition.numberLessThanEquals` - matches if a numeric field is less than or equal to the given value\n* `Condition.numberLessThanEqualsJsonPath` - matches if a numeric field is less than or equal to the numeric value at given mapping path\n* `Condition.numberGreaterThan` - matches if a numeric field is greater than the given value\n* `Condition.numberGreaterThanJsonPath` - matches if a numeric field is greater than the value at a given mapping path\n* `Condition.numberGreaterThanEquals` - matches if a numeric field is greater than or equal to the given value\n* `Condition.numberGreaterThanEqualsJsonPath` - matches if a numeric field is greater than or equal to the value at a given mapping path\n* `Condition.timestampEquals` - matches if a timestamp field is the same time as the given timestamp\n* `Condition.timestampEqualsJsonPath` - matches if a timestamp field is the same time as the timestamp at a given mapping path\n* `Condition.timestampLessThan` - matches if a timestamp field is before the given timestamp\n* `Condition.timestampLessThanJsonPath` - matches if a timestamp field is before the timestamp at a given mapping path\n* `Condition.timestampLessThanEquals` - matches if a timestamp field is before or equal to the given timestamp\n* `Condition.timestampLessThanEqualsJsonPath` - matches if a timestamp field is before or equal to the timestamp at a given mapping path\n* `Condition.timestampGreaterThan` - matches if a timestamp field is after the timestamp at a given mapping path\n* `Condition.timestampGreaterThanJsonPath` - matches if a timestamp field is after the timestamp at a given mapping path\n* `Condition.timestampGreaterThanEquals` - matches if a timestamp field is after or equal to the given timestamp\n* `Condition.timestampGreaterThanEqualsJsonPath` - matches if a timestamp field is after or equal to the timestamp at a given mapping path\n* `Condition.stringMatches` - matches if a field matches a string pattern that can contain a wild card (\\*) e.g: log-\\*.txt or \\*LATEST\\*. No other characters other than \"\\*\" have any special meaning - \\* can be escaped: \\\\\\\\*\n\n### Parallel\n\nA `Parallel` state executes one or more subworkflows in parallel. It can also\nbe used to catch and recover from errors in subworkflows.\n\n```ts\nconst parallel = new sfn.Parallel(this, 'Do the work in parallel');\n\n// Add branches to be executed in parallel\nconst shipItem = new sfn.Pass(this, 'ShipItem');\nconst sendInvoice = new sfn.Pass(this, 'SendInvoice');\nconst restock = new sfn.Pass(this, 'Restock');\nparallel.branch(shipItem);\nparallel.branch(sendInvoice);\nparallel.branch(restock);\n\n// Retry the whole workflow if something goes wrong\nparallel.addRetry({ maxAttempts: 1 });\n\n// How to recover from errors\nconst sendFailureNotification = new sfn.Pass(this, 'SendFailureNotification');\nparallel.addCatch(sendFailureNotification);\n\n// What to do in case everything succeeded\nconst closeOrder = new sfn.Pass(this, 'CloseOrder');\nparallel.next(closeOrder);\n```\n\n### Succeed\n\nReaching a `Succeed` state terminates the state machine execution with a\nsuccessful status.\n\n```ts\nconst success = new sfn.Succeed(this, 'We did it!');\n```\n\n### Fail\n\nReaching a `Fail` state terminates the state machine execution with a\nfailure status. The fail state should report the reason for the failure.\nFailures can be caught by encompassing `Parallel` states.\n\n```ts\nconst success = new sfn.Fail(this, 'Fail', {\n error: 'WorkflowFailure',\n cause: \"Something went wrong\",\n});\n```\n\n### Map\n\nA `Map` state can be used to run a set of steps for each element of an input array.\nA `Map` state will execute the same steps for multiple entries of an array in the state input.\n\nWhile the `Parallel` state executes multiple branches of steps using the same input, a `Map` state will\nexecute the same steps for multiple entries of an array in the state input.\n\n```ts\nconst map = new sfn.Map(this, 'Map State', {\n maxConcurrency: 1,\n itemsPath: sfn.JsonPath.stringAt('$.inputForMap'),\n});\nmap.iterator(new sfn.Pass(this, 'Pass State'));\n```\n\n### Custom State\n\nIt's possible that the high-level constructs for the states or `stepfunctions-tasks` do not have\nthe states or service integrations you are looking for. The primary reasons for this lack of\nfunctionality are:\n\n* A [service integration](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-service-integrations.html) is available through Amazon States Langauge, but not available as construct\n classes in the CDK.\n* The state or state properties are available through Step Functions, but are not configurable\n through constructs\n\nIf a feature is not available, a `CustomState` can be used to supply any Amazon States Language\nJSON-based object as the state definition.\n\n[Code Snippets](https://docs.aws.amazon.com/step-functions/latest/dg/tutorial-code-snippet.html#tutorial-code-snippet-1) are available and can be plugged in as the state definition.\n\nCustom states can be chained together with any of the other states to create your state machine\ndefinition. You will also need to provide any permissions that are required to the `role` that\nthe State Machine uses.\n\nThe following example uses the `DynamoDB` service integration to insert data into a DynamoDB table.\n\n```ts\nimport { aws_dynamodb as dynamodb } from 'aws-cdk-lib';\n\n// create a table\nconst table = new dynamodb.Table(this, 'montable', {\n partitionKey: {\n name: 'id',\n type: dynamodb.AttributeType.STRING,\n },\n});\n\nconst finalStatus = new sfn.Pass(this, 'final step');\n\n// States language JSON to put an item into DynamoDB\n// snippet generated from https://docs.aws.amazon.com/step-functions/latest/dg/tutorial-code-snippet.html#tutorial-code-snippet-1\nconst stateJson = {\n Type: 'Task',\n Resource: 'arn:aws:states:::dynamodb:putItem',\n Parameters: {\n TableName: table.tableName,\n Item: {\n id: {\n S: 'MyEntry',\n },\n },\n },\n ResultPath: null,\n};\n\n// custom state which represents a task to insert data into DynamoDB\nconst custom = new sfn.CustomState(this, 'my custom task', {\n stateJson,\n});\n\nconst chain = sfn.Chain.start(custom)\n .next(finalStatus);\n\nconst sm = new sfn.StateMachine(this, 'StateMachine', {\n definition: chain,\n timeout: Duration.seconds(30),\n});\n\n// don't forget permissions. You need to assign them\ntable.grantWriteData(sm);\n```\n\n## Task Chaining\n\nTo make defining work flows as convenient (and readable in a top-to-bottom way)\nas writing regular programs, it is possible to chain most methods invocations.\nIn particular, the `.next()` method can be repeated. The result of a series of\n`.next()` calls is called a **Chain**, and can be used when defining the jump\ntargets of `Choice.on` or `Parallel.branch`:\n\n```ts\nconst step1 = new sfn.Pass(this, 'Step1');\nconst step2 = new sfn.Pass(this, 'Step2');\nconst step3 = new sfn.Pass(this, 'Step3');\nconst step4 = new sfn.Pass(this, 'Step4');\nconst step5 = new sfn.Pass(this, 'Step5');\nconst step6 = new sfn.Pass(this, 'Step6');\nconst step7 = new sfn.Pass(this, 'Step7');\nconst step8 = new sfn.Pass(this, 'Step8');\nconst step9 = new sfn.Pass(this, 'Step9');\nconst step10 = new sfn.Pass(this, 'Step10');\nconst choice = new sfn.Choice(this, 'Choice');\nconst condition1 = sfn.Condition.stringEquals('$.status', 'SUCCESS');\nconst parallel = new sfn.Parallel(this, 'Parallel');\nconst finish = new sfn.Pass(this, 'Finish');\n\nconst definition = step1\n .next(step2)\n .next(choice\n .when(condition1, step3.next(step4).next(step5))\n .otherwise(step6)\n .afterwards())\n .next(parallel\n .branch(step7.next(step8))\n .branch(step9.next(step10)))\n .next(finish);\n\nnew sfn.StateMachine(this, 'StateMachine', {\n definition,\n});\n```\n\nIf you don't like the visual look of starting a chain directly off the first\nstep, you can use `Chain.start`:\n\n```ts\nconst step1 = new sfn.Pass(this, 'Step1');\nconst step2 = new sfn.Pass(this, 'Step2');\nconst step3 = new sfn.Pass(this, 'Step3');\n\nconst definition = sfn.Chain\n .start(step1)\n .next(step2)\n .next(step3)\n // ...\n```\n\n## State Machine Fragments\n\nIt is possible to define reusable (or abstracted) mini-state machines by\ndefining a construct that implements `IChainable`, which requires you to define\ntwo fields:\n\n* `startState: State`, representing the entry point into this state machine.\n* `endStates: INextable[]`, representing the (one or more) states that outgoing\n transitions will be added to if you chain onto the fragment.\n\nSince states will be named after their construct IDs, you may need to prefix the\nIDs of states if you plan to instantiate the same state machine fragment\nmultiples times (otherwise all states in every instantiation would have the same\nname).\n\nThe class `StateMachineFragment` contains some helper functions (like\n`prefixStates()`) to make it easier for you to do this. If you define your state\nmachine as a subclass of this, it will be convenient to use:\n\n```ts nofixture\nimport { Construct, Stack } from 'aws-cdk-lib';\nimport { aws_stepfunctions as sfn } from 'aws-cdk-lib';\nimport { aws_stepfunctions_tasks as tasks } from 'aws-cdk-lib';\n\ninterface MyJobProps {\n jobFlavor: string;\n}\n\nclass MyJob extends sfn.StateMachineFragment {\n public readonly startState: sfn.State;\n public readonly endStates: sfn.INextable[];\n\n constructor(parent: Construct, id: string, props: MyJobProps) {\n super(parent, id);\n\n const choice = new sfn.Choice(this, 'Choice')\n .when(sfn.Condition.stringEquals('$.branch', 'left'), new sfn.Pass(this, 'Left Branch'))\n .when(sfn.Condition.stringEquals('$.branch', 'right'), new sfn.Pass(this, 'Right Branch'));\n\n // ...\n\n this.startState = choice;\n this.endStates = choice.afterwards().endStates;\n }\n}\n\nclass MyStack extends Stack {\n constructor(scope: Construct, id: string) {\n super(scope, id);\n // Do 3 different variants of MyJob in parallel\n new sfn.Parallel(this, 'All jobs')\n .branch(new MyJob(this, 'Quick', { jobFlavor: 'quick' }).prefixStates())\n .branch(new MyJob(this, 'Medium', { jobFlavor: 'medium' }).prefixStates())\n .branch(new MyJob(this, 'Slow', { jobFlavor: 'slow' }).prefixStates());\n }\n}\n```\n\nA few utility functions are available to parse state machine fragments.\n\n* `State.findReachableStates`: Retrieve the list of states reachable from a given state.\n* `State.findReachableEndStates`: Retrieve the list of end or terminal states reachable from a given state.\n\n## Activity\n\n**Activities** represent work that is done on some non-Lambda worker pool. The\nStep Functions workflow will submit work to this Activity, and a worker pool\nthat you run yourself, probably on EC2, will pull jobs from the Activity and\nsubmit the results of individual jobs back.\n\nYou need the ARN to do so, so if you use Activities be sure to pass the Activity\nARN into your worker pool:\n\n```ts\nconst activity = new sfn.Activity(this, 'Activity');\n\n// Read this CloudFormation Output from your application and use it to poll for work on\n// the activity.\nnew CfnOutput(this, 'ActivityArn', { value: activity.activityArn });\n```\n\n### Activity-Level Permissions\n\nGranting IAM permissions to an activity can be achieved by calling the `grant(principal, actions)` API:\n\n```ts\nconst activity = new sfn.Activity(this, 'Activity');\n\nconst role = new iam.Role(this, 'Role', {\n assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),\n});\n\nactivity.grant(role, 'states:SendTaskSuccess');\n```\n\nThis will grant the IAM principal the specified actions onto the activity.\n\n## Metrics\n\n`Task` object expose various metrics on the execution of that particular task. For example,\nto create an alarm on a particular task failing:\n\n```ts\ndeclare const task: sfn.Task;\nnew cloudwatch.Alarm(this, 'TaskAlarm', {\n metric: task.metricFailed(),\n threshold: 1,\n evaluationPeriods: 1,\n});\n```\n\nThere are also metrics on the complete state machine:\n\n```ts\ndeclare const stateMachine: sfn.StateMachine;\nnew cloudwatch.Alarm(this, 'StateMachineAlarm', {\n metric: stateMachine.metricFailed(),\n threshold: 1,\n evaluationPeriods: 1,\n});\n```\n\nAnd there are metrics on the capacity of all state machines in your account:\n\n```ts\nnew cloudwatch.Alarm(this, 'ThrottledAlarm', {\n metric: sfn.StateTransitionMetric.metricThrottledEvents(),\n threshold: 10,\n evaluationPeriods: 2,\n});\n```\n\n## Error names\n\nStep Functions identifies errors in the Amazon States Language using case-sensitive strings, known as error names. \nThe Amazon States Language defines a set of built-in strings that name well-known errors, all beginning with the `States.` prefix. \n\n* `States.ALL` - A wildcard that matches any known error name.\n* `States.Runtime` - An execution failed due to some exception that could not be processed. Often these are caused by errors at runtime, such as attempting to apply InputPath or OutputPath on a null JSON payload. A `States.Runtime` error is not retriable, and will always cause the execution to fail. A retry or catch on `States.ALL` will NOT catch States.Runtime errors.\n* `States.DataLimitExceeded` - A States.DataLimitExceeded exception will be thrown for the following:\n * When the output of a connector is larger than payload size quota.\n * When the output of a state is larger than payload size quota.\n * When, after Parameters processing, the input of a state is larger than the payload size quota.\n * See [the AWS documentation](https://docs.aws.amazon.com/step-functions/latest/dg/limits-overview.html) to learn more about AWS Step Functions Quotas.\n* `States.HeartbeatTimeout` - A Task state failed to send a heartbeat for a period longer than the HeartbeatSeconds value.\n* `States.Timeout` - A Task state either ran longer than the TimeoutSeconds value, or failed to send a heartbeat for a period longer than the HeartbeatSeconds value.\n* `States.TaskFailed`- A Task state failed during the execution. When used in a retry or catch, `States.TaskFailed` acts as a wildcard that matches any known error name except for `States.Timeout`.\n\n## Logging\n\nEnable logging to CloudWatch by passing a logging configuration with a\ndestination LogGroup:\n\n```ts\nimport { aws_logs as logs } from 'aws-cdk-lib';\n\nconst logGroup = new logs.LogGroup(this, 'MyLogGroup');\n\nnew sfn.StateMachine(this, 'MyStateMachine', {\n definition: sfn.Chain.start(new sfn.Pass(this, 'Pass')),\n logs: {\n destination: logGroup,\n level: sfn.LogLevel.ALL,\n },\n});\n```\n\n## X-Ray tracing\n\nEnable X-Ray tracing for StateMachine:\n\n```ts\nnew sfn.StateMachine(this, 'MyStateMachine', {\n definition: sfn.Chain.start(new sfn.Pass(this, 'Pass')),\n tracingEnabled: true,\n});\n```\n\nSee [the AWS documentation](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-xray-tracing.html)\nto learn more about AWS Step Functions's X-Ray support.\n\n## State Machine Permission Grants\n\nIAM roles, users, or groups which need to be able to work with a State Machine should be granted IAM permissions.\n\nAny object that implements the `IGrantable` interface (has an associated principal) can be granted permissions by calling:\n\n* `stateMachine.grantStartExecution(principal)` - grants the principal the ability to execute the state machine\n* `stateMachine.grantRead(principal)` - grants the principal read access\n* `stateMachine.grantTaskResponse(principal)` - grants the principal the ability to send task tokens to the state machine\n* `stateMachine.grantExecution(principal, actions)` - grants the principal execution-level permissions for the IAM actions specified\n* `stateMachine.grant(principal, actions)` - grants the principal state-machine-level permissions for the IAM actions specified\n\n### Start Execution Permission\n\nGrant permission to start an execution of a state machine by calling the `grantStartExecution()` API.\n\n```ts\nconst role = new iam.Role(this, 'Role', {\n assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),\n});\n\ndeclare const definition: sfn.IChainable;\nconst stateMachine = new sfn.StateMachine(this, 'StateMachine', {\n definition,\n});\n\n// Give role permission to start execution of state machine\nstateMachine.grantStartExecution(role);\n```\n\nThe following permission is provided to a service principal by the `grantStartExecution()` API:\n\n* `states:StartExecution` - to state machine\n\n### Read Permissions\n\nGrant `read` access to a state machine by calling the `grantRead()` API.\n\n```ts\nconst role = new iam.Role(this, 'Role', {\n assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),\n});\n\ndeclare const definition: sfn.IChainable;\nconst stateMachine = new sfn.StateMachine(this, 'StateMachine', {\n definition,\n});\n\n// Give role read access to state machine\nstateMachine.grantRead(role);\n```\n\nThe following read permissions are provided to a service principal by the `grantRead()` API:\n\n* `states:ListExecutions` - to state machine\n* `states:ListStateMachines` - to state machine\n* `states:DescribeExecution` - to executions\n* `states:DescribeStateMachineForExecution` - to executions\n* `states:GetExecutionHistory` - to executions\n* `states:ListActivities` - to `*`\n* `states:DescribeStateMachine` - to `*`\n* `states:DescribeActivity` - to `*`\n\n### Task Response Permissions\n\nGrant permission to allow task responses to a state machine by calling the `grantTaskResponse()` API:\n\n```ts\nconst role = new iam.Role(this, 'Role', {\n assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),\n});\n\ndeclare const definition: sfn.IChainable;\nconst stateMachine = new sfn.StateMachine(this, 'StateMachine', {\n definition,\n});\n\n// Give role task response permissions to the state machine\nstateMachine.grantTaskResponse(role);\n```\n\nThe following read permissions are provided to a service principal by the `grantRead()` API:\n\n* `states:SendTaskSuccess` - to state machine\n* `states:SendTaskFailure` - to state machine\n* `states:SendTaskHeartbeat` - to state machine\n\n### Execution-level Permissions\n\nGrant execution-level permissions to a state machine by calling the `grantExecution()` API:\n\n```ts\nconst role = new iam.Role(this, 'Role', {\n assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),\n});\n\ndeclare const definition: sfn.IChainable;\nconst stateMachine = new sfn.StateMachine(this, 'StateMachine', {\n definition,\n});\n\n// Give role permission to get execution history of ALL executions for the state machine\nstateMachine.grantExecution(role, 'states:GetExecutionHistory');\n```\n\n### Custom Permissions\n\nYou can add any set of permissions to a state machine by calling the `grant()` API.\n\n```ts\nconst user = new iam.User(this, 'MyUser');\n\ndeclare const definition: sfn.IChainable;\nconst stateMachine = new sfn.StateMachine(this, 'StateMachine', {\n definition,\n});\n\n//give user permission to send task success to the state machine\nstateMachine.grant(user, 'states:SendTaskSuccess');\n```\n\n## Import\n\nAny Step Functions state machine that has been created outside the stack can be imported\ninto your CDK stack.\n\nState machines can be imported by their ARN via the `StateMachine.fromStateMachineArn()` API\n\n```ts\nconst app = new App();\nconst stack = new Stack(app, 'MyStack');\nsfn.StateMachine.fromStateMachineArn(\n stack,\n 'ImportedStateMachine',\n 'arn:aws:states:us-east-1:123456789012:stateMachine:StateMachine2E01A3A5-N5TJppzoevKQ',\n);\n```\n"
3730
3730
  },
3731
3731
  "targets": {
3732
3732
  "dotnet": {
@@ -3746,7 +3746,7 @@
3746
3746
  "line": 187
3747
3747
  },
3748
3748
  "readme": {
3749
- "markdown": "# Tasks for AWS Step Functions\n\n\n[AWS Step Functions](https://docs.aws.amazon.com/step-functions/latest/dg/welcome.html) is a web service that enables you to coordinate the\ncomponents of distributed applications and microservices using visual workflows.\nYou build applications from individual components that each perform a discrete\nfunction, or task, allowing you to scale and change applications quickly.\n\nA [Task](https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-task-state.html) state represents a single unit of work performed by a state machine.\nAll work in your state machine is performed by tasks.\n\nThis module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project.\n\n## Table Of Contents\n\n- [Tasks for AWS Step Functions](#tasks-for-aws-step-functions)\n - [Table Of Contents](#table-of-contents)\n - [Task](#task)\n - [Paths](#paths)\n - [InputPath](#inputpath)\n - [OutputPath](#outputpath)\n - [ResultPath](#resultpath)\n - [Task parameters from the state JSON](#task-parameters-from-the-state-json)\n - [Evaluate Expression](#evaluate-expression)\n - [API Gateway](#api-gateway)\n - [Call REST API Endpoint](#call-rest-api-endpoint)\n - [Call HTTP API Endpoint](#call-http-api-endpoint)\n - [AWS SDK](#aws-sdk)\n - [Athena](#athena)\n - [StartQueryExecution](#startqueryexecution)\n - [GetQueryExecution](#getqueryexecution)\n - [GetQueryResults](#getqueryresults)\n - [StopQueryExecution](#stopqueryexecution)\n - [Batch](#batch)\n - [SubmitJob](#submitjob)\n - [CodeBuild](#codebuild)\n - [StartBuild](#startbuild)\n - [DynamoDB](#dynamodb)\n - [GetItem](#getitem)\n - [PutItem](#putitem)\n - [DeleteItem](#deleteitem)\n - [UpdateItem](#updateitem)\n - [ECS](#ecs)\n - [RunTask](#runtask)\n - [EC2](#ec2)\n - [Fargate](#fargate)\n - [EMR](#emr)\n - [Create Cluster](#create-cluster)\n - [Termination Protection](#termination-protection)\n - [Terminate Cluster](#terminate-cluster)\n - [Add Step](#add-step)\n - [Cancel Step](#cancel-step)\n - [Modify Instance Fleet](#modify-instance-fleet)\n - [Modify Instance Group](#modify-instance-group)\n - [EKS](#eks)\n - [Call](#call)\n - [EventBridge](#eventbridge)\n - [Put Events](#put-events)\n - [Glue](#glue)\n - [Glue DataBrew](#glue-databrew)\n - [Lambda](#lambda)\n - [SageMaker](#sagemaker)\n - [Create Training Job](#create-training-job)\n - [Create Transform Job](#create-transform-job)\n - [Create Endpoint](#create-endpoint)\n - [Create Endpoint Config](#create-endpoint-config)\n - [Create Model](#create-model)\n - [Update Endpoint](#update-endpoint)\n - [SNS](#sns)\n - [Step Functions](#step-functions)\n - [Start Execution](#start-execution)\n - [Invoke Activity](#invoke-activity)\n - [SQS](#sqs)\n\n## Task\n\nA Task state represents a single unit of work performed by a state machine. In the\nCDK, the exact work to be done is determined by a class that implements `IStepFunctionsTask`.\n\nAWS Step Functions [integrates](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-service-integrations.html) with some AWS services so that you can call API\nactions, and coordinate executions directly from the Amazon States Language in\nStep Functions. You can directly call and pass parameters to the APIs of those\nservices.\n\n## Paths\n\nIn the Amazon States Language, a [path](https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-paths.html) is a string beginning with `$` that you\ncan use to identify components within JSON text.\n\nLearn more about input and output processing in Step Functions [here](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-input-output-filtering.html)\n\n### InputPath\n\nBoth `InputPath` and `Parameters` fields provide a way to manipulate JSON as it\nmoves through your workflow. AWS Step Functions applies the `InputPath` field first,\nand then the `Parameters` field. You can first filter your raw input to a selection\nyou want using InputPath, and then apply Parameters to manipulate that input\nfurther, or add new values. If you don't specify an `InputPath`, a default value\nof `$` will be used.\n\nThe following example provides the field named `input` as the input to the `Task`\nstate that runs a Lambda function.\n\n```ts\nconst submitJob = new tasks.LambdaInvoke(this, 'Invoke Handler', {\n lambdaFunction: fn,\n inputPath: '$.input'\n});\n```\n\n### OutputPath\n\nTasks also allow you to select a portion of the state output to pass to the next\nstate. This enables you to filter out unwanted information, and pass only the\nportion of the JSON that you care about. If you don't specify an `OutputPath`,\na default value of `$` will be used. This passes the entire JSON node to the next\nstate.\n\nThe [response](https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html#API_Invoke_ResponseSyntax) from a Lambda function includes the response from the function\nas well as other metadata.\n\nThe following example assigns the output from the Task to a field named `result`\n\n```ts\nconst submitJob = new tasks.LambdaInvoke(this, 'Invoke Handler', {\n lambdaFunction: fn,\n outputPath: '$.Payload.result'\n});\n```\n\n### ResultSelector\n\nYou can use [`ResultSelector`](https://docs.aws.amazon.com/step-functions/latest/dg/input-output-inputpath-params.html#input-output-resultselector)\nto manipulate the raw result of a Task, Map or Parallel state before it is\npassed to [`ResultPath`](###ResultPath). For service integrations, the raw\nresult contains metadata in addition to the response payload. You can use\nResultSelector to construct a JSON payload that becomes the effective result\nusing static values or references to the raw result or context object.\n\nThe following example extracts the output payload of a Lambda function Task and combines\nit with some static values and the state name from the context object.\n\n```ts\nnew tasks.LambdaInvoke(this, 'Invoke Handler', {\n lambdaFunction: fn,\n resultSelector: {\n lambdaOutput: sfn.JsonPath.stringAt('$.Payload'),\n invokeRequestId: sfn.JsonPath.stringAt('$.SdkResponseMetadata.RequestId'),\n staticValue: {\n foo: 'bar',\n },\n stateName: sfn.JsonPath.stringAt('$$.State.Name'),\n },\n})\n```\n\n### ResultPath\n\nThe output of a state can be a copy of its input, the result it produces (for\nexample, output from a Task state’s Lambda function), or a combination of its\ninput and result. Use [`ResultPath`](https://docs.aws.amazon.com/step-functions/latest/dg/input-output-resultpath.html) to control which combination of these is\npassed to the state output. If you don't specify an `ResultPath`, a default\nvalue of `$` will be used.\n\nThe following example adds the item from calling DynamoDB's `getItem` API to the state\ninput and passes it to the next state.\n\n```ts\nnew tasks.DynamoPutItem(this, 'PutItem', {\n item: {\n MessageId: tasks.DynamoAttributeValue.fromString('message-id')\n },\n table: myTable,\n resultPath: `$.Item`,\n});\n```\n\n⚠️ The `OutputPath` is computed after applying `ResultPath`. All service integrations\nreturn metadata as part of their response. When using `ResultPath`, it's not possible to\nmerge a subset of the task output to the input.\n\n## Task parameters from the state JSON\n\nMost tasks take parameters. Parameter values can either be static, supplied directly\nin the workflow definition (by specifying their values), or a value available at runtime\nin the state machine's execution (either as its input or an output of a prior state).\nParameter values available at runtime can be specified via the `JsonPath` class,\nusing methods such as `JsonPath.stringAt()`.\n\nThe following example provides the field named `input` as the input to the Lambda function\nand invokes it asynchronously.\n\n```ts\nconst submitJob = new tasks.LambdaInvoke(this, 'Invoke Handler', {\n lambdaFunction: fn,\n payload: sfn.TaskInput.fromJsonPathAt('$.input'),\n invocationType: tasks.LambdaInvocationType.EVENT,\n});\n```\n\nYou can also use [intrinsic functions](https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-intrinsic-functions.html) with `JsonPath.stringAt()`.\nHere is an example of starting an Athena query that is dynamically created using the task input:\n\n```ts\nconst startQueryExecutionJob = new tasks.AthenaStartQueryExecution(this, 'Athena Start Query', {\n queryString: sfn.JsonPath.stringAt(\"States.Format('select contacts where year={};', $.year)\"),\n queryExecutionContext: {\n databaseName: 'interactions',\n },\n resultConfiguration: {\n encryptionConfiguration: {\n encryptionOption: tasks.EncryptionOption.S3_MANAGED,\n },\n outputLocation: {\n bucketName: 'mybucket',\n objectKey: 'myprefix',\n },\n },\n integrationPattern: sfn.IntegrationPattern.RUN_JOB,\n});\n```\n\nEach service integration has its own set of parameters that can be supplied.\n\n## Evaluate Expression\n\nUse the `EvaluateExpression` to perform simple operations referencing state paths. The\n`expression` referenced in the task will be evaluated in a Lambda function\n(`eval()`). This allows you to not have to write Lambda code for simple operations.\n\nExample: convert a wait time from milliseconds to seconds, concat this in a message and wait:\n\n```ts\nconst convertToSeconds = new tasks.EvaluateExpression(this, 'Convert to seconds', {\n expression: '$.waitMilliseconds / 1000',\n resultPath: '$.waitSeconds',\n});\n\nconst createMessage = new tasks.EvaluateExpression(this, 'Create message', {\n // Note: this is a string inside a string.\n expression: '`Now waiting ${$.waitSeconds} seconds...`',\n runtime: lambda.Runtime.NODEJS_14_X,\n resultPath: '$.message',\n});\n\nconst publishMessage = new tasks.SnsPublish(this, 'Publish message', {\n topic: new sns.Topic(this, 'cool-topic'),\n message: sfn.TaskInput.fromJsonPathAt('$.message'),\n resultPath: '$.sns',\n});\n\nconst wait = new sfn.Wait(this, 'Wait', {\n time: sfn.WaitTime.secondsPath('$.waitSeconds')\n});\n\nnew sfn.StateMachine(this, 'StateMachine', {\n definition: convertToSeconds\n .next(createMessage)\n .next(publishMessage)\n .next(wait)\n});\n```\n\nThe `EvaluateExpression` supports a `runtime` prop to specify the Lambda\nruntime to use to evaluate the expression. Currently, only runtimes\nof the Node.js family are supported.\n\n## API Gateway\n\nStep Functions supports [API Gateway](https://docs.aws.amazon.com/step-functions/latest/dg/connect-api-gateway.html) through the service integration pattern.\n\nHTTP APIs are designed for low-latency, cost-effective integrations with AWS services, including AWS Lambda, and HTTP endpoints.\nHTTP APIs support OIDC and OAuth 2.0 authorization, and come with built-in support for CORS and automatic deployments.\nPrevious-generation REST APIs currently offer more features. More details can be found [here](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-vs-rest.html).\n\n### Call REST API Endpoint\n\nThe `CallApiGatewayRestApiEndpoint` calls the REST API endpoint.\n\n```ts\nimport { aws_stepfunctions as sfn } from 'aws-cdk-lib';\nimport * as tasks from `@aws-cdk/aws-stepfunctions-tasks`;\n\nconst restApi = new apigateway.RestApi(stack, 'MyRestApi');\n\nconst invokeTask = new tasks.CallApiGatewayRestApiEndpoint(stack, 'Call REST API', {\n api: restApi,\n stageName: 'prod',\n method: HttpMethod.GET,\n});\n```\n\n### Call HTTP API Endpoint\n\nThe `CallApiGatewayHttpApiEndpoint` calls the HTTP API endpoint.\n\n```ts\nimport { aws_stepfunctions as sfn } from 'aws-cdk-lib';\nimport * as tasks from `@aws-cdk/aws-stepfunctions-tasks`;\n\nconst httpApi = new apigatewayv2.HttpApi(stack, 'MyHttpApi');\n\nconst invokeTask = new tasks.CallApiGatewayHttpApiEndpoint(stack, 'Call HTTP API', {\n apiId: httpApi.apiId,\n apiStack: cdk.Stack.of(httpApi),\n method: HttpMethod.GET,\n});\n```\n\n### AWS SDK\n\nStep Functions supports calling [AWS service's API actions](https://docs.aws.amazon.com/step-functions/latest/dg/supported-services-awssdk.html)\nthrough the service integration pattern.\n\nYou can use Step Functions' AWS SDK integrations to call any of the over two hundred AWS services\ndirectly from your state machine, giving you access to over nine thousand API actions.\n\n```ts\nconst getObject = new tasks.CallAwsService(this, 'GetObject', {\n service: 's3',\n action: 'getObject',\n parameters: {\n Bucket: myBucket.bucketName,\n Key: sfn.JsonPath.stringAt('$.key')\n },\n iamResources: [myBucket.arnForObjects('*')],\n});\n```\n\nUse camelCase for actions and PascalCase for parameter names.\n\nThe task automatically adds an IAM statement to the state machine role's policy based on the\nservice and action called. The resources for this statement must be specified in `iamResources`.\n\nUse the `iamAction` prop to manually specify the IAM action name in the case where the IAM\naction name does not match with the API service/action name:\n\n```ts\nconst listBuckets = new tasks.CallAwsService(this, 'ListBuckets', {\n service: 's3',\n action: 'ListBuckets',\n iamResources: ['*'],\n iamAction: 's3:ListAllMyBuckets'\n});\n```\n\n## Athena\n\nStep Functions supports [Athena](https://docs.aws.amazon.com/step-functions/latest/dg/connect-athena.html) through the service integration pattern.\n\n### StartQueryExecution\n\nThe [StartQueryExecution](https://docs.aws.amazon.com/athena/latest/APIReference/API_StartQueryExecution.html) API runs the SQL query statement.\n\n```ts\nconst startQueryExecutionJob = new tasks.AthenaStartQueryExecution(this, 'Start Athena Query', {\n queryString: sfn.JsonPath.stringAt('$.queryString'),\n queryExecutionContext: {\n databaseName: 'mydatabase',\n },\n resultConfiguration: {\n encryptionConfiguration: {\n encryptionOption: tasks.EncryptionOption.S3_MANAGED,\n },\n outputLocation: {\n bucketName: 'query-results-bucket',\n objectKey: 'folder',\n },\n },\n});\n```\n\n### GetQueryExecution\n\nThe [GetQueryExecution](https://docs.aws.amazon.com/athena/latest/APIReference/API_GetQueryExecution.html) API gets information about a single execution of a query.\n\n```ts\nconst getQueryExecutionJob = new tasks.AthenaGetQueryExecution(this, 'Get Query Execution', {\n queryExecutionId: sfn.JsonPath.stringAt('$.QueryExecutionId'),\n});\n```\n\n### GetQueryResults\n\nThe [GetQueryResults](https://docs.aws.amazon.com/athena/latest/APIReference/API_GetQueryResults.html) API that streams the results of a single query execution specified by QueryExecutionId from S3.\n\n```ts\nconst getQueryResultsJob = new tasks.AthenaGetQueryResults(this, 'Get Query Results', {\n queryExecutionId: sfn.JsonPath.stringAt('$.QueryExecutionId'),\n});\n```\n\n### StopQueryExecution\n\nThe [StopQueryExecution](https://docs.aws.amazon.com/athena/latest/APIReference/API_StopQueryExecution.html) API that stops a query execution.\n\n```ts\nconst stopQueryExecutionJob = new tasks.AthenaStopQueryExecution(this, 'Stop Query Execution', {\n queryExecutionId: sfn.JsonPath.stringAt('$.QueryExecutionId'),\n});\n```\n\n## Batch\n\nStep Functions supports [Batch](https://docs.aws.amazon.com/step-functions/latest/dg/connect-batch.html) through the service integration pattern.\n\n### SubmitJob\n\nThe [SubmitJob](https://docs.aws.amazon.com/batch/latest/APIReference/API_SubmitJob.html) API submits an AWS Batch job from a job definition.\n\n```ts fixture=with-batch-job\nconst task = new tasks.BatchSubmitJob(this, 'Submit Job', {\n jobDefinitionArn: batchJobDefinitionArn,\n jobName: 'MyJob',\n jobQueueArn: batchQueueArn,\n});\n```\n\n## CodeBuild\n\nStep Functions supports [CodeBuild](https://docs.aws.amazon.com/step-functions/latest/dg/connect-codebuild.html) through the service integration pattern.\n\n### StartBuild\n\n[StartBuild](https://docs.aws.amazon.com/codebuild/latest/APIReference/API_StartBuild.html) starts a CodeBuild Project by Project Name.\n\n```ts\nimport { aws_codebuild as codebuild } from 'aws-cdk-lib';\n\nconst codebuildProject = new codebuild.Project(this, 'Project', {\n projectName: 'MyTestProject',\n buildSpec: codebuild.BuildSpec.fromObject({\n version: '0.2',\n phases: {\n build: {\n commands: [\n 'echo \"Hello, CodeBuild!\"',\n ],\n },\n },\n }),\n});\n\nconst task = new tasks.CodeBuildStartBuild(this, 'Task', {\n project: codebuildProject,\n integrationPattern: sfn.IntegrationPattern.RUN_JOB,\n environmentVariablesOverride: {\n ZONE: {\n type: codebuild.BuildEnvironmentVariableType.PLAINTEXT,\n value: sfn.JsonPath.stringAt('$.envVariables.zone'),\n },\n },\n});\n```\n\n## DynamoDB\n\nYou can call DynamoDB APIs from a `Task` state.\nRead more about calling DynamoDB APIs [here](https://docs.aws.amazon.com/step-functions/latest/dg/connect-ddb.html)\n\n### GetItem\n\nThe [GetItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_GetItem.html) operation returns a set of attributes for the item with the given primary key.\n\n```ts\nnew tasks.DynamoGetItem(this, 'Get Item', {\n key: { messageId: tasks.DynamoAttributeValue.fromString('message-007') },\n table: myTable,\n});\n```\n\n### PutItem\n\nThe [PutItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html) operation creates a new item, or replaces an old item with a new item.\n\n```ts\nnew tasks.DynamoPutItem(this, 'PutItem', {\n item: {\n MessageId: tasks.DynamoAttributeValue.fromString('message-007'),\n Text: tasks.DynamoAttributeValue.fromString(sfn.JsonPath.stringAt('$.bar')),\n TotalCount: tasks.DynamoAttributeValue.fromNumber(10),\n },\n table: myTable,\n});\n```\n\n### DeleteItem\n\nThe [DeleteItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DeleteItem.html) operation deletes a single item in a table by primary key.\n\n```ts\nnew tasks.DynamoDeleteItem(this, 'DeleteItem', {\n key: { MessageId: tasks.DynamoAttributeValue.fromString('message-007') },\n table: myTable,\n resultPath: sfn.JsonPath.DISCARD,\n});\n```\n\n### UpdateItem\n\nThe [UpdateItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateItem.html) operation edits an existing item's attributes, or adds a new item\nto the table if it does not already exist.\n\n```ts\nnew tasks.DynamoUpdateItem(this, 'UpdateItem', {\n key: {\n MessageId: tasks.DynamoAttributeValue.fromString('message-007')\n },\n table: myTable,\n expressionAttributeValues: {\n ':val': tasks.DynamoAttributeValue.numberFromString(sfn.JsonPath.stringAt('$.Item.TotalCount.N')),\n ':rand': tasks.DynamoAttributeValue.fromNumber(20),\n },\n updateExpression: 'SET TotalCount = :val + :rand',\n});\n```\n\n## ECS\n\nStep Functions supports [ECS/Fargate](https://docs.aws.amazon.com/step-functions/latest/dg/connect-ecs.html) through the service integration pattern.\n\n### RunTask\n\n[RunTask](https://docs.aws.amazon.com/step-functions/latest/dg/connect-ecs.html) starts a new task using the specified task definition.\n\n#### EC2\n\nThe EC2 launch type allows you to run your containerized applications on a cluster\nof Amazon EC2 instances that you manage.\n\nWhen a task that uses the EC2 launch type is launched, Amazon ECS must determine where\nto place the task based on the requirements specified in the task definition, such as\nCPU and memory. Similarly, when you scale down the task count, Amazon ECS must determine\nwhich tasks to terminate. You can apply task placement strategies and constraints to\ncustomize how Amazon ECS places and terminates tasks. Learn more about [task placement](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-placement.html)\n\nThe latest ACTIVE revision of the passed task definition is used for running the task.\n\nThe following example runs a job from a task definition on EC2\n\n```ts\nimport { aws_ecs as ecs } from 'aws-cdk-lib';\n\nconst vpc = ec2.Vpc.fromLookup(this, 'Vpc', {\n isDefault: true,\n});\n\nconst cluster = new ecs.Cluster(this, 'Ec2Cluster', { vpc });\ncluster.addCapacity('DefaultAutoScalingGroup', {\n instanceType: new ec2.InstanceType('t2.micro'),\n vpcSubnets: { subnetType: ec2.SubnetType.PUBLIC },\n});\n\nconst taskDefinition = new ecs.TaskDefinition(this, 'TD', {\n compatibility: ecs.Compatibility.EC2,\n});\n\ntaskDefinition.addContainer('TheContainer', {\n image: ecs.ContainerImage.fromRegistry('foo/bar'),\n memoryLimitMiB: 256,\n});\n\nconst runTask = new tasks.EcsRunTask(this, 'Run', {\n integrationPattern: sfn.IntegrationPattern.RUN_JOB,\n cluster,\n taskDefinition,\n launchTarget: new tasks.EcsEc2LaunchTarget({\n placementStrategies: [\n ecs.PlacementStrategy.spreadAcrossInstances(),\n ecs.PlacementStrategy.packedByCpu(),\n ecs.PlacementStrategy.randomly(),\n ],\n placementConstraints: [\n ecs.PlacementConstraint.memberOf('blieptuut')\n ],\n }),\n});\n```\n\n#### Fargate\n\nAWS Fargate is a serverless compute engine for containers that works with Amazon\nElastic Container Service (ECS). Fargate makes it easy for you to focus on building\nyour applications. Fargate removes the need to provision and manage servers, lets you\nspecify and pay for resources per application, and improves security through application\nisolation by design. Learn more about [Fargate](https://aws.amazon.com/fargate/)\n\nThe Fargate launch type allows you to run your containerized applications without the need\nto provision and manage the backend infrastructure. Just register your task definition and\nFargate launches the container for you. The latest ACTIVE revision of the passed\ntask definition is used for running the task. Learn more about\n[Fargate Versioning](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_DescribeTaskDefinition.html)\n\nThe following example runs a job from a task definition on Fargate\n\n```ts\nimport { aws_ecs as ecs } from 'aws-cdk-lib';\n\nconst vpc = ec2.Vpc.fromLookup(this, 'Vpc', {\n isDefault: true,\n});\n\nconst cluster = new ecs.Cluster(this, 'FargateCluster', { vpc });\n\nconst taskDefinition = new ecs.TaskDefinition(this, 'TD', {\n memoryMiB: '512',\n cpu: '256',\n compatibility: ecs.Compatibility.FARGATE,\n});\n\nconst containerDefinition = taskDefinition.addContainer('TheContainer', {\n image: ecs.ContainerImage.fromRegistry('foo/bar'),\n memoryLimitMiB: 256,\n});\n\nconst runTask = new tasks.EcsRunTask(this, 'RunFargate', {\n integrationPattern: sfn.IntegrationPattern.RUN_JOB,\n cluster,\n taskDefinition,\n assignPublicIp: true,\n containerOverrides: [{\n containerDefinition,\n environment: [{ name: 'SOME_KEY', value: sfn.JsonPath.stringAt('$.SomeKey') }],\n }],\n launchTarget: new tasks.EcsFargateLaunchTarget(),\n});\n```\n\n## EMR\n\nStep Functions supports Amazon EMR through the service integration pattern.\nThe service integration APIs correspond to Amazon EMR APIs but differ in the\nparameters that are used.\n\n[Read more](https://docs.aws.amazon.com/step-functions/latest/dg/connect-emr.html) about the differences when using these service integrations.\n\n### Create Cluster\n\nCreates and starts running a cluster (job flow).\nCorresponds to the [`runJobFlow`](https://docs.aws.amazon.com/emr/latest/APIReference/API_RunJobFlow.html) API in EMR.\n\n```ts\n\nconst clusterRole = new iam.Role(this, 'ClusterRole', {\n assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'),\n});\n\nconst serviceRole = new iam.Role(this, 'ServiceRole', {\n assumedBy: new iam.ServicePrincipal('elasticmapreduce.amazonaws.com'),\n});\n\nconst autoScalingRole = new iam.Role(this, 'AutoScalingRole', {\n assumedBy: new iam.ServicePrincipal('elasticmapreduce.amazonaws.com'),\n});\n\nautoScalingRole.assumeRolePolicy?.addStatements(\n new iam.PolicyStatement({\n effect: iam.Effect.ALLOW,\n principals: [\n new iam.ServicePrincipal('application-autoscaling.amazonaws.com'),\n ],\n actions: [\n 'sts:AssumeRole',\n ],\n }));\n)\n\nnew tasks.EmrCreateCluster(this, 'Create Cluster', {\n instances: {},\n clusterRole,\n name: sfn.TaskInput.fromJsonPathAt('$.ClusterName').value,\n serviceRole,\n autoScalingRole,\n});\n```\n\nIf you want to run multiple steps in [parallel](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-concurrent-steps.html),\nyou can specify the `stepConcurrencyLevel` property. The concurrency range is between 1\nand 256 inclusive, where the default concurrency of 1 means no step concurrency is allowed.\n`stepConcurrencyLevel` requires the EMR release label to be 5.28.0 or above.\n\n```ts\nnew tasks.EmrCreateCluster(this, 'Create Cluster', {\n // ...\n stepConcurrencyLevel: 10,\n});\n```\n\n### Termination Protection\n\nLocks a cluster (job flow) so the EC2 instances in the cluster cannot be\nterminated by user intervention, an API call, or a job-flow error.\n\nCorresponds to the [`setTerminationProtection`](https://docs.aws.amazon.com/step-functions/latest/dg/connect-emr.html) API in EMR.\n\n```ts\nnew tasks.EmrSetClusterTerminationProtection(this, 'Task', {\n clusterId: 'ClusterId',\n terminationProtected: false,\n});\n```\n\n### Terminate Cluster\n\nShuts down a cluster (job flow).\nCorresponds to the [`terminateJobFlows`](https://docs.aws.amazon.com/emr/latest/APIReference/API_TerminateJobFlows.html) API in EMR.\n\n```ts\nnew tasks.EmrTerminateCluster(this, 'Task', {\n clusterId: 'ClusterId'\n});\n```\n\n### Add Step\n\nAdds a new step to a running cluster.\nCorresponds to the [`addJobFlowSteps`](https://docs.aws.amazon.com/emr/latest/APIReference/API_AddJobFlowSteps.html) API in EMR.\n\n```ts\nnew tasks.EmrAddStep(this, 'Task', {\n clusterId: 'ClusterId',\n name: 'StepName',\n jar: 'Jar',\n actionOnFailure: tasks.ActionOnFailure.CONTINUE,\n});\n```\n\n### Cancel Step\n\nCancels a pending step in a running cluster.\nCorresponds to the [`cancelSteps`](https://docs.aws.amazon.com/emr/latest/APIReference/API_CancelSteps.html) API in EMR.\n\n```ts\nnew tasks.EmrCancelStep(this, 'Task', {\n clusterId: 'ClusterId',\n stepId: 'StepId',\n});\n```\n\n### Modify Instance Fleet\n\nModifies the target On-Demand and target Spot capacities for the instance\nfleet with the specified InstanceFleetName.\n\nCorresponds to the [`modifyInstanceFleet`](https://docs.aws.amazon.com/emr/latest/APIReference/API_ModifyInstanceFleet.html) API in EMR.\n\n```ts\nnew tasks.EmrModifyInstanceFleetByName(this, 'Task', {\n clusterId: 'ClusterId',\n instanceFleetName: 'InstanceFleetName',\n targetOnDemandCapacity: 2,\n targetSpotCapacity: 0,\n});\n```\n\n### Modify Instance Group\n\nModifies the number of nodes and configuration settings of an instance group.\n\nCorresponds to the [`modifyInstanceGroups`](https://docs.aws.amazon.com/emr/latest/APIReference/API_ModifyInstanceGroups.html) API in EMR.\n\n```ts\nnew tasks.EmrModifyInstanceGroupByName(this, 'Task', {\n clusterId: 'ClusterId',\n instanceGroupName: sfn.JsonPath.stringAt('$.InstanceGroupName'),\n instanceGroup: {\n instanceCount: 1,\n },\n});\n```\n\n## EKS\n\nStep Functions supports Amazon EKS through the service integration pattern.\nThe service integration APIs correspond to Amazon EKS APIs.\n\n[Read more](https://docs.aws.amazon.com/step-functions/latest/dg/connect-eks.html) about the differences when using these service integrations.\n\n### Call\n\nRead and write Kubernetes resource objects via a Kubernetes API endpoint.\nCorresponds to the [`call`](https://docs.aws.amazon.com/step-functions/latest/dg/connect-eks.html) API in Step Functions Connector.\n\nThe following code snippet includes a Task state that uses eks:call to list the pods.\n\n```ts\nimport { aws_eks as eks } from 'aws-cdk-lib';\nimport { aws_stepfunctions as sfn } from 'aws-cdk-lib';\nimport { aws_stepfunctions_tasks as tasks } from 'aws-cdk-lib';\n\nconst myEksCluster = new eks.Cluster(this, 'my sample cluster', {\n version: eks.KubernetesVersion.V1_18,\n clusterName: 'myEksCluster',\n});\n\nnew tasks.EksCall(stack, 'Call a EKS Endpoint', {\n cluster: myEksCluster,\n httpMethod: MethodType.GET,\n httpPath: '/api/v1/namespaces/default/pods',\n});\n```\n\n## EventBridge\n\nStep Functions supports Amazon EventBridge through the service integration pattern.\nThe service integration APIs correspond to Amazon EventBridge APIs.\n\n[Read more](https://docs.aws.amazon.com/step-functions/latest/dg/connect-eventbridge.html) about the differences when using these service integrations.\n\n### Put Events\n\nSend events to an EventBridge bus.\nCorresponds to the [`put-events`](https://docs.aws.amazon.com/step-functions/latest/dg/connect-eventbridge.html) API in Step Functions Connector.\n\nThe following code snippet includes a Task state that uses events:putevents to send an event to the default bus.\n\n```ts\nimport { aws_events as events } from 'aws-cdk-lib';\nimport { aws_stepfunctions as sfn } from 'aws-cdk-lib';\nimport { aws_stepfunctions_tasks as tasks } from 'aws-cdk-lib';\n\nconst myEventBus = events.EventBus(stack, 'EventBus', {\n eventBusName: 'MyEventBus1',\n});\n\nnew tasks.EventBridgePutEvents(stack, 'Send an event to EventBridge', {\n entries: [{\n detail: sfn.TaskInput.fromObject({\n Message: 'Hello from Step Functions!',\n }),\n eventBus: myEventBus,\n detailType: 'MessageFromStepFunctions',\n source: 'step.functions',\n }],\n});\n```\n\n## Glue\n\nStep Functions supports [AWS Glue](https://docs.aws.amazon.com/step-functions/latest/dg/connect-glue.html) through the service integration pattern.\n\nYou can call the [`StartJobRun`](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-api-jobs-runs.html#aws-glue-api-jobs-runs-StartJobRun) API from a `Task` state.\n\n```ts\nnew tasks.GlueStartJobRun(this, 'Task', {\n glueJobName: 'my-glue-job',\n arguments: sfn.TaskInput.fromObject({\n key: 'value',\n }),\n timeout: cdk.Duration.minutes(30),\n notifyDelayAfter: cdk.Duration.minutes(5),\n});\n```\n\n## Glue DataBrew\n\nStep Functions supports [AWS Glue DataBrew](https://docs.aws.amazon.com/step-functions/latest/dg/connect-databrew.html) through the service integration pattern.\n\nYou can call the [`StartJobRun`](https://docs.aws.amazon.com/databrew/latest/dg/API_StartJobRun.html) API from a `Task` state.\n\n```ts\nnew tasks.GlueDataBrewStartJobRun(this, 'Task', {\n name: 'databrew-job',\n});\n```\n\n## Lambda\n\n[Invoke](https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html) a Lambda function.\n\nYou can specify the input to your Lambda function through the `payload` attribute.\nBy default, Step Functions invokes Lambda function with the state input (JSON path '$')\nas the input.\n\nThe following snippet invokes a Lambda Function with the state input as the payload\nby referencing the `$` path.\n\n```ts\nnew tasks.LambdaInvoke(this, 'Invoke with state input', {\n lambdaFunction: fn,\n});\n```\n\nWhen a function is invoked, the Lambda service sends [these response\nelements](https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html#API_Invoke_ResponseElements)\nback.\n\n⚠️ The response from the Lambda function is in an attribute called `Payload`\n\nThe following snippet invokes a Lambda Function by referencing the `$.Payload` path\nto reference the output of a Lambda executed before it.\n\n```ts\nnew tasks.LambdaInvoke(this, 'Invoke with empty object as payload', {\n lambdaFunction: fn,\n payload: sfn.TaskInput.fromObject({}),\n});\n\n// use the output of fn as input\nnew tasks.LambdaInvoke(this, 'Invoke with payload field in the state input', {\n lambdaFunction: fn,\n payload: sfn.TaskInput.fromJsonPathAt('$.Payload'),\n});\n```\n\nThe following snippet invokes a Lambda and sets the task output to only include\nthe Lambda function response.\n\n```ts\nnew tasks.LambdaInvoke(this, 'Invoke and set function response as task output', {\n lambdaFunction: fn,\n outputPath: '$.Payload',\n});\n```\n\nIf you want to combine the input and the Lambda function response you can use\nthe `payloadResponseOnly` property and specify the `resultPath`. This will put the\nLambda function ARN directly in the \"Resource\" string, but it conflicts with the\nintegrationPattern, invocationType, clientContext, and qualifier properties.\n\n```ts\nnew tasks.LambdaInvoke(this, 'Invoke and combine function response with task input', {\n lambdaFunction: fn,\n payloadResponseOnly: true,\n resultPath: '$.fn',\n});\n```\n\nYou can have Step Functions pause a task, and wait for an external process to\nreturn a task token. Read more about the [callback pattern](https://docs.aws.amazon.com/step-functions/latest/dg/callback-task-sample-sqs.html#call-back-lambda-example)\n\nTo use the callback pattern, set the `token` property on the task. Call the Step\nFunctions `SendTaskSuccess` or `SendTaskFailure` APIs with the token to\nindicate that the task has completed and the state machine should resume execution.\n\nThe following snippet invokes a Lambda with the task token as part of the input\nto the Lambda.\n\n```ts\nnew tasks.LambdaInvoke(this, 'Invoke with callback', {\n lambdaFunction: fn,\n integrationPattern: sfn.IntegrationPattern.WAIT_FOR_TASK_TOKEN,\n payload: sfn.TaskInput.fromObject({\n token: sfn.JsonPath.taskToken,\n input: sfn.JsonPath.stringAt('$.someField'),\n }),\n});\n```\n\n⚠️ The task will pause until it receives that task token back with a `SendTaskSuccess` or `SendTaskFailure`\ncall. Learn more about [Callback with the Task\nToken](https://docs.aws.amazon.com/step-functions/latest/dg/connect-to-resource.html#connect-wait-token).\n\nAWS Lambda can occasionally experience transient service errors. In this case, invoking Lambda\nresults in a 500 error, such as `ServiceException`, `AWSLambdaException`, or `SdkClientException`.\nAs a best practice, the `LambdaInvoke` task will retry on those errors with an interval of 2 seconds,\na back-off rate of 2 and 6 maximum attempts. Set the `retryOnServiceExceptions` prop to `false` to\ndisable this behavior.\n\n## SageMaker\n\nStep Functions supports [AWS SageMaker](https://docs.aws.amazon.com/step-functions/latest/dg/connect-sagemaker.html) through the service integration pattern.\n\nIf your training job or model uses resources from AWS Marketplace,\n[network isolation is required](https://docs.aws.amazon.com/sagemaker/latest/dg/mkt-algo-model-internet-free.html).\nTo do so, set the `enableNetworkIsolation` property to `true` for `SageMakerCreateModel` or `SageMakerCreateTrainingJob`.\n\n### Create Training Job\n\nYou can call the [`CreateTrainingJob`](https://docs.aws.amazon.com/sagemaker/latest/dg/API_CreateTrainingJob.html) API from a `Task` state.\n\n```ts\nnew tasks.SageMakerCreateTrainingJob(this, 'TrainSagemaker', {\n trainingJobName: sfn.JsonPath.stringAt('$.JobName'),\n algorithmSpecification: {\n algorithmName: 'BlazingText',\n trainingInputMode: tasks.InputMode.FILE,\n },\n inputDataConfig: [{\n channelName: 'train',\n dataSource: {\n s3DataSource: {\n s3DataType: tasks.S3DataType.S3_PREFIX,\n s3Location: tasks.S3Location.fromJsonExpression('$.S3Bucket'),\n },\n },\n }],\n outputDataConfig: {\n s3OutputLocation: tasks.S3Location.fromBucket(s3.Bucket.fromBucketName(this, 'Bucket', 'mybucket'), 'myoutputpath'),\n },\n resourceConfig: {\n instanceCount: 1,\n instanceType: new ec2.InstanceType(JsonPath.stringAt('$.InstanceType')),\n volumeSize: cdk.Size.gibibytes(50),\n }, // optional: default is 1 instance of EC2 `M4.XLarge` with `10GB` volume\n stoppingCondition: {\n maxRuntime: cdk.Duration.hours(2),\n }, // optional: default is 1 hour\n});\n```\n\n### Create Transform Job\n\nYou can call the [`CreateTransformJob`](https://docs.aws.amazon.com/sagemaker/latest/dg/API_CreateTransformJob.html) API from a `Task` state.\n\n```ts\nnew tasks.SageMakerCreateTransformJob(this, 'Batch Inference', {\n transformJobName: 'MyTransformJob',\n modelName: 'MyModelName',\n modelClientOptions: {\n invocationsMaxRetries: 3, // default is 0\n invocationsTimeout: cdk.Duration.minutes(5), // default is 60 seconds\n },\n transformInput: {\n transformDataSource: {\n s3DataSource: {\n s3Uri: 's3://inputbucket/train',\n s3DataType: tasks.S3DataType.S3_PREFIX,\n }\n }\n },\n transformOutput: {\n s3OutputPath: 's3://outputbucket/TransformJobOutputPath',\n },\n transformResources: {\n instanceCount: 1,\n instanceType: ec2.InstanceType.of(ec2.InstanceClass.M4, ec2.InstanceSize.XLARGE),\n }\n});\n\n```\n\n### Create Endpoint\n\nYou can call the [`CreateEndpoint`](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateEndpoint.html) API from a `Task` state.\n\n```ts\nnew tasks.SageMakerCreateEndpoint(this, 'SagemakerEndpoint', {\n endpointName: sfn.JsonPath.stringAt('$.EndpointName'),\n endpointConfigName: sfn.JsonPath.stringAt('$.EndpointConfigName'),\n});\n```\n\n### Create Endpoint Config\n\nYou can call the [`CreateEndpointConfig`](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateEndpointConfig.html) API from a `Task` state.\n\n```ts\nnew tasks.SageMakerCreateEndpointConfig(this, 'SagemakerEndpointConfig', {\n endpointConfigName: 'MyEndpointConfig',\n productionVariants: [{\n initialInstanceCount: 2,\n instanceType: ec2.InstanceType.of(ec2.InstanceClass.M5, ec2.InstanceSize.XLARGE),\n modelName: 'MyModel',\n variantName: 'awesome-variant',\n }],\n});\n```\n\n### Create Model\n\nYou can call the [`CreateModel`](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateModel.html) API from a `Task` state.\n\n```ts\nnew tasks.SageMakerCreateModel(this, 'Sagemaker', {\n modelName: 'MyModel',\n primaryContainer: new tasks.ContainerDefinition({\n image: tasks.DockerImage.fromJsonExpression(sfn.JsonPath.stringAt('$.Model.imageName')),\n mode: tasks.Mode.SINGLE_MODEL,\n modelS3Location: tasks.S3Location.fromJsonExpression('$.TrainingJob.ModelArtifacts.S3ModelArtifacts'),\n }),\n});\n```\n\n### Update Endpoint\n\nYou can call the [`UpdateEndpoint`](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_UpdateEndpoint.html) API from a `Task` state.\n\n```ts\nnew tasks.SageMakerUpdateEndpoint(this, 'SagemakerEndpoint', {\n endpointName: sfn.JsonPath.stringAt('$.Endpoint.Name'),\n endpointConfigName: sfn.JsonPath.stringAt('$.Endpoint.EndpointConfig'),\n});\n```\n\n## SNS\n\nStep Functions supports [Amazon SNS](https://docs.aws.amazon.com/step-functions/latest/dg/connect-sns.html) through the service integration pattern.\n\nYou can call the [`Publish`](https://docs.aws.amazon.com/sns/latest/api/API_Publish.html) API from a `Task` state to publish to an SNS topic.\n\n```ts\nconst topic = new sns.Topic(this, 'Topic');\n\n// Use a field from the execution data as message.\nconst task1 = new tasks.SnsPublish(this, 'Publish1', {\n topic,\n integrationPattern: sfn.IntegrationPattern.REQUEST_RESPONSE,\n message: sfn.TaskInput.fromDataAt('$.state.message'),\n messageAttributes: {\n place: {\n value: sfn.JsonPath.stringAt('$.place'),\n },\n pic: {\n // BINARY must be explicitly set\n type: MessageAttributeDataType.BINARY,\n value: sfn.JsonPath.stringAt('$.pic'),\n },\n people: {\n value: 4,\n },\n handles: {\n value: ['@kslater', '@jjf', null, '@mfanning'],\n },\n },\n});\n\n// Combine a field from the execution data with\n// a literal object.\nconst task2 = new tasks.SnsPublish(this, 'Publish2', {\n topic,\n message: sfn.TaskInput.fromObject({\n field1: 'somedata',\n field2: sfn.JsonPath.stringAt('$.field2'),\n }),\n});\n```\n\n## Step Functions\n\n### Start Execution\n\nYou can manage [AWS Step Functions](https://docs.aws.amazon.com/step-functions/latest/dg/connect-stepfunctions.html) executions.\n\nAWS Step Functions supports it's own [`StartExecution`](https://docs.aws.amazon.com/step-functions/latest/apireference/API_StartExecution.html) API as a service integration.\n\n```ts\n// Define a state machine with one Pass state\nconst child = new sfn.StateMachine(this, 'ChildStateMachine', {\n definition: sfn.Chain.start(new sfn.Pass(this, 'PassState')),\n});\n\n// Include the state machine in a Task state with callback pattern\nconst task = new tasks.StepFunctionsStartExecution(this, 'ChildTask', {\n stateMachine: child,\n integrationPattern: sfn.IntegrationPattern.WAIT_FOR_TASK_TOKEN,\n input: sfn.TaskInput.fromObject({\n token: sfn.JsonPath.taskToken,\n foo: 'bar',\n }),\n name: 'MyExecutionName',\n});\n\n// Define a second state machine with the Task state above\nnew sfn.StateMachine(this, 'ParentStateMachine', {\n definition: task,\n});\n```\n\nYou can utilize [Associate Workflow Executions](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-nested-workflows.html#nested-execution-startid)\nvia the `associateWithParent` property. This allows the Step Functions UI to link child\nexecutions from parent executions, making it easier to trace execution flow across state machines.\n\n```ts\nconst task = new tasks.StepFunctionsStartExecution(this, 'ChildTask', {\n stateMachine: child,\n associateWithParent: true,\n});\n```\n\nThis will add the payload `AWS_STEP_FUNCTIONS_STARTED_BY_EXECUTION_ID.$: $$.Execution.Id` to the\n`input`property for you, which will pass the execution ID from the context object to the\nexecution input. It requires `input` to be an object or not be set at all.\n\n### Invoke Activity\n\nYou can invoke a [Step Functions Activity](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-activities.html) which enables you to have\na task in your state machine where the work is performed by a *worker* that can\nbe hosted on Amazon EC2, Amazon ECS, AWS Lambda, basically anywhere. Activities\nare a way to associate code running somewhere (known as an activity worker) with\na specific task in a state machine.\n\nWhen Step Functions reaches an activity task state, the workflow waits for an\nactivity worker to poll for a task. An activity worker polls Step Functions by\nusing GetActivityTask, and sending the ARN for the related activity.\n\nAfter the activity worker completes its work, it can provide a report of its\nsuccess or failure by using `SendTaskSuccess` or `SendTaskFailure`. These two\ncalls use the taskToken provided by GetActivityTask to associate the result\nwith that task.\n\nThe following example creates an activity and creates a task that invokes the activity.\n\n```ts\nconst submitJobActivity = new sfn.Activity(this, 'SubmitJob');\n\nnew tasks.StepFunctionsInvokeActivity(this, 'Submit Job', {\n activity: submitJobActivity,\n});\n```\n\n## SQS\n\nStep Functions supports [Amazon SQS](https://docs.aws.amazon.com/step-functions/latest/dg/connect-sqs.html)\n\nYou can call the [`SendMessage`](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html) API from a `Task` state\nto send a message to an SQS queue.\n\n```ts\nconst queue = new sqs.Queue(this, 'Queue');\n\n// Use a field from the execution data as message.\nconst task1 = new tasks.SqsSendMessage(this, 'Send1', {\n queue,\n messageBody: sfn.TaskInput.fromJsonPathAt('$.message'),\n});\n\n// Combine a field from the execution data with\n// a literal object.\nconst task2 = new tasks.SqsSendMessage(this, 'Send2', {\n queue,\n messageBody: sfn.TaskInput.fromObject({\n field1: 'somedata',\n field2: sfn.JsonPath.stringAt('$.field2'),\n }),\n});\n```\n"
3749
+ "markdown": "# Tasks for AWS Step Functions\n\n\n[AWS Step Functions](https://docs.aws.amazon.com/step-functions/latest/dg/welcome.html) is a web service that enables you to coordinate the\ncomponents of distributed applications and microservices using visual workflows.\nYou build applications from individual components that each perform a discrete\nfunction, or task, allowing you to scale and change applications quickly.\n\nA [Task](https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-task-state.html) state represents a single unit of work performed by a state machine.\nAll work in your state machine is performed by tasks.\n\nThis module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project.\n\n## Table Of Contents\n\n- [Tasks for AWS Step Functions](#tasks-for-aws-step-functions)\n - [Table Of Contents](#table-of-contents)\n - [Task](#task)\n - [Paths](#paths)\n - [InputPath](#inputpath)\n - [OutputPath](#outputpath)\n - [ResultPath](#resultpath)\n - [Task parameters from the state JSON](#task-parameters-from-the-state-json)\n - [Evaluate Expression](#evaluate-expression)\n - [API Gateway](#api-gateway)\n - [Call REST API Endpoint](#call-rest-api-endpoint)\n - [Call HTTP API Endpoint](#call-http-api-endpoint)\n - [AWS SDK](#aws-sdk)\n - [Athena](#athena)\n - [StartQueryExecution](#startqueryexecution)\n - [GetQueryExecution](#getqueryexecution)\n - [GetQueryResults](#getqueryresults)\n - [StopQueryExecution](#stopqueryexecution)\n - [Batch](#batch)\n - [SubmitJob](#submitjob)\n - [CodeBuild](#codebuild)\n - [StartBuild](#startbuild)\n - [DynamoDB](#dynamodb)\n - [GetItem](#getitem)\n - [PutItem](#putitem)\n - [DeleteItem](#deleteitem)\n - [UpdateItem](#updateitem)\n - [ECS](#ecs)\n - [RunTask](#runtask)\n - [EC2](#ec2)\n - [Fargate](#fargate)\n - [EMR](#emr)\n - [Create Cluster](#create-cluster)\n - [Termination Protection](#termination-protection)\n - [Terminate Cluster](#terminate-cluster)\n - [Add Step](#add-step)\n - [Cancel Step](#cancel-step)\n - [Modify Instance Fleet](#modify-instance-fleet)\n - [Modify Instance Group](#modify-instance-group)\n - [EKS](#eks)\n - [Call](#call)\n - [EventBridge](#eventbridge)\n - [Put Events](#put-events)\n - [Glue](#glue)\n - [Glue DataBrew](#glue-databrew)\n - [Lambda](#lambda)\n - [SageMaker](#sagemaker)\n - [Create Training Job](#create-training-job)\n - [Create Transform Job](#create-transform-job)\n - [Create Endpoint](#create-endpoint)\n - [Create Endpoint Config](#create-endpoint-config)\n - [Create Model](#create-model)\n - [Update Endpoint](#update-endpoint)\n - [SNS](#sns)\n - [Step Functions](#step-functions)\n - [Start Execution](#start-execution)\n - [Invoke Activity](#invoke-activity)\n - [SQS](#sqs)\n\n## Task\n\nA Task state represents a single unit of work performed by a state machine. In the\nCDK, the exact work to be done is determined by a class that implements `IStepFunctionsTask`.\n\nAWS Step Functions [integrates](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-service-integrations.html) with some AWS services so that you can call API\nactions, and coordinate executions directly from the Amazon States Language in\nStep Functions. You can directly call and pass parameters to the APIs of those\nservices.\n\n## Paths\n\nIn the Amazon States Language, a [path](https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-paths.html) is a string beginning with `$` that you\ncan use to identify components within JSON text.\n\nLearn more about input and output processing in Step Functions [here](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-input-output-filtering.html)\n\n### InputPath\n\nBoth `InputPath` and `Parameters` fields provide a way to manipulate JSON as it\nmoves through your workflow. AWS Step Functions applies the `InputPath` field first,\nand then the `Parameters` field. You can first filter your raw input to a selection\nyou want using InputPath, and then apply Parameters to manipulate that input\nfurther, or add new values. If you don't specify an `InputPath`, a default value\nof `$` will be used.\n\nThe following example provides the field named `input` as the input to the `Task`\nstate that runs a Lambda function.\n\n```ts\ndeclare const fn: lambda.Function;\nconst submitJob = new tasks.LambdaInvoke(this, 'Invoke Handler', {\n lambdaFunction: fn,\n inputPath: '$.input',\n});\n```\n\n### OutputPath\n\nTasks also allow you to select a portion of the state output to pass to the next\nstate. This enables you to filter out unwanted information, and pass only the\nportion of the JSON that you care about. If you don't specify an `OutputPath`,\na default value of `$` will be used. This passes the entire JSON node to the next\nstate.\n\nThe [response](https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html#API_Invoke_ResponseSyntax) from a Lambda function includes the response from the function\nas well as other metadata.\n\nThe following example assigns the output from the Task to a field named `result`\n\n```ts\ndeclare const fn: lambda.Function;\nconst submitJob = new tasks.LambdaInvoke(this, 'Invoke Handler', {\n lambdaFunction: fn,\n outputPath: '$.Payload.result',\n});\n```\n\n### ResultSelector\n\nYou can use [`ResultSelector`](https://docs.aws.amazon.com/step-functions/latest/dg/input-output-inputpath-params.html#input-output-resultselector)\nto manipulate the raw result of a Task, Map or Parallel state before it is\npassed to [`ResultPath`](###ResultPath). For service integrations, the raw\nresult contains metadata in addition to the response payload. You can use\nResultSelector to construct a JSON payload that becomes the effective result\nusing static values or references to the raw result or context object.\n\nThe following example extracts the output payload of a Lambda function Task and combines\nit with some static values and the state name from the context object.\n\n```ts\ndeclare const fn: lambda.Function;\nnew tasks.LambdaInvoke(this, 'Invoke Handler', {\n lambdaFunction: fn,\n resultSelector: {\n lambdaOutput: sfn.JsonPath.stringAt('$.Payload'),\n invokeRequestId: sfn.JsonPath.stringAt('$.SdkResponseMetadata.RequestId'),\n staticValue: {\n foo: 'bar',\n },\n stateName: sfn.JsonPath.stringAt('$$.State.Name'),\n },\n});\n```\n\n### ResultPath\n\nThe output of a state can be a copy of its input, the result it produces (for\nexample, output from a Task state’s Lambda function), or a combination of its\ninput and result. Use [`ResultPath`](https://docs.aws.amazon.com/step-functions/latest/dg/input-output-resultpath.html) to control which combination of these is\npassed to the state output. If you don't specify an `ResultPath`, a default\nvalue of `$` will be used.\n\nThe following example adds the item from calling DynamoDB's `getItem` API to the state\ninput and passes it to the next state.\n\n```ts\ndeclare const myTable: dynamodb.Table;\nnew tasks.DynamoPutItem(this, 'PutItem', {\n item: {\n MessageId: tasks.DynamoAttributeValue.fromString('message-id'),\n },\n table: myTable,\n resultPath: `$.Item`,\n});\n```\n\n⚠️ The `OutputPath` is computed after applying `ResultPath`. All service integrations\nreturn metadata as part of their response. When using `ResultPath`, it's not possible to\nmerge a subset of the task output to the input.\n\n## Task parameters from the state JSON\n\nMost tasks take parameters. Parameter values can either be static, supplied directly\nin the workflow definition (by specifying their values), or a value available at runtime\nin the state machine's execution (either as its input or an output of a prior state).\nParameter values available at runtime can be specified via the `JsonPath` class,\nusing methods such as `JsonPath.stringAt()`.\n\nThe following example provides the field named `input` as the input to the Lambda function\nand invokes it asynchronously.\n\n```ts\ndeclare const fn: lambda.Function;\nconst submitJob = new tasks.LambdaInvoke(this, 'Invoke Handler', {\n lambdaFunction: fn,\n payload: sfn.TaskInput.fromJsonPathAt('$.input'),\n invocationType: tasks.LambdaInvocationType.EVENT,\n});\n```\n\nYou can also use [intrinsic functions](https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-intrinsic-functions.html) with `JsonPath.stringAt()`.\nHere is an example of starting an Athena query that is dynamically created using the task input:\n\n```ts\nconst startQueryExecutionJob = new tasks.AthenaStartQueryExecution(this, 'Athena Start Query', {\n queryString: sfn.JsonPath.stringAt(\"States.Format('select contacts where year={};', $.year)\"),\n queryExecutionContext: {\n databaseName: 'interactions',\n },\n resultConfiguration: {\n encryptionConfiguration: {\n encryptionOption: tasks.EncryptionOption.S3_MANAGED,\n },\n outputLocation: {\n bucketName: 'mybucket',\n objectKey: 'myprefix',\n },\n },\n integrationPattern: sfn.IntegrationPattern.RUN_JOB,\n});\n```\n\nEach service integration has its own set of parameters that can be supplied.\n\n## Evaluate Expression\n\nUse the `EvaluateExpression` to perform simple operations referencing state paths. The\n`expression` referenced in the task will be evaluated in a Lambda function\n(`eval()`). This allows you to not have to write Lambda code for simple operations.\n\nExample: convert a wait time from milliseconds to seconds, concat this in a message and wait:\n\n```ts\nconst convertToSeconds = new tasks.EvaluateExpression(this, 'Convert to seconds', {\n expression: '$.waitMilliseconds / 1000',\n resultPath: '$.waitSeconds',\n});\n\nconst createMessage = new tasks.EvaluateExpression(this, 'Create message', {\n // Note: this is a string inside a string.\n expression: '`Now waiting ${$.waitSeconds} seconds...`',\n runtime: lambda.Runtime.NODEJS_14_X,\n resultPath: '$.message',\n});\n\nconst publishMessage = new tasks.SnsPublish(this, 'Publish message', {\n topic: new sns.Topic(this, 'cool-topic'),\n message: sfn.TaskInput.fromJsonPathAt('$.message'),\n resultPath: '$.sns',\n});\n\nconst wait = new sfn.Wait(this, 'Wait', {\n time: sfn.WaitTime.secondsPath('$.waitSeconds'),\n});\n\nnew sfn.StateMachine(this, 'StateMachine', {\n definition: convertToSeconds\n .next(createMessage)\n .next(publishMessage)\n .next(wait),\n});\n```\n\nThe `EvaluateExpression` supports a `runtime` prop to specify the Lambda\nruntime to use to evaluate the expression. Currently, only runtimes\nof the Node.js family are supported.\n\n## API Gateway\n\nStep Functions supports [API Gateway](https://docs.aws.amazon.com/step-functions/latest/dg/connect-api-gateway.html) through the service integration pattern.\n\nHTTP APIs are designed for low-latency, cost-effective integrations with AWS services, including AWS Lambda, and HTTP endpoints.\nHTTP APIs support OIDC and OAuth 2.0 authorization, and come with built-in support for CORS and automatic deployments.\nPrevious-generation REST APIs currently offer more features. More details can be found [here](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-vs-rest.html).\n\n### Call REST API Endpoint\n\nThe `CallApiGatewayRestApiEndpoint` calls the REST API endpoint.\n\n```ts\nimport { aws_apigateway as apigateway } from 'aws-cdk-lib';\nconst restApi = new apigateway.RestApi(this, 'MyRestApi');\n\nconst invokeTask = new tasks.CallApiGatewayRestApiEndpoint(this, 'Call REST API', {\n api: restApi,\n stageName: 'prod',\n method: tasks.HttpMethod.GET,\n});\n```\n\n### Call HTTP API Endpoint\n\nThe `CallApiGatewayHttpApiEndpoint` calls the HTTP API endpoint.\n\n```ts\nimport { aws_apigatewayv2 as apigatewayv2 } from 'aws-cdk-lib';\nconst httpApi = new apigatewayv2.HttpApi(this, 'MyHttpApi');\n\nconst invokeTask = new tasks.CallApiGatewayHttpApiEndpoint(this, 'Call HTTP API', {\n apiId: httpApi.apiId,\n apiStack: Stack.of(httpApi),\n method: tasks.HttpMethod.GET,\n});\n```\n\n### AWS SDK\n\nStep Functions supports calling [AWS service's API actions](https://docs.aws.amazon.com/step-functions/latest/dg/supported-services-awssdk.html)\nthrough the service integration pattern.\n\nYou can use Step Functions' AWS SDK integrations to call any of the over two hundred AWS services\ndirectly from your state machine, giving you access to over nine thousand API actions.\n\n```ts\ndeclare const myBucket: s3.Bucket;\nconst getObject = new tasks.CallAwsService(this, 'GetObject', {\n service: 's3',\n action: 'getObject',\n parameters: {\n Bucket: myBucket.bucketName,\n Key: sfn.JsonPath.stringAt('$.key')\n },\n iamResources: [myBucket.arnForObjects('*')],\n});\n```\n\nUse camelCase for actions and PascalCase for parameter names.\n\nThe task automatically adds an IAM statement to the state machine role's policy based on the\nservice and action called. The resources for this statement must be specified in `iamResources`.\n\nUse the `iamAction` prop to manually specify the IAM action name in the case where the IAM\naction name does not match with the API service/action name:\n\n```ts\nconst listBuckets = new tasks.CallAwsService(this, 'ListBuckets', {\n service: 's3',\n action: 'ListBuckets',\n iamResources: ['*'],\n iamAction: 's3:ListAllMyBuckets',\n});\n```\n\n## Athena\n\nStep Functions supports [Athena](https://docs.aws.amazon.com/step-functions/latest/dg/connect-athena.html) through the service integration pattern.\n\n### StartQueryExecution\n\nThe [StartQueryExecution](https://docs.aws.amazon.com/athena/latest/APIReference/API_StartQueryExecution.html) API runs the SQL query statement.\n\n```ts\nconst startQueryExecutionJob = new tasks.AthenaStartQueryExecution(this, 'Start Athena Query', {\n queryString: sfn.JsonPath.stringAt('$.queryString'),\n queryExecutionContext: {\n databaseName: 'mydatabase',\n },\n resultConfiguration: {\n encryptionConfiguration: {\n encryptionOption: tasks.EncryptionOption.S3_MANAGED,\n },\n outputLocation: {\n bucketName: 'query-results-bucket',\n objectKey: 'folder',\n },\n },\n});\n```\n\n### GetQueryExecution\n\nThe [GetQueryExecution](https://docs.aws.amazon.com/athena/latest/APIReference/API_GetQueryExecution.html) API gets information about a single execution of a query.\n\n```ts\nconst getQueryExecutionJob = new tasks.AthenaGetQueryExecution(this, 'Get Query Execution', {\n queryExecutionId: sfn.JsonPath.stringAt('$.QueryExecutionId'),\n});\n```\n\n### GetQueryResults\n\nThe [GetQueryResults](https://docs.aws.amazon.com/athena/latest/APIReference/API_GetQueryResults.html) API that streams the results of a single query execution specified by QueryExecutionId from S3.\n\n```ts\nconst getQueryResultsJob = new tasks.AthenaGetQueryResults(this, 'Get Query Results', {\n queryExecutionId: sfn.JsonPath.stringAt('$.QueryExecutionId'),\n});\n```\n\n### StopQueryExecution\n\nThe [StopQueryExecution](https://docs.aws.amazon.com/athena/latest/APIReference/API_StopQueryExecution.html) API that stops a query execution.\n\n```ts\nconst stopQueryExecutionJob = new tasks.AthenaStopQueryExecution(this, 'Stop Query Execution', {\n queryExecutionId: sfn.JsonPath.stringAt('$.QueryExecutionId'),\n});\n```\n\n## Batch\n\nStep Functions supports [Batch](https://docs.aws.amazon.com/step-functions/latest/dg/connect-batch.html) through the service integration pattern.\n\n### SubmitJob\n\nThe [SubmitJob](https://docs.aws.amazon.com/batch/latest/APIReference/API_SubmitJob.html) API submits an AWS Batch job from a job definition.\n\n```ts\nimport { aws_batch as batch } from 'aws-cdk-lib';\ndeclare const batchJobDefinition: batch.JobDefinition;\ndeclare const batchQueue: batch.JobQueue;\n\nconst task = new tasks.BatchSubmitJob(this, 'Submit Job', {\n jobDefinitionArn: batchJobDefinition.jobDefinitionArn,\n jobName: 'MyJob',\n jobQueueArn: batchQueue.jobQueueArn,\n});\n```\n\n## CodeBuild\n\nStep Functions supports [CodeBuild](https://docs.aws.amazon.com/step-functions/latest/dg/connect-codebuild.html) through the service integration pattern.\n\n### StartBuild\n\n[StartBuild](https://docs.aws.amazon.com/codebuild/latest/APIReference/API_StartBuild.html) starts a CodeBuild Project by Project Name.\n\n```ts\nimport { aws_codebuild as codebuild } from 'aws-cdk-lib';\n\nconst codebuildProject = new codebuild.Project(this, 'Project', {\n projectName: 'MyTestProject',\n buildSpec: codebuild.BuildSpec.fromObject({\n version: '0.2',\n phases: {\n build: {\n commands: [\n 'echo \"Hello, CodeBuild!\"',\n ],\n },\n },\n }),\n});\n\nconst task = new tasks.CodeBuildStartBuild(this, 'Task', {\n project: codebuildProject,\n integrationPattern: sfn.IntegrationPattern.RUN_JOB,\n environmentVariablesOverride: {\n ZONE: {\n type: codebuild.BuildEnvironmentVariableType.PLAINTEXT,\n value: sfn.JsonPath.stringAt('$.envVariables.zone'),\n },\n },\n});\n```\n\n## DynamoDB\n\nYou can call DynamoDB APIs from a `Task` state.\nRead more about calling DynamoDB APIs [here](https://docs.aws.amazon.com/step-functions/latest/dg/connect-ddb.html)\n\n### GetItem\n\nThe [GetItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_GetItem.html) operation returns a set of attributes for the item with the given primary key.\n\n```ts\ndeclare const myTable: dynamodb.Table;\nnew tasks.DynamoGetItem(this, 'Get Item', {\n key: { messageId: tasks.DynamoAttributeValue.fromString('message-007') },\n table: myTable,\n});\n```\n\n### PutItem\n\nThe [PutItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html) operation creates a new item, or replaces an old item with a new item.\n\n```ts\ndeclare const myTable: dynamodb.Table;\nnew tasks.DynamoPutItem(this, 'PutItem', {\n item: {\n MessageId: tasks.DynamoAttributeValue.fromString('message-007'),\n Text: tasks.DynamoAttributeValue.fromString(sfn.JsonPath.stringAt('$.bar')),\n TotalCount: tasks.DynamoAttributeValue.fromNumber(10),\n },\n table: myTable,\n});\n```\n\n### DeleteItem\n\nThe [DeleteItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DeleteItem.html) operation deletes a single item in a table by primary key.\n\n```ts\ndeclare const myTable: dynamodb.Table;\nnew tasks.DynamoDeleteItem(this, 'DeleteItem', {\n key: { MessageId: tasks.DynamoAttributeValue.fromString('message-007') },\n table: myTable,\n resultPath: sfn.JsonPath.DISCARD,\n});\n```\n\n### UpdateItem\n\nThe [UpdateItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateItem.html) operation edits an existing item's attributes, or adds a new item\nto the table if it does not already exist.\n\n```ts\ndeclare const myTable: dynamodb.Table;\nnew tasks.DynamoUpdateItem(this, 'UpdateItem', {\n key: {\n MessageId: tasks.DynamoAttributeValue.fromString('message-007')\n },\n table: myTable,\n expressionAttributeValues: {\n ':val': tasks.DynamoAttributeValue.numberFromString(sfn.JsonPath.stringAt('$.Item.TotalCount.N')),\n ':rand': tasks.DynamoAttributeValue.fromNumber(20),\n },\n updateExpression: 'SET TotalCount = :val + :rand',\n});\n```\n\n## ECS\n\nStep Functions supports [ECS/Fargate](https://docs.aws.amazon.com/step-functions/latest/dg/connect-ecs.html) through the service integration pattern.\n\n### RunTask\n\n[RunTask](https://docs.aws.amazon.com/step-functions/latest/dg/connect-ecs.html) starts a new task using the specified task definition.\n\n#### EC2\n\nThe EC2 launch type allows you to run your containerized applications on a cluster\nof Amazon EC2 instances that you manage.\n\nWhen a task that uses the EC2 launch type is launched, Amazon ECS must determine where\nto place the task based on the requirements specified in the task definition, such as\nCPU and memory. Similarly, when you scale down the task count, Amazon ECS must determine\nwhich tasks to terminate. You can apply task placement strategies and constraints to\ncustomize how Amazon ECS places and terminates tasks. Learn more about [task placement](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-placement.html)\n\nThe latest ACTIVE revision of the passed task definition is used for running the task.\n\nThe following example runs a job from a task definition on EC2\n\n```ts\nconst vpc = ec2.Vpc.fromLookup(this, 'Vpc', {\n isDefault: true,\n});\n\nconst cluster = new ecs.Cluster(this, 'Ec2Cluster', { vpc });\ncluster.addCapacity('DefaultAutoScalingGroup', {\n instanceType: new ec2.InstanceType('t2.micro'),\n vpcSubnets: { subnetType: ec2.SubnetType.PUBLIC },\n});\n\nconst taskDefinition = new ecs.TaskDefinition(this, 'TD', {\n compatibility: ecs.Compatibility.EC2,\n});\n\ntaskDefinition.addContainer('TheContainer', {\n image: ecs.ContainerImage.fromRegistry('foo/bar'),\n memoryLimitMiB: 256,\n});\n\nconst runTask = new tasks.EcsRunTask(this, 'Run', {\n integrationPattern: sfn.IntegrationPattern.RUN_JOB,\n cluster,\n taskDefinition,\n launchTarget: new tasks.EcsEc2LaunchTarget({\n placementStrategies: [\n ecs.PlacementStrategy.spreadAcrossInstances(),\n ecs.PlacementStrategy.packedByCpu(),\n ecs.PlacementStrategy.randomly(),\n ],\n placementConstraints: [\n ecs.PlacementConstraint.memberOf('blieptuut'),\n ],\n }),\n});\n```\n\n#### Fargate\n\nAWS Fargate is a serverless compute engine for containers that works with Amazon\nElastic Container Service (ECS). Fargate makes it easy for you to focus on building\nyour applications. Fargate removes the need to provision and manage servers, lets you\nspecify and pay for resources per application, and improves security through application\nisolation by design. Learn more about [Fargate](https://aws.amazon.com/fargate/)\n\nThe Fargate launch type allows you to run your containerized applications without the need\nto provision and manage the backend infrastructure. Just register your task definition and\nFargate launches the container for you. The latest ACTIVE revision of the passed\ntask definition is used for running the task. Learn more about\n[Fargate Versioning](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_DescribeTaskDefinition.html)\n\nThe following example runs a job from a task definition on Fargate\n\n```ts\nconst vpc = ec2.Vpc.fromLookup(this, 'Vpc', {\n isDefault: true,\n});\n\nconst cluster = new ecs.Cluster(this, 'FargateCluster', { vpc });\n\nconst taskDefinition = new ecs.TaskDefinition(this, 'TD', {\n memoryMiB: '512',\n cpu: '256',\n compatibility: ecs.Compatibility.FARGATE,\n});\n\nconst containerDefinition = taskDefinition.addContainer('TheContainer', {\n image: ecs.ContainerImage.fromRegistry('foo/bar'),\n memoryLimitMiB: 256,\n});\n\nconst runTask = new tasks.EcsRunTask(this, 'RunFargate', {\n integrationPattern: sfn.IntegrationPattern.RUN_JOB,\n cluster,\n taskDefinition,\n assignPublicIp: true,\n containerOverrides: [{\n containerDefinition,\n environment: [{ name: 'SOME_KEY', value: sfn.JsonPath.stringAt('$.SomeKey') }],\n }],\n launchTarget: new tasks.EcsFargateLaunchTarget(),\n});\n```\n\n## EMR\n\nStep Functions supports Amazon EMR through the service integration pattern.\nThe service integration APIs correspond to Amazon EMR APIs but differ in the\nparameters that are used.\n\n[Read more](https://docs.aws.amazon.com/step-functions/latest/dg/connect-emr.html) about the differences when using these service integrations.\n\n### Create Cluster\n\nCreates and starts running a cluster (job flow).\nCorresponds to the [`runJobFlow`](https://docs.aws.amazon.com/emr/latest/APIReference/API_RunJobFlow.html) API in EMR.\n\n```ts\nconst clusterRole = new iam.Role(this, 'ClusterRole', {\n assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'),\n});\n\nconst serviceRole = new iam.Role(this, 'ServiceRole', {\n assumedBy: new iam.ServicePrincipal('elasticmapreduce.amazonaws.com'),\n});\n\nconst autoScalingRole = new iam.Role(this, 'AutoScalingRole', {\n assumedBy: new iam.ServicePrincipal('elasticmapreduce.amazonaws.com'),\n});\n\nautoScalingRole.assumeRolePolicy?.addStatements(\n new iam.PolicyStatement({\n effect: iam.Effect.ALLOW,\n principals: [\n new iam.ServicePrincipal('application-autoscaling.amazonaws.com'),\n ],\n actions: [\n 'sts:AssumeRole',\n ],\n }));\n)\n\nnew tasks.EmrCreateCluster(this, 'Create Cluster', {\n instances: {},\n clusterRole,\n name: sfn.TaskInput.fromJsonPathAt('$.ClusterName').value,\n serviceRole,\n autoScalingRole,\n});\n```\n\nIf you want to run multiple steps in [parallel](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-concurrent-steps.html),\nyou can specify the `stepConcurrencyLevel` property. The concurrency range is between 1\nand 256 inclusive, where the default concurrency of 1 means no step concurrency is allowed.\n`stepConcurrencyLevel` requires the EMR release label to be 5.28.0 or above.\n\n```ts\nnew tasks.EmrCreateCluster(this, 'Create Cluster', {\n instances: {},\n name: sfn.TaskInput.fromJsonPathAt('$.ClusterName').value,\n stepConcurrencyLevel: 10,\n});\n```\n\n### Termination Protection\n\nLocks a cluster (job flow) so the EC2 instances in the cluster cannot be\nterminated by user intervention, an API call, or a job-flow error.\n\nCorresponds to the [`setTerminationProtection`](https://docs.aws.amazon.com/step-functions/latest/dg/connect-emr.html) API in EMR.\n\n```ts\nnew tasks.EmrSetClusterTerminationProtection(this, 'Task', {\n clusterId: 'ClusterId',\n terminationProtected: false,\n});\n```\n\n### Terminate Cluster\n\nShuts down a cluster (job flow).\nCorresponds to the [`terminateJobFlows`](https://docs.aws.amazon.com/emr/latest/APIReference/API_TerminateJobFlows.html) API in EMR.\n\n```ts\nnew tasks.EmrTerminateCluster(this, 'Task', {\n clusterId: 'ClusterId',\n});\n```\n\n### Add Step\n\nAdds a new step to a running cluster.\nCorresponds to the [`addJobFlowSteps`](https://docs.aws.amazon.com/emr/latest/APIReference/API_AddJobFlowSteps.html) API in EMR.\n\n```ts\nnew tasks.EmrAddStep(this, 'Task', {\n clusterId: 'ClusterId',\n name: 'StepName',\n jar: 'Jar',\n actionOnFailure: tasks.ActionOnFailure.CONTINUE,\n});\n```\n\n### Cancel Step\n\nCancels a pending step in a running cluster.\nCorresponds to the [`cancelSteps`](https://docs.aws.amazon.com/emr/latest/APIReference/API_CancelSteps.html) API in EMR.\n\n```ts\nnew tasks.EmrCancelStep(this, 'Task', {\n clusterId: 'ClusterId',\n stepId: 'StepId',\n});\n```\n\n### Modify Instance Fleet\n\nModifies the target On-Demand and target Spot capacities for the instance\nfleet with the specified InstanceFleetName.\n\nCorresponds to the [`modifyInstanceFleet`](https://docs.aws.amazon.com/emr/latest/APIReference/API_ModifyInstanceFleet.html) API in EMR.\n\n```ts\nnew tasks.EmrModifyInstanceFleetByName(this, 'Task', {\n clusterId: 'ClusterId',\n instanceFleetName: 'InstanceFleetName',\n targetOnDemandCapacity: 2,\n targetSpotCapacity: 0,\n});\n```\n\n### Modify Instance Group\n\nModifies the number of nodes and configuration settings of an instance group.\n\nCorresponds to the [`modifyInstanceGroups`](https://docs.aws.amazon.com/emr/latest/APIReference/API_ModifyInstanceGroups.html) API in EMR.\n\n```ts\nnew tasks.EmrModifyInstanceGroupByName(this, 'Task', {\n clusterId: 'ClusterId',\n instanceGroupName: sfn.JsonPath.stringAt('$.InstanceGroupName'),\n instanceGroup: {\n instanceCount: 1,\n },\n});\n```\n\n## EKS\n\nStep Functions supports Amazon EKS through the service integration pattern.\nThe service integration APIs correspond to Amazon EKS APIs.\n\n[Read more](https://docs.aws.amazon.com/step-functions/latest/dg/connect-eks.html) about the differences when using these service integrations.\n\n### Call\n\nRead and write Kubernetes resource objects via a Kubernetes API endpoint.\nCorresponds to the [`call`](https://docs.aws.amazon.com/step-functions/latest/dg/connect-eks.html) API in Step Functions Connector.\n\nThe following code snippet includes a Task state that uses eks:call to list the pods.\n\n```ts\nimport { aws_eks as eks } from 'aws-cdk-lib';\n\nconst myEksCluster = new eks.Cluster(this, 'my sample cluster', {\n version: eks.KubernetesVersion.V1_18,\n clusterName: 'myEksCluster',\n});\n\nnew tasks.EksCall(this, 'Call a EKS Endpoint', {\n cluster: myEksCluster,\n httpMethod: tasks.HttpMethods.GET,\n httpPath: '/api/v1/namespaces/default/pods',\n});\n```\n\n## EventBridge\n\nStep Functions supports Amazon EventBridge through the service integration pattern.\nThe service integration APIs correspond to Amazon EventBridge APIs.\n\n[Read more](https://docs.aws.amazon.com/step-functions/latest/dg/connect-eventbridge.html) about the differences when using these service integrations.\n\n### Put Events\n\nSend events to an EventBridge bus.\nCorresponds to the [`put-events`](https://docs.aws.amazon.com/step-functions/latest/dg/connect-eventbridge.html) API in Step Functions Connector.\n\nThe following code snippet includes a Task state that uses events:putevents to send an event to the default bus.\n\n```ts\nimport { aws_events as events } from 'aws-cdk-lib';\n\nconst myEventBus = new events.EventBus(this, 'EventBus', {\n eventBusName: 'MyEventBus1',\n});\n\nnew tasks.EventBridgePutEvents(this, 'Send an event to EventBridge', {\n entries: [{\n detail: sfn.TaskInput.fromObject({\n Message: 'Hello from Step Functions!',\n }),\n eventBus: myEventBus,\n detailType: 'MessageFromStepFunctions',\n source: 'step.functions',\n }],\n});\n```\n\n## Glue\n\nStep Functions supports [AWS Glue](https://docs.aws.amazon.com/step-functions/latest/dg/connect-glue.html) through the service integration pattern.\n\nYou can call the [`StartJobRun`](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-api-jobs-runs.html#aws-glue-api-jobs-runs-StartJobRun) API from a `Task` state.\n\n```ts\nnew tasks.GlueStartJobRun(this, 'Task', {\n glueJobName: 'my-glue-job',\n arguments: sfn.TaskInput.fromObject({\n key: 'value',\n }),\n timeout: Duration.minutes(30),\n notifyDelayAfter: Duration.minutes(5),\n});\n```\n\n## Glue DataBrew\n\nStep Functions supports [AWS Glue DataBrew](https://docs.aws.amazon.com/step-functions/latest/dg/connect-databrew.html) through the service integration pattern.\n\nYou can call the [`StartJobRun`](https://docs.aws.amazon.com/databrew/latest/dg/API_StartJobRun.html) API from a `Task` state.\n\n```ts\nnew tasks.GlueDataBrewStartJobRun(this, 'Task', {\n name: 'databrew-job',\n});\n```\n\n## Lambda\n\n[Invoke](https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html) a Lambda function.\n\nYou can specify the input to your Lambda function through the `payload` attribute.\nBy default, Step Functions invokes Lambda function with the state input (JSON path '$')\nas the input.\n\nThe following snippet invokes a Lambda Function with the state input as the payload\nby referencing the `$` path.\n\n```ts\ndeclare const fn: lambda.Function;\nnew tasks.LambdaInvoke(this, 'Invoke with state input', {\n lambdaFunction: fn,\n});\n```\n\nWhen a function is invoked, the Lambda service sends [these response\nelements](https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html#API_Invoke_ResponseElements)\nback.\n\n⚠️ The response from the Lambda function is in an attribute called `Payload`\n\nThe following snippet invokes a Lambda Function by referencing the `$.Payload` path\nto reference the output of a Lambda executed before it.\n\n```ts\ndeclare const fn: lambda.Function;\nnew tasks.LambdaInvoke(this, 'Invoke with empty object as payload', {\n lambdaFunction: fn,\n payload: sfn.TaskInput.fromObject({}),\n});\n\n// use the output of fn as input\nnew tasks.LambdaInvoke(this, 'Invoke with payload field in the state input', {\n lambdaFunction: fn,\n payload: sfn.TaskInput.fromJsonPathAt('$.Payload'),\n});\n```\n\nThe following snippet invokes a Lambda and sets the task output to only include\nthe Lambda function response.\n\n```ts\ndeclare const fn: lambda.Function;\nnew tasks.LambdaInvoke(this, 'Invoke and set function response as task output', {\n lambdaFunction: fn,\n outputPath: '$.Payload',\n});\n```\n\nIf you want to combine the input and the Lambda function response you can use\nthe `payloadResponseOnly` property and specify the `resultPath`. This will put the\nLambda function ARN directly in the \"Resource\" string, but it conflicts with the\nintegrationPattern, invocationType, clientContext, and qualifier properties.\n\n```ts\ndeclare const fn: lambda.Function;\nnew tasks.LambdaInvoke(this, 'Invoke and combine function response with task input', {\n lambdaFunction: fn,\n payloadResponseOnly: true,\n resultPath: '$.fn',\n});\n```\n\nYou can have Step Functions pause a task, and wait for an external process to\nreturn a task token. Read more about the [callback pattern](https://docs.aws.amazon.com/step-functions/latest/dg/callback-task-sample-sqs.html#call-back-lambda-example)\n\nTo use the callback pattern, set the `token` property on the task. Call the Step\nFunctions `SendTaskSuccess` or `SendTaskFailure` APIs with the token to\nindicate that the task has completed and the state machine should resume execution.\n\nThe following snippet invokes a Lambda with the task token as part of the input\nto the Lambda.\n\n```ts\ndeclare const fn: lambda.Function;\nnew tasks.LambdaInvoke(this, 'Invoke with callback', {\n lambdaFunction: fn,\n integrationPattern: sfn.IntegrationPattern.WAIT_FOR_TASK_TOKEN,\n payload: sfn.TaskInput.fromObject({\n token: sfn.JsonPath.taskToken,\n input: sfn.JsonPath.stringAt('$.someField'),\n }),\n});\n```\n\n⚠️ The task will pause until it receives that task token back with a `SendTaskSuccess` or `SendTaskFailure`\ncall. Learn more about [Callback with the Task\nToken](https://docs.aws.amazon.com/step-functions/latest/dg/connect-to-resource.html#connect-wait-token).\n\nAWS Lambda can occasionally experience transient service errors. In this case, invoking Lambda\nresults in a 500 error, such as `ServiceException`, `AWSLambdaException`, or `SdkClientException`.\nAs a best practice, the `LambdaInvoke` task will retry on those errors with an interval of 2 seconds,\na back-off rate of 2 and 6 maximum attempts. Set the `retryOnServiceExceptions` prop to `false` to\ndisable this behavior.\n\n## SageMaker\n\nStep Functions supports [AWS SageMaker](https://docs.aws.amazon.com/step-functions/latest/dg/connect-sagemaker.html) through the service integration pattern.\n\nIf your training job or model uses resources from AWS Marketplace,\n[network isolation is required](https://docs.aws.amazon.com/sagemaker/latest/dg/mkt-algo-model-internet-free.html).\nTo do so, set the `enableNetworkIsolation` property to `true` for `SageMakerCreateModel` or `SageMakerCreateTrainingJob`.\n\n### Create Training Job\n\nYou can call the [`CreateTrainingJob`](https://docs.aws.amazon.com/sagemaker/latest/dg/API_CreateTrainingJob.html) API from a `Task` state.\n\n```ts\nnew tasks.SageMakerCreateTrainingJob(this, 'TrainSagemaker', {\n trainingJobName: sfn.JsonPath.stringAt('$.JobName'),\n algorithmSpecification: {\n algorithmName: 'BlazingText',\n trainingInputMode: tasks.InputMode.FILE,\n },\n inputDataConfig: [{\n channelName: 'train',\n dataSource: {\n s3DataSource: {\n s3DataType: tasks.S3DataType.S3_PREFIX,\n s3Location: tasks.S3Location.fromJsonExpression('$.S3Bucket'),\n },\n },\n }],\n outputDataConfig: {\n s3OutputLocation: tasks.S3Location.fromBucket(s3.Bucket.fromBucketName(this, 'Bucket', 'mybucket'), 'myoutputpath'),\n },\n resourceConfig: {\n instanceCount: 1,\n instanceType: new ec2.InstanceType(sfn.JsonPath.stringAt('$.InstanceType')),\n volumeSize: Size.gibibytes(50),\n }, // optional: default is 1 instance of EC2 `M4.XLarge` with `10GB` volume\n stoppingCondition: {\n maxRuntime: Duration.hours(2),\n }, // optional: default is 1 hour\n});\n```\n\n### Create Transform Job\n\nYou can call the [`CreateTransformJob`](https://docs.aws.amazon.com/sagemaker/latest/dg/API_CreateTransformJob.html) API from a `Task` state.\n\n```ts\nnew tasks.SageMakerCreateTransformJob(this, 'Batch Inference', {\n transformJobName: 'MyTransformJob',\n modelName: 'MyModelName',\n modelClientOptions: {\n invocationsMaxRetries: 3, // default is 0\n invocationsTimeout: Duration.minutes(5), // default is 60 seconds\n },\n transformInput: {\n transformDataSource: {\n s3DataSource: {\n s3Uri: 's3://inputbucket/train',\n s3DataType: tasks.S3DataType.S3_PREFIX,\n }\n }\n },\n transformOutput: {\n s3OutputPath: 's3://outputbucket/TransformJobOutputPath',\n },\n transformResources: {\n instanceCount: 1,\n instanceType: ec2.InstanceType.of(ec2.InstanceClass.M4, ec2.InstanceSize.XLARGE),\n }\n});\n\n```\n\n### Create Endpoint\n\nYou can call the [`CreateEndpoint`](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateEndpoint.html) API from a `Task` state.\n\n```ts\nnew tasks.SageMakerCreateEndpoint(this, 'SagemakerEndpoint', {\n endpointName: sfn.JsonPath.stringAt('$.EndpointName'),\n endpointConfigName: sfn.JsonPath.stringAt('$.EndpointConfigName'),\n});\n```\n\n### Create Endpoint Config\n\nYou can call the [`CreateEndpointConfig`](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateEndpointConfig.html) API from a `Task` state.\n\n```ts\nnew tasks.SageMakerCreateEndpointConfig(this, 'SagemakerEndpointConfig', {\n endpointConfigName: 'MyEndpointConfig',\n productionVariants: [{\n initialInstanceCount: 2,\n instanceType: ec2.InstanceType.of(ec2.InstanceClass.M5, ec2.InstanceSize.XLARGE),\n modelName: 'MyModel',\n variantName: 'awesome-variant',\n }],\n});\n```\n\n### Create Model\n\nYou can call the [`CreateModel`](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateModel.html) API from a `Task` state.\n\n```ts\nnew tasks.SageMakerCreateModel(this, 'Sagemaker', {\n modelName: 'MyModel',\n primaryContainer: new tasks.ContainerDefinition({\n image: tasks.DockerImage.fromJsonExpression(sfn.JsonPath.stringAt('$.Model.imageName')),\n mode: tasks.Mode.SINGLE_MODEL,\n modelS3Location: tasks.S3Location.fromJsonExpression('$.TrainingJob.ModelArtifacts.S3ModelArtifacts'),\n }),\n});\n```\n\n### Update Endpoint\n\nYou can call the [`UpdateEndpoint`](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_UpdateEndpoint.html) API from a `Task` state.\n\n```ts\nnew tasks.SageMakerUpdateEndpoint(this, 'SagemakerEndpoint', {\n endpointName: sfn.JsonPath.stringAt('$.Endpoint.Name'),\n endpointConfigName: sfn.JsonPath.stringAt('$.Endpoint.EndpointConfig'),\n});\n```\n\n## SNS\n\nStep Functions supports [Amazon SNS](https://docs.aws.amazon.com/step-functions/latest/dg/connect-sns.html) through the service integration pattern.\n\nYou can call the [`Publish`](https://docs.aws.amazon.com/sns/latest/api/API_Publish.html) API from a `Task` state to publish to an SNS topic.\n\n```ts\nconst topic = new sns.Topic(this, 'Topic');\n\n// Use a field from the execution data as message.\nconst task1 = new tasks.SnsPublish(this, 'Publish1', {\n topic,\n integrationPattern: sfn.IntegrationPattern.REQUEST_RESPONSE,\n message: sfn.TaskInput.fromDataAt('$.state.message'),\n messageAttributes: {\n place: {\n value: sfn.JsonPath.stringAt('$.place'),\n },\n pic: {\n // BINARY must be explicitly set\n dataType: tasks.MessageAttributeDataType.BINARY,\n value: sfn.JsonPath.stringAt('$.pic'),\n },\n people: {\n value: 4,\n },\n handles: {\n value: ['@kslater', '@jjf', null, '@mfanning'],\n },\n },\n});\n\n// Combine a field from the execution data with\n// a literal object.\nconst task2 = new tasks.SnsPublish(this, 'Publish2', {\n topic,\n message: sfn.TaskInput.fromObject({\n field1: 'somedata',\n field2: sfn.JsonPath.stringAt('$.field2'),\n }),\n});\n```\n\n## Step Functions\n\n### Start Execution\n\nYou can manage [AWS Step Functions](https://docs.aws.amazon.com/step-functions/latest/dg/connect-stepfunctions.html) executions.\n\nAWS Step Functions supports it's own [`StartExecution`](https://docs.aws.amazon.com/step-functions/latest/apireference/API_StartExecution.html) API as a service integration.\n\n```ts\n// Define a state machine with one Pass state\nconst child = new sfn.StateMachine(this, 'ChildStateMachine', {\n definition: sfn.Chain.start(new sfn.Pass(this, 'PassState')),\n});\n\n// Include the state machine in a Task state with callback pattern\nconst task = new tasks.StepFunctionsStartExecution(this, 'ChildTask', {\n stateMachine: child,\n integrationPattern: sfn.IntegrationPattern.WAIT_FOR_TASK_TOKEN,\n input: sfn.TaskInput.fromObject({\n token: sfn.JsonPath.taskToken,\n foo: 'bar',\n }),\n name: 'MyExecutionName',\n});\n\n// Define a second state machine with the Task state above\nnew sfn.StateMachine(this, 'ParentStateMachine', {\n definition: task,\n});\n```\n\nYou can utilize [Associate Workflow Executions](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-nested-workflows.html#nested-execution-startid)\nvia the `associateWithParent` property. This allows the Step Functions UI to link child\nexecutions from parent executions, making it easier to trace execution flow across state machines.\n\n```ts\ndeclare const child: sfn.StateMachine;\nconst task = new tasks.StepFunctionsStartExecution(this, 'ChildTask', {\n stateMachine: child,\n associateWithParent: true,\n});\n```\n\nThis will add the payload `AWS_STEP_FUNCTIONS_STARTED_BY_EXECUTION_ID.$: $$.Execution.Id` to the\n`input`property for you, which will pass the execution ID from the context object to the\nexecution input. It requires `input` to be an object or not be set at all.\n\n### Invoke Activity\n\nYou can invoke a [Step Functions Activity](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-activities.html) which enables you to have\na task in your state machine where the work is performed by a *worker* that can\nbe hosted on Amazon EC2, Amazon ECS, AWS Lambda, basically anywhere. Activities\nare a way to associate code running somewhere (known as an activity worker) with\na specific task in a state machine.\n\nWhen Step Functions reaches an activity task state, the workflow waits for an\nactivity worker to poll for a task. An activity worker polls Step Functions by\nusing GetActivityTask, and sending the ARN for the related activity.\n\nAfter the activity worker completes its work, it can provide a report of its\nsuccess or failure by using `SendTaskSuccess` or `SendTaskFailure`. These two\ncalls use the taskToken provided by GetActivityTask to associate the result\nwith that task.\n\nThe following example creates an activity and creates a task that invokes the activity.\n\n```ts\nconst submitJobActivity = new sfn.Activity(this, 'SubmitJob');\n\nnew tasks.StepFunctionsInvokeActivity(this, 'Submit Job', {\n activity: submitJobActivity,\n});\n```\n\n## SQS\n\nStep Functions supports [Amazon SQS](https://docs.aws.amazon.com/step-functions/latest/dg/connect-sqs.html)\n\nYou can call the [`SendMessage`](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html) API from a `Task` state\nto send a message to an SQS queue.\n\n```ts\nconst queue = new sqs.Queue(this, 'Queue');\n\n// Use a field from the execution data as message.\nconst task1 = new tasks.SqsSendMessage(this, 'Send1', {\n queue,\n messageBody: sfn.TaskInput.fromJsonPathAt('$.message'),\n});\n\n// Combine a field from the execution data with\n// a literal object.\nconst task2 = new tasks.SqsSendMessage(this, 'Send2', {\n queue,\n messageBody: sfn.TaskInput.fromObject({\n field1: 'somedata',\n field2: sfn.JsonPath.stringAt('$.field2'),\n }),\n});\n```\n"
3750
3750
  },
3751
3751
  "targets": {
3752
3752
  "dotnet": {
@@ -7038,6 +7038,6 @@
7038
7038
  "symbolId": "lib/subnet-group:SubnetGroupProps"
7039
7039
  }
7040
7040
  },
7041
- "version": "2.0.0-alpha.3",
7042
- "fingerprint": "LCDdpqc42SFZqmg4qa39MyWnEDpVQMuszSlRV51ofPQ="
7041
+ "version": "2.0.0-alpha.4",
7042
+ "fingerprint": "m7FhL8gmfummR5k3BpmixMs3SQGZSEtGAQ5kcBV6718="
7043
7043
  }
package/lib/cluster.js CHANGED
@@ -27,7 +27,7 @@ class EngineVersion {
27
27
  }
28
28
  exports.EngineVersion = EngineVersion;
29
29
  _a = JSII_RTTI_SYMBOL_1;
30
- EngineVersion[_a] = { fqn: "@aws-cdk/aws-neptune-alpha.EngineVersion", version: "2.0.0-alpha.3" };
30
+ EngineVersion[_a] = { fqn: "@aws-cdk/aws-neptune-alpha.EngineVersion", version: "2.0.0-alpha.4" };
31
31
  /**
32
32
  * (experimental) Neptune engine version 1.0.1.0.
33
33
  *
@@ -139,7 +139,7 @@ class DatabaseClusterBase extends aws_cdk_lib_1.Resource {
139
139
  }
140
140
  exports.DatabaseClusterBase = DatabaseClusterBase;
141
141
  _b = JSII_RTTI_SYMBOL_1;
142
- DatabaseClusterBase[_b] = { fqn: "@aws-cdk/aws-neptune-alpha.DatabaseClusterBase", version: "2.0.0-alpha.3" };
142
+ DatabaseClusterBase[_b] = { fqn: "@aws-cdk/aws-neptune-alpha.DatabaseClusterBase", version: "2.0.0-alpha.4" };
143
143
  /**
144
144
  * (experimental) Create a clustered database with a given number of instances.
145
145
  *
@@ -254,7 +254,7 @@ class DatabaseCluster extends DatabaseClusterBase {
254
254
  }
255
255
  exports.DatabaseCluster = DatabaseCluster;
256
256
  _c = JSII_RTTI_SYMBOL_1;
257
- DatabaseCluster[_c] = { fqn: "@aws-cdk/aws-neptune-alpha.DatabaseCluster", version: "2.0.0-alpha.3" };
257
+ DatabaseCluster[_c] = { fqn: "@aws-cdk/aws-neptune-alpha.DatabaseCluster", version: "2.0.0-alpha.4" };
258
258
  /**
259
259
  * (experimental) The default number of instances in the Neptune cluster if none are specified.
260
260
  *
package/lib/endpoint.js CHANGED
@@ -24,5 +24,5 @@ class Endpoint {
24
24
  }
25
25
  exports.Endpoint = Endpoint;
26
26
  _a = JSII_RTTI_SYMBOL_1;
27
- Endpoint[_a] = { fqn: "@aws-cdk/aws-neptune-alpha.Endpoint", version: "2.0.0-alpha.3" };
27
+ Endpoint[_a] = { fqn: "@aws-cdk/aws-neptune-alpha.Endpoint", version: "2.0.0-alpha.4" };
28
28
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW5kcG9pbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJlbmRwb2ludC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDZDQUFvQzs7Ozs7Ozs7QUFHcEMsTUFBYSxRQUFROzs7O0lBVW5CLFlBQVksT0FBZSxFQUFFLElBQVk7UUFDdkMsSUFBSSxDQUFDLFFBQVEsR0FBRyxPQUFPLENBQUM7UUFDeEIsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFFakIsTUFBTSxRQUFRLEdBQUcsbUJBQUssQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLG1CQUFLLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7UUFDeEUsSUFBSSxDQUFDLGFBQWEsR0FBRyxHQUFHLE9BQU8sSUFBSSxRQUFRLEVBQUUsQ0FBQztJQUNoRCxDQUFDOztBQWhCSCw0QkFpQkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBUb2tlbiB9IGZyb20gJ2F3cy1jZGstbGliJztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG5leHBvcnQgY2xhc3MgRW5kcG9pbnQge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHB1YmxpYyByZWFkb25seSBob3N0bmFtZTogc3RyaW5nO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgcmVhZG9ubHkgcG9ydDogbnVtYmVyO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIHJlYWRvbmx5IHNvY2tldEFkZHJlc3M6IHN0cmluZztcblxuICBjb25zdHJ1Y3RvcihhZGRyZXNzOiBzdHJpbmcsIHBvcnQ6IG51bWJlcikge1xuICAgIHRoaXMuaG9zdG5hbWUgPSBhZGRyZXNzO1xuICAgIHRoaXMucG9ydCA9IHBvcnQ7XG5cbiAgICBjb25zdCBwb3J0RGVzYyA9IFRva2VuLmlzVW5yZXNvbHZlZChwb3J0KSA/IFRva2VuLmFzU3RyaW5nKHBvcnQpIDogcG9ydDtcbiAgICB0aGlzLnNvY2tldEFkZHJlc3MgPSBgJHthZGRyZXNzfToke3BvcnREZXNjfWA7XG4gIH1cbn1cbiJdfQ==
package/lib/instance.js CHANGED
@@ -32,7 +32,7 @@ class InstanceType {
32
32
  }
33
33
  exports.InstanceType = InstanceType;
34
34
  _a = JSII_RTTI_SYMBOL_1;
35
- InstanceType[_a] = { fqn: "@aws-cdk/aws-neptune-alpha.InstanceType", version: "2.0.0-alpha.3" };
35
+ InstanceType[_a] = { fqn: "@aws-cdk/aws-neptune-alpha.InstanceType", version: "2.0.0-alpha.4" };
36
36
  /**
37
37
  * (experimental) db.r5.large.
38
38
  *
@@ -163,5 +163,5 @@ class DatabaseInstance extends cdk.Resource {
163
163
  }
164
164
  exports.DatabaseInstance = DatabaseInstance;
165
165
  _b = JSII_RTTI_SYMBOL_1;
166
- DatabaseInstance[_b] = { fqn: "@aws-cdk/aws-neptune-alpha.DatabaseInstance", version: "2.0.0-alpha.3" };
166
+ DatabaseInstance[_b] = { fqn: "@aws-cdk/aws-neptune-alpha.DatabaseInstance", version: "2.0.0-alpha.4" };
167
167
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5zdGFuY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbnN0YW5jZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDJDQUEyQztBQUMzQyxtQ0FBbUM7QUFHbkMseUNBQXNDO0FBQ3RDLHlEQUF3RDs7Ozs7O0FBSXhELE1BQWEsWUFBWTtJQW1EdkIsWUFBb0IsWUFBb0I7UUFDdEMsSUFBSSxHQUFHLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxZQUFZLENBQUMsSUFBSSxZQUFZLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxFQUFFO1lBQzFFLElBQUksQ0FBQyxhQUFhLEdBQUcsWUFBWSxDQUFDO1NBQ25DO2FBQU07WUFDTCxNQUFNLElBQUksS0FBSyxDQUFDLDZDQUE2QyxZQUFZLEdBQUcsQ0FBQyxDQUFDO1NBQy9FO0lBQ0gsQ0FBQzs7Ozs7O0lBZk0sTUFBTSxDQUFDLEVBQUUsQ0FBQyxZQUFvQjtRQUNuQyxPQUFPLElBQUksWUFBWSxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBQ3hDLENBQUM7O0FBNUNILG9DQTBEQzs7Ozs7Ozs7QUF2RHdCLHFCQUFRLEdBQUcsWUFBWSxDQUFDLEVBQUUsQ0FBQyxhQUFhLENBQUMsQ0FBQzs7Ozs7O0FBRzFDLHNCQUFTLEdBQUcsWUFBWSxDQUFDLEVBQUUsQ0FBQyxjQUFjLENBQUMsQ0FBQzs7Ozs7O0FBRzVDLHVCQUFVLEdBQUcsWUFBWSxDQUFDLEVBQUUsQ0FBQyxlQUFlLENBQUMsQ0FBQzs7Ozs7O0FBRzlDLHVCQUFVLEdBQUcsWUFBWSxDQUFDLEVBQUUsQ0FBQyxlQUFlLENBQUMsQ0FBQzs7Ozs7O0FBRzlDLHVCQUFVLEdBQUcsWUFBWSxDQUFDLEVBQUUsQ0FBQyxlQUFlLENBQUMsQ0FBQzs7Ozs7O0FBRzlDLHdCQUFXLEdBQUcsWUFBWSxDQUFDLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDOzs7Ozs7QUFHaEQsd0JBQVcsR0FBRyxZQUFZLENBQUMsRUFBRSxDQUFDLGdCQUFnQixDQUFDLENBQUM7Ozs7OztBQUdoRCxxQkFBUSxHQUFHLFlBQVksQ0FBQyxFQUFFLENBQUMsYUFBYSxDQUFDLENBQUM7Ozs7OztBQUcxQyxzQkFBUyxHQUFHLFlBQVksQ0FBQyxFQUFFLENBQUMsY0FBYyxDQUFDLENBQUM7Ozs7OztBQUc1Qyx1QkFBVSxHQUFHLFlBQVksQ0FBQyxFQUFFLENBQUMsZUFBZSxDQUFDLENBQUM7Ozs7OztBQUc5Qyx1QkFBVSxHQUFHLFlBQVksQ0FBQyxFQUFFLENBQUMsZUFBZSxDQUFDLENBQUM7Ozs7OztBQUc5Qyx1QkFBVSxHQUFHLFlBQVksQ0FBQyxFQUFFLENBQUMsZUFBZSxDQUFDLENBQUM7Ozs7OztBQUc5QyxzQkFBUyxHQUFHLFlBQVksQ0FBQyxFQUFFLENBQUMsY0FBYyxDQUFDLENBQUM7Ozs7Ozs7QUFzRXJFLE1BQWEsZ0JBQWlCLFNBQVEsR0FBRyxDQUFDLFFBQVE7Ozs7SUErQmhELFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsS0FBNEI7O1FBQ3BFLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFakIsTUFBTSxRQUFRLEdBQUcsSUFBSSwyQkFBYSxDQUFDLElBQUksRUFBRSxVQUFVLEVBQUU7WUFDbkQsbUJBQW1CLEVBQUUsS0FBSyxDQUFDLE9BQU8sQ0FBQyxpQkFBaUI7WUFDcEQsZUFBZSxFQUFFLEtBQUssQ0FBQyxZQUFZLENBQUMsYUFBYTtZQUNqRCxnQkFBZ0IsRUFBRSxLQUFLLENBQUMsZ0JBQWdCO1lBQ3hDLG9CQUFvQixFQUFFLEtBQUssQ0FBQyxjQUFjO1lBQzFDLG9CQUFvQixRQUFFLEtBQUssQ0FBQyxjQUFjLDBDQUFFLGtCQUFrQjtTQUMvRCxDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUM7UUFDN0IsSUFBSSxDQUFDLGtCQUFrQixHQUFHLFFBQVEsQ0FBQyxHQUFHLENBQUM7UUFDdkMsSUFBSSxDQUFDLHlCQUF5QixHQUFHLFFBQVEsQ0FBQyxZQUFZLENBQUM7UUFDdkQsSUFBSSxDQUFDLHNCQUFzQixHQUFHLFFBQVEsQ0FBQyxRQUFRLENBQUM7UUFFaEQsaUVBQWlFO1FBQ2pFLE1BQU0sYUFBYSxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUM1RCxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxtQkFBUSxDQUFDLFFBQVEsQ0FBQyxZQUFZLEVBQUUsYUFBYSxDQUFDLENBQUM7UUFFM0UsUUFBUSxDQUFDLGtCQUFrQixDQUFDLEtBQUssQ0FBQyxhQUFhLEVBQUU7WUFDL0MsMEJBQTBCLEVBQUUsSUFBSTtTQUNqQyxDQUFDLENBQUM7SUFDTCxDQUFDOzs7Ozs7SUFuRE0sTUFBTSxDQUFDLDhCQUE4QixDQUFDLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQWlDO1FBQzFHLE1BQU0sTUFBTyxTQUFRLEdBQUcsQ0FBQyxRQUFRO1lBQWpDOztnQkFDa0IsZ0JBQVcsR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQ3ZDLHVCQUFrQixHQUFHLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQztnQkFDOUMsOEJBQXlCLEdBQUcsS0FBSyxDQUFDLHVCQUF1QixDQUFDO2dCQUMxRCwyQkFBc0IsR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO2dCQUMvQyxxQkFBZ0IsR0FBRyxJQUFJLG1CQUFRLENBQUMsS0FBSyxDQUFDLHVCQUF1QixFQUFFLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUM3RixDQUFDO1NBQUE7UUFFRCxPQUFPLElBQUksTUFBTSxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztJQUMvQixDQUFDOztBQWJILDRDQXVEQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGVjMiBmcm9tICdhd3MtY2RrLWxpYi9hd3MtZWMyJztcbmltcG9ydCAqIGFzIGNkayBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IElEYXRhYmFzZUNsdXN0ZXIgfSBmcm9tICcuL2NsdXN0ZXInO1xuaW1wb3J0IHsgRW5kcG9pbnQgfSBmcm9tICcuL2VuZHBvaW50JztcbmltcG9ydCB7IENmbkRCSW5zdGFuY2UgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbmVwdHVuZSc7XG5pbXBvcnQgeyBJUGFyYW1ldGVyR3JvdXAgfSBmcm9tICcuL3BhcmFtZXRlci1ncm91cCc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuZXhwb3J0IGNsYXNzIEluc3RhbmNlVHlwZSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBSNV9MQVJHRSA9IEluc3RhbmNlVHlwZS5vZignZGIucjUubGFyZ2UnKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBSNV9YTEFSR0UgPSBJbnN0YW5jZVR5cGUub2YoJ2RiLnI1LnhsYXJnZScpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBSNV8yWExBUkdFID0gSW5zdGFuY2VUeXBlLm9mKCdkYi5yNS4yeGxhcmdlJyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IFI1XzRYTEFSR0UgPSBJbnN0YW5jZVR5cGUub2YoJ2RiLnI1LjR4bGFyZ2UnKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgUjVfOFhMQVJHRSA9IEluc3RhbmNlVHlwZS5vZignZGIucjUuOHhsYXJnZScpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgUjVfMTJYTEFSR0UgPSBJbnN0YW5jZVR5cGUub2YoJ2RiLnI1LjEyeGxhcmdlJyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBSNV8yNFhMQVJHRSA9IEluc3RhbmNlVHlwZS5vZignZGIucjUuMjR4bGFyZ2UnKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IFI0X0xBUkdFID0gSW5zdGFuY2VUeXBlLm9mKCdkYi5yNC5sYXJnZScpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IFI0X1hMQVJHRSA9IEluc3RhbmNlVHlwZS5vZignZGIucjQueGxhcmdlJyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IFI0XzJYTEFSR0UgPSBJbnN0YW5jZVR5cGUub2YoJ2RiLnI0LjJ4bGFyZ2UnKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgUjRfNFhMQVJHRSA9IEluc3RhbmNlVHlwZS5vZignZGIucjQuNHhsYXJnZScpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBSNF84WExBUkdFID0gSW5zdGFuY2VUeXBlLm9mKCdkYi5yNC44eGxhcmdlJyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgVDNfTUVESVVNID0gSW5zdGFuY2VUeXBlLm9mKCdkYi50My5tZWRpdW0nKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgc3RhdGljIG9mKGluc3RhbmNlVHlwZTogc3RyaW5nKTogSW5zdGFuY2VUeXBlIHtcbiAgICByZXR1cm4gbmV3IEluc3RhbmNlVHlwZShpbnN0YW5jZVR5cGUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcmVhZG9ubHkgX2luc3RhbmNlVHlwZTogc3RyaW5nO1xuXG4gIHByaXZhdGUgY29uc3RydWN0b3IoaW5zdGFuY2VUeXBlOiBzdHJpbmcpIHtcbiAgICBpZiAoY2RrLlRva2VuLmlzVW5yZXNvbHZlZChpbnN0YW5jZVR5cGUpIHx8IGluc3RhbmNlVHlwZS5zdGFydHNXaXRoKCdkYi4nKSkge1xuICAgICAgdGhpcy5faW5zdGFuY2VUeXBlID0gaW5zdGFuY2VUeXBlO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGluc3RhbmNlIHR5cGUgbXVzdCBzdGFydCB3aXRoICdkYi4nOyAoZ290ICR7aW5zdGFuY2VUeXBlfSlgKTtcbiAgICB9XG4gIH1cbn1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG5leHBvcnQgaW50ZXJmYWNlIElEYXRhYmFzZUluc3RhbmNlIGV4dGVuZHMgY2RrLklSZXNvdXJjZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICByZWFkb25seSBpbnN0YW5jZUlkZW50aWZpZXI6IHN0cmluZztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHJlYWRvbmx5IGluc3RhbmNlRW5kcG9pbnQ6IEVuZHBvaW50O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICByZWFkb25seSBkYkluc3RhbmNlRW5kcG9pbnRBZGRyZXNzOiBzdHJpbmc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcmVhZG9ubHkgZGJJbnN0YW5jZUVuZHBvaW50UG9ydDogc3RyaW5nO1xufVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuZXhwb3J0IGludGVyZmFjZSBEYXRhYmFzZUluc3RhbmNlQXR0cmlidXRlcyB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICByZWFkb25seSBpbnN0YW5jZUlkZW50aWZpZXI6IHN0cmluZztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcmVhZG9ubHkgaW5zdGFuY2VFbmRwb2ludEFkZHJlc3M6IHN0cmluZztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcmVhZG9ubHkgcG9ydDogbnVtYmVyO1xufVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbmV4cG9ydCBpbnRlcmZhY2UgRGF0YWJhc2VJbnN0YW5jZVByb3BzIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICByZWFkb25seSBjbHVzdGVyOiBJRGF0YWJhc2VDbHVzdGVyO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHJlYWRvbmx5IGluc3RhbmNlVHlwZTogSW5zdGFuY2VUeXBlO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHJlYWRvbmx5IGF2YWlsYWJpbGl0eVpvbmU/OiBzdHJpbmc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHJlYWRvbmx5IGRiSW5zdGFuY2VOYW1lPzogc3RyaW5nO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHJlYWRvbmx5IHBhcmFtZXRlckdyb3VwPzogSVBhcmFtZXRlckdyb3VwO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICByZWFkb25seSByZW1vdmFsUG9saWN5PzogY2RrLlJlbW92YWxQb2xpY3lcbn1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbmV4cG9ydCBjbGFzcyBEYXRhYmFzZUluc3RhbmNlIGV4dGVuZHMgY2RrLlJlc291cmNlIGltcGxlbWVudHMgSURhdGFiYXNlSW5zdGFuY2Uge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIHN0YXRpYyBmcm9tRGF0YWJhc2VJbnN0YW5jZUF0dHJpYnV0ZXMoc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgYXR0cnM6IERhdGFiYXNlSW5zdGFuY2VBdHRyaWJ1dGVzKTogSURhdGFiYXNlSW5zdGFuY2Uge1xuICAgIGNsYXNzIEltcG9ydCBleHRlbmRzIGNkay5SZXNvdXJjZSBpbXBsZW1lbnRzIElEYXRhYmFzZUluc3RhbmNlIHtcbiAgICAgIHB1YmxpYyByZWFkb25seSBkZWZhdWx0UG9ydCA9IGVjMi5Qb3J0LnRjcChhdHRycy5wb3J0KTtcbiAgICAgIHB1YmxpYyByZWFkb25seSBpbnN0YW5jZUlkZW50aWZpZXIgPSBhdHRycy5pbnN0YW5jZUlkZW50aWZpZXI7XG4gICAgICBwdWJsaWMgcmVhZG9ubHkgZGJJbnN0YW5jZUVuZHBvaW50QWRkcmVzcyA9IGF0dHJzLmluc3RhbmNlRW5kcG9pbnRBZGRyZXNzO1xuICAgICAgcHVibGljIHJlYWRvbmx5IGRiSW5zdGFuY2VFbmRwb2ludFBvcnQgPSBhdHRycy5wb3J0LnRvU3RyaW5nKCk7XG4gICAgICBwdWJsaWMgcmVhZG9ubHkgaW5zdGFuY2VFbmRwb2ludCA9IG5ldyBFbmRwb2ludChhdHRycy5pbnN0YW5jZUVuZHBvaW50QWRkcmVzcywgYXR0cnMucG9ydCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBJbXBvcnQoc2NvcGUsIGlkKTtcbiAgfVxuXG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgcmVhZG9ubHkgY2x1c3RlcjogSURhdGFiYXNlQ2x1c3RlcjtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgcmVhZG9ubHkgaW5zdGFuY2VJZGVudGlmaWVyOiBzdHJpbmc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIHJlYWRvbmx5IGluc3RhbmNlRW5kcG9pbnQ6IEVuZHBvaW50O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHB1YmxpYyByZWFkb25seSBkYkluc3RhbmNlRW5kcG9pbnRBZGRyZXNzOiBzdHJpbmc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIHJlYWRvbmx5IGRiSW5zdGFuY2VFbmRwb2ludFBvcnQ6IHN0cmluZztcblxuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogRGF0YWJhc2VJbnN0YW5jZVByb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcblxuICAgIGNvbnN0IGluc3RhbmNlID0gbmV3IENmbkRCSW5zdGFuY2UodGhpcywgJ1Jlc291cmNlJywge1xuICAgICAgZGJDbHVzdGVySWRlbnRpZmllcjogcHJvcHMuY2x1c3Rlci5jbHVzdGVySWRlbnRpZmllcixcbiAgICAgIGRiSW5zdGFuY2VDbGFzczogcHJvcHMuaW5zdGFuY2VUeXBlLl9pbnN0YW5jZVR5cGUsXG4gICAgICBhdmFpbGFiaWxpdHlab25lOiBwcm9wcy5hdmFpbGFiaWxpdHlab25lLFxuICAgICAgZGJJbnN0YW5jZUlkZW50aWZpZXI6IHByb3BzLmRiSW5zdGFuY2VOYW1lLFxuICAgICAgZGJQYXJhbWV0ZXJHcm91cE5hbWU6IHByb3BzLnBhcmFtZXRlckdyb3VwPy5wYXJhbWV0ZXJHcm91cE5hbWUsXG4gICAgfSk7XG5cbiAgICB0aGlzLmNsdXN0ZXIgPSBwcm9wcy5jbHVzdGVyO1xuICAgIHRoaXMuaW5zdGFuY2VJZGVudGlmaWVyID0gaW5zdGFuY2UucmVmO1xuICAgIHRoaXMuZGJJbnN0YW5jZUVuZHBvaW50QWRkcmVzcyA9IGluc3RhbmNlLmF0dHJFbmRwb2ludDtcbiAgICB0aGlzLmRiSW5zdGFuY2VFbmRwb2ludFBvcnQgPSBpbnN0YW5jZS5hdHRyUG9ydDtcblxuICAgIC8vIGNyZWF0ZSBhIG51bWJlciB0b2tlbiB0aGF0IHJlcHJlc2VudHMgdGhlIHBvcnQgb2YgdGhlIGluc3RhbmNlXG4gICAgY29uc3QgcG9ydEF0dHJpYnV0ZSA9IGNkay5Ub2tlbi5hc051bWJlcihpbnN0YW5jZS5hdHRyUG9ydCk7XG4gICAgdGhpcy5pbnN0YW5jZUVuZHBvaW50ID0gbmV3IEVuZHBvaW50KGluc3RhbmNlLmF0dHJFbmRwb2ludCwgcG9ydEF0dHJpYnV0ZSk7XG5cbiAgICBpbnN0YW5jZS5hcHBseVJlbW92YWxQb2xpY3kocHJvcHMucmVtb3ZhbFBvbGljeSwge1xuICAgICAgYXBwbHlUb1VwZGF0ZVJlcGxhY2VQb2xpY3k6IHRydWUsXG4gICAgfSk7XG4gIH1cbn1cbiJdfQ==
@@ -42,7 +42,7 @@ class ClusterParameterGroup extends aws_cdk_lib_1.Resource {
42
42
  }
43
43
  exports.ClusterParameterGroup = ClusterParameterGroup;
44
44
  _a = JSII_RTTI_SYMBOL_1;
45
- ClusterParameterGroup[_a] = { fqn: "@aws-cdk/aws-neptune-alpha.ClusterParameterGroup", version: "2.0.0-alpha.3" };
45
+ ClusterParameterGroup[_a] = { fqn: "@aws-cdk/aws-neptune-alpha.ClusterParameterGroup", version: "2.0.0-alpha.4" };
46
46
  /**
47
47
  * (experimental) DB parameter group.
48
48
  *
@@ -80,5 +80,5 @@ class ParameterGroup extends aws_cdk_lib_1.Resource {
80
80
  }
81
81
  exports.ParameterGroup = ParameterGroup;
82
82
  _b = JSII_RTTI_SYMBOL_1;
83
- ParameterGroup[_b] = { fqn: "@aws-cdk/aws-neptune-alpha.ParameterGroup", version: "2.0.0-alpha.3" };
83
+ ParameterGroup[_b] = { fqn: "@aws-cdk/aws-neptune-alpha.ParameterGroup", version: "2.0.0-alpha.4" };
84
84
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFyYW1ldGVyLWdyb3VwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsicGFyYW1ldGVyLWdyb3VwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsNkNBQWtEO0FBRWxELHlEQUEwRjs7Ozs7OztBQWlDMUYsTUFBYSxxQkFBc0IsU0FBUSxzQkFBUTs7OztJQVlqRCxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQWlDO1FBQ3pFLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFakIsTUFBTSxRQUFRLEdBQUcsSUFBSSx3Q0FBMEIsQ0FBQyxJQUFJLEVBQUUsVUFBVSxFQUFFO1lBQ2hFLElBQUksRUFBRSxLQUFLLENBQUMseUJBQXlCO1lBQ3JDLFdBQVcsRUFBRSxLQUFLLENBQUMsV0FBVyxJQUFJLGdEQUFnRDtZQUNsRixNQUFNLEVBQUUsVUFBVTtZQUNsQixVQUFVLEVBQUUsS0FBSyxDQUFDLFVBQVU7U0FDN0IsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLHlCQUF5QixHQUFHLFFBQVEsQ0FBQyxHQUFHLENBQUM7SUFDaEQsQ0FBQzs7Ozs7O0lBckJNLE1BQU0sQ0FBQyw2QkFBNkIsQ0FBQyxLQUFnQixFQUFFLEVBQVUsRUFBRSx5QkFBaUM7UUFDekcsTUFBTSxNQUFPLFNBQVEsc0JBQVE7WUFBN0I7O2dCQUNrQiw4QkFBeUIsR0FBRyx5QkFBeUIsQ0FBQztZQUN4RSxDQUFDO1NBQUE7UUFDRCxPQUFPLElBQUksTUFBTSxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztJQUMvQixDQUFDOztBQVBILHNEQXdCQzs7Ozs7Ozs7O0FBU0QsTUFBYSxjQUFlLFNBQVEsc0JBQVE7Ozs7SUFZMUMsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUEwQjtRQUNsRSxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRWpCLE1BQU0sUUFBUSxHQUFHLElBQUksaUNBQW1CLENBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRTtZQUN6RCxJQUFJLEVBQUUsS0FBSyxDQUFDLGtCQUFrQjtZQUM5QixXQUFXLEVBQUUsS0FBSyxDQUFDLFdBQVcsSUFBSSxtREFBbUQ7WUFDckYsTUFBTSxFQUFFLFVBQVU7WUFDbEIsVUFBVSxFQUFFLEtBQUssQ0FBQyxVQUFVO1NBQzdCLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxrQkFBa0IsR0FBRyxRQUFRLENBQUMsR0FBRyxDQUFDO0lBQ3pDLENBQUM7Ozs7OztJQXJCTSxNQUFNLENBQUMsc0JBQXNCLENBQUMsS0FBZ0IsRUFBRSxFQUFVLEVBQUUsa0JBQTBCO1FBQzNGLE1BQU0sTUFBTyxTQUFRLHNCQUFRO1lBQTdCOztnQkFDa0IsdUJBQWtCLEdBQUcsa0JBQWtCLENBQUM7WUFDMUQsQ0FBQztTQUFBO1FBQ0QsT0FBTyxJQUFJLE1BQU0sQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDL0IsQ0FBQzs7QUFQSCx3Q0F3QkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJUmVzb3VyY2UsIFJlc291cmNlIH0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBDZm5EQkNsdXN0ZXJQYXJhbWV0ZXJHcm91cCwgQ2ZuREJQYXJhbWV0ZXJHcm91cCB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1uZXB0dW5lJztcblxuLyoqXG4gKiBQcm9wZXJ0aWVzIGZvciBhIHBhcmFtZXRlciBncm91cFxuICovXG5pbnRlcmZhY2UgUGFyYW1ldGVyR3JvdXBQcm9wc0Jhc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICByZWFkb25seSBkZXNjcmlwdGlvbj86IHN0cmluZztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICByZWFkb25seSBwYXJhbWV0ZXJzOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9O1xufVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbmV4cG9ydCBpbnRlcmZhY2UgQ2x1c3RlclBhcmFtZXRlckdyb3VwUHJvcHMgZXh0ZW5kcyBQYXJhbWV0ZXJHcm91cFByb3BzQmFzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHJlYWRvbmx5IGNsdXN0ZXJQYXJhbWV0ZXJHcm91cE5hbWU/OiBzdHJpbmc7XG59XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuZXhwb3J0IGludGVyZmFjZSBQYXJhbWV0ZXJHcm91cFByb3BzIGV4dGVuZHMgUGFyYW1ldGVyR3JvdXBQcm9wc0Jhc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICByZWFkb25seSBwYXJhbWV0ZXJHcm91cE5hbWU/OiBzdHJpbmc7XG59XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbmV4cG9ydCBpbnRlcmZhY2UgSUNsdXN0ZXJQYXJhbWV0ZXJHcm91cCBleHRlbmRzIElSZXNvdXJjZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHJlYWRvbmx5IGNsdXN0ZXJQYXJhbWV0ZXJHcm91cE5hbWU6IHN0cmluZztcbn1cblxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbmV4cG9ydCBjbGFzcyBDbHVzdGVyUGFyYW1ldGVyR3JvdXAgZXh0ZW5kcyBSZXNvdXJjZSBpbXBsZW1lbnRzIElDbHVzdGVyUGFyYW1ldGVyR3JvdXAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHB1YmxpYyBzdGF0aWMgZnJvbUNsdXN0ZXJQYXJhbWV0ZXJHcm91cE5hbWUoc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgY2x1c3RlclBhcmFtZXRlckdyb3VwTmFtZTogc3RyaW5nKTogSUNsdXN0ZXJQYXJhbWV0ZXJHcm91cCB7XG4gICAgY2xhc3MgSW1wb3J0IGV4dGVuZHMgUmVzb3VyY2UgaW1wbGVtZW50cyBJQ2x1c3RlclBhcmFtZXRlckdyb3VwIHtcbiAgICAgIHB1YmxpYyByZWFkb25seSBjbHVzdGVyUGFyYW1ldGVyR3JvdXBOYW1lID0gY2x1c3RlclBhcmFtZXRlckdyb3VwTmFtZTtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBJbXBvcnQoc2NvcGUsIGlkKTtcbiAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIHJlYWRvbmx5IGNsdXN0ZXJQYXJhbWV0ZXJHcm91cE5hbWU6IHN0cmluZztcblxuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogQ2x1c3RlclBhcmFtZXRlckdyb3VwUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgY29uc3QgcmVzb3VyY2UgPSBuZXcgQ2ZuREJDbHVzdGVyUGFyYW1ldGVyR3JvdXAodGhpcywgJ1Jlc291cmNlJywge1xuICAgICAgbmFtZTogcHJvcHMuY2x1c3RlclBhcmFtZXRlckdyb3VwTmFtZSxcbiAgICAgIGRlc2NyaXB0aW9uOiBwcm9wcy5kZXNjcmlwdGlvbiB8fCAnQ2x1c3RlciBwYXJhbWV0ZXIgZ3JvdXAgZm9yIG5lcHR1bmUgZGIgY2x1c3RlcicsXG4gICAgICBmYW1pbHk6ICduZXB0dW5lMScsXG4gICAgICBwYXJhbWV0ZXJzOiBwcm9wcy5wYXJhbWV0ZXJzLFxuICAgIH0pO1xuXG4gICAgdGhpcy5jbHVzdGVyUGFyYW1ldGVyR3JvdXBOYW1lID0gcmVzb3VyY2UucmVmO1xuICB9XG59XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbmV4cG9ydCBpbnRlcmZhY2UgSVBhcmFtZXRlckdyb3VwIGV4dGVuZHMgSVJlc291cmNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcmVhZG9ubHkgcGFyYW1ldGVyR3JvdXBOYW1lOiBzdHJpbmc7XG59XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbmV4cG9ydCBjbGFzcyBQYXJhbWV0ZXJHcm91cCBleHRlbmRzIFJlc291cmNlIGltcGxlbWVudHMgSVBhcmFtZXRlckdyb3VwIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgc3RhdGljIGZyb21QYXJhbWV0ZXJHcm91cE5hbWUoc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcGFyYW1ldGVyR3JvdXBOYW1lOiBzdHJpbmcpOiBJUGFyYW1ldGVyR3JvdXAge1xuICAgIGNsYXNzIEltcG9ydCBleHRlbmRzIFJlc291cmNlIGltcGxlbWVudHMgSVBhcmFtZXRlckdyb3VwIHtcbiAgICAgIHB1YmxpYyByZWFkb25seSBwYXJhbWV0ZXJHcm91cE5hbWUgPSBwYXJhbWV0ZXJHcm91cE5hbWU7XG4gICAgfVxuICAgIHJldHVybiBuZXcgSW1wb3J0KHNjb3BlLCBpZCk7XG4gIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHB1YmxpYyByZWFkb25seSBwYXJhbWV0ZXJHcm91cE5hbWU6IHN0cmluZztcblxuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogUGFyYW1ldGVyR3JvdXBQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICBjb25zdCByZXNvdXJjZSA9IG5ldyBDZm5EQlBhcmFtZXRlckdyb3VwKHRoaXMsICdSZXNvdXJjZScsIHtcbiAgICAgIG5hbWU6IHByb3BzLnBhcmFtZXRlckdyb3VwTmFtZSxcbiAgICAgIGRlc2NyaXB0aW9uOiBwcm9wcy5kZXNjcmlwdGlvbiB8fCAnSW5zdGFuY2UgcGFyYW1ldGVyIGdyb3VwIGZvciBuZXB0dW5lIGRiIGluc3RhbmNlcycsXG4gICAgICBmYW1pbHk6ICduZXB0dW5lMScsXG4gICAgICBwYXJhbWV0ZXJzOiBwcm9wcy5wYXJhbWV0ZXJzLFxuICAgIH0pO1xuXG4gICAgdGhpcy5wYXJhbWV0ZXJHcm91cE5hbWUgPSByZXNvdXJjZS5yZWY7XG4gIH1cbn1cbiJdfQ==
@@ -46,5 +46,5 @@ class SubnetGroup extends aws_cdk_lib_1.Resource {
46
46
  }
47
47
  exports.SubnetGroup = SubnetGroup;
48
48
  _a = JSII_RTTI_SYMBOL_1;
49
- SubnetGroup[_a] = { fqn: "@aws-cdk/aws-neptune-alpha.SubnetGroup", version: "2.0.0-alpha.3" };
49
+ SubnetGroup[_a] = { fqn: "@aws-cdk/aws-neptune-alpha.SubnetGroup", version: "2.0.0-alpha.4" };
50
50
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3VibmV0LWdyb3VwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3VibmV0LWdyb3VwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsMkNBQTJDO0FBQzNDLDZDQUFpRTtBQUVqRSx5REFBMkQ7Ozs7Ozs7QUEyQjNELE1BQWEsV0FBWSxTQUFRLHNCQUFROzs7O0lBV3ZDLFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsS0FBdUI7O1FBQy9ELEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFakIsTUFBTSxFQUFFLFNBQVMsRUFBRSxHQUFHLEtBQUssQ0FBQyxHQUFHLENBQUMsYUFBYSxPQUFDLEtBQUssQ0FBQyxVQUFVLG1DQUFJLEVBQUUsVUFBVSxFQUFFLEdBQUcsQ0FBQyxVQUFVLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztRQUUxRyxNQUFNLFdBQVcsR0FBRyxJQUFJLDhCQUFnQixDQUFDLElBQUksRUFBRSxVQUFVLEVBQUU7WUFDekQsd0JBQXdCLEVBQUUsS0FBSyxDQUFDLFdBQVcsSUFBSSwwQkFBMEI7WUFDekUsaUJBQWlCLEVBQUUsS0FBSyxDQUFDLGVBQWU7WUFDeEMsU0FBUztTQUNWLENBQUMsQ0FBQztRQUVILElBQUksS0FBSyxDQUFDLGFBQWEsRUFBRTtZQUN2QixXQUFXLENBQUMsa0JBQWtCLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxDQUFDO1NBQ3JEO1FBRUQsSUFBSSxDQUFDLGVBQWUsR0FBRyxXQUFXLENBQUMsR0FBRyxDQUFDO0lBQ3pDLENBQUM7Ozs7OztJQXhCTSxNQUFNLENBQUMsbUJBQW1CLENBQUMsS0FBZ0IsRUFBRSxFQUFVLEVBQUUsZUFBdUI7UUFDckYsT0FBTyxJQUFJLEtBQU0sU0FBUSxzQkFBUTtZQUF0Qjs7Z0JBQ08sb0JBQWUsR0FBRyxlQUFlLENBQUM7WUFDcEQsQ0FBQztTQUFBLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ2YsQ0FBQzs7QUFQSCxrQ0E0QkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBlYzIgZnJvbSAnYXdzLWNkay1saWIvYXdzLWVjMic7XG5pbXBvcnQgeyBJUmVzb3VyY2UsIFJlbW92YWxQb2xpY3ksIFJlc291cmNlIH0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBDZm5EQlN1Ym5ldEdyb3VwIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLW5lcHR1bmUnO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG5leHBvcnQgaW50ZXJmYWNlIElTdWJuZXRHcm91cCBleHRlbmRzIElSZXNvdXJjZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICByZWFkb25seSBzdWJuZXRHcm91cE5hbWU6IHN0cmluZztcbn1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuZXhwb3J0IGludGVyZmFjZSBTdWJuZXRHcm91cFByb3BzIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICByZWFkb25seSBkZXNjcmlwdGlvbj86IHN0cmluZztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHJlYWRvbmx5IHZwYzogZWMyLklWcGM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICByZWFkb25seSBzdWJuZXRHcm91cE5hbWU/OiBzdHJpbmc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcmVhZG9ubHkgdnBjU3VibmV0cz86IGVjMi5TdWJuZXRTZWxlY3Rpb247XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcmVhZG9ubHkgcmVtb3ZhbFBvbGljeT86IFJlbW92YWxQb2xpY3lcbn1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbmV4cG9ydCBjbGFzcyBTdWJuZXRHcm91cCBleHRlbmRzIFJlc291cmNlIGltcGxlbWVudHMgSVN1Ym5ldEdyb3VwIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgc3RhdGljIGZyb21TdWJuZXRHcm91cE5hbWUoc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgc3VibmV0R3JvdXBOYW1lOiBzdHJpbmcpOiBJU3VibmV0R3JvdXAge1xuICAgIHJldHVybiBuZXcgY2xhc3MgZXh0ZW5kcyBSZXNvdXJjZSBpbXBsZW1lbnRzIElTdWJuZXRHcm91cCB7XG4gICAgICBwdWJsaWMgcmVhZG9ubHkgc3VibmV0R3JvdXBOYW1lID0gc3VibmV0R3JvdXBOYW1lO1xuICAgIH0oc2NvcGUsIGlkKTtcbiAgfVxuXG4gIHB1YmxpYyByZWFkb25seSBzdWJuZXRHcm91cE5hbWU6IHN0cmluZztcblxuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogU3VibmV0R3JvdXBQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICBjb25zdCB7IHN1Ym5ldElkcyB9ID0gcHJvcHMudnBjLnNlbGVjdFN1Ym5ldHMocHJvcHMudnBjU3VibmV0cyA/PyB7IHN1Ym5ldFR5cGU6IGVjMi5TdWJuZXRUeXBlLlBSSVZBVEUgfSk7XG5cbiAgICBjb25zdCBzdWJuZXRHcm91cCA9IG5ldyBDZm5EQlN1Ym5ldEdyb3VwKHRoaXMsICdSZXNvdXJjZScsIHtcbiAgICAgIGRiU3VibmV0R3JvdXBEZXNjcmlwdGlvbjogcHJvcHMuZGVzY3JpcHRpb24gfHwgJ1N1Ym5ldCBncm91cCBmb3IgTmVwdHVuZScsXG4gICAgICBkYlN1Ym5ldEdyb3VwTmFtZTogcHJvcHMuc3VibmV0R3JvdXBOYW1lLFxuICAgICAgc3VibmV0SWRzLFxuICAgIH0pO1xuXG4gICAgaWYgKHByb3BzLnJlbW92YWxQb2xpY3kpIHtcbiAgICAgIHN1Ym5ldEdyb3VwLmFwcGx5UmVtb3ZhbFBvbGljeShwcm9wcy5yZW1vdmFsUG9saWN5KTtcbiAgICB9XG5cbiAgICB0aGlzLnN1Ym5ldEdyb3VwTmFtZSA9IHN1Ym5ldEdyb3VwLnJlZjtcbiAgfVxufVxuIl19
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aws-cdk/aws-neptune-alpha",
3
- "version": "2.0.0-alpha.3",
3
+ "version": "2.0.0-alpha.4",
4
4
  "private": false,
5
5
  "description": "The CDK Construct Library for AWS::Neptune",
6
6
  "main": "lib/index.js",
@@ -77,18 +77,18 @@
77
77
  },
78
78
  "license": "Apache-2.0",
79
79
  "devDependencies": {
80
- "@aws-cdk/cdk-build-tools": "2.0.0-rc.26",
81
- "@aws-cdk/cdk-integ-tools": "2.0.0-rc.26",
82
- "@aws-cdk/cfn2ts": "2.0.0-rc.26",
83
- "@aws-cdk/pkglint": "2.0.0-rc.26",
80
+ "@aws-cdk/cdk-build-tools": "2.0.0-rc.27",
81
+ "@aws-cdk/cdk-integ-tools": "2.0.0-rc.27",
82
+ "@aws-cdk/cfn2ts": "2.0.0-rc.27",
83
+ "@aws-cdk/pkglint": "2.0.0-rc.27",
84
84
  "@types/jest": "^26.0.24",
85
- "aws-cdk-lib": "2.0.0-rc.26",
85
+ "aws-cdk-lib": "2.0.0-rc.27",
86
86
  "constructs": "^10.0.0",
87
- "@aws-cdk/assertions-alpha": "2.0.0-alpha.3"
87
+ "@aws-cdk/assertions-alpha": "2.0.0-alpha.4"
88
88
  },
89
89
  "dependencies": {},
90
90
  "peerDependencies": {
91
- "aws-cdk-lib": "^2.0.0-rc.26",
91
+ "aws-cdk-lib": "^2.0.0-rc.27",
92
92
  "constructs": "^10.0.0"
93
93
  },
94
94
  "engines": {