jason
jason

Reputation: 407

Cloudformation template error - Template validation error: Template format error: Every Mappings member Type must be a map

I have a cloudformation template.

It should create an EC2 instance, change the Adminstrator password and rename the server.

I am passing couple of parameters to the stack template. When I run it, it gives "Template format error: Every Mappings member Type must be a map".

I made sure whatever I am referring in the template, are in the "Mappings" section. Not sure why I am getting this error.

Any suggestions are very helpful.

{
   "AWSTemplateFormatVersion": "2010-09-09",

   "Parameters": {

"LocalAdminPassword" :
{
  "Type": "String",
  "NoEcho" : "true",
  "Description": "Password for the local server administrator account."
   }   
},

 "Mappings": {  

"EnvironmentTypeName" :
{
  "PlatformName" : {"Dev" : "D", "Test" : "T", "Prod" : "P"}
},
"QRMEnvironmentType" : 
{
  "Description"   :   "QRM Dev, test, or Prod Platform",
  "Type"          :   "String",
  "AllowedValues" :  ["Dev", "Test", "Prod"],
  "Default" : "Dev",
  "ConstraintDescription" : "must be either Dev, test, or Prod"
},
"QRMAvailabilityZoneIndex" :
{
  "Description"   :   "QRM Platform AZ letter A,B, or C for Dev, Test, or Prod",
  "Type"          :   "String",
  "AllowedValues" :  ["A", "B", "C"],
  "Default" : "A",
  "ConstraintDescription" : "Must be a letter of the AZ in the specified Region"
  }   
},

 "Resources": {
      "MyInstance": {
      "Type": "AWS::EC2::Instance",
      "Metadata" : {
          "AWS::CloudFormation::Init" : {
         "config" : {
           "files" : {
             "c:\\cfn\\cfn-hup.conf" : {
               "content" : { "Fn::Join" : ["", [
                 "[main]\n",
                 "stack=", { "Ref" : "AWS::StackId" }, "\n",
                 "region=", { "Ref" : "AWS::Region" }, "\n"
                 ]]}
             },
             "c:\\cfn\\hooks.d\\cfn-auto-reloader.conf" : {
               "content": { "Fn::Join" : ["", [
                 "[cfn-auto-reloader-hook]\n",
                 "triggers=post.update\n",
           "path=Resources.MyInstance.Metadata.AWS::CloudFormation::Init\n",
                "action=cfn-init.exe -v -s ", { "Ref" : "AWS::StackId" },
                                                 " -r MyInstance",
                                                 " --region ", { "Ref" : "AWS::Region" }, "\n"
               ]]}
            },
            "c:\\scripts\\test.ps1" : {
               "content": { "Fn::Join" : ["", [
                 "Write-Host Hello World!\n"
               ]]}
             }
           },
           "commands" : {

           "1-run-script" : 
            {
                "command" : 
                    {   
                      "Fn::Join" : 
                      [ 
                        "", 
                        [  
                          "Powershell.exe  ([adsi]\\\"WinNT://$env:computername/Administrator\\\").SetPassword('",{ "Ref": "LocalAdminPassword"},"')"  
                        ] 
                      ]
                    }
            },
            "02-rename-server" :
                  {
                    "command" :
                    {
                      "Fn::Join" : 
                      [ 
                        "", 
                        [ 
                          "powershell.exe Rename-Computer -NewName ",  {"Fn::Join"  : [ "",[ "AW", {"Fn::FindInMap" : [ "EnvironmentTypeName", "PlatformName", {"Ref" : "QRMEnvironmentType"} ]},"W",{"Ref": "QRMAvailabilityZoneIndex"},"QRMHEAD"]] }    ," -force -restart"
                        ]
                      ]
                    },
                    "WaitAfterCompletion" : "forever"
                  },                
              "3-run-script" : {
                    "command" : { "Fn::Join" : [ "", [
                        "Powershell.exe Set-ExecutionPolicy Unrestricted -force \n",
                        "Powershell.exe C:\\scripts\\test.ps1 \n",
                        "Powershell.exe Start-Sleep -s 60; . C:\\PowershellScripts\\WindowsServiceManager.ps1;StopWindowsService Dnscache" , "\n"
                        ]]}}
                },
            "services": {
               "windows": {
                  "cfn-hup": {
                            "enabled": "true",
                            "ensureRunning": "true",
                            "files": ["c:\\cfn\\cfn-hup.conf", "c:\\cfn\\hooks.d\\cfn-auto-reloader.conf"]
                                                            }
                                 }
                                            }
     }                                   
                            }
   },
 "Properties": {
   "DisableApiTermination": "FALSE",
   "ImageId": "ami-3723c04f",
   "InstanceType": "t2.micro",
   "KeyName": "EC2Instances",
   "Monitoring": "false",
   "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
     "<script>\n",
     "cfn-init.exe -v -s ", { "Ref" : "AWS::StackName" },
     " -r MyInstance",
     " --region ", { "Ref" : "AWS::Region" }, "\n",

     "cfn-signal.exe -e 0 ", { "Fn::Base64" : { "Ref" : "WindowsServerWaitHandle" }}, "\n",

     "</script>\n"
     ]]}},
   "Tags": [
     {
       "Key": "Name",
       "Value": "MyEC2Instance"
     }
   ],

     }
  ,
    "WindowsServerWaitHandle": {
         "Type": "AWS::CloudFormation::WaitConditionHandle"
    },
     "WindowsServerWaitCondition": {
          "Type": "AWS::CloudFormation::WaitCondition",
          "DependsOn": "MyInstance",
      "Properties": {
     "Handle": { "Ref": "WindowsServerWaitHandle" },
     "Timeout": "1800"
   }
   }        
 }
}

Upvotes: 16

Views: 14060

Answers (2)

alex
alex

Reputation: 7471

I'm pretty sure that the issue is that you have parameters in your mappings section. It becomes more evident when you format the JSON document:

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Parameters": {
    "LocalAdminPassword": {
      "Type": "String",
      "NoEcho": "true",
      "Description": "Password for the local server administrator account."
    }
  },
  "Mappings": {
    "EnvironmentTypeName": {
      "PlatformName": {
        "Dev": "D",
        "Test": "T",
        "Prod": "P"
      }
    },
    "QRMEnvironmentType": {
      "Description": "QRM Dev, test, or Prod Platform",
      "Type": "String",
      "AllowedValues": [
        "Dev",
        "Test",
        "Prod"
      ],
      "Default": "Dev",
      "ConstraintDescription": "must be either Dev, test, or Prod"
    },
    enter code here

...

I also want to add that Igor's answer seems to be entirely valid - and more often than not, users running into this error will experience it for this reason.

Per the AWS docs: if you want to dereference anything in the mappings section with !FindInMap ... the Mapping section layout is highly-opinionated and must describe mappings in the following format:

Mappings:
  TopLevelMapping:
    TopLevelKey:
      SecondLevelKey: "the real thing you need to dereference"

That means that this would be an invalid mapping:

Mappings:
  AmiId: ami-0123456789

And that means that this would also be an invalid mapping:

Mappings:
  GlobalVariables:
    AmiId: ami-0123456789

But this would be considered a valid mapping:

Mappings:
  GlobalVariables:
    GlobalVariables:
      AmiId: ami-0123456789

This appears to be how the system was intentionally designed.

Upvotes: 0

Igor Gelfgat
Igor Gelfgat

Reputation: 111

I had the same problem with yaml template. It looks like only 2-level mappings are supported in the template, so you need to add another level where relevant, eg,

...
"QRMEnvironmentType" : 
{
  "Description"   :   {"Value": "QRM Dev, test, or Prod Platform"},
  "Type"          :   {"Value": "String"},
  ...
}
...

Upvotes: 11

Related Questions