New to Kestra?
Use blueprints to kickstart your first workflows.
Two-stage Ansible pattern with Kestra: download playbooks containing Kestra expressions, render them with runtime outputs, then run the result.
Sometimes the playbook itself needs Kestra data: an IP produced by a provisioning task, a message from an upstream API call, a secret-derived value. This blueprint demonstrates the two-stage pattern that makes it work. Stage one downloads (or, here, generates) inventories and playbooks that contain unrendered Kestra expressions, protected by {% raw %} markers. Stage two loops over every downloaded file, renders the expressions with live execution context using render(read(...)), writes the results back to the same relative paths, and runs the rendered playbook with the Ansible CLI.
dummy_values task (io.kestra.plugin.core.output.OutputValues) produces the runtime data to inject; in real use this is any upstream task output.setup task (io.kestra.plugin.core.flow.WorkingDirectory) simulates a Git checkout: shell scripts create ansible_inventory/inventory.ini and ansible_playbooks/playbook.yml, where the playbook references {{ outputs.dummy_values.values.message }} wrapped in {% raw %} so it survives the first pass unrendered. Everything is exported via outputFiles: ansible_*/**.render_and_run task opens a fresh WorkingDirectory. Its render_all_files script (io.kestra.plugin.scripts.shell.Script) iterates outputs.setup.outputFiles with a Pebble {% for %} loop, recreates each directory, and writes {{ render(read(entry.value)) }}: the file content with all Kestra expressions now evaluated.ansible_run_playbook task (io.kestra.plugin.ansible.cli.AnsibleCLI) runs the rendered playbook inside cytopia/ansible:latest-tools, printing the injected message.{% raw %} escape pattern that lets you commit Kestra expressions inside Git-managed files.outputs.<task>.outputFiles + render(read(...))) reusable for Terraform vars, Helm values, or config bundles.Ansible's own templating cannot see your orchestrator's state: task outputs, KV values, secrets, execution metadata. Kestra's Pebble engine can, and this pattern applies it to whole directories of files at runtime. Combined with WorkingDirectory for shared filesystems and outputFiles for passing artifacts between isolated stages, you get late-bound configuration without maintaining a custom rendering script per repository.
setup scripts for io.kestra.plugin.git.Clone).GITHUB_ACCESS_TOKEN) when cloning private repositories, and reference secrets inside templated files with {{ secret('NAME') }}.localhost inside the container and prints the templated message.setup shell scripts with a Clone of your templated repository.{% raw %}...{% endraw %}.ansible-playbook command at your real inventory and playbook paths..tfvars, Helm values, or Kubernetes manifests the same way.ansible-lint, yamllint) between rendering and execution.outputFiles for multi-stage pipelines.io.kestra.plugin.core.flow.ForEach.