Ansible vault + roles

This commit is contained in:
wendrul
2025-04-03 18:26:44 +02:00
parent dd3074a23c
commit a22d0e0680
3 changed files with 80 additions and 8 deletions

View File

@@ -217,6 +217,8 @@ pub struct AnsibleRequirements {
pub vars: Vec<(String, String)>,
pub resources: Vec<(String, String)>,
pub options: AnsiblePlaybookOptions,
pub vault_password_file: Option<String>,
pub vault_id: Vec<String>,
}
fn parse_inventories(inventory_yaml: &Yaml) -> anyhow::Result<Vec<AnsibleInventory>> {
@@ -290,6 +292,8 @@ pub fn parse_ansible_reqs(
vars: vec![],
resources: vec![],
options: opts,
vault_password_file: None,
vault_id: vec![],
};
if let Yaml::Hash(doc) = &docs[0] {
@@ -345,6 +349,24 @@ pub fn parse_ansible_reqs(
Yaml::String(key) if key == "inventory" => {
ret.inventories = parse_inventories(value)?;
}
Yaml::String(key) if key == "vault_password_file" => {
let Yaml::String(filename) = value else {
return Err(anyhow!("Vault Password File expects a String containing the file name"));
};
ret.vault_password_file = Some(filename.to_string());
}
Yaml::String(key) if key == "vault_id" => {
let Yaml::Array(filenames) = value else {
return Err(anyhow!("Vault ID field expects an array of strings in the format: `label@filename`"));
};
for f in filenames {
let Yaml::String(filename) = f else {
return Err(anyhow!("The elements of the vault_id field should be strings in the format: `label@filename`"));
};
ret.vault_id.push(filename.to_string());
}
}
Yaml::String(key) if key == "options" => {
if let Yaml::Array(opts) = &value {
ret.options = parse_ansible_options(opts);

View File

@@ -136,15 +136,48 @@ async fn install_galaxy_collections(
db,
)
.await;
let mut galaxy_command = Command::new(ANSIBLE_GALAXY_PATH.as_str());
galaxy_command
let mut galaxy_roles_cmd = Command::new(ANSIBLE_GALAXY_PATH.as_str());
galaxy_roles_cmd
.current_dir(job_dir)
.env_clear()
.envs(PROXY_ENVS.clone())
.env("PATH", PATH_ENV.as_str())
.env("TZ", TZ_ENV.as_str())
.args(vec![
"install",
"-r",
"requirements.yml",
"-p",
"./",
])
.stdout(Stdio::piped())
.stderr(Stdio::piped());
let child = start_child_process(galaxy_roles_cmd, ANSIBLE_GALAXY_PATH.as_str()).await?;
handle_child(
job_id,
db,
mem_peak,
canceled_by,
child,
!*DISABLE_NSJAIL,
worker_name,
w_id,
"ansible galaxy install",
None,
false,
&mut Some(occupancy_metrics),
)
.await?;
let mut galaxy_collections_cmd = Command::new(ANSIBLE_GALAXY_PATH.as_str());
galaxy_collections_cmd
.current_dir(job_dir)
.env_clear()
.envs(PROXY_ENVS.clone())
.env("PATH", PATH_ENV.as_str())
.env("TZ", TZ_ENV.as_str())
// .env("BASE_INTERNAL_URL", base_internal_url)
// .env("HOME", HOME_ENV.as_str())
.args(vec![
"collection",
"install",
@@ -156,7 +189,7 @@ async fn install_galaxy_collections(
.stdout(Stdio::piped())
.stderr(Stdio::piped());
let child = start_child_process(galaxy_command, ANSIBLE_GALAXY_PATH.as_str()).await?;
let child = start_child_process(galaxy_collections_cmd, ANSIBLE_GALAXY_PATH.as_str()).await?;
handle_child(
job_id,
db,
@@ -265,7 +298,7 @@ pub async fn handle_ansible_job(
.unwrap_or_else(|| vec![]);
let mut nsjail_extra_mounts = vec![];
if let Some(r) = reqs {
if let Some(r) = reqs.as_ref() {
nsjail_extra_mounts = create_file_resources(
&job.id,
&job.workspace_id,
@@ -277,9 +310,9 @@ pub async fn handle_ansible_job(
)
.await?;
if let Some(collections) = r.collections {
if let Some(collections) = r.collections.as_ref() {
install_galaxy_collections(
collections.as_str(),
collections,
job_dir,
&job.id,
worker_name,
@@ -299,6 +332,18 @@ pub async fn handle_ansible_job(
db,
)
.await;
let mut passwords_cfg = String::new();
if let Some(vault_password_file) = reqs.as_ref().and_then(|r| r.vault_password_file.as_ref()) {
passwords_cfg.push_str(&format!("vault_password_file = {vault_password_file}\n"));
}
if let Some(vault_ids) = reqs.as_ref().map(|r| &r.vault_id) {
if !vault_ids.is_empty() {
let password_files = vault_ids.join(",");
passwords_cfg.push_str(&format!("vault_identity_list = {password_files}\n"));
}
}
let ansible_cfg_content = format!(
r#"
[defaults]
@@ -307,8 +352,10 @@ roles_path = ./roles
home={job_dir}/.ansible
local_tmp={job_dir}/.ansible/tmp
remote_tmp={job_dir}/.ansible/tmp
{passwords_cfg}
"#
);
write_file(job_dir, "ansible.cfg", &ansible_cfg_content)?;
let mut reserved_variables =

View File

@@ -85,6 +85,7 @@
dotnet-sdk_9
oracle-instantclient
svelte-language-server
ansible
]);
packages = [
(pkgs.writeScriptBin "wm-caddy" ''
@@ -145,6 +146,8 @@
DOTNET_PATH = "${pkgs.dotnet-sdk_9}/bin/dotnet";
DOTNET_ROOT = "${pkgs.dotnet-sdk_9}/share/dotnet";
ORACLE_LIB_DIR = "${pkgs.oracle-instantclient.lib}/lib";
ANSIBLE_PLAYBOOK_PATH = "${pkgs.ansible}/bin/ansible-playbook";
ANSIBLE_GALAXY_PATH = "${pkgs.ansible}/bin/ansible-galaxy";
};
packages.default = self.packages.${system}.windmill;
packages.windmill-client = pkgs.buildNpmPackage {