Reputation: 407
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
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
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