difftreelog
feat fleet tf now executes terraform by itself
in: trunk
3 files changed
cmds/fleet/src/cmds/tf.rsdiffbeforeafterboth--- a/cmds/fleet/src/cmds/tf.rs
+++ b/cmds/fleet/src/cmds/tf.rs
@@ -1,17 +1,23 @@
use std::{
collections::{BTreeMap, HashMap},
+ ffi::OsString,
path::PathBuf,
};
-use anyhow::{bail, Context, Result};
+use anyhow::{Context, Result};
use clap::Parser;
use fleet_base::host::Config;
use nix_eval::nix_go;
use serde::Deserialize;
use serde_json::Value;
-use tokio::{fs::copy, process::Command};
+use tempfile::NamedTempFile;
+use tokio::{
+ fs::{self, create_dir_all},
+ process::Command,
+};
+use tracing::debug;
-#[derive(Deserialize)]
+#[derive(Deserialize, Debug)]
pub struct TfData {
// Dummy
#[allow(dead_code)]
@@ -23,44 +29,56 @@
}
#[derive(Parser)]
-pub enum Tf {
- /// Generate fleet.tf.json file for running terraform.
- Generate,
- /// Fetch data from terraform to fleet.
- Refresh,
+pub struct Tf {
+ args: Vec<OsString>,
}
impl Tf {
pub async fn run(&self, config: &Config) -> Result<()> {
- match self {
- Tf::Generate => {
- let system = &config.local_system;
- let config = &config.config_field;
- let data: HashMap<String, PathBuf> = nix_go!(config.tf({ system })).build().await?;
- let data = &data["out"];
+ let dir = config.directory.join(".fleet/tf/default");
+ // TODO: consider postponing fleet init until this step, as it might be
+ // highly preferred to extract terraform configuration using multithreaded nix or
+ // lazy-trees nix. lazy-trees nix is very fast and perfect for this task.
+ {
+ debug!("generating terraform configs");
+ let system = &config.local_system;
+ let config = &config.config_field;
+ let data: HashMap<String, PathBuf> = nix_go!(config.tf({ system })).build().await?;
+ let data = &data["out"];
+ let data = fs::read(&data).await?;
+
+ create_dir_all(&dir).await?;
- copy(data, "fleet.tf.json").await?;
- }
- Tf::Refresh => {
- let cmd = Command::new("terraform").arg("refresh").status().await?;
- if !cmd.success() {
- bail!("terraform refresh failed")
- }
+ let tmp = NamedTempFile::new_in(&dir)?;
+ fs::write(tmp.path(), data).await?;
+ tmp.persist(dir.join("fleet.tf.json"))?;
+ }
- let data = Command::new("terraform")
- .arg("output")
- .arg("-json")
- .arg("fleet")
- .output()
- .await?;
- let tf_data: TfData = serde_json::from_slice(&data.stdout)
- .context("failed to parse terraform fleet output")?;
+ {
+ debug!("running terraform command");
+ Command::new("terraform")
+ .current_dir(&dir)
+ .args(&self.args)
+ .status()
+ .await?;
+ }
+ {
+ debug!("syncing terraform data");
+ let data = Command::new("terraform")
+ .current_dir(dir)
+ .arg("output")
+ .arg("-json")
+ .arg("fleet")
+ .output()
+ .await?;
+ let tf_data: TfData = serde_json::from_slice(&data.stdout)
+ .context("failed to parse terraform fleet output")?;
- let mut data = config.data();
- data.extra.insert(
- "terraformHosts".to_owned(),
- serde_json::to_value(tf_data.hosts).expect("should be valid extra"),
- );
- }
+ let mut data = config.data();
+ debug!("synchronized done = {tf_data:?}");
+ data.extra.insert(
+ "terraformHosts".to_owned(),
+ serde_json::to_value(tf_data.hosts).expect("should be valid extra"),
+ );
}
Ok(())
cmds/fleet/src/main.rsdiffbeforeafterboth82 #[clap(hide(true))]82 #[clap(hide(true))]83 Complete(Complete),83 Complete(Complete),84 /// Compile and evaluate terranix configuration84 /// Compile and evaluate terranix configuration85 #[clap(subcommand)]86 Tf(Tf),85 Tf(Tf),87}86}8887cmds/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