difftreelog
feat fleet tf now executes terraform by itself
in: trunk
3 files changed
cmds/fleet/src/cmds/tf.rsdiffbeforeafterboth1use std::{1use std::{2 collections::{BTreeMap, HashMap},2 collections::{BTreeMap, HashMap},3 ffi::OsString,3 path::PathBuf,4 path::PathBuf,4};5};566use anyhow::{bail, Context, Result};7use anyhow::{Context, Result};7use clap::Parser;8use clap::Parser;8use fleet_base::host::Config;9use fleet_base::host::Config;9use nix_eval::nix_go;10use nix_eval::nix_go;10use serde::Deserialize;11use serde::Deserialize;11use serde_json::Value;12use serde_json::Value;13use tempfile::NamedTempFile;12use tokio::{fs::copy, process::Command};14use tokio::{15 fs::{self, create_dir_all},16 process::Command,17};18use tracing::debug;131914#[derive(Deserialize)]20#[derive(Deserialize, Debug)]15pub struct TfData {21pub struct TfData {16 // Dummy22 // Dummy17 #[allow(dead_code)]23 #[allow(dead_code)]23}29}243025#[derive(Parser)]31#[derive(Parser)]26pub enum Tf {32pub struct Tf {27 /// Generate fleet.tf.json file for running terraform.33 args: Vec<OsString>,28 Generate,29 /// Fetch data from terraform to fleet.30 Refresh,31}34}32impl Tf {35impl Tf {33 pub async fn run(&self, config: &Config) -> Result<()> {36 pub async fn run(&self, config: &Config) -> Result<()> {34 match self {37 let dir = config.directory.join(".fleet/tf/default");35 Tf::Generate => {38 // TODO: consider postponing fleet init until this step, as it might be39 // highly preferred to extract terraform configuration using multithreaded nix or40 // lazy-trees nix. lazy-trees nix is very fast and perfect for this task.41 {42 debug!("generating terraform configs");36 let system = &config.local_system;43 let system = &config.local_system;37 let config = &config.config_field;44 let config = &config.config_field;38 let data: HashMap<String, PathBuf> = nix_go!(config.tf({ system })).build().await?;45 let data: HashMap<String, PathBuf> = nix_go!(config.tf({ system })).build().await?;39 let data = &data["out"];46 let data = &data["out"];4047 let data = fs::read(&data).await?;4849 create_dir_all(&dir).await?;5051 let tmp = NamedTempFile::new_in(&dir)?;52 fs::write(tmp.path(), data).await?;53 tmp.persist(dir.join("fleet.tf.json"))?;54 }5556 {57 debug!("running terraform command");41 copy(data, "fleet.tf.json").await?;58 Command::new("terraform")42 }59 .current_dir(&dir)43 Tf::Refresh => {60 .args(&self.args)61 .status()44 let cmd = Command::new("terraform").arg("refresh").status().await?;62 .await?;45 if !cmd.success() {63 }64 {46 bail!("terraform refresh failed")65 debug!("syncing terraform data");47 }4849 let data = Command::new("terraform")66 let data = Command::new("terraform")50 .arg("output")67 .current_dir(dir)51 .arg("-json")68 .arg("output")52 .arg("fleet")69 .arg("-json")53 .output()70 .arg("fleet")54 .await?;71 .output()72 .await?;55 let tf_data: TfData = serde_json::from_slice(&data.stdout)73 let tf_data: TfData = serde_json::from_slice(&data.stdout)56 .context("failed to parse terraform fleet output")?;74 .context("failed to parse terraform fleet output")?;577558 let mut data = config.data();76 let mut data = config.data();77 debug!("synchronized done = {tf_data:?}");59 data.extra.insert(78 data.extra.insert(60 "terraformHosts".to_owned(),79 "terraformHosts".to_owned(),61 serde_json::to_value(tf_data.hosts).expect("should be valid extra"),80 serde_json::to_value(tf_data.hosts).expect("should be valid extra"),62 );81 );63 }82 }64 }658366 Ok(())84 Ok(())67 }85 }cmds/fleet/src/main.rsdiffbeforeafterboth--- a/cmds/fleet/src/main.rs
+++ b/cmds/fleet/src/main.rs
@@ -82,7 +82,6 @@
#[clap(hide(true))]
Complete(Complete),
/// Compile and evaluate terranix configuration
- #[clap(subcommand)]
Tf(Tf),
}
cmds/terraform-provider-fleet/Cargo.tomldiffbeforeafterboth--- /dev/null
+++ b/cmds/terraform-provider-fleet/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+name = "terraform-provider-fleet"
+edition = "2021"
+version.workspace = true
+
+[dependencies]
+anyhow.workspace = true
+async-trait = "0.1.81"
+serde = { workspace = true, features = ["derive"] }
+tf-provider = "0.2.2"
+tokio.workspace = true