Loading...

How to generate IaC templates for your AWS Resources

Infrastruture as code is tedious to write and sometimes abstracted from the source vendor's docs. Thankfully, automating it is getting easier.
In fact, by 2027 the IaC industry is projected to be worth 2.3 billion dollars. A flood of companies automating IaC creation for you. Still, being able to generate it with your own logic could be satisfactory for your needs and save the budget for other tooling.
Let's see how we can automate IaC generation of an AWS DynamoDB table into both Cloudformation and Terraform templates. The same logic can be expanded to codify entire solutions.

Setting up environment

Create an automate-iac folder and open it in your prefered IDE. Let's create a python environment and install dependencies. For this example we are using cf2tf module to convert cloudformation to terraform.

python -m venv env
env/bin/pip install boto3 cf2tf

Code Walkthrough

Now lets step through the relevant code blocks.
First we create a cloudformation template of an existing AWS resource. Most of the popular AWS services are supported by the create_generated_template call. Refer to the docs for configuration of various resources. Once the template is created you can retrieve the YAML and save it locally with the get_generated_template call. And just like that you have a cloudformation template that you can deploy in another account, etc

# create cloudformation client
client = boto3.client('cloudformation')

# generate template
response = client.create_generated_template(
   Resources=[
       {
           'ResourceType': 'AWS::DynamoDB::Table',
           'LogicalResourceId': 'mytable',
           'ResourceIdentifier': {
               'TableName': 'mytablename'
           }
       },
   ],
   GeneratedTemplateName='mytablename_template',
   TemplateConfiguration={
       'DeletionPolicy': 'RETAIN',
       'UpdateReplacePolicy': 'RETAIN'
   }
)
# get template body
response = client.get_generated_template(
   Format='YAML',
   GeneratedTemplateName='mytablename_template'
).get('TemplateBody')

# save template locally to a file
with open('cf.yaml','w') as f:
   f.writelines(response)

But what if we have to use terraform (or OpenTofu). That's where cf2tf comes in handy. Specify the source and destination locations and let TemplateConverter do the magic!

# specify the path to the cloudformation file
tmpl_path = Path('cf.yaml')

# specify to write the resultant tf file to the current working directory
output_writer = cf2tf.save.create_writer('./')

cf_template = Template.from_yaml(tmpl_path).template

# convert cloudformation template into a terraform configuration
search_manager = code.search_manager()
config = TemplateConverter(tmpl_path.stem, cf_template, search_manager).convert()

# Save configuration to disk
config.save(output_writer)

Here's the complete code -

import boto3

import cf2tf.save
from cf2tf.cloudformation import Template
from cf2tf.convert import TemplateConverter
from cf2tf.terraform import code
from pathlib import Path

# create cloudformation client
client = boto3.client('cloudformation')

# generate template
response = client.create_generated_template(
   Resources=[
       {
           'ResourceType': 'AWS::DynamoDB::Table',
           'LogicalResourceId': 'mytable',
           'ResourceIdentifier': {
               'TableName': 'mytablename'
           }
       },
   ],
   GeneratedTemplateName='mytablename_template',
   TemplateConfiguration={
       'DeletionPolicy': 'RETAIN',
       'UpdateReplacePolicy': 'RETAIN'
   }
)
# get template body
response = client.get_generated_template(
   Format='YAML',
   GeneratedTemplateName='mytablename_template'
).get('TemplateBody')

# save template locally to a file
with open('cf.yaml','w') as f:
   f.writelines(response)

# specify the path to the cloudformation file
tmpl_path = Path('cf.yaml')

# specify to write the resultant tf file to the current working directory
output_writer = cf2tf.save.create_writer('./')

cf_template = Template.from_yaml(tmpl_path).template

# convert cloudformation template into a terraform configuration
search_manager = code.search_manager()
config = TemplateConverter(tmpl_path.stem, cf_template, search_manager).convert()

# Save configuration to disk
config.save(output_writer)

Take the next step

The above example demonstrates how easy it is to generate IaC for your assets in AWS. Azure also has similar capabilities for generating ARM templates of their resources.
This logic could be adapted to create an IaC backed environment where Click Ops is the status quo. It could be a massive help in DR situations or when lower environments need to be created from production ones.
Echelon One can help take the simple logic above and force multiply it to a fully production ready enterprise infrastructure as code manager for your environment. From storing the templates in a centralized place, to making it trivial to manage the execution on an ongoing basis, to safeguarding it with access controls - Echelon One has you covered.
Reach out to us and we'll run a free automation lab of this with your team!

Your Transformation Journey Awaits!

Experience a tailored, obligation-free demo crafted just for you.