CDK Ansible by Rust
This project is in an alpha state.
CDK-Ansible is a CDK (Cloud Development Kit) for Ansible, and inspired by AWS CDK.
While Ansible's playbook and inventory files are written in YAML format, managing YAML templating can be challenging.
CDK-Ansible enables you to generate Ansible files using Rust as a type-safe programming language.
WARNING: This project does not use JSii.

Features
- cdk-ansible can define an abstract Ansible Playbook using Rust.
- cdk-ansible-cli (
cdk-ansiblecommand) generates Rust code compatible with existing Ansible modules.
Version Compatibility
{cdk-ansible,cdk-ansible-cli}>=0.2.0 compatibility is shown in the table below.
| cdk-ansible | cdk-ansible-cli |
|---|---|
>=0.2.0 |
>=0.2.0 |
{cdk-ansible,cdk-ansible-cli}<v0.2.0 are guaranteed to work only with matching versions.
Quick Start
Template project can see in cdk-ansible-examples and support cargo-generate.
-
Install mise (not required but recommended)
-
Install cargo-generate, for example:
-
Init your project from template and 'Enter' (select default template)
-
Execute the sample command in your local environment.
# For the command details, refer to `[tasks.run]` in `mise.toml`. -
Edit
src/stack/*.rsandsrc/inventory/*.rs(orsrc/inventory.rs) as you like.
What can cdk-ansible do?
Define Plays
Define Ansible Play in Rust.
let play = Boxnew,
Define Stacks (L1 Stack)
Create cdk-ansible's Stack and define the relationship between Play (Sequential, Parallel, etc.).
// let play1, play2, play3, ...
%%{init: {'theme': 'redux', 'themeVariables': { 'fontSize': '30pt'}}}%%
stateDiagram
direction LR
state ForkExeParallel1 <<fork>>
state ForkExeParallel2 <<fork>>
state JoinExeParallel2 <<join>>
state JoinExeParallel1 <<join>>
[*] --> play1
play1 --> play2
play2 --> ForkExeParallel1
ForkExeParallel1 --> ForkExeParallel2
ForkExeParallel2 --> play3
ForkExeParallel2 --> play4
ForkExeParallel2 --> play5
play3 --> JoinExeParallel2
play4 --> JoinExeParallel2
play5 --> JoinExeParallel2
ForkExeParallel1 --> play6
play6 --> play7
ForkExeParallel1 --> play8
JoinExeParallel2 --> JoinExeParallel1
play7 --> JoinExeParallel1
play8 --> JoinExeParallel1
JoinExeParallel1 --> play9
play9 --> [*]
Instantiate an App
Instantiate CDK-Ansible's App and add Inventory and Stack to it.
Run the App
Run your app.
If your ansible command is installed through uv, pass --playbook-command option like below.
L2 Stack (Recommended)
CDK-Ansible can also define higher-level L2 (Layer 2) stacks. In comparison, the previous Stack is called an L1 Stack.
- L1 Stack first statically defines all Inventory and Play objects before moving to the execution phase.
- In contrast, L2 Stack generates Inventory and Play objects just before executing each Play.
- This allows generating Inventory and Play objects based on the execution state up to that point. This functionality can serve as an alternative to Ansible's Dynamic Inventory.
%%{init: {'theme': 'redux', 'themeVariables': { 'fontSize': '30pt'}}}%%
stateDiagram
direction LR
state ForkExeParallel2 <<fork>>
state JoinExeParallel2 <<join>>
[*] --> LazyPlayL2_1
LazyPlayL2_1 --> ForkExeParallel2
ForkExeParallel2 --> LazyPlayL2_2
ForkExeParallel2 --> LazyPlayL2_3
LazyPlayL2_2 --> JoinExeParallel2
LazyPlayL2_3 --> JoinExeParallel2
JoinExeParallel2 --> LazyPlayL2_4
LazyPlayL2_4 --> [*]
%%{init: {'theme': 'redux', 'themeVariables': { 'fontSize': '10pt'}}}%%
stateDiagram
direction LR
classDef Rose stroke-width:1px,stroke-dasharray:none,stroke:#FF5978,fill:#FFDFE5,color:#8E2236;
state LazyPlayL2_1 {
direction LR
[*] --> s2
s2 --> s4
s4 --> [*]
}
[*] --> LazyPlayL2_1
LazyPlayL2_1 --> [*]
s2:Generate Inventory<br>and Play (Playbook)
s4:Run Playbook
class s2 Rose
The definition of L2 Stack is similar to L1, but it implements the StackL2 trait.
The difference is that fn exe_play returns &LazyExePlayL2.
LazyExePlayL2 corresponds to ExePlay, but it can accept objects that implement the LazyPlayL2 trait instead of Play objects.
The LazyPlayL2 trait implements an async function fn lazy_play_l2 which can generate information equivalent to an Ansible Play within this function.
PlayL2::hosts is not a simple string, but an object that implements the HostInventoryVarsGenerator trait.
This allows you to generate Inventory dynamically based on the execution state up to that point.
cdk-ansible-cli (cdk-ansible command)
Install
mise
MISE is recommended as it allows you to keep the versions of the cdk-ansible crate and CLI in sync.
binstall
shell
cargo install
Requirements
- cdk-ansible-cli
- rustfmt
rustup component add rustfmt
- rustfmt
Tutorial
Create Ansible Module package for a workspace
Running cdk-ansible module command generates a Rust package for the specified Ansible module.
# '<namespace>.<collection>.<module>' only generates the specified module.
cdkam_ansible in below example is auto-generated by cdk-ansible module command.
your-cdk-ansible-app/
|-- Cargo.toml
`-- crates/
`-- my-app/ ... your app (run `cdk_ansible::App`)
`-- cdkam_ansible/ ... auto-generated by `cdk-ansible module` command
|-- Cargo.toml
`-- src/
|-- lib.rs
|-- m/ansible/builtin/debug.rs
`-- ...
cdk-ansible module command has other options.
# '<namespace>.<collection>' generates all modules in the collection.
# '<namespace>' generates all modules in the namespace.
# If you don't specify `--module-name` or `--module-name-regex`,
# all modules accessible from your ansible environment will be generated.
# (This is the same as `--module-name-regex '*'`)
# If you are using uv to manage your ansible project, move to the directory or specify the `--project` option.