Why is AWS CloudFormation throwing "Encountered unsupported property InstanceGroups"? - amazon-web-services

When I deploy the below AWS CloudFormation script, I am getting the following error: "Encountered unsupported property InstanceGroups"
I have used InstanceGroups in the past without any issues. Here is an example of how others using it: https://noise.getoto.net/tag/amazon-emr/
I am using EMR 5.17.0, which I have used to set up before.
{
"Description": "Spark ETL EMR CloudFormation",
"Resources": {
"EMRCluster": {
"Type": "AWS::EMR::Cluster",
"Properties": {
"Applications": [
{
"Name": "Hadoop"
},
{
"Name": "Spark"
},
{
"Name": "Ganglia"
},
{
"Name": "Zeppelin"
}
],
"AutoScalingRole": "EMR_AutoScaling_DefaultRole",
"BootstrapActions": [
{
"Path": "s3://somepath/scripts/install_pip36_dependencies.sh",
"Args": [
"relay==0.0.1"
],
"Name": "install_pip36_dependencies"
}
],
"Configurations": [
{
"Classification": "yarn-site",
"Properties": {
"yarn.scheduler.fair.preemption": "False",
"yarn.resourcemanager.am.max-attempts": "1"
},
"Configurations": []
},
{
"Classification": "core-site",
"Properties": {
"fs.s3.canned.acl": "BucketOwnerFullControl"
},
"Configurations": []
}
],
"EbsRootVolumeSize": 10,
"InstanceGroups": [
{
"Name": "Master",
"Market": "ON_DEMAND",
"InstanceRole": "MASTER",
"InstanceType": "m5.2xlarge",
"InstanceCount": 1,
"EbsConfiguration": {
"EbsBlockDeviceConfigs": [
{
"VolumeSpecification": {
"SizeInGB": 100,
"VolumeType": "64"
},
"VolumesPerInstance": 1
}
],
"EbsOptimized": "True"
}
},
{
"Name": "Core",
"Market": "ON_DEMAND",
"InstanceGroupType": "CORE",
"InstanceType": "m5.2xlarge",
"InstanceCount": 5,
"EbsConfiguration": {
"EbsBlockDeviceConfigs": [
{
"VolumeSpecification": {
"SizeInGB": 100,
"VolumeType": "gp2"
},
"VolumesPerInstance": 1
}
],
"EbsOptimized": "True"
}
},
{
"Name": "Task - 3",
"Market": "ON_DEMAND",
"InstanceGroupType": "TASK",
"InstanceType": "m5.2xlarge",
"InstanceCount": 2,
"EbsConfiguration": {
"EbsBlockDeviceConfigs": [
{
"VolumeSpecification": {
"SizeInGB": 32,
"VolumeType": "gp2"
},
"VolumesPerInstance": 1
}
],
"EbsOptimized": "True"
}
}
],
"LogUri": "s3://somepath/emr-logs/",
"Name": "EMR CF",
"ReleaseLabel": "emr-5.17.0",
"ServiceRole": "EMR_DefaultRole",
"VisibleToAllUsers": "True"
}
}
}
}
When the CF script is loaded, it should create an AWS EMR cluster

Aws recommends that you set MasterInstanceGroup and CoreInstanceGroup under Instances
I give you an example of the Instances property of an EMR Cluster with Hadoop, Hbase, Spark, Ganglia and Zookeeper:
Instances:
Ec2KeyName: !Ref KeyName
Ec2SubnetId: !ImportValue MySubnetPrivateA
EmrManagedMasterSecurityGroup: !ImportValue EmrMasterSgId
AdditionalMasterSecurityGroups:
- !ImportValue EmrMasterAdditionalSgId
EmrManagedSlaveSecurityGroup: !ImportValue EmrSlaveSgId
AdditionalSlaveSecurityGroups:
- !ImportValue EmrSlaveAdditionalSgId
ServiceAccessSecurityGroup: !ImportValue EmrServiceSgId
MasterInstanceGroup:
InstanceCount: 1
InstanceType: !Ref MasterInstanceType
Market: ON_DEMAND
Name: Master
CoreInstanceGroup:
InstanceCount: !Ref NumberOfCoreInstances
InstanceType: !Ref CoreInstanceType
Market: ON_DEMAND
Name: Core
TerminationProtected: false
VisibleToAllUsers: true
JobFlowRole: !Ref EMRClusterinstanceProfile
ReleaseLabel: !Ref ReleaseLabel
LogUri: !Ref LogUri
Name: !Ref EMRClusterName
AutoScalingRole: EMR_AutoScaling_DefaultRole
ServiceRole: !Ref EMRClusterServiceRole
Tags:
-
Key: "cluster_name"
Value: "master.emr.my.com"
You can see the complete AWS template here.

Related

EKS Managed Nodegroup with Capacity Reservation in Launch Template through CloudFormation does not use Capacity Reservation

I am creating a Managed Nodegroup for EKS using CloudFormation.
I have an EC2 Launch Template with a CapacityReservationSpecification defined.
The Launch Template is linked to the Managed Nodegroup using CloudFormation. When the Managed Node Group is initialised the Launch Template is copied with an eks-*** prefix in the name. The CapacityReservationSpecification is not copied to the newly generated Launch Template. Cloud Formation script Example:
LaunchTemplate:
Resources:
LaunchTemplateAux:
Type: 'AWS::EC2::LaunchTemplate'
Properties:
LaunchTemplateData:
InstanceType: t3.medium
CapacityReservationSpecification:
CapacityReservationTarget:
CapacityReservationResourceGroupArn: {{reservation_group_arn}}
MetadataOptions:
HttpPutResponseHopLimit: 2
HttpTokens: optional
SecurityGroupIds:
- xxxxx
LaunchTemplateName: !Sub '${AWS::StackName}Aux'
NodeGroup:
ManagedNodeGroupAux:
Type: 'AWS::EKS::Nodegroup'
Properties:
AmiType: AL2_x86_64
ClusterName: test-cluster
Labels:
alpha.eksctl.io/cluster-name: test-cluster
alpha.eksctl.io/nodegroup-name: test-ng-aux
LaunchTemplate:
Id: !Ref LaunchTemplateAux
NodeRole: node-instance-role::NodeInstanceRole'
NodegroupName: test-nodegroup
ScalingConfig:
DesiredSize: 1
MaxSize: 2
MinSize: 1
Subnets:
- xxx
The resulting launch templates are as follows. Obtained using the following command aws ec2 describe-launch-template-versions --launch-template-id <template-id>
My Launch template Output:
{
"LaunchTemplateVersions": [
{
"LaunchTemplateId": "lt-xx",
"LaunchTemplateName": "test-cluster-ngAux",
"VersionNumber": 1,
"CreateTime": "2022-03-24T12:35:05+00:00",
"CreatedBy": "xxx:user/xxx",
"DefaultVersion": true,
"LaunchTemplateData": {
"InstanceType": "t3.medium",
"SecurityGroupIds": [
"sg-xxx"
],
"CapacityReservationSpecification": {
"CapacityReservationTarget": {
"CapacityReservationResourceGroupArn": "arn:aws:resource-groups:xxxxx:group/my-group"
}
},
"MetadataOptions": {
"HttpTokens": "optional",
"HttpPutResponseHopLimit": 2
}
}
}
]
}
Launch template copied by EKS API:
{
"LaunchTemplateVersions": [
{
"LaunchTemplateId": "lt-xxx",
"LaunchTemplateName": "eks-xxx",
"VersionNumber": 1,
"CreateTime": "2022-03-24T12:35:46+00:00",
"CreatedBy": "xxx:assumed-role/AWSServiceRoleForAmazonEKSNodegroup/EKS",
"DefaultVersion": true,
"LaunchTemplateData": {
"IamInstanceProfile": {
"Name": "xxx"
},
"ImageId": "ami-0c37e3f6cdf6a9007",
"InstanceType": "t3.medium",
"UserData": "xxx",
"TagSpecifications": [
{
"ResourceType": "volume",
"Tags": [
{
"Key": "eks:cluster-name",
"Value": "test-cluster"
},
{
"Key": "eks:nodegroup-name",
"Value": "test-cluster-ng-aux"
}
]
},
{
"ResourceType": "instance",
"SecurityGroupIds": [
"xxx"
],
"MetadataOptions": {
"HttpTokens": "optional",
"HttpPutResponseHopLimit": 2
}
}
}
]
}
This seems to be a bug in AWS. They have informed me that they will fix it.
https://repost.aws/questions/QUaid5sRdmRu2OFi7SQyxytg#ANF8uJ5RulQtmrVMaabAKZZg

aws cloudformation template for spot request in ec2 instance

I need a sample cloud formation template to add spot requests while provisioning the ec2 instance in AWS.I have tried with console to provision spot instances but I couldn't find any exact template for add spot request in ec2
You Can create a SpotFleet resource, here's an example
SpotFleet:
Type: AWS::EC2::SpotFleet
Properties:
SpotFleetRequestConfigData:
IamFleetRole: !GetAtt [IAMFleetRole, Arn]
SpotPrice: '1000'
TargetCapacity:
Ref: TargetCapacity
LaunchSpecifications:
- EbsOptimized: 'false'
InstanceType:
Ref: InstanceType
ImageId:
Fn::FindInMap:
- AWSRegionArch2AMI
- Ref: AWS::Region
- Fn::FindInMap:
- AWSInstanceType2Arch
- Ref: InstanceType
- Arch
SubnetId:
Ref: Subnet1
WeightedCapacity: '8'
- EbsOptimized: 'true'
InstanceType:
Ref: InstanceType
ImageId:
Fn::FindInMap:
- AWSRegionArch2AMI
- Ref: AWS::Region
- Fn::FindInMap:
- AWSInstanceType2Arch
- Ref: InstanceType
- Arch
Monitoring:
Enabled: 'true'
SecurityGroups:
- GroupId:
Fn::GetAtt:
- SG0
- GroupId
SubnetId:
Ref: Subnet0
IamInstanceProfile:
Arn:
Fn::GetAtt:
- RootInstanceProfile
- Arn
WeightedCapacity: '8'
You need to create Spot-fleet resource.
Example :
"SpotFleet": {
"Type": "AWS::EC2::SpotFleet",
"Properties": {
"SpotFleetRequestConfigData": {
"IamFleetRole": { "Fn::GetAtt": [ "IAMFleetRole", "Arn"] },
"SpotPrice": "1000",
"TargetCapacity": { "Ref": "TargetCapacity" },
"LaunchSpecifications": [
{
"EbsOptimized": "false",
"InstanceType": { "Ref": "InstanceType" },
"ImageId": { "Fn::FindInMap": [ "AWSRegionArch2AMI", { "Ref": "AWS::Region" },
{ "Fn::FindInMap": [ "AWSInstanceType2Arch", { "Ref": "InstanceType" }, "Arch" ] }
]},
"SubnetId": { "Ref": "Subnet1" },
"WeightedCapacity": "8"
},
{
"EbsOptimized": "true",
"InstanceType": { "Ref": "InstanceType" },
"ImageId": { "Fn::FindInMap": [ "AWSRegionArch2AMI", { "Ref": "AWS::Region" },
{ "Fn::FindInMap": [ "AWSInstanceType2Arch", { "Ref": "InstanceType" }, "Arch" ] }
]},
"Monitoring": { "Enabled": "true" },
"SecurityGroups": [ { "GroupId": { "Fn::GetAtt": [ "SG0", "GroupId" ] } } ],
"SubnetId": { "Ref": "Subnet0" },
"IamInstanceProfile": { "Arn": { "Fn::GetAtt": [ "RootInstanceProfile", "Arn" ] } },
"WeightedCapacity": "8"
}
]
}
}
}
More details can be found in this link :
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-spotfleet.html

Invalid Parameter Combination when creating a new Elasticache Redis Instance using Cloudformation

I am creating a new stack which includes a Redis instance, after starting the creation, I get this error for redis:
Cannot use the given parameters when creating new replication group
in an existing global replication group. (Service: AmazonElastiCache;
Status Code: 400; Error Code: InvalidParameterCombination;
I am new to using elasticache within cloudformation and the documentation doesn't provide a lot of helpful information for the valid/correct combination.
I am using the following snippet:
cachesubnet:
Type: AWS::ElastiCache::SubnetGroup
Properties:
CacheSubnetGroupName: !Join ["-" , ["rb", !Ref Environment, "redis-subnet-group"]]
Description: subnet group for redis
SubnetIds:
- !Ref private1a
- !Ref private1b
Tags:
- Key: environment
Value: !Ref Environment
redis2:
Type: AWS::ElastiCache::ReplicationGroup
Properties:
AtRestEncryptionEnabled: True
AutomaticFailoverEnabled: True
AutoMinorVersionUpgrade: True
CacheNodeType: cache.m5.large
CacheParameterGroupName: default.redis5.0
CacheSubnetGroupName: !Ref cachesubnet
Engine: redis
EngineVersion: 5.0.6
NumNodeGroups: 1
GlobalReplicationGroupId: !Join ["-" , ["rb-horizon", !Ref Environment]]
MultiAZEnabled: True
NodeGroupConfiguration:
- PrimaryAvailabilityZone: us-east-1a
- ReplicaAvailabilityZones:
- us-east-1b
- ReplicaCount: 1
PreferredCacheClusterAZs:
- us-east-1a
- us-east-1b
PreferredMaintenanceWindow: mon:06:30-mon:07:30
ReplicationGroupDescription: Horizon for env
ReplicationGroupId: !Join ["-" , ["rb-horizon", !Ref Environment, rgi]]
SecurityGroupIds:
- !GetAtt mainSecGroup.GroupId
Tags:
- Key: environment
Value: !Ref Environment
Ran into a similar issue today and was able to solve it via some information gleaned from this thread https://old.reddit.com/r/aws/comments/rvgv15/demystifying_redis_in_cloudformation_multiaz_and/
You do not need to specify parameters such as Engine, EngineVersion, CacheNodeType, etc... because ElastiCache will know to use the same values as the ones provided in the primary replication group of the global datastore.
While it says there that the params are not needed, they actually do raise the above error message. I added a condition around those fields and then my stack went through fine.
// edited to add example below
Example redis template. I removed the mappings and snipped the security group ingress rules which are not relevant for demonstration purposes.
The GlobalReplicationGroupId param should not be set for the PRIMARY redis group. Instead, the PRIMARY is joined to the global data store while creating the GlobalReplicationGroup. You should only add the primary member in that resource.
For creating the secondary groups, first launch redis with this param empty and then update it with the param pointing to the previously created GlobalReplicationGroup to join the global store.
{
"AWSTemplateFormatVersion": "2010-09-09",
"Parameters": {
"GlobalReplicationGroupId": {
"Description": "ID of the previously created Global Replication Group (optional)",
"Type": "String",
"Default": ""
}
},
"Conditions": {
"IsGlobalStore": {
"Fn::Not": [{
"Fn::Equals": [ { "Ref": "GlobalReplicationGroupId" }, "" ]
}]
}
},
"Resources": {
"RedisParameterGroup": {
"Type": "AWS::ElastiCache::ParameterGroup",
"Properties": {
"CacheParameterGroupFamily": "redis6.x",
"Description": {
"Fn::Join": [
"",
[
"Redis Parameter Group ",
{
"Ref": "EnvironmentName"
}
]
]
}
}
},
"RedisSubnetGroup": {
"Type": "AWS::ElastiCache::SubnetGroup",
"Properties": {
"CacheSubnetGroupName": {
"Fn::Join": [
"", [
"", { "Ref": "EnvironmentName" }, "-redis-subnet-group"
]
]
},
"SubnetIds": {
"Fn::FindInMap": [
"privateSubnets",
{
"Ref": "AWS::Region"
},
{
"Ref": "EnvironmentName"
}
]
},
"Description": {
"Fn::Join": [
"",
[
"Redis Subnet Group ",
{
"Ref": "EnvironmentName"
}
]
]
}
}
},
"RedisSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": {
"Fn::Join": [
"",
[
"Redis Security Group ",
{
"Ref": "EnvironmentName"
}
]
]
},
"VpcId": {
"Fn::FindInMap": [
"vpcId",
{
"Ref": "AWS::Region"
},
{
"Ref": "EnvironmentName"
}
]
},
"SecurityGroupIngress": [
],
"Tags": [
{
"Key": "Name",
"Value": {
"Fn::Join": [
"",
[
"Redis-",
{
"Ref": "EnvironmentName"
},
"-SecurityGroup"
]
]
}
},
{
"Key": "Product",
"Value": "Redis"
},
{
"Key": "Environment",
"Value": {
"Ref": "EnvironmentName"
}
}
]
}
},
"RedisReplicationGroup": {
"Type": "AWS::ElastiCache::ReplicationGroup",
"Properties": {
"GlobalReplicationGroupId": {
"Fn::If": [
"IsGlobalStore",
{"Ref": "GlobalReplicationGroupId"},
{"Ref": "AWS::NoValue"}
]
},
"AutomaticFailoverEnabled": "true",
"CacheNodeType": {
"Fn::If": [
"IsGlobalStore",
{
"Ref": "AWS::NoValue"
},
{
"Fn::FindInMap": [
"RedisNodeType",
{
"Ref": "AWS::Region"
},
{
"Ref": "EnvironmentName"
}
]
}
]
},
"CacheParameterGroupName": {
"Fn::If": [
"IsGlobalStore",
{
"Ref": "AWS::NoValue"
},
{
"Ref": "RedisParameterGroup"
}
]
},
"CacheSubnetGroupName": {
"Ref": "RedisSubnetGroup"
},
"Engine": {
"Fn::If": [
"IsGlobalStore",
{
"Ref": "AWS::NoValue"
},
"redis"
]
},
"EngineVersion": {
"Fn::If": [
"IsGlobalStore",
{
"Ref": "AWS::NoValue"
},
"6.2"
]
},
"NumCacheClusters": {
"Fn::FindInMap": [
"NumCacheClusters",
{
"Ref": "AWS::Region"
},
{
"Ref": "EnvironmentName"
}
]
},
"PreferredCacheClusterAZs": {
"Fn::FindInMap": [
"ZoneMap",
{
"Ref": "AWS::Region"
},
"AZ"
]
},
"ReplicationGroupDescription": {
"Fn::Join": [
"",
[
"Redis Replication Group ",
{
"Ref": "EnvironmentName"
}
]
]
},
"SecurityGroupIds": [
{
"Ref": "RedisSecurityGroup"
}
],
"Tags": [
{
"Key": "Name",
"Value": {
"Fn::Join": [
"",
[
"Redis-",
{
"Ref": "EnvironmentName"
}
]
]
}
},
{
"Key": "Product",
"Value": "Redis"
},
{
"Key": "Environment",
"Value": {
"Ref": "EnvironmentName"
}
}
]
}
}
},
"Outputs": {}
}

Cloudformation unable to create resource policy for apigateway

The resource policy is working fine when i directly pass it to the console.
Below is resource policy example :-
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "execute-api:Invoke",
"Resource": "arn:aws:execute-api:us-west-2:339159142535:ooxmwl6q4e/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": [
""14.98.8.190/32""
]
}
}
}
]
}
Now how to create a cloudformation template for this to get created and get attached to the apigateway
I tried to create a policy but as per new policy "Principal" is depricated.
I created a role also but no help. Below is role snippet :-
{
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"Apifirewall": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"apigateway.amazonaws.com"
]
},
"Action": [
"sts:AssumeRole"
]
}
]
},
"Policies": [
{
"PolicyName": "Apifirewall",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "*",
"Resource": [
"arn:aws:execute-api:us-west-2:339159142535:ooxmwl6q4e/*"
],
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"14.98.8.190/32"
]
}
}
}
]
}
}
]
}
}
},
"Outputs": {
"Apifirewall": {
"Value": {
"Fn::GetAtt": [
"Apifirewall",
"Arn"
]
}
}
}
}
APIGateway resource policy is not binding to IAM Policy, it's different kind of resource.
So to implement it on your RestApi your should use the Policy parameter on AWS::ApiGateway::RestApi resource on
{
"Type" : "AWS::ApiGateway::RestApi",
"Properties" : {
"ApiKeySourceType" : String,
"BinaryMediaTypes" : [ String, ... ],
"Body" : JSON object,
"BodyS3Location" : S3Location,
"CloneFrom" : String,
"Description" : String,
"EndpointConfiguration" : EndpointConfiguration,
"FailOnWarnings" : Boolean,
"MinimumCompressionSize" : Integer,
"Name" : String,
"Parameters" : { String:String, ... },
"Policy" : JSON object
}
}
Below is the entire CFT for api deployment with lambda integration
{
"AWSTemplateFormatVersion": "2010-09-09",
"Parameters": {
"AppEnv": {
"Type": "String",
"Description": "Application environment, for this deployment"
},
"DeployTag": {
"Type": "String",
"Description": "Distinct deployment tag ex: BLUE, GREEN"
}
},
"Resources": {
"LambdaExecutionRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"lambda.amazonaws.com"
]
},
"Action": [
"sts:AssumeRole"
]
}
]
},
"ManagedPolicyArns": [
"arn:aws:iam::aws:policy/AWSLambdaFullAccess"
]
}
},
"RecommenderLambda": {
"Type": "AWS::Lambda::Function",
"Properties": {
"Handler": "recommender_field_validation_lambda.lambda_handler",
"FunctionName": "recommenderlambda2",
"Role": {
"Fn::GetAtt": [
"LambdaExecutionRole",
"Arn"
]
},
"Environment": {
"Variables": {
"S3_BUCKET": "belcorp.recommender.test",
"REGION_NAME": "us-west-2",
"TOPIC_ARN": {
"Fn::ImportValue": "RecommenderTopicARN"
},
"TABLE_NAME": {
"Fn::ImportValue": "recommederrequestinfo"
}
}
},
"Code": {
"S3Bucket": "belcorp.recommender.lambdas",
"S3Key": "recommender_field_validation_lambda.zip"
},
"Runtime": "python3.6",
"Timeout": 25
}
},
"LambdaPermission": {
"DependsOn": "RecommenderLambda",
"Type": "AWS::Lambda::Permission",
"Properties": {
"Action": "lambda:invokeFunction",
"FunctionName": "recommenderlambda2",
"Principal": "apigateway.amazonaws.com",
"SourceArn": {
"Fn::Join": [
"",
[
"arn:aws:execute-api:",
{
"Ref": "AWS::Region"
},
":",
{
"Ref": "AWS::AccountId"
},
":",
{
"Ref": "RecommenderApi"
},
"/*"
]
]
}
}
},
"RecommenderApi": {
"Type": "AWS::ApiGateway::RestApi",
"Properties": {
"EndpointConfiguration": {
"Types": [
"EDGE"
]
},
"Description": "RecommenderAPI",
"Name": {
"Fn::Sub": "RecommenderApi-${AppEnv}-${DeployTag}"
},
"Policy": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "execute-api:Invoke",
"Resource": {
"Fn::Sub": "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:*/*"
},
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"14.98.8.190/32"
]
}
}
}
]
}
}
},
"ApiGatewayAccount": {
"Type": "AWS::ApiGateway::Account",
"Properties": {
"CloudWatchRoleArn": {
"Fn::ImportValue": "cloudwatchRole"
}
}
},
"ApiDeployment": {
"Type": "AWS::ApiGateway::Deployment",
"DependsOn": [
"OfferPostMethod",
"OrderPostMethod"
],
"Properties": {
"RestApiId": {
"Ref": "RecommenderApi"
},
"StageName": "dev"
}
},
"ProcessInput": {
"Type": "AWS::ApiGateway::Resource",
"Properties": {
"RestApiId": {
"Ref": "RecommenderApi"
},
"ParentId": {
"Fn::GetAtt": [
"RecommenderApi",
"RootResourceId"
]
},
"PathPart": "process-input"
}
},
"OfferLevel": {
"Type": "AWS::ApiGateway::Resource",
"Properties": {
"RestApiId": {
"Ref": "RecommenderApi"
},
"ParentId": {
"Ref": "ProcessInput"
},
"PathPart": "offer-level"
}
},
"OrderLevel": {
"Type": "AWS::ApiGateway::Resource",
"Properties": {
"RestApiId": {
"Ref": "RecommenderApi"
},
"ParentId": {
"Ref": "ProcessInput"
},
"PathPart": "order-level"
}
},
"OfferPostMethod": {
"DependsOn": "RecommenderLambda",
"Type": "AWS::ApiGateway::Method",
"Properties": {
"RestApiId": {
"Ref": "RecommenderApi"
},
"ResourceId": {
"Ref": "OfferLevel"
},
"HttpMethod": "POST",
"AuthorizationType": "NONE",
"Integration": {
"Type": "AWS_PROXY",
"IntegrationHttpMethod": "POST",
"Uri": {
"Fn::Join": [
"",
[
"arn:aws:apigateway:",
{
"Ref": "AWS::Region"
},
":lambda:path/2015-03-31/functions/",
{
"Fn::GetAtt": [
"RecommenderLambda",
"Arn"
]
},
"/invocations"
]
]
},
"IntegrationResponses": [
{
"StatusCode": 200,
"ResponseTemplates": {
"application/json": "$input.json('$.body')"
}
}
]
}
}
},
"OrderPostMethod": {
"DependsOn": "RecommenderLambda",
"Type": "AWS::ApiGateway::Method",
"Properties": {
"RestApiId": {
"Ref": "RecommenderApi"
},
"ResourceId": {
"Ref": "OrderLevel"
},
"HttpMethod": "POST",
"AuthorizationType": "NONE",
"Integration": {
"Type": "AWS_PROXY",
"IntegrationHttpMethod": "POST",
"Uri": {
"Fn::Join": [
"",
[
"arn:aws:apigateway:",
{
"Ref": "AWS::Region"
},
":lambda:path/2015-03-31/functions/",
{
"Fn::GetAtt": [
"RecommenderLambda",
"Arn"
]
},
"/invocations"
]
]
},
"IntegrationResponses": [
{
"StatusCode": 200,
"ResponseTemplates": {
"application/json": "$input.json('$.body')"
}
}
]
}
}
}
},
"Outputs": {
"RootUrl": {
"Description": "Root URL of the API gateway",
"Value": {
"Fn::Join": [
"",
[
"https://",
{
"Ref": "RecommenderApi"
},
".execute-api.",
{
"Ref": "AWS::Region"
},
".amazonaws.com"
]
]
}
},
"OfferUrl": {
"Description": "Root URL of the API gateway",
"Value": {
"Fn::Join": [
"",
[
"https://",
{
"Ref": "RecommenderApi"
},
".execute-api.",
{
"Ref": "AWS::Region"
},
".amazonaws.com",
"/dev/process-input/offer-level"
]
]
}
},
"OrderUrl": {
"Description": "Root URL of the API gateway",
"Value": {
"Fn::Join": [
"",
[
"https://",
{
"Ref": "RecommenderApi"
},
".execute-api.",
{
"Ref": "AWS::Region"
},
".amazonaws.com",
"/dev/process-input/order-level"
]
]
}
}
}
}
Too long for a comment. This is the transformed YAML from this answer, which a commenter pointed out can be done in CloudFormation Designer:
AWSTemplateFormatVersion: 2010-09-09
Parameters:
AppEnv:
Type: String
Description: 'Application environment, for this deployment'
DeployTag:
Type: String
Description: 'Distinct deployment tag ex: BLUE, GREEN'
Resources:
LambdaExecutionRole:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- 'sts:AssumeRole'
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/AWSLambdaFullAccess'
RecommenderLambda:
Type: 'AWS::Lambda::Function'
Properties:
Handler: recommender_field_validation_lambda.lambda_handler
FunctionName: recommenderlambda2
Role: !GetAtt
- LambdaExecutionRole
- Arn
Environment:
Variables:
S3_BUCKET: belcorp.recommender.test
REGION_NAME: us-west-2
TOPIC_ARN: !ImportValue RecommenderTopicARN
TABLE_NAME: !ImportValue recommederrequestinfo
Code:
S3Bucket: belcorp.recommender.lambdas
S3Key: recommender_field_validation_lambda.zip
Runtime: python3.6
Timeout: 25
LambdaPermission:
DependsOn: RecommenderLambda
Type: 'AWS::Lambda::Permission'
Properties:
Action: 'lambda:invokeFunction'
FunctionName: recommenderlambda2
Principal: apigateway.amazonaws.com
SourceArn: !Join
- ''
- - 'arn:aws:execute-api:'
- !Ref 'AWS::Region'
- ':'
- !Ref 'AWS::AccountId'
- ':'
- !Ref RecommenderApi
- /*
RecommenderApi:
Type: 'AWS::ApiGateway::RestApi'
Properties:
EndpointConfiguration:
Types:
- EDGE
Description: RecommenderAPI
Name: !Sub 'RecommenderApi-${AppEnv}-${DeployTag}'
Policy:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal: '*'
Action: 'execute-api:Invoke'
Resource: !Sub 'arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:*/*'
Condition:
IpAddress:
'aws:SourceIp':
- 14.98.8.190/32
ApiGatewayAccount:
Type: 'AWS::ApiGateway::Account'
Properties:
CloudWatchRoleArn: !ImportValue cloudwatchRole
ApiDeployment:
Type: 'AWS::ApiGateway::Deployment'
DependsOn:
- OfferPostMethod
- OrderPostMethod
Properties:
RestApiId: !Ref RecommenderApi
StageName: dev
ProcessInput:
Type: 'AWS::ApiGateway::Resource'
Properties:
RestApiId: !Ref RecommenderApi
ParentId: !GetAtt
- RecommenderApi
- RootResourceId
PathPart: process-input
OfferLevel:
Type: 'AWS::ApiGateway::Resource'
Properties:
RestApiId: !Ref RecommenderApi
ParentId: !Ref ProcessInput
PathPart: offer-level
OrderLevel:
Type: 'AWS::ApiGateway::Resource'
Properties:
RestApiId: !Ref RecommenderApi
ParentId: !Ref ProcessInput
PathPart: order-level
OfferPostMethod:
DependsOn: RecommenderLambda
Type: 'AWS::ApiGateway::Method'
Properties:
RestApiId: !Ref RecommenderApi
ResourceId: !Ref OfferLevel
HttpMethod: POST
AuthorizationType: NONE
Integration:
Type: AWS_PROXY
IntegrationHttpMethod: POST
Uri: !Join
- ''
- - 'arn:aws:apigateway:'
- !Ref 'AWS::Region'
- ':lambda:path/2015-03-31/functions/'
- !GetAtt
- RecommenderLambda
- Arn
- /invocations
IntegrationResponses:
- StatusCode: 200
ResponseTemplates:
application/json: $input.json('$.body')
OrderPostMethod:
DependsOn: RecommenderLambda
Type: 'AWS::ApiGateway::Method'
Properties:
RestApiId: !Ref RecommenderApi
ResourceId: !Ref OrderLevel
HttpMethod: POST
AuthorizationType: NONE
Integration:
Type: AWS_PROXY
IntegrationHttpMethod: POST
Uri: !Join
- ''
- - 'arn:aws:apigateway:'
- !Ref 'AWS::Region'
- ':lambda:path/2015-03-31/functions/'
- !GetAtt
- RecommenderLambda
- Arn
- /invocations
IntegrationResponses:
- StatusCode: 200
ResponseTemplates:
application/json: $input.json('$.body')
Outputs:
RootUrl:
Description: Root URL of the API gateway
Value: !Join
- ''
- - 'https://'
- !Ref RecommenderApi
- .execute-api.
- !Ref 'AWS::Region'
- .amazonaws.com
OfferUrl:
Description: Root URL of the API gateway
Value: !Join
- ''
- - 'https://'
- !Ref RecommenderApi
- .execute-api.
- !Ref 'AWS::Region'
- .amazonaws.com
- /dev/process-input/offer-level
OrderUrl:
Description: Root URL of the API gateway
Value: !Join
- ''
- - 'https://'
- !Ref RecommenderApi
- .execute-api.
- !Ref 'AWS::Region'
- .amazonaws.com
- /dev/process-input/order-level
If you are using YAML for CloudFormation, the Policy can be in YAML. There is no need to use JSON for it. For example:
Parameters:
ApiAllowedIps:
Type: CommaDelimitedList
RestApi:
Type: AWS::ApiGateway::RestApi
Properties:
...
Policy:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action: '*'
Principal: '*'
Resource: '*'
Condition:
IpAddress:
aws:SourceIp: !Ref ApiAllowedIps

How to configure Batch job queue as targets for AWS::Events::Rule in AWS cloudformation template

My AWS cloudformation template has this:
"ScheduledRule": {
"Type": "AWS::Events::Rule",
"Properties": {
"Description": "ScheduledRule",
"ScheduleExpression": "cron(0/5 * * * ? *)",
"State": "ENABLED",
"Targets": [{
"Here I want to set batch job queue"
}]
}
}
I have created necessary entities for AWS Batch in the template.
"JobDefinition": {
"Type": "AWS::Batch::JobDefinition",
"Properties": {
"Type": "container",
"ContainerProperties": {
"Image": {
"Ref": "ImageUrl"
},
"Vcpus": 2,
"Memory": 2000,
"Command": ["node", "server.js"]
},
"RetryStrategy": {
"Attempts": 1
}
}
},
"JobQueue": {
"Type": "AWS::Batch::JobQueue",
"Properties": {
"Priority": 1,
"ComputeEnvironmentOrder": [
{
"order": 1,
"ComputeEnvironment": { "Ref": "ComputeEnvironment" }
}
]
}
},
"ComputeEnvironment": {
"Type": "AWS::Batch::ComputeEnvironment",
"Properties": {
"Type": "MANAGED",
"ComputeResourses": {
"Type": "EC2",
"MinvCpus": 2,
"DesiredvCpus": 4,
"MaxvCpus": 64,
"InstanceTypes": [
"optimal"
],
"Subnets" : [{ "Ref" : "Subnet" }],
"SecurityGroupIds" : [{ "Ref" : "SecurityGroup" }],
"InstanceRole" : { "Ref" : "IamInstanceProfile" }
},
"ServiceRole" : { "Ref" : "BatchServiceRole" }
}
}
I came to know that it is possible to submit batch job through aws cloudwatch event. AWS cloudwatch event target
I want to use Batch job queue target to submit my job through cloudformation template. I have seen many examples where batch job submission is done through AWS lambda function but I don't want to use lambda function. I didn't find any cloudformation template where Batch job queue target is configured in "AWS::Events::Rule"
Hey I was trying to find a sample myself but didn't find any. With some testing I figured it out. Thought I'd share it here.
Targets:
- Arn:
Ref: BatchProcessingJobQueue
Id: {your_id}
RoleArn: {your_role_arn}
BatchParameters:
JobDefinition:
Ref: BatchProcessingJobDefinition
JobName: {your_job_name}
Input:
!Sub
- '{"Parameters": {"param1": "--param.name1=${param1}", "param2": "--param.name2=${param2}"}}'
- param1: {param1_value}
param2: {param2_value}