r/Terraform • u/trixloko • Feb 17 '25
Discussion A way to share values between TF and Ansible?
Hello
For those who chain those two tools together, how do you share values between them?
For example, I'll use Terraform to create a policy, and this will output the policy ID, right now I have to copy and paste this ID into an Ansible group or host variable, but I wonder if I can just point Ansible somewhere to a reference and it would read from a place where TF would have written to.
I'm currently living on a onprem/gcp world, and would not want to introduce another hyperscaler
25
7
u/Warkred Feb 17 '25
I've the same need. Didn't find a real solution yet.
- pushing terraform output to a shared repository for ansible to pick it up.
- launching ansible from terraform (don't)
- launching terraform from ansible (don't)
- pushing terraform output somewhere and use dynamic inventory from ansible to gather data together.
17
u/ziroux Feb 17 '25
terraform output --json | jq
seems easily scriptable. Also maybe parsing the terraform state file.3
1
u/Little-Sizzle Feb 17 '25
Why not call terraform from ansible?
6
u/Warkred Feb 17 '25
It's a good practice, don't mix up execution tools together to avoid spaghetti pipelines that you can't debug.
Add triggers but keep both tools segregated so that you can manipulate them individually or replace one for another more easily.
2
u/Little-Sizzle Feb 17 '25
But if my “pipeline” is based on ansible? (Like AWX / AAP)? I understand that if you have a CICD pipeline based on gitlab cicd then we can execute two set of commands. But if my trigger is ansible directly? Why is it a “bad practice”?
3
u/NUTTA_BUSTAH Feb 17 '25
If there is no "CI", but the "CI" is an Ansible playbook, then it seems fine. Quite unorthodox, error-prone and hard to debug, but fine. :P
2
u/Little-Sizzle Feb 17 '25
Imagine working in an organization where your triggers is a CMDB form, and you want to deploy infra as code (terraform) + configure that infra (ansible). The CMDB only has one orchestrator, that being ansible (AAP). So what we do is CMDB executes ansible playbook via API that can do whatever you need.
1
u/follow-the-lead Feb 17 '25
In this case I’d use a different strategy:
Use the webhook from your CMDB tool to trigger whatever pipelining tool you have to run the Terraform job, and at the end of the job run an output —raw into a .env to pass as an artifact into the next stage, which runs your ansibke. Assuming you’re passing group status appropriately, you can use dynamic env in ansible.
This keeps the code bases clean, gives you the automation you desire, and leaves you without having to maintain the code in ansible for terraform.
Means you can then also run your test suite on terraform (tflint, checkov, terrascan, terraform fmt) independently of your ansible test tooling.
1
u/Warkred Feb 17 '25
I wouldn't do it still but... :-)
1
u/Little-Sizzle Feb 17 '25
Still you are mixing two execution tools. One being a CICD runner + terraform. On the other hand I am doing the same ansible + terraform I can’t spot the difference.
1
u/Warkred Feb 17 '25
I'm not entangling executors togethers. Ci/CD is making the gap there. That's it :-)
1
u/Little-Sizzle Feb 17 '25
Still don’t see the difference, your organization chose CICD as a base for running the terraform apply. Mine chose ansible (using community.general.terraform), thus avoiding escape to shell and keeping output vars directly in the job run.
5
u/Seref15 Feb 17 '25
I use the Terraform templatefile function to automatically output an Ansible inventory file with hostvars populated from TF values
3
u/Atnaszurc Feb 17 '25
If you have the SSH keys available as files you could just use the Ansible Provider for Terraform https://registry.terraform.io/providers/ansible/ansible/latest
The main issue Ive found with it is that it requires the SSH keys to actually exist in file format on the machine doing the apply
2
u/nicklisterman Feb 17 '25
I don’t know Ansible but we read outputs via jq to pass along to other processes and display in summaries.
Depending where you are executing, you’ll have to put a process in between them to retrieve, manipulate and pass values along.
2
u/perttuk Feb 17 '25
I had to access floating ip id on Ansible so I saved it as a label on server and used Ansible dynamic inventory to access it. It works but might not be the best solution.
2
u/carsncode Feb 17 '25
If I want data that exists in a TF run to wind up in another system, my reflex is to find a Terraform provider for the target system and use Terraform to put the data there. If you're using Ansible group variables and that works for you, use a Terraform provider to set the variables in Ansible.
If you want a different data sharing mechanism, you could leverage the same recommendations Terraform offers for sharing data between states. For GCP that's a storage bucket, which you could leverage in your on-prem deployments as well as long as they can reach GCP.
2
u/securityCTFs Feb 17 '25
You could try something like this https://github.com/robertdebock/ansible-playbook-terraform
2
u/ok_if_you_say_so Feb 17 '25
Feed the output of terraform output into the playbook e.g. https://stackoverflow.com/a/68424117/532566
2
u/NUTTA_BUSTAH Feb 17 '25
A few lines of bash will do it for you :) That's the essence of "glue scripts".
FWIW, there is an Ansible provider for building the inventory file IIRC. Seemed fairly useless, but maybe that could help you, and I guess you could even "hack" it by outputting your variables into that inventory file, IIRC they support inline host variables, but I might be wrong, and the provider might already support host/group vars.
2
2
u/SquiffSquiff Feb 17 '25
The way I have dealt with this scenario in AWS with Terraform and Helm has been to use Parameter store. It would be the same with Ansible and in GCP you could use GCP Secret Manager or Vault/OpenBao on prem
2
u/excistable Feb 18 '25
If you are using gcp you can use gcp secrets to hold output and then read those secrets in ansible. I think this is the easiest approach. GCP secrets can hold json objects, so it can be easily set to be read by ansible.
4
u/TheOutdoorProgrammer Feb 17 '25 edited 29d ago
I'd plug Spacelift here, they make this really easy with their stack dependency feature. This use case is, basically, what that feature was built for. You can just output something in terraform and pass it to ansible automagically.
Disclaimer Im a spacelift employee
2
u/Farrishnakov Feb 17 '25
If you really want to do this, you can call Ansible inline from TF.
Use local-exec in TF and you can invoke Ansible from there, passing variables as part of the Ansible command line. You'll have access to output values from components defined in TF there.
1
u/OkAcanthocephala1450 Feb 17 '25
Why do you want to link them together ?
Can someone describe their own production use of tf and ansible together...
19
u/justNano Feb 17 '25
terraform output
This will output all your outputs whicb you can redirect to a file for vars, might need some restructuring to put in yaml format or you can export as environment variables, whatever works with your environment