I have a Cloudformation template that modifies an Opsworks stack by adding few resources.
The Opsworks stack is deployed in the region eu-west-1 which is the API endpoint region as well and it shows on the side of the name of the stack: Regional.
When I run the Cloudformation template ( I give the stack ID as a parameter) I get this error:
Unable to find stack with ID xxxxxxx
I guess Cloudformation can only see the opsworks resources which are in us-east-1 region?
I tried changing the region of Cloudformation and deploy the template but the stack is still unfound.
How can I let Cloudformation search for the stack in all regions?
Should I clone the opsworks stack and change the endpoint to us-east-1 region?
What would be the best solution?
Template
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Add a layer to an existing stack",
"Mappings": {
"Region2Principal": {
"eu-west-1": {
"EC2Principal": "ec2.amazonaws.com",
"OpsWorksPrincipal": "opsworks.amazonaws.com"
}
},
},
"Parameters": {
"Environment" : {
"Description": "The Environnement variable ",
"Type": "String",
"Default": "dev",
"AllowedValues" : ["test", "prod"]
},
"InstanceType": {
"Type": "String",
"Default": "m4.large",
"AllowedValues" : ["t2.micro", "m1.small", "m1.large","m4.large","m4.xlarge","m4.2xlarge","m4.4xlarge","m4.10xlarge","m4.16xlarge","c4.large" , "c4.xlarge" ,"c4.2xlarge" , "c4.4xlarge","c4.8xlarge" , "c3.large" , "c3.xlarge", "c3.2xlarge", "c3.4xlarge" ,"c3.8xlarge"],
"ConstraintDescription": "must be a valid EC2 instance type"
},
"StackID": {
"Type": "String",
"Description": "ID of the existing opsworks stack to edit"
},
"vpcId": {
"Description": "VPC id of corresponding to the Environment",
"Type": "String"
},
"subnetIds" :{
"Description": "list of sunbnets in the chosen VPC",
"Type": "List<AWS::EC2::Subnet::Id>"
},
"ScriptSG":{
"Description": "script security group",
"Type" : "String"
},
"SG": {
"Description": " layer security group",
"Type": "String"
}
},
"Resources":{
"Layer": {
"Type": "AWS::OpsWorks::Layer",
"Properties": {
"AutoAssignElasticIps" : false,
"AutoAssignPublicIps" : true
}
},
"SInstance1": {
"Type": "AWS::OpsWorks::Instance",
"Properties": {
"Hostname": "S1",
"AutoScalingType": "timer",
"TimeBasedAutoScaling" : {
"Friday" : { "0" : "on", "6" : "on", "12" : "on", "18" : "on" },
"Monday" : { "0" : "on", "6" : "on", "12" : "on", "18" : "on" }
},
"RootDeviceType": "ebs",
"StackId": {"Ref": "StackID"},
"LayerIds": [{"Ref": "Layer"}],
"InstanceType": {"Ref" : "InstanceType"}
}
},
"Instance2": {
"Type": "AWS::OpsWorks::Instance",
"Properties": {
"Hostname": "S2",
"AutoScalingType": "timer",
"TimeBasedAutoScaling" : {
"Saturday": { "0" : "on", "6" : "on", "12" : "on", "18" : "on" },
"Sunday" : { "0" : "on", "6" : "on", "12" : "on", "18" : "on" },
"Thursday": { "0" : "on", "6" : "on", "12" : "on", "18" : "on" },
"Tuesday" : { "0" : "on", "6" : "on", "12" : "on", "18" : "on" },
"Wednesday":{ "0" : "on", "6" : "on", "12" : "on", "18" : "on" }
},
"RootDeviceType": "ebs",
"StackId": {"Ref": "StackID"},
"LayerIds": [{"Ref": "Layer"}],
"InstanceType": {"Ref" : "InstanceType"}
}
},
"ELB": {
"Type": "AWS::ElasticLoadBalancing::LoadBalancer",
"Properties": {
"ConnectionDrainingPolicy" : {
"Enabled" : true,
"Timeout" : 300
},
"ConnectionSettings" : {
"IdleTimeout" : 60
},
"CrossZone" : true,
"HealthCheck" : {
"HealthyThreshold" : "3",
"Interval" : "30",
"Target" : "HTTP:80/ping",
"Timeout" : "5",
"UnhealthyThreshold" : "2"
},
"LoadBalancerName": "loadBalancer",
"Listeners" : [{
"InstancePort" : "80",
"InstanceProtocol" : "HTTP",
"LoadBalancerPort" : "80",
"Protocol" : "HTTP"
}],
"Scheme" : "internal",
"SecurityGroups" : [{ "Ref" : "ELBSecurityGroup" }],
"Subnets" : { "Ref" : "subnetIds"}
}
},
"ELBAttach":{
"Type": "AWS::OpsWorks::ElasticLoadBalancerAttachment",
"Properties": {
"ElasticLoadBalancerName" : {"Ref" : "ELB"},
"LayerId" : {"Ref" : "Layer" }
}
}
},
}
It looks like you will need to move them to the same region.
Resources can be managed only in the region in which they are created. Resources that are created in one regional endpoint are not available, nor can they be cloned to, another regional endpoint.
http://docs.aws.amazon.com/general/latest/gr/rande.html#opsworks_region
https://aws.amazon.com/about-aws/whats-new/2016/08/aws-opsworks-adds-nine-regional-endpoints-and-asia-pacific-seoul-region-support/
Layer is missing the stackID parameter.
{
"Type": "AWS::OpsWorks::Layer",
"Properties": {
"Attributes" : { String:String },
"AutoAssignElasticIps" : Boolean,
"AutoAssignPublicIps" : Boolean,
"CustomInstanceProfileArn" : String,
"CustomJson" : JSON object,
"CustomRecipes" : Recipes,
"CustomSecurityGroupIds" : [ String, ... ],
"EnableAutoHealing" : Boolean,
"InstallUpdatesOnBoot" : Boolean,
"LifecycleEventConfiguration" : LifeCycleEventConfiguration,
"LoadBasedAutoScaling" : LoadBasedAutoScaling,
"Name" : String,
"Packages" : [ String, ... ],
"Shortname" : String,
"StackId" : String,
"Type" : String,
"VolumeConfigurations" : [ VolumeConfiguration, ... ]
}
}
http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-opsworks-layer.html
Related
I started with an input JSON as such.
{
"trackingNumber": "1ZEA83550362028861",
"localActivityDate": "20210324",
"localActivityTime": "183500",
"scheduledDeliveryDate": "20210324",
"actualDeliveryDate": "20210324",
"actualdeliveryTime": "183500",
"gmtActivityDate": "20210324",
"gmtActivityTime": "223500",
"activityStatus": {
"type": "G",
"code": "OR",
"description": "Origin Scan"
},
"activityLocation": {
"city": "RANDALLSTOWN,",
"stateProvince": "MD",
"postalCode": "21133",
"country": "US"
}
}
This is the JOLT transformation spec that i have written as of now.
[
{
"operation": "modify-overwrite-beta",
"spec": {
"tsY": "=substring(#(1,localActivityDate),0,4)",
"tsM": "=substring(#(1,localActivityDate),4,6)",
"tsD": "=substring(#(1,localActivityDate),6,8)",
"tsH": "=substring(#(1,localActivityTime),0,2)",
"tsMi": "=substring(#(1,localActivityTime),2,4)",
"tsS": "=substring(#(1,localActivityTime),4,6)",
"timeStamp": "=concat(#(1,tsY),'-',#(1,tsM),'-',#(1,tsD),'T',#(1,tsH),':',#(1,tsMi),':',#(1,tsS),'Z')",
"aTY": "=substring(#(1,scheduledDeliveryDate),0,4)",
"aTM": "=substring(#(1,scheduledDeliveryDate),4,6)",
"aTD": "=substring(#(1,scheduledDeliveryDate),6,8)",
"appointmentTime": "=concat(#(1,aTY),'-',#(1,aTM),'-',#(1,aTD))",
"dTY": "=substring(#(1,actualDeliveryDate),0,4)",
"dTM": "=substring(#(1,actualDeliveryDate),4,6)",
"dTD": "=substring(#(1,actualDeliveryDate),6,8)",
"dTH": "=substring(#(1,actualdeliveryTime),0,2)",
"dTMi": "=substring(#(1,actualdeliveryTime),2,4)",
"dTS": "=substring(#(1,actualdeliveryTime),4,6)",
"deliveryTime": "=concat(#(1,dTY),'-',#(1,dTM),'-',#(1,dTD),'T',#(1,dTH),':',#(1,dTMi),':',#(1,dTS),'Z')"
}
},
{
"operation": "shift",
"spec": {
"*Number": "transformedPayload.&(0,1)Info",
"activityStatus": {
"*": "transformedPayload.events.&"
},
"activityLocation": {
"*": "transformedPayload.address.&"
},
"timeStamp": "transformedPayload.events[0].&",
"appointmentTime": "transformedPayload.events[1].&",
"deliveryTime": "transformedPayload.events[2].&",
"activityStatus": {
"type": "transformedPayload.events[0].type",
"code": "transformedPayload.events[0].statusCode",
"description": "transformedPayload.events[0].statusDescription"
},
"activityLocation": {
"city": "transformedPayload.address.city",
"stateProvince": "transformedPayload.address.state",
"postalCode": "transformedPayload.address.postalCode",
"country": "transformedPayload.address.country"
}
}
},
{
"operation": "modify-default-beta",
"spec": {
"metaData": {
"domain": "LTL",
"eventType": "statusUpdate",
"version": "v1"
},
"transformedPayload": {
"events": {
"[1]": {
"statusCode": "AB",
"statusDescription": "Delivery Scheduled"
},
"[2]": {
"statusCode": "D1",
"statusDescription": "Delivered"
}
}
}
}
}
]
The resultant JSON created by this transformation looks like this.
{
"transformedPayload" : {
"events" : [ {
"type" : "G",
"statusCode" : "OR",
"statusDescription" : "Origin Scan",
"timeStamp" : "2021-03-24T18:35:00Z"
}, {
"appointmentTime" : "2021-03-24",
"statusCode" : "AB",
"statusDescription" : "Delivery Scheduled"
}, {
"deliveryTime" : "2021-03-24T18:35:00Z",
"statusCode" : "D1",
"statusDescription" : "Delivered"
} ],
"address" : {
"city" : "RANDALLSTOWN,",
"state" : "MD",
"postalCode" : "21133",
"country" : "US"
},
"trackingInfo" : "1ZEA83550362028861"
},
"metaData" : {
"domain" : "LTL",
"eventType" : "statusUpdate",
"version" : "v1"
}
}
I just need a small tweak in this where the appointmentTime and the deliveryTime fields in the index [1] and [2] of the events array also need to be named as "timestamp" (as seen in the [0]th index). So that finally the correct output JSON looks something like this.
{
"transformedPayload" : {
"events" : [ {
"type" : "G",
"statusCode" : "OR",
"statusDescription" : "Origin Scan",
"timeStamp" : "2021-03-24T18:35:00Z"
}, {
"timestamp" : "2021-03-24",
"statusCode" : "AB",
"statusDescription" : "Delivery Scheduled"
}, {
"timestamp" : "2021-03-24T18:35:00Z",
"statusCode" : "D1",
"statusDescription" : "Delivered"
} ],
"address" : {
"city" : "RANDALLSTOWN,",
"state" : "MD",
"postalCode" : "21133",
"country" : "US"
},
"trackingInfo" : "1ZEA83550362028861"
},
"metaData" : {
"domain" : "LTL",
"eventType" : "statusUpdate",
"version" : "v1"
}
}
I have tried renaming the field in the shift operation itself but that did not work. I am completely new to JOLT transformation so it seems a bit tricky doing this small change. So any help is appreciated. Thanks
Just convert the related lines within the shift transformation spec from
"appointmentTime": "transformedPayload.events[1].&",
"deliveryTime": "transformedPayload.events[2].&",
to
"appointmentTime": "transformedPayload.events[1].timestamp",
"deliveryTime": "transformedPayload.events[2].timestamp",
instead of the replicating operator & used in the previous one.
I am trying to enable Spot Instance option on my CloudFormation template that I then ingest into AWS Service Catalog.
I am getting an error regarding my MarketType parameter specifically for the InstanceMarketOptions Parameter and can't seem to figure out what the issue is, as the parameter is right out of the AWS Documentation.
Any direction would be great. Thank you
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "Creates an EC2 instance running the Custom DATA Ubuntu Image",
"Parameters" : {
"KeyName": {
"Description" : "Name of an existing EC2 key pair for SSH access to the EC2 instance.",
"Type": "AWS::EC2::KeyPair::KeyName"
},
"SubnetId": {
"Type" : "String",
"Default" : "subnet-0b53e6d08c86dc68d",
"AllowedValues": ["subnet-0b53e6d08c86dc68d"],
"Description" : "SubnetId of an existing subnet in your Virtual Private Cloud (VPC)"
},
"SecurityGroupId": {
"Type": "String",
"Default": "sg-040b93c603129931f",
"Description":"The SecurityGroupId of an existing EC2 SecurityGroup in your Virtual Private Cloud (VPC)"
},
"InstanceType" : {
"Description" : "EC2 instance type.",
"Type" : "String",
"Default" : "m5.large",
"AllowedValues" : [ "m5.large","m5.xlarge","m5.2xlarge"," m5.4xlarge","m5.8xlarge","m5.12xlarge","m5.16xlarge","p2.xlarge"]
},
"InstanceMarketOptions" : {
"Description" : "EC2 Spot Instance",
"MarketType" : "spot"
},
"SSHLocation" : {
"Description" : "The IP address range that can SSH to the EC2 instance.",
"Type": "String",
"MinLength": "9",
"MaxLength": "18",
"Default": "10.0.0.0/8",
"AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
"ConstraintDescription": "Must be a valid IP CIDR range of the form x.x.x.x/x."
}
},
"Metadata" : {
"AWS::CloudFormation::Interface" : {
"ParameterGroups" : [{
"Label" : {"default": "Instance configuration"},
"Parameters" : ["InstanceType", "MarketType"]
},{
"Label" : {"default": "Security configuration"},
"Parameters" : ["KeyName", "SSHLocation"]
}],
"ParameterLabels" : {
"InstanceType": {"default": "Server size:"},
"KeyName": {"default": "Key pair:"},
"SSHLocation": {"default": "CIDR range:"},
"MarketType": {"default": "Spot:"}
}
}
},
"Mappings" : {
"AWSRegionArch2AMI" : {
"us-east-1" : { "HVM64" : "ami-xxxxxxxxxxxx" }
}
},
"Resources" : {
"EC2Instance" : {
"Type" : "AWS::EC2::Instance",
"Properties" : {
"InstanceType" : { "Ref" : "InstanceType" },
"SecurityGroupIds" : [ { "Ref" : "SecurityGroupId" } ],
"KeyName" : { "Ref" : "KeyName" },
"MarketType" : {"Ref" : "InstanceMarketOptions" },
"SubnetId" : { "Ref" : "SubnetId" },
"ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" }, "HVM64" ] }
}
}
},
"Outputs" : {
"PrivateDNSName" : {
"Description" : "Private DNS name of the new EC2 instance",
"Value" : { "Fn::GetAtt" : [ "EC2Instance", "PrivateDnsName" ] }
},
"PrivateIPAddress" : {
"Description" : "Private IP address of the new EC2 instance",
"Value" : { "Fn::GetAtt" : [ "EC2Instance", "PrivateIp" ] }
}
}
}
MarketType is not a property you can set for AWS::EC2::Instance
The closest thing to what I think you are looking for is AWS::EC2::LaunchTemplate LaunchTemplateData with InstanceMarketOptions.
I'm working on a cloudformation template that has many parameters, like the ID of the elastic file system and the DNS of the MountTarget. I want to retreive these parameters from the existing resources, but if they are not already created I want to create them in the template :
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "AWS CloudFormation Template : Stack OpsWorks Slave pour deployer les instances script",
"Mappings": {
"Region2Principal": {
"us-east-1": {
"EC2Principal": "ec2.amazonaws.com",
"OpsWorksPrincipal": "opsworks.amazonaws.com"
},
"us-west-2": {
"EC2Principal": "ec2.amazonaws.com",
"OpsWorksPrincipal": "opsworks.amazonaws.com"
},
"us-west-1": {
"EC2Principal": "ec2.amazonaws.com",
"OpsWorksPrincipal": "opsworks.amazonaws.com"
},
"eu-west-1": {
"EC2Principal": "ec2.amazonaws.com",
"OpsWorksPrincipal": "opsworks.amazonaws.com"
}
},
"AWSInstanceType2Arch" : {
"t1.micro" : { "Arch" : "PV64" },
"t2.micro" : { "Arch" : "HVM64" },
"m1.small" : { "Arch" : "PV64" },
"m1.large" : { "Arch" : "PV64" },
"m4.large" : { "Arch" : "HVM64" },
"m4.xlarge" : { "Arch" : "HVM64" },
"m4.2xlarge" : { "Arch" : "HVM64" },
"m4.4xlarge" : { "Arch" : "HVM64" },
"m4.10xlarge" : { "Arch" : "HVM64" },
"m4.16xlarge" : { "Arch" : "HVM64" },
"c3.large" : { "Arch" : "HVM64" },
"c3.xlarge" : { "Arch" : "HVM64" },
"c3.2xlarge" : { "Arch" : "HVM64" },
"c3.4xlarge" : { "Arch" : "HVM64" },
"c3.8xlarge" : { "Arch" : "HVM64" },
"c4.large" : { "Arch" : "HVM64" },
"c4.xlarge" : { "Arch" : "HVM64" },
"c4.2xlarge" : { "Arch" : "HVM64" },
"c4.4xlarge" : { "Arch" : "HVM64" },
"c4.8xlarge" : { "Arch" : "HVM64" }
},
"AWSRegionArch2AMI" : {
"us-east-1" : { "PV64" : "ami-5fb8c835", "HVM64" : "ami-60b6c60a" },
"us-west-1" : { "PV64" : "ami-56ea8636", "HVM64" : "ami-d5ea86b5" },
"eu-west-1" : { "PV64" : "ami-95e33ce6", "HVM64" : "ami-bff32ccc" },
"us-west-2" : { "PV64" : "ami-d93622b8", "HVM64" : "ami-f0091d91" }
}
},
"Parameters": {
"OpsWorksStackColor": {
"Description": "RGB Color to use for OpsWorks Stack",
"Type": "String",
"Default": "rgb(38, 146, 168)"
},
"Region" : {
"Type":"String",
"Description": "Region location of the template resources",
"Default": "eu-west-1",
"AllowedValues" : [ "us-east-1", "us-west-1", "us-west-2", "eu-west-1" ]
},
"SecurityGroupIds": {
"Description": "Security groups that can be used to access the EC2 instances, do not select more than 5 SG",
"Type": "List<AWS::EC2::SecurityGroup::Id>",
"ConstraintDescription": "must be list of EC2 security group ids"
},
"VpcId": {
"Type": "AWS::EC2::VPC::Id",
"Description": "VPC associated with the provided subnets",
"Default": "vpc-69e3320c",
"ConstraintDescription": "must be an existing VPC ID"
},
"SubnetId": {
"Type": "String",
"Default": "subnet-6820eb31",
"ConstraintDescription": "must be an existing subnet ID"
},
"InstanceType": {
"Type": "String",
"Default": "c3.large",
"AllowedValues" : ["t2.micro", "m1.small", "m1.large","m4.large","m4.xlarge","m4.2xlarge","m4.4xlarge","m4.10xlarge","m4.16xlarge","c4.large" , "c4.xlarge" ,"c4.2xlarge" , "c4.4xlarge","c4.8xlarge" , "c3.large" , "c3.xlarge", "c3.2xlarge", "c3.4xlarge" ,"c3.8xlarge"],
"ConstraintDescription": "must be a valid EC2 instance type"
},
"KeyPairName": {
"Type": "AWS::EC2::KeyPair::KeyName",
"Default": "test-generic-ec2",
"ConstraintDescription": "must be the name of an existing EC2 KeyPair"
},
"CookbookS3" : {
"Type": "String",
"Default": "https://s3-eu-west-1.amazonaws.com/mybucket.test.cookbooks/cookbook-v1.tar.gz",
"ConstraintDescription": "the Url to the cookbook"
},
"CookbookS3AccessID": {
"Type": "String",
"ConstraintDescription": "username to the appropriate IAM access key ID"
},
"CookbookS3AccessKey": {
"Type": "String",
"NoEcho" : "true",
"ConstraintDescription": "password to the appropriate IAM secret access key"
},
"MountPoint" : {
"Description" : "The Linux mount point for the EFS volume",
"Type": "String",
"MinLength": "1",
"Default": "efs-file-appli-tmp"
},
"MountPointDNS" : {
"Description" : "Mount target DNS name",
"Type" : "String",
"Default" : "eu-west-1a.fs-c2388dc0b.efs.eu-west-1.amazonaws.com"
},
"FileSystem" : {
"Description" :"The Id of the FileSystem",
"Type": "String",
"Default": "fs-c2388dc0b"
},
"NewRelicLicence" : {
"Description": "The licence key of newrelic",
"Type": "String"
},
"Environnement" : {
"Description": "The Environnement variable ",
"Type": "String",
"Default": "test",
"AllowedValues" : ["dev", "test", "int", "prod"]
}
},
"Conditions" : {
"CreateProdResources" : { "Fn::Not" : [{ "Fn::Equals" : [ {"Ref" : "Environnement"},"test" ] }] }
},
"Resources": {
"MyStack": {
"Type": "AWS::OpsWorks::Stack",
"Properties": {
"AgentVersion" : "LATEST",
"Name": { "Ref": "AWS::StackName" },
"Attributes": { "Color": { "Ref": "OpsWorksStackColor" } },
"ChefConfiguration": {},
"ConfigurationManager": { "Name": "Chef", "Version": "12" },
"CustomCookbooksSource": {
"Type": "s3",
"Password" : { "Ref": "CookbookS3AccessKey" },
"Username" : { "Ref": "CookbookS3AccessID" },
"Url": { "Ref": "CookbookS3" }
},
"CustomJson": {
"mount" : { "mountdir" : {
"default" : { "dirname" : { "Ref" : "MountPoint" } } }
},
"mountadd" : { "mountdns" : {
"default" : { "mdns" : { "Ref" : "MountPointDNS" }}}
}
},
"DefaultInstanceProfileArn": { "Fn::GetAtt": [ "OpsWorksInstanceProfile","Arn" ] },
"DefaultOs": "Ubuntu 14.04 LTS",
"DefaultRootDeviceType": "ebs",
"DefaultSshKeyName": { "Ref": "KeyPairName" },
"DefaultSubnetId" : {"Ref" : "SubnetId" },
"ServiceRoleArn": { "Fn::GetAtt": ["OpsWorksServiceRole", "Arn"] },
"UseCustomCookbooks": true,
"UseOpsworksSecurityGroups" : true,
"VpcId" : { "Ref" : "VpcId" }
}
},
"MyLayer": {
"Type": "AWS::OpsWorks::Layer",
"DependsOn" : "OpsWorksServiceRole",
"Properties": {
"AutoAssignElasticIps" : false,
"AutoAssignPublicIps" : true,
"CustomRecipes" : {
"Setup" : ["cassandra-php-driver::setup","awscli::setup","crontab::setup","prometheus-server::setup","awslogs::setup","newrelic::php_agent","settings::setup"],
"Configure" : ["cassandra-php-driver::configure","security::configure","settings::default"],
"Deploy": ["imports::deploy"]
},
"CustomSecurityGroupIds" : { "Ref" : "SecurityGroupIds" },
"EnableAutoHealing" : true,
"InstallUpdatesOnBoot": false,
"LifecycleEventConfiguration": {
"ShutdownEventConfiguration": {
"DelayUntilElbConnectionsDrained": false,
"ExecutionTimeout": 120 }
},
"Name": "script-node",
"Shortname" : "node",
"StackId": { "Ref": "MyStack" },
"Type": "custom",
"UseEbsOptimizedInstances": true,
"VolumeConfigurations": [ {
"Iops": 10000,
"MountPoint": "/dev/sda1",
"NumberOfDisks": 1,
"Size": 20,
"VolumeType": "gp2"
}]
}
},
"OpsWorksServiceRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version" : "2012-10-17",
"Statement": [ {
"Effect": "Allow",
"Principal": { "Service": [ { "Fn::FindInMap": [ "Region2Principal",{ "Ref": "AWS::Region" },"OpsWorksPrincipal" ] } ] },
"Action" : [ "sts:AssumeRole" ]
} ]
},
"Path": "/",
"Policies": [ {
"PolicyName": "opsworks-service",
"PolicyDocument": {
"Version" : "2012-10-17",
"Statement": [ {
"Effect": "Allow",
"Action": "*",
"Resource": "*"
} ]
}
} ]
}
},
"OpsWorksInstanceRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version" : "2012-10-17",
"Statement": [ {
"Effect": "Allow",
"Principal": { "Service" : [ { "Fn::FindInMap": [ "Region2Principal", { "Ref": "AWS::Region" },"EC2Principal" ] } ] },
"Action" : [ "sts:AssumeRole" ]
}]
},
"Path": "/",
"Policies": [{
"PolicyName": "aws-opsworks-instance",
"PolicyDocument": {
"Statement": [{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}]
}
}]
}
},
"OpsWorksInstanceProfile": {
"Type": "AWS::IAM::InstanceProfile",
"Properties": {
"Path": "/",
"Roles": [ { "Ref": "OpsWorksInstanceRole" } ]
}
},
"MyInstance": {
"Type": "AWS::OpsWorks::Instance",
"Properties": {
"Hostname": "Script",
"RootDeviceType": "ebs",
"StackId": {"Ref": "MyStack"},
"LayerIds": [{"Ref": "MyLayer"}],
"InstanceType": {"Ref" : "InstanceType"}
}
},
"MyApp": {
"Type": "AWS::OpsWorks::App",
"Properties": {
"AppSource" : {
"Type" : "git",
"Url" : "git://github.com:globlW/My-imports.git",
"Revision" : "develop"
},
"Description": "Dataimport and connectors",
"Name" : "app-Imports",
"Shortname" : "app_imports",
"StackId" : {"Ref": "MyStack"},
"Type" : "other"
}
},
"MyFileSystem" : {
"Type" : "AWS::EFS::FileSystem",
"Condition" : "CreateProdResources",
"Properties" : {
"FileSystemTags" : [{
"Key" : "Name",
"Value" : {"Ref" : "MountPoint"}
}]
}
},
"MountTarget": {
"Type": "AWS::EFS::MountTarget",
"Condition" : "CreateProdResources",
"Properties": {
"FileSystemId": { "Ref": "MyFileSystem" },
"SubnetId": { "Ref": "SubnetId" },
"SecurityGroups": [ { "Ref": "SecurityGroupIds" } ]
}
}
}
}
As you see, I use often the { "Ref" : "FileSystem" } , { "Ref" : "MountPointDNS" } and { "Ref" : "MountPoint" }, I specially need them in the CustomJson. The problem is how to link the parameters with the recent created resources and how to name them ? can I give the same name so that I can always get a value to customjson ?
I hope my issue is clear.
Thank you
It is possible to conditionally use an existing resource using Condition Functions. See the Conditionally use an existing resource example in the documentation, which demonstrates the following pattern:
Parameters:
ExistingResource:
Description: An existing resource (optional).
Default: NONE
Type: String
Conditions:
CreateNewResource: !Equals [!Ref ExistingResource, NONE]
Resources:
NewResource:
Condition: CreateNewResource
Type: # Resource type
Properties: # Resource properties
Outputs:
ResourceId:
Description: Reference to either a newly-created or existing resource.
Value: !If [CreateNewResource, !Ref NewResource, !Ref ExistingResource]
I trying to build infrastracture with Cloudformation json template. When I added two Subnets and SubnetRouteTableAssociation in both availability zones that i need. But creating process failing to create Loadbalancers with error:
CREATE_FAILED AWS::ElasticLoadBalancing::LoadBalancer Rest ELB cannot
be attached to multiple subnets in the same AZ.
Here is the Parameters of AZs:
"AZs" : {
"Description" : "The list of AvailabilityZones.",
"Type" : "CommaDelimitedList",
"Default" : "us-east-1a,us-east-1c"
}
Here is Resources of Subnets, SubnetRouteTableAssociation in both availability zones and ElasticLoadBalancing of Rest:
"PublicSubnet1a" : {
"Type" : "AWS::EC2::Subnet",
"Properties" : {
"VpcId" : { "Ref" : "VPC" },
"CidrBlock" : "10.0.0.0/24",
"AvailabilityZone": {
"Fn::Select": ["1", { "Ref": "AZs" }]
},
"Tags" : [
{"Key": "Name", "Value": {"Fn::Join": ["", ["Offering-", {"Ref": "Env"}, {"Ref": "EnvNum"}, "-VPC"]]}},
{"Key" : "Network", "Value" : "Public" }
]
}
},
"PublicSubnet1c" : {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": { "Ref" : "VPC" },
"CidrBlock": "10.0.1.0/24",
"AvailabilityZone": {
"Fn::Select": ["1", { "Ref": "AZs" }]
},
"Tags" : [
{"Key": "Name", "Value": {"Fn::Join": ["", ["Offering-", {"Ref": "Env"}, {"Ref": "EnvNum"}, "-VPC"]]}},
{"Key" : "Network", "Value" : "Public" }
]
}
},
"PublicSubnet1aRouteTableAssociation" : {
"Type" : "AWS::EC2::SubnetRouteTableAssociation",
"Properties" : {
"SubnetId" : { "Ref" : "PublicSubnet1a" },
"RouteTableId" : { "Ref" : "PublicRouteTable" }
}
},
"PublicSubnet1cRouteTableAssociation" : {
"Type" : "AWS::EC2::SubnetRouteTableAssociation",
"Properties" : {
"SubnetId" : { "Ref" : "PublicSubnet1c" },
"RouteTableId" : { "Ref" : "PublicRouteTable" }
}
},
"RestELB" : {
"Type" : "AWS::ElasticLoadBalancing::LoadBalancer",
"DependsOn": "AttachGateway",
"Properties": {
"LoadBalancerName": {"Fn::Join": ["",["Rest-ELB-", {"Ref": "VPC"}]]},
"CrossZone" : "true",
"Subnets": [{ "Ref": "PublicSubnet1a" },{ "Ref": "PublicSubnet1c" }],
"Listeners" : [
{"LoadBalancerPort" : "80", "InstancePort" : "80","Protocol" : "HTTP"},
{"LoadBalancerPort" : "6060", "InstancePort" : "6060","Protocol" : "HTTP"}
],
"HealthCheck" : {
"Target" : "HTTP:80/",
"HealthyThreshold" : "3",
"UnhealthyThreshold" : "5",
"Interval" : "90",
"Timeout" : "60"
}
}
}
What I'm doing wrong?
Thanks!
"PublicSubnet1a" : {
...
"AvailabilityZone": {
"Fn::Select": ["1", { "Ref": "AZs" }] // <---- selects index 1 from AZs list
},
...
"PublicSubnet1c" : {
...
"AvailabilityZone": {
"Fn::Select": ["1", { "Ref": "AZs" }] // <---- selects the same index 1 from AZs list
},
both of your subnets are selecting the same index from AZs list (see "FN::select" statement). Change the select statement for PublicSubnet1a to be
"Fn::Select": ["0", { "Ref": "AZs" }]
Given i have this example template:
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Mappings" : {
"RegionMap" : {
"us-west-1" : { "AMI" : "ami-655a0a20" },
...
}
},
"Resources" : {
"Ec2Instance" : {
"Type" : "AWS::EC2::Instance",
"Properties" : {
...
},
"DependsOn" : "myDB"
},
"myDB" : {
"Type" : "AWS::RDS::DBInstance",
"Properties" : {
...
}
},
"myDB2" : {
"Type" : "AWS::RDS::DBInstance",
"Properties" : {
...
}
}
}
}
Is it possible to specify multiple DependsOn in any way?
Would be great to have somethink like:
"DependsOn" : ["myDB", "myDB2"]
Whats the normal way?
Yes,
The DependsOn attribute can take a single string or list of strings.
http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-dependson.html
Syntax:
"DependsOn" : [ String, ... ]
This answer comes up first in Google, so I will include how to do multiple dependson attributes in YAML, which I found in this answer.
AnotherProductionResource:
Type: AWS::CloudFormation::Stack
Condition: ISProduction
DependsOn:
- AResource
- MyProductionResource
Properties:
[...]
Yes,
"DependsOn" can take multiple strings. I have listed an example below:
"DependsOn": [ "S3BucketAppElbLogs", "ElbLogAppBucketPolicy" ]
{
"Description": "Create a variable number of EC2 instance resources.",
"Parameters": {
"InstanceCount": {
"Description": "Number of EC2 instances (must be between 1 and 5).",
"Type": "Number",
"Default": 1,
"MinValue": 1,
"MaxValue": 5,
"ConstraintDescription": "Must be a number between 1 and 5."
},
"ImageId": {
"Description": "Image ID to launch EC2 instances.",
"Type": "AWS::EC2::Image::Id",
"Default": "ami-31c9924e"
},
"InstanceType": {
"Description": "Instance type to launch EC2 instances.",
"Type": "String",
"Default": "m3.medium",
"AllowedValues": [
"m3.medium",
"m3.large",
"m3.xlarge",
"m3.2xlarge"
]
}
},
"Conditions": {
"Launch1" : {"Fn::Equals" : [{"Ref" : "InstanceCount"}, "1"]},
"Launch2" : {"Fn::Equals" : [{"Ref" : "InstanceCount"}, "2"]}
},
"Resources": {
"Instance2": {
"Condition": "Launch2",
"Type": "AWS::EC2::Instance",
"Properties": {
"ImageId": {
"Ref": "ImageId"
},
"InstanceType": {
"Ref": "InstanceType"
}
},
"DependsOn": "Instance1"
},
"Instance1": {
"Condition": "Launch1",
"Type": "AWS::EC2::Instance",
"Properties": {
"ImageId": {
"Ref": "ImageId"
},
"InstanceType": {
"Ref": "InstanceType"
}
}
}
}
}