I searching for what are the metadata that AWS uses for each and every service. For AWS instance it uses ami-id, ami_launch-index, hostname, instance-action and many more as the metadata like wise where i can find metadata for all the services like EBS, VPN....
Reference
Information obtained from Amazon Elastic Compute Cloud User Guide for Microsoft Windows Instances pdf pg no : 232 – 242
I believe you are interested in knowing the properties of the each AWS Resource / Service and not the meta-data. I don't think there is a straight answer. The work around what I can recommend is using the AWS CloudFormation's Syntax definition of each AWS Resource.
For Example :
EC2 Instance is represented by the following syntax. Not all of them are mandatory. http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html
Look at the KEYS of the Key:Value pair provided below [ "AvailabilityZone" : String ]
{
"Type" : "AWS::EC2::Instance",
"Properties" : {
"AvailabilityZone" : String,
"BlockDeviceMappings" : [ EC2 Block Device Mapping, ... ],
"DisableApiTermination" : Boolean,
"EbsOptimized" : Boolean,
"IamInstanceProfile" : String,
"ImageId" : String,
"InstanceInitiatedShutdownBehavior" : String,
"InstanceType" : String,
"KernelId" : String,
"KeyName" : String,
"Monitoring" : Boolean,
"NetworkInterfaces" : [ EC2 Network Interface, ... ],
"PlacementGroupName" : String,
"PrivateIpAddress" : String,
"RamdiskId" : String,
"SecurityGroupIds" : [ String, ... ],
"SecurityGroups" : [ String, ... ],
"SourceDestCheck" : Boolean,
"SsmAssociations" : [ SSMAssociation, ... ]
"SubnetId" : String,
"Tags" : [ Resource Tag, ... ],
"Tenancy" : String,
"UserData" : String,
"Volumes" : [ EC2 MountPoint, ... ],
"AdditionalInfo" : String
}
}
For VPC [http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc.html]
{
"Type" : "AWS::EC2::VPC",
"Properties" : {
"CidrBlock" : String,
"EnableDnsSupport" : Boolean,
"EnableDnsHostnames" : Boolean,
"InstanceTenancy" : String,
"Tags" : [ Resource Tag, ... ]
}
}
For EBS Volume [http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-ebs-volume.html]
{
"Type":"AWS::EC2::Volume",
"Properties" : {
"AutoEnableIO" : Boolean,
"AvailabilityZone" : String,
"Encrypted" : Boolean,
"Iops" : Number,
"KmsKeyId" : String,
"Size" : String,
"SnapshotId" : String,
"Tags" : [ Resource Tag, ... ],
"VolumeType" : String
}
}
The CloudFormation Resource Page has details for most of the items [http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html]. Below is the current list as of today [7 Jan 2016]
AWS::AutoScaling::AutoScalingGroup
AWS::AutoScaling::LaunchConfiguration
AWS::AutoScaling::LifecycleHook
AWS::AutoScaling::ScalingPolicy
AWS::AutoScaling::ScheduledAction
AWS::CloudFormation::Authentication
AWS::CloudFormation::CustomResource
AWS::CloudFormation::Init
AWS::CloudFormation::Interface
AWS::CloudFormation::Stack
AWS::CloudFormation::WaitCondition
AWS::CloudFormation::WaitConditionHandle
AWS::CloudFront::Distribution
AWS::CloudTrail::Trail
AWS::CloudWatch::Alarm
AWS::CodeDeploy::Application
AWS::CodeDeploy::DeploymentConfig
AWS::CodeDeploy::DeploymentGroup
AWS::CodePipeline::CustomActionType
AWS::CodePipeline::Pipeline
AWS::Config::ConfigRule
AWS::Config::ConfigurationRecorder
AWS::Config::DeliveryChannel
AWS::DataPipeline::Pipeline
AWS::DirectoryService::MicrosoftAD
AWS::DirectoryService::SimpleAD
AWS::DynamoDB::Table
AWS::EC2::CustomerGateway
AWS::EC2::DHCPOptions
AWS::EC2::EIP
AWS::EC2::EIPAssociation
AWS::EC2::Instance
AWS::EC2::InternetGateway
AWS::EC2::NetworkAcl
AWS::EC2::NetworkAclEntry
AWS::EC2::NetworkInterface
AWS::EC2::NetworkInterfaceAttachment
AWS::EC2::PlacementGroup
AWS::EC2::Route
AWS::EC2::RouteTable
AWS::EC2::SecurityGroup
AWS::EC2::SecurityGroupEgress
AWS::EC2::SecurityGroupIngress
AWS::EC2::SpotFleet
AWS::EC2::Subnet
AWS::EC2::SubnetNetworkAclAssociation
AWS::EC2::SubnetRouteTableAssociation
AWS::EC2::Volume
AWS::EC2::VolumeAttachment
AWS::EC2::VPC
AWS::EC2::VPCDHCPOptionsAssociation
AWS::EC2::VPCEndpoint
AWS::EC2::VPCGatewayAttachment
AWS::EC2::VPCPeeringConnection
AWS::EC2::VPNConnection
AWS::EC2::VPNConnectionRoute
AWS::EC2::VPNGateway
AWS::EC2::VPNGatewayRoutePropagation
AWS::ECS::Cluster
AWS::ECS::Service
AWS::ECS::TaskDefinition
AWS::EFS::FileSystem
AWS::EFS::MountTarget
AWS::ElastiCache::CacheCluster
AWS::ElastiCache::ParameterGroup
AWS::ElastiCache::ReplicationGroup
AWS::ElastiCache::SecurityGroup
AWS::ElastiCache::SecurityGroupIngress
AWS::ElastiCache::SubnetGroup
AWS::ElasticBeanstalk::Application
AWS::ElasticBeanstalk::ApplicationVersion
AWS::ElasticBeanstalk::ConfigurationTemplate
AWS::ElasticBeanstalk::Environment
AWS::ElasticLoadBalancing::LoadBalancer
AWS::IAM::AccessKey
AWS::IAM::Group
AWS::IAM::InstanceProfile
AWS::IAM::ManagedPolicy
AWS::IAM::Policy
AWS::IAM::Role
AWS::IAM::User
AWS::IAM::UserToGroupAddition
AWS::Kinesis::Stream
AWS::KMS::Key
AWS::Lambda::EventSourceMapping
AWS::Lambda::Function
AWS::Lambda::Permission
AWS::Logs::Destination
AWS::Logs::LogGroup
AWS::Logs::LogStream
AWS::Logs::MetricFilter
AWS::Logs::SubscriptionFilter
AWS::OpsWorks::App
AWS::OpsWorks::ElasticLoadBalancerAttachment
AWS::OpsWorks::Instance
AWS::OpsWorks::Layer
AWS::OpsWorks::Stack
AWS::RDS::DBCluster
AWS::RDS::DBClusterParameterGroup
AWS::RDS::DBInstance
AWS::RDS::DBParameterGroup
AWS::RDS::DBSecurityGroup
AWS::RDS::DBSecurityGroupIngress
AWS::RDS::DBSubnetGroup
AWS::RDS::EventSubscription
AWS::RDS::OptionGroup
AWS::Redshift::Cluster
AWS::Redshift::ClusterParameterGroup
AWS::Redshift::ClusterSecurityGroup
AWS::Redshift::ClusterSecurityGroupIngress
AWS::Redshift::ClusterSubnetGroup
AWS::Route53::HealthCheck
AWS::Route53::HostedZone
AWS::Route53::RecordSet
AWS::Route53::RecordSetGroup
AWS::S3::Bucket
AWS::S3::BucketPolicy
AWS::SDB::Domain
Try using AWS CLI.
You can execute the describe commands of the various services to see and understand the metadata
Related
I have an organization account with several managed accounts underneath it. Each managed account has multiple VPCs in them. One of the VPC in each managed account will have a tag "ServiceName":"True" while the others in that account will have a "ServiceName":"False" tag instead.
I'm trying to create a stackset with a stack dedicated to create a security group with ingress rules attached to it and I need to dynamically assign the "VpcId" property of that security group to be the "VpcId" of VPC with the "ServiceName":"True" tag in that account.
Obviously, if I don't specify a VPC ID in the VpcId field, it creates the security group but attach it to the default VPC of that account. I can't specify manually a VPC either since it's going to be ran in multiple accounts. Leaving me with the only option available to search and assign VPCs by running some sort of function to extract the "VpcId".
The stack itself works fine as I ran it in a test environment while specifying a VPC ID. So, it's just a matter getting that "VpcId" dynamically.
In the end, I'm looking to do something that would resemble this:
{
"Parameters": {
"MyValidVPCID": {
"Description": "My Valid VPC ID where ServiceName tag equals true. Do some Lambda Kung Fu to get the VPC ID using something that would let me parse the equivalent of aws ec2 describe-vpcs command.",
"Type": "String"
}
},
"Resources": {
"SG": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "Security Group Desc.",
"Tags": [
{
"Key": "Key1",
"Value": "ABC"
},
{
"Key": "Key2",
"Value": "DEF"
}
],
"VpcId" : { "Ref" : "MyValidVPCID" }
}
},
"SGIngressRule01":
{
"Type": "AWS::EC2::SecurityGroupIngress",
"DependsOn": "SG",
"Properties": {
"GroupId" : { "Fn::GetAtt": [ "SG", "GroupId" ] },
"Description": "Rule 1 description",
"IpProtocol": "tcp",
"FromPort": 123,
"ToPort": 456,
"CidrIp": "0.0.0.0/0"
}
}
}
I really don't know if it's a feasible approach or what would be the extra steps needed to recuperate that VpcId based on the tag. That's why if I could get some input from people used to work with CloudFormation, it would help me a lot.
getting that "VpcId" dynamically.
You have to use custom resource for that. You would have to create it as a lambda function which would take any input arguments you want, and using AWS SDK, would query or modify the VPC/Security groups in your stack.
Thanks Marcin for pointing me in the right direction with the custom resources. For those who are wondering what the basic code to make it work looks like, it looks something like this:
Resources:
FunctionNameLambdaFunctionRole:
Type: "AWS::IAM::Role"
Properties:
RoleName: FunctionNameLambdaFunctionRole
Path: "/"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
FunctionNameLambdaFunctionRolePolicy:
Type: "AWS::IAM::Policy"
Properties:
PolicyName: admin3cx
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action: "*"
Resource: "*"
Roles:
- Ref: FunctionNameLambdaFunctionRole
FunctionNameLambdaFunctionCode:
Type: "AWS::Lambda::Function"
DeletionPolicy: Delete
DependsOn:
- FunctionNameLambdaFunctionRole
Properties:
FunctionName: FunctionNameLambdaFunctionCode
Role: !GetAtt FunctionNameLambdaFunctionRole.Arn
Runtime: python3.7
Handler: index.handler
MemorySize: 128
Timeout: 30
Code:
ZipFile: |
import boto3
import cfnresponse
ec2 = boto3.resource('ec2')
client = boto3.client('ec2')
def handler(event, context):
responseData = {}
filters =[{'Name':'tag:ServiceName', 'Values':['True']}]
vpcs = list(ec2.vpcs.filter(Filters=filters))
for vpc in vpcs:
responseVPC = vpc.id
responseData['ServiceName'] = responseVPC
cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, "CustomResourcePhysicalID")
FunctionNameLambdaFunctionInvocationCode:
Type: "Custom::FunctionNameLambdaFunctionInvocationCode"
Properties:
ServiceToken: !GetAtt FunctionNameLambdaFunctionCode.Arn
SGFunctionName:
Type: "AWS::EC2::SecurityGroup"
Properties:
GroupDescription: Description
VpcId: !GetAtt FunctionNameLambdaFunctionInvocationCode.ServiceName
...
Some stuff has been redacted and I made the switch to YAML. The code will be refined obviously. The point was just to make sure I was able to get a return value based on a filter in a Lambda function inside a CloudFormation stack.
I'm trying to set an IPSet on my Beanstalk Environment.
into my .ebextensions I have a waf.config containing :
option_settings:
aws:elasticbeanstalk:environment:
LoadBalancerType: application
Resources:
IPSet:
Type: "AWS::WAFv2::IPSet"
Properties:
Name: '`{ "Ref" : "AWSEBEnvironmentName" }`-IPset'
Addresses:
- 10.10.10.10/32
IPAddressVersion: IPV4
Scope: REGIONAL
Tags:
- Key: "Scope"
Value: "Sqreen"
WafAcl:
Type: "AWS::WAFv2::WebACL"
Properties:
Description: 'Web ACL to Block bad requests on `{ "Ref" : "AWSEBEnvironmentName" }`'
Name: '`{ "Ref" : "AWSEBEnvironmentName" }`-WebACL'
Scope: REGIONAL
DefaultAction:
Allow : {}
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: '`{ "Ref" : "AWSEBEnvironmentName" }`-WebACL'
Rules:
- Name: DenyListIPSet
Priority: 0
OverrideAction:
Block: {}
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: DenyIps
Statement:
IPSetReferenceStatement:
Arn: '`{ "Fn::GetAtt" : ["IPSet", "Arn" ]}`'
WebACLAssociation:
Type: AWS::WAFv2::WebACLAssociation
Properties:
ResourceArn: '`{ "Ref" : "AWSEBV2LoadBalancer" }`'
WebACLArn: '`{ "Fn::GetAtt" : ["WafAcl", "Arn" ]}`'
But the cloudformation stack gave me : "Error reason: A reference in your rule statement is not valid., field: RULE, parameter: Statement (Service: Wafv2, Status Code: 400
The cloudformation stack looks valid to me. I don't see any other statment that could be match better for my need....
EDIT: Solution
"RuleAction" and "OverrideAction", kindly reference [3] and [4] respectively.
[3] https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wafv2-webacl-ruleaction.html
[4] https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wafv2-webacl-overrideaction.html
With Action (instead of override action) the WAF works as expected !
"RuleAction" and "OverrideAction", kindly reference [3] and [4] respectively.
[3] https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wafv2-webacl-ruleaction.html [4] https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wafv2-webacl-overrideaction.html
With Action (instead of override action) the WAF works as expected !
I want to create a EC2 instance type t3.medium on all environments and m5.large on production.
I'm using .ebextensions (YAML) like so:
option 1:
Mappings:
EnvironmentMap:
"production":
TheType: "m5.large"
SecurityGroup: "foo"
...
"staging":
TheType: "t3.medium"
SecurityGroup: "bar"
...
option_settings:
aws:autoscaling:launchconfiguration:
IamInstanceProfile: "aws-elasticbeanstalk-ec2-role"
InstanceType: !FindInMap
- EnvironmentMap
- !Ref 'AWSEBEnvironmentName'
- TheType
SecurityGroups:
- {"Fn::FindInMap": ["EnvironmentMap", {"Ref": "AWSEBEnvironmentName"}, "SecurityGroup"]}
Option 2:
InstanceType: {"Fn::FindInMap": ["EnvironmentMap", {"Ref": "AWSEBEnvironmentName"}, "EC2InstanceType"]}
Option 3:
InstanceType:
- {"Fn::FindInMap": ["EnvironmentMap", {"Ref": "AWSEBEnvironmentName"}, "EC2InstanceType"]}
Results
Option 1 fails with Invalid Yaml (but I took this from this AWS example.
Option 2 and 3 fail with the same problem.
The FindInMap function is not "called":
Invalid option value: '{"Fn::FindInMap":["EnvironmentMap","EC2InstanceType"]},{"Ref":"AWSEBEnvironmentName"}' (Namespace: 'aws:autoscaling:launchconfiguration', OptionName: 'InstanceType'): Value is not one of the allowed values: [c1.medium, c1.xlarge, c3.2xlarge, ....
It tries to interpret the whole function/thing as a string.
For the SecurityGroups property it works, for InstanceType it does not.
I can't do it dynamically and I can't find how to achieve this neither on AWS doc, SO, or anywhere else. I would assume this is simple stuff. What am I missing?
EDIT:
Option 4: using conditionals
Conditions:
IsProduction: !Equals [ !Ref AWSEBEnvironmentName, production ]
option_settings:
aws:autoscaling:launchconfiguration:
InstanceType: !If [ IsProduction, m5.large, t3.medium ]
SecurityGroups:
- {"Fn::FindInMap": ["EnvironmentMap", {"Ref": "AWSEBEnvironmentName"}, "SecurityGroup"]}
Error: YAML exception: Invalid Yaml: could not determine a constructor for the tag !Equals in...
But this comes from documentation on conditions and if.
EDIT 2:
I eventually found out that the option InstanceType is obsolute and we should use:
aws:ec2:instances
InstanceTypes: "t3.medium"
But alas, this does not solve the problem either because I cannot use the replacement functions here as well (Fn:findInMap).
The reason why FindInMap does not work in option_settings is the fact that only four intrinsic functions are allowed there (from docs):
Ref
Fn::GetAtt
Fn::Join
Fn::GetOptionSetting
I'm not convinced that SecurityGroups worked. I think your script failed before FindInMap in SecurityGroups got chance to be evaluated.
However, I tried to find a way using Resources. The closes I got was with the following config file:
Mappings:
EnvironmentMap:
production:
TheType: "t3.medium"
staging:
TheType: "t2.small"
Resources:
AWSEBAutoScalingLaunchConfiguration:
Type: AWS::AutoScaling::LaunchConfiguration
Properties:
InstanceType:
? "Fn::FindInMap"
:
- EnvironmentMap
-
Ref: "AWSEBEnvironmentName"
- TheType
Although this is a step closer, it ultimately fails as well. The reason is that when EB is jointing our Resources config file with its own template, it produces the following:
"InstanceType": {
"Ref": "InstanceType", # <--- this should NOT be here :-(
"Fn::FindInMap": [
"EnvironmentMap",
{
"Ref": "AWSEBEnvironmentName"
},
"TheType"
]
},
instead of
"InstanceType": {
"Fn::FindInMap": [
"EnvironmentMap",
{
"Ref": "AWSEBEnvironmentName"
},
"TheType"
]
},
And this happens because the original InstanceType (before the joint operation) is:
"InstanceType":{"Ref":"InstanceType"},
Therefore, EB instead of replacing InstanceType with our custom InstanceType provided in our config file, it just merges them.
I want to create Route53 HostedZone with CloudFormation so I want to check some information in Route53 about HostedZone is exist.
In logic of my case I need check if resource is exist, ignore the resource creation. How I can handle this problem.
My CloudFormation template show at below.
"myDNSRecord" : {
"Type" : "AWS::Route53::RecordSet",
"Properties" : {
"HostedZoneName" : { "Ref" : "HostedZoneResource" },
"Comment" : "DNS name for my instance.",
"Name" : {
"Fn::Join" : [ "", [
{"Ref" : "Ec2Instance"}, ".",
{"Ref" : "AWS::Region"}, ".",
{"Ref" : "HostedZone"} ,"."
] ]
},
"Type" : "A",
"TTL" : "900",
"ResourceRecords" : [
{ "Fn::GetAtt" : [ "Ec2Instance", "PublicIp" ] }
]
}
}
This is not exactly the answer you need. But in general, you can use Conditions for this. In you template, you define your condition in Conditions section and use it to conditionally create the resource. e.g.
Parameters:
EnvironmentSize:
Type: String
Default: Micro
AllowedValues:
- Micro
- Small
- Medium
- AuroraCluster
Conditions:
isntAuroraCluster:
!Not [!Equals [!Ref EnvironmentSize, "AuroraCluster"]]
DBInstance:
Type: AWS::RDS::DBInstance
Condition: isntAuroraCluster
Properties:
DBInstanceClass: !FindInMap [InstanceSize, !Ref EnvironmentSize, DB]
<Rest of properties>
Here my RDS DBinstance is only created if my environment size is not AuroraCluster.
If you don't find a better solution, you could take that as user input (whether to create a record set or not) & use that as condition to create your resource. Hope it helps.
The best way to do this would be to do the following:
Create a lambda backed custom resource
Check using lambda whether your resource exists or not, depending on that return an identifier
Use cloudformation conditions to check on the value of the returned identifier and then correspondingly create or not create the resource.
You can fetch the return value of the custom resource using !GetAtt
More information can be found on the AWS websites relating to custom resource:
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-custom-resources.html
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cfn-customresource.html
You can try to orchestrate creation of specific resources using AWS::NoValue
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/pseudo-parameter-reference.html
Below is taken from variables creation for LambdaFunction
Conditions:
IsProd: !Equals [!Ref Env, "production"]
Environment:
Variables:
USER: !If [IsProd, !GetAtt ...., Ref: AWS::NoValue]
What would be a good strategy to have a default value on mappings?
I.E.
I have a parameter called country
Based on that country I reference a DNS using mappings
"Mappings" : {
"DNS":{
"us" : {"dns" : "mypage.us.com", "ttl" : "600"},
"mx" : {"dns" : "mypage.default.com", "ttl" : "300"},
"ar" : {"dns" : "mypage.default.com", "ttl" : "300"},
"br" : {"dns" : "mypage.default.com", "ttl" : "300"}
}
}
If us it's been mapped:
{ "Fn::FindInMap" : [ "DNS", { "Ref" : "country" }, "dns" ]}
I get "mypage.us.com" for the other countries I've created a huge list of countries with a default value mypage.default.com, in the future, this values will be changing and we will be adding more countries, is there a better approach to this?
The only way I was able to do this was to chain Fn::If statements instead of using the map. I tried using a combination of Fn::If and Fn::FindInMap but Fn::FindInMap will always raise an error it if can't find the mapping.
Therefore the only solution for me was to resort to using something like the following (for me it was setting ecs memory based on instance type):
Conditions:
IsT2Micro: !Equals [!Ref InstanceType, "t2.micro"]
IsT2Small: !Equals [!Ref InstanceType, "t2.small"]
...
taskdefinition:
Type: AWS::ECS::TaskDefinition
Properties:
...
Memory: !If [ IsT2Micro, 900, !If [ IsT2Small, 1900, !Ref "AWS::NoValue"]]
To elaborate on Steve Smith's answer.
Cloudformation always expects a valid mapping, even behind a missed logic gate.
You can combine !Sub and !If for a fair amount of flexibility though.
For example, we do this for dynamic staging ECS Env vars:
Parameters:
Env:
Type: String
Branch:
Type: String
DevelopUrl:
Type: String
Default: "develop.example.com"
MasterUrl:
Type: String
Default: "master.example.com"
...(ECS Resource)
Environment:
- !If
- IsStaging
- Name: SOME_CALLBACK_URL
Value: !Sub
- "https://${Url}/some-callback-endpoint"
- Url: !If [ IsDevelop, !Ref DevelopUrl, !If [ IsMaster, !Ref MasterUrl, !GetAtt MyLoadBalancer.DNSName ] ]
- !Ref "AWS::NoValue"
Cloud Formation helps create AWS resources once in the beginning of their life. You can also do updates with it, but I think in your case it sounds like you'll be better off building your DNS config logic into your application. Maybe create a Database table in DynamoDB with the mapping data. You could pass the Country value into the servers as an environment variable, and have them query the DynamoDB table on launch based on their environment variable.
Alternatively, you can have Cloud Formation invoke a Lambda function when it launches a new stack to query DynamoDB to get the value of the DNS config based on the country so you don't have to keep modifying your stack JSON every time there's a new entry and don't have to change your application.
In your mapping, add a default entry:
"Mappings" : {
"DNS":{
"us" : {"dns" : "mypage.us.com", "ttl" : "600"},
"mx" : {"dns" : "mypage.mx.com", "ttl" : "300"},
"default" : {"dns" : "mypage.default.com", "ttl" : "300"}
}
}
Then create a condition (YAML):
Conditions:
HasSpecialDNS: !Or:
- !Equals [!Ref country, "us"]
- !Equals [!Ref country, "mx"]
Then change the 2nd parameter of FindInMap to:
{ "Fn::FindInMap" : [ "DNS", { "Fn::If": ["HasSpecialDNS", {"Ref" : "country"}, "default" ]}, "dns" ]}
Or YAML:
Fn::FindInMap:
- DNS
- !If ["HasSpecialDNS", !Ref country, "default" ]
- "dns"