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 g
8000
enerate Ansible files using Rust as a type-safe programming language.
WARNING: This project does not use JSii.
- cdk-ansible can define an abstract Ansible Playbook using Rust.
- cdk-ansible-cli (
cdk-ansible
command) generates Rust code compatible with existing Ansible modules.
Full example project can see in cdk-ansible-examples's cli-init directory.
Define Ansible Play in Rust.
let play = Box::new(Play {
name: "sample-play".into(),
hosts: hosts.into(),
options: PlayOptions::default(),
tasks: vec![Task {
name: "Debug".into(),
options: TaskOptions::default(),
command: Box::new(::cdkam::ansible::builtin::debug::Module {
module: ::cdkam::ansible::builtin::debug::Args {
options: ::cdkam::ansible::builtin::debug::Opt {
msg: OptU::Some("Hello, world!".into()),
..Default::default()
},
},
}),
}],
}),
Create cdk-ansible's Stack and define the relationship between Play in Rust (Sequential, Parallel, etc.).
// let play1, play2, play3, ...
pub struct SampleStack {
exe_play: ExePlay,
}
impl SampleStack {
pub fn new(hp: &HostPool) -> Self {
let hosts = hp.localhost.name.as_str();
Self {
exe_play: ExeSequential(vec![
ExeSingle(Box::new(play1)),
ExeSingle(Box::new(play2)),
ExeParallel(vec![
ExeParallel(vec![
ExeSingle(Box::new(play3)),
ExeSingle(Box::new(play4)),
ExeSingle(Box::new(play5)),
]),
ExeSequential(vec![
ExeSingle(Box::new(play6)),
ExeSingle(Box::new(play7)),
]),
ExeSingle(Box::new(play8)),
]),
ExeSingle(Box::new(play9)),
]),
}
}
}
stateDiagram-v2
[*] --> play1
play1 --> play2
state ForkExeParallel1 <<fork>>
play2 --> ForkExeParallel1
state ForkExeParallel2 <<fork>>
ForkExeParallel1 --> ForkExeParallel2
ForkExeParallel2 --> play3
ForkExeParallel2 --> play4
ForkExeParallel2 --> play5
state JoinExeParallel2 <<join>>
play3 --> JoinExeParallel2
play4 --> JoinExeParallel2
play5 --> JoinExeParallel2
ForkExeParallel1 --> play6
play6 --> play7
ForkExeParallel1 --> play8
state JoinExeParallel1 <<join>>
JoinExeParallel2 --> JoinExeParallel1
play7 --> JoinExeParallel1
play8 --> JoinExeParallel1
JoinExeParallel1 --> play9
play9 --> [*]
Instantiate CDK-Ansible's App and add Inventory and Stack to it.
pub fn run() -> Result<()> {
let host_pool = HostPool {
localhost: LocalHost {
name: "localhost".into(),
},
host_a: Rc::new(HostA {
name: "host-a".into(),
fqdn: "host-a.example.com".into(),
}),
host_b: RefCell::new(HostB {
name: "host-b".into(),
fqdn: "host-b.example.com".into(),
}),
};
let mut app = App::new(std::env::args().collect());
app.add_inventory(host_pool.to_inventory()?)?;
app.add_stack(Box::new(SampleStack::new(&host_pool)))?;
app.run()
}
Run your app.
cargo run --package my-app -- deploy -P 3 -i dev SampleStack
If your ansible command is installed through uv
, pass --playbook-command
option like below.
MISE is recommended as it allows you to keep the versions of the cdk-ansible crate and CLI in sync.
mise use cargo:cdk-ansible-cli
cargo binstall cdk-ansible-cli
cargo install cdk-ansible-cli
- cdk-ansible-cli
- rustfmt
rustup component add rustfmt
- rustfmt
While we plan to provide an init command in the future, for now it is recommended to copy the following sample project.
Running cdk-ansible module
command generates a Rust package for the specified Ansible module.
# '<namespace>.<collection>.<module>' only generates the specified module.
cdk-ansible module --output-dir crates/ --module-name ansible.builtin.debug
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.
cdk-ansible module --output-dir crates/ --module-name-regex 'ansible\.builtin\..*'
# '<namespace>' generates all modules in the namespace.
cdk-ansible module --output-dir crates/ --module-name-regex 'ansible\..*'
# 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 '*'`)
cdk-ansible module --output-dir crates/
# If you are using uv to manage your ansible project, move to the directory or specify the `--project` option.
uv --project /path/to/your/ansible-project run \
cdk-ansible module --output-dir crates/ --module-name ansible.builtin.debug