Reputation: 173
I am unable to load parameters into the python boto3 Cloudformation client.
Below is my parameter file:
[
{"ParameterKey": "pVpcId", "ParameterValue": "vpc-XXXXXX"},
{"ParameterKey": "pContact", "ParameterValue": "XDXDXX"},
{"ParameterKey": "pCC", "ParameterValue": "XXXXX" },
{"ParameterKey": "pFormat", "ParameterValue": "True"}
]
I'm loading it into the program in the following way:
with open(parameter_file, 'r') as infile:
parameters=ast.literal_eval(infile.read())
client = boto3.client('cloudformation',aws_access_key_id=access_key,aws_secret_access_key=secret_key,aws_session_token=session_token,region_name=region)
response = client.create_stack(
StackName=stack_name,
TemplateURL=stack_url,
Parameters=parameters
)
When I establish a boto3 client with Cloudformation and call it, I get the error described below. The call works without the parameters, so it's definitely something to do with the parameter file.
Traceback (most recent call last):
File "cf_create_stack", line 85, in <module>
Parameters=parameters
File "/usr/lib/python2.7/site-packages/botocore/client.py", line 357, in _api_call
return self._make_api_call(operation_name, kwargs)
File "/usr/lib/python2.7/site-packages/botocore/client.py", line 661, in _make_api_call
raise error_class(parsed_response, operation_name)
botocore.exceptions.ClientError: An error occurred (ValidationError) when calling the CreateStack operation: Template format error: unsupported structure.
Upvotes: 4
Views: 4753
Reputation: 566
So the TemplateBody param is expecting the content/str of the CloudFormation Template file and not just the filename.
The following should work satisfactorily.
cf_template = open('batch-job-cft.yml').read()
cf_client.create_stack(StackName='Batch Job', TemplateBody=cf_template)
# OR
# Optimal usage would be as below
with open('batch-job-cft.yml', 'r') as cf_file:
cft_template = cf_file.read()
cf_client.create_stack(StackName='Batch Job', TemplateBody=cft_template)
Upvotes: 4
Reputation: 173
Here's how I was able to resolve this:
In order to load the parameter file (which loads as a list of dictionaries), I had the following code:
with open(parameter_file) as f: parameters=json.load(f)
for l in parameters: l['UsePreviousValue']=eval('False')
In order to pass the Cloudformation template, I used the following code (basically reading it as a string):
with open(cloudformation_template) as g: template_body=g.read()
Finally, I passed both variables into the cloudformation client:
response = client.create_stack(
StackName=stack_name,
TemplateBody=template_body,
Parameters=parameters
)
The thing that was going wrong for me was that boto3 'Cloudformation' client expects a 'list of dictionaries' for parameters but expects a 'string' for the cloudformation template.
This is very frustrating and I'm trying to find a way to raise this to AWS.
Upvotes: 1
Reputation: 15472
I believe it is impossible that you got that response based on the code sample you provided.
I think you might have tried TemplateBody
rather than TemplateURL
?
To reproduce the error message, try this simple example:
#!/usr/bin/env python
import boto3
import ast
parameter_file = 'parameters.json'
client = boto3.client('cloudformation')
with open(parameter_file, 'r') as infile:
parameters = ast.literal_eval(infile.read())
response = client.create_stack(
StackName='TestStack',
TemplateBody='file://cloudformation.yml',
Parameters=parameters
)
If you place the parameters file and template in the expected locations and run this, you should then see the exact error message you are seeing:
Traceback (most recent call last):
File "test.py", line 17, in <module>
Parameters=parameters
File "/Users/alexharvey/git/home/python-test/virtualenv/lib/python2.7/site-packages/botocore/client.py", line 357, in _api_call
return self._make_api_call(operation_name, kwargs)
File "/Users/alexharvey/git/home/python-test/virtualenv/lib/python2.7/site-packages/botocore/client.py", line 661, in _make_api_call
raise error_class(parsed_response, operation_name)
botocore.exceptions.ClientError: An error occurred (ValidationError) when calling the CreateStack operation: Template format error: unsupported structure.
Note that this error:
Template format error: unsupported structure
Comes from the AWS API, not Boto3.
The error is caused when you pass in a file:// URI or URL to the TemplateBody parameter.
Moreover, I believe it is simply impossible to get that response if you really passed anything to TemplateURL.
See also:
Upvotes: 1