Cloudformation模板错误:每个Ref对象必须具有单个String值

时间:2015-11-11 13:00:59

标签: amazon-web-services amazon-cloudformation

我在验证我的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"

1 个答案:

答案 0 :(得分:2)

问题是您的Ref内在函数(例如,{ "Ref" => [ "NATRole" ] }当前具有字符串数组值[ "NATRole" ],但它们应该只是常规字符串"NATRole"

从模板中的Ref函数中删除数组括号,并且CloudFormation应正确处理引用。