我在验证我的cfn时收到此错误。
'Template error: every Ref object must have a single String value.`
是否有人能告诉我我的cfn模板出错了。
我无法分辨它指的是哪个参考,因为我已经检查了它们,并且可以看到所有参考都被定义为参数。
CloudFormation {
#Script Parameters
Parameter ("region") {
Type String
Default region
}
Parameter ("environment") {
Type String
Default environment.capitalize
}
Parameter ("vpcId") {
Type String
Default vpcId
}
Parameter ("vpcCidr") {
Type String
Default vpcCidr
}
Parameter ("keyName") {
Type String
Default keyName
}
Parameter ("pubSub1") {
Type String
Default pubSub1
}
Parameter ("pubSub2") {
Type String
Default pubSub2
}
Parameter ("priRtb1") {
Type String
Default priRtb1
}
Parameter ("priRtb2") {
Type String
Default priRtb2
}
Parameter ("natType") {
Type String
Default natType
}
Parameter ("nuPings") {
Type String
Default nuPings
}
Parameter ("pingTimeout") {
Type String
Default pingTimeout
}
Parameter ("pingWait") {
Type String
Default pingWait
}
Parameter ("instStopWait") {
Type String
Default instStopWait
}
Parameter ("instStartWait") {
Type String
Default instStartWait
}
Mapping("AWSNATAMI", {
"us-east-1" => {
"AMI" => "ami-54cf5c3d"
},
"us-west-2" => {
"AMI" => "ami-8e27adbe"
},
"us-west-1" => {
"AMI" => "ami-b63210f3"
},
"eu-west-1" => {
"AMI" => "ami-3c5f5748"
},
"ap-southeast-1" => {
"AMI" => "ami-ba7538e8"
},
"ap-southeast-2" => {
"AMI" => "ami-b6df4e8c"
},
"ap-northeast-1" => {
"AMI" => "ami-5d7dfa5c"
},
"sa-east-1" => {
"AMI" => "ami-89c81394"
}
})
Resource("NATRole") do
Type("AWS::IAM::Role")
Property("PolicyName", "NAT_Takeover")
Property("Path", "/")
Property("AssumeRolePolicyDocument", {
"Effect" => "Allow",
"Principal"=> {
"Service" => [ "ec2.amazonaws.com" ]
},
"Action" => [ "sts:AssumeRole" ]
})
Property("Policies", [
{
"PolicyDocument" => {
"Statement" => [
{
"Action" => [
"ec2:DescribeInstances",
"ec2:DescribeRouteTables",
"ec2:CreateRoute",
"ec2:ReplaceRoute",
"ec2:StartInstances",
"ec2:StopInstances"
],
"Effect" => "Allow",
"Resource" => "*"
}
]
}
}
])
end
Resource("NATRoleProfile") do
Type("AWS::IAM::Role")
Property("Path", "/")
Property("Roles", {
"Ref" => [ "NATRole" ]
})
end
Resource("NAT1EIP") do
Type("AWS::EC2::EIP")
Property("Domain", "vpc")
Property("InstanceId", {
"Ref" => [ "NAT1Instance" ]
})
end
Resource("NAT2EIP") do
Type("AWS::EC2::EIP")
Property("Domain", "vpc")
Property("InstanceId", {
"Ref" => [ "NAT2Instance" ]
})
end
Resource("NAT1Instance") do
Type("AWS::EC2::Instance")
Metadata("Comment1", "Create NAT #1")
Property("InstanceType", {
"Ref" => [ "natType" ]
})
Property("KeyName", {
"Ref" => [ "keyName" ]
})
Property("IamInstanceProfile", {
"Ref" => [ "NATRoleProfile" ]
})
Property("SubnetId", {
"Ref" => [ "pubSub1" ]
})
Property("SourceDestCheck", "false")
Property("ImageID", FnFindInMap("AWSNATAMI", Ref("region"), "AMI"))
Property("SecurityGroupIds", {
"Ref" => [ "NATSecurityGroup" ]
})
Property("Tags", {
"Key" => [ "Name" ],
"Value" => [ "NAT #1" ],
})
Property("UserData", FnBase64(FnJoin("", [
"#!/bin/bash\n",
"yum update -y aws*\n",
". /etc/profile.d/aws-apitools-common.sh\n",
"# Configure iptables\n",
"/sbin/iptables -t nat -A POSTROUTING -o eth0 -s 0.0.0.0/0 -j MASQUERADE\n",
"/sbin/iptables-save > /etc/sysconfig/iptables\n",
"# Configure ip forwarding and redirects\n",
"echo 1 > /proc/sys/net/ipv4/ip_forward && echo 0 > /proc/sys/net/ipv4/conf/eth0/send_redirects\n",
"mkdir -p /etc/sysctl.d/\n",
"cat <<EOF > /etc/sysctl.d/nat.conf\n",
"net.ipv4.ip_forward = 1\n",
"net.ipv4.conf.eth0.send_redirects = 0\n",
"EOF\n",
"# Download nat_monitor.sh and configure\n",
"cd /root\n",
"wget http://media.amazonwebservices.com/articles/nat_monitor_files/nat_monitor.sh\n",
"# Wait for NAT #2 to boot up and update PrivateRouteTable2\n",
"sleep 180\n",
"NAT_ID=\n",
"# CloudFormation should have updated the PrivateRouteTable2 by now (due to yum update), however loop to make sure\n",
"while [ \"$NAT_ID\" == \"\" ]; do\n",
" sleep 60\n",
" NAT_ID=`/opt/aws/bin/ec2-describe-route-tables ", Ref( "priRtb2"),
" -U https://ec2.", Ref("region"), ".amazonaws.com | grep 0.0.0.0/0 | awk '{print $2;}'`\n",
" #echo `date` \"-- NAT_ID=$NAT_ID\" >> /tmp/test.log\n",
"done\n",
"# Update NAT_ID, NAT_RT_ID, and My_RT_ID\n",
"sed \"s/NAT_ID=/NAT_ID=$NAT_ID/g\" /root/nat_monitor.sh > /root/nat_monitor.tmp\n",
"sed \"s/NAT_RT_ID=/NAT_RT_ID=",
Ref("priRtb2" ),
"/g\" /root/nat_monitor.tmp > /root/nat_monitor.sh\n",
"sed \"s/My_RT_ID=/My_RT_ID=",
Ref("priRtb1"),
"/g\" /root/nat_monitor.sh > /root/nat_monitor.tmp\n",
"sed \"s/EC2_URL=/EC2_URL=https:\\/\\/ec2.",
Ref("region"),
".amazonaws.com",
"/g\" /root/nat_monitor.tmp > /root/nat_monitor.sh\n",
"sed \"s/Num_Pings=3/Num_Pings=",
Ref("nuPings"),
"/g\" /root/nat_monitor.sh > /root/nat_monitor.tmp\n",
"sed \"s/Ping_Timeout=1/Ping_Timeout=",
Ref("pingTimeout"),
"/g\" /root/nat_monitor.tmp > /root/nat_monitor.sh\n",
"sed \"s/Wait_Between_Pings=2/Wait_Between_Pings=",
Ref("pingWait"),
"/g\" /root/nat_monitor.sh > /root/nat_monitor.tmp\n",
"sed \"s/Wait_for_Instance_Stop=60/Wait_for_Instance_Stop=",
Ref("instStopWait"),
"/g\" /root/nat_monitor.tmp > /root/nat_monitor.sh\n",
"sed \"s/Wait_for_Instance_Start=300/Wait_for_Instance_Start=",
Ref("instStartWait"),
"/g\" /root/nat_monitor.sh > /root/nat_monitor.tmp\n",
"mv /root/nat_monitor.tmp /root/nat_monitor.sh\n",
"chmod a+x /root/nat_monitor.sh\n",
"echo '@reboot /root/nat_monitor.sh > /tmp/nat_monitor.log' | crontab\n",
"/root/nat_monitor.sh > /tmp/nat_monitor.log &\n"
])))
end
Resource("NAT2Instance") do
Type("AWS::EC2::Instance")
Metadata("Comment1", "Create NAT #2")
Property("InstanceType", {
"Ref" => [ "natType" ]
})
Property("KeyName", {
"Ref" => [ "keyName" ]
})
Property("IamInstanceProfile", {
"Ref" => [ "NATRoleProfile" ]
})
Property("SubnetId", {
"Ref" => [ "pubSub2" ]
})
Property("SourceDestCheck", "false")
Property("ImageID", FnFindInMap("AWSNATAMI", Ref("region"), "AMI"))
Property("SecurityGroupIds", {
"Ref" => [ "NATSecurityGroup" ]
})
Property("Tags", {
"Key" => [ "Name" ],
"Value" => [ "NAT #2" ],
})
Property("UserData", FnBase64(FnJoin("", [
"#!/bin/bash -v\n",
"yum update -y aws*\n",
"# Configure iptables\n",
"/sbin/iptables -t nat -A POSTROUTING -o eth0 -s 0.0.0.0/0 -j MASQUERADE\n",
"/sbin/iptables-save > /etc/sysconfig/iptables\n",
"# Configure ip forwarding and redirects\n",
"echo 1 > /proc/sys/net/ipv4/ip_forward && echo 0 > /proc/sys/net/ipv4/conf/eth0/send_redirects\n",
"mkdir -p /etc/sysctl.d/\n",
"cat <<EOF > /etc/sysctl.d/nat.conf\n",
"net.ipv4.ip_forward = 1\n",
"net.ipv4.conf.eth0.send_redirects = 0\n",
"EOF\n",
"# Download nat_monitor.sh and configure\n",
"cd /root\n",
"wget http://media.amazonwebservices.com/articles/nat_monitor_files/nat_monitor.sh\n",
"# Update NAT_ID, NAT_RT_ID, and My_RT_ID\n",
"sed \"s/NAT_ID=/NAT_ID=",
Ref("NAT1Instance"),
"/g\" /root/nat_monitor.sh > /root/nat_monitor.tmp\n",
"sed \"s/NAT_RT_ID=/NAT_RT_ID=",
Ref("priRtb1"),
"/g\" /root/nat_monitor.tmp > /root/nat_monitor.sh\n",
"sed \"s/My_RT_ID=/My_RT_ID=",
Ref("priRtb2"),
"/g\" /root/nat_monitor.sh > /root/nat_monitor.tmp\n",
"sed \"s/EC2_URL=/EC2_URL=https:\\/\\/ec2.",
Ref("region"), ".amazonaws.com",
"/g\" /root/nat_monitor.tmp > /root/nat_monitor.sh\n",
"sed \"s/Num_Pings=3/Num_Pings=",
Ref("nuPings"),
"/g\" /root/nat_monitor.sh > /root/nat_monitor.tmp\n",
"sed \"s/Ping_Timeout=1/Ping_Timeout=",
Ref("pingTimeout"),
"/g\" /root/nat_monitor.tmp > /root/nat_monitor.sh\n",
"sed \"s/Wait_Between_Pings=2/Wait_Between_Pings=",
Ref("pingWait"),
"/g\" /root/nat_monitor.sh > /root/nat_monitor.tmp\n",
"sed \"s/Wait_for_Instance_Stop=60/Wait_for_Instance_Stop=",
Ref("instStopWait"),
"/g\" /root/nat_monitor.tmp > /root/nat_monitor.sh\n",
"sed \"s/Wait_for_Instance_Start=300/Wait_for_Instance_Start=",
Ref("instStartWait"),
"/g\" /root/nat_monitor.sh > /root/nat_monitor.tmp\n",
"mv /root/nat_monitor.tmp /root/nat_monitor.sh\n",
"chmod a+x /root/nat_monitor.sh\n",
"echo '@reboot /root/nat_monitor.sh > /tmp/nat_monitor.log' | crontab\n",
"/root/nat_monitor.sh >> /tmp/nat_monitor.log &\n"
])))
end
Resource("NATSecurityGroup") do
Type("AWS::EC2::SecurityGroup")
Property("GroupDescription", "Rules for allowing access to HA Nodes")
Property("VpcId", {
"Ref" => [ "vpcId" ]
})
Property("SecurityGroupIngress", [
{
"CidrIp" => "0.0.0.0/0",
"FromPort" => "22",
"IpProtocol" => "tcp",
"ToPort" => "22"
},
{
"CidrIp" => "0.0.0.0/0",
"FromPort" => "0",
"IpProtocol" => "-1",
"ToPort" => "65535"
}
])
Property("SecurityGroupEgress", [
{
"CidrIp" => "0.0.0.0/0",
"FromPort" => "0",
"IpProtocol" => "-1",
"ToPort" => "65535"
}
])
end
Resource("NATAllowICMP") do
Type("AWS::EC2::SecurityGroupIngress")
Property("GroupId", {
"Ref" => [ "NATSecurityGroup" ]
})
Property("IpProtocol", "icmp")
Property("FromPort", "-1")
Property("ToPort", "-1")
Property("SourceSecurityGroupId", {
"Ref" => [ "NATSecurityGroup" ]
})
end
}'
从我的cfndsl
生成json时,我正在使用参数文件---
region: "us-east-1"
environment: "test"
vpcId: "vpc-xxxxxxxx"
vpcCidr: "10.0.0.0/16"
keyName: "xxxxxx"
pubSub1: "subnet-xxxxxxx"
pubSub2: "subnet-xxxxxxx"
priRtb1: "rtb-xxxxxxx"
priRtb2: "rtb-xxxxxxx"
natType: "t2.micro"
nuPings: "3"
pingTimeout: "1"
pingWait: "2"
instStopWait: "60"
instStartWait: "300"
答案 0 :(得分:2)
问题是您的Ref
内在函数(例如,{ "Ref" => [ "NATRole" ] }
当前具有字符串数组值[ "NATRole" ]
,但它们应该只是常规字符串"NATRole"
。
从模板中的Ref
函数中删除数组括号,并且CloudFormation应正确处理引用。