I recently had to work with Ansible for the first time. I needed to install software on several EC2 instances, and I was given an Ansible playbook that I needed to execute.
When examining the structure of the Ansible folder, I noticed that I had to update certain variables within a file named 'specifics.yml.' These variables were formatted as follows:
nfs_mounts:
- src: "myNfsDNSname:/"
my_super_infra:
hosts:
10.10.10.10:
I initially began working with it. However, as I continued testing, I found myself making numerous deployments with Terraform. Each time, I had to modify my code to include the new EFS DNS name, which proved to be quite a hassle.
For context, I had established a CI/CD pipeline using Gitlab-CI for this project, which had the following structure:
From that point on, I needed to discover a way to dynamically obtain values generated during the Terraform 'apply' stage. Initially, I considered using Terraform to create a file at the end of the 'apply' stage containing the output of my modules. While this approach would work, it would also make the execution of the Ansible job dependent on the completion of the Terraform 'apply' stage. This was not what I wanted; I aimed to run the Ansible playbook without having to go through Terraform each time.
So, I came up with this idea: introduce a Terraform module that stores the necessary variables in the AWS SSM Parameter Store. This module takes certain variables as input, which are the outputs of my modules that I wish to retrieve in Ansible, such as the EFS DNS name. To achieve this, you only need to include the following code snippet for each of your variables:
resource "aws_ssm_parameter" "efs_dns_url" {
name = "OUTPUT_EFS_DNS_URL"
type = "String"
value = var.efs_dns_url
}
You can also use count if you have a list (for example a list of IPs) :
resource "aws_ssm_parameter" "my_ip" {
count = length(var.my_ip)
name = "OUTPUT_MY_IP_${count.index}"
type = "String"
value = var.my_ip[count.index]
}
With this step, the initial part of my strategy was set up. The next challenge was to retrieve these values within my Ansible 'specifics.yml' file. As I delved into the documentation, I came across a page in the Ansible documentation that was precisely what I needed! The first step was to include the requirements in the 'requirements.yml' file:
- name: amazon.aws
version: 6.5.0
Then, you remember the specifics.yml ? it now looks like this :
nfs_mounts:
- src: "{{ lookup('amazon.aws.aws_ssm', 'OUTPUT_EFS_DNS_URL', region='eu-central-1' ) }}:/"
It's as straightforward as that! You can now fetch specific values from Terraform directly into your Ansible playbook. This is incredibly convenient. The only drawback I've encountered here is the output when you execute the playbook, particularly when you utilize it for the host section, like:
my_block:
hosts:
"{{ lookup('amazon.aws.aws_ssm', 'OUTPUT_MY_IP_0', region='eu-central-1' )}}":
"{{ lookup('amazon.aws.aws_ssm', 'OUTPUT_MY_IP_1', region='eu-central-1' )}}":
When you run the playbook with this kind of setup, you get an output which looks like this :
This is not ideal, you can change it using variables, but I havenโt found a way yet to get the IP here instead of a placeholder. If you have an idea, feel free to reach out to me via the comments or on my socials.
Top comments (0)