tf_bindgen_cli/
lib.rs

1use serde_json::Value;
2use std::process::Command;
3use tf_bindgen_core::Stack;
4
5const PATH: &str = "target/stacks/";
6
7/// Used to store the result of the terraform command.
8pub struct Terraform;
9
10impl Terraform {
11    /// Generates the Terraform JSON configuration and writes to a file at
12    /// `target/stacks/{stack_name}/cdk.tf.json`.
13    ///
14    /// # Errors
15    ///
16    /// Will return `Err` if failed to write JSON document or to create stack directory.
17    ///
18    /// # Panics
19    ///
20    /// Will panic if failed to generate JSON document.
21    pub fn synth(stack: &Stack) -> std::io::Result<()> {
22        let document = stack.to_document();
23        let document = serde_json::to_value(&document).expect("valid JSON document");
24        let document = match document {
25            Value::Object(mut mapping) => {
26                let fields = vec!["data", "resource", "provider"];
27                for field in fields {
28                    if let Some(Value::Object(fields)) = mapping.get(field) {
29                        if fields.is_empty() {
30                            mapping.remove(field);
31                        }
32                    }
33                }
34                Value::Object(mapping)
35            }
36            _ => unimplemented!(),
37        };
38        let document = serde_json::to_string_pretty(&document).unwrap();
39        let path = format!("{PATH}/{}", stack.name());
40        std::fs::create_dir_all(&path)?;
41        std::fs::write(format!("{path}/cdk.tf.json"), document)?;
42        Ok(())
43    }
44
45    /// Will synthesize (see [`Terraform::synth`]). Returns a prepared Terraform command to run
46    /// initialization.
47    ///
48    /// # Errors
49    ///
50    /// Will return `Err` if failed to synthesize stack (see [`Terraform::synth`]).
51    ///
52    /// # Panics
53    ///
54    /// Will panic if failed to generate document (see [`Terraform::synth`]).
55    pub fn init(stack: &Stack) -> std::io::Result<Command> {
56        Self::synth(stack)?;
57        let mut command = Command::new("terraform");
58        let path = format!("{PATH}/{}", stack.name());
59        command.arg(format!("-chdir={}", path));
60        command.arg("init");
61        Ok(command)
62    }
63
64    /// Will synthesize (see [`Terraform::synth`]). Returns a prepared Terraform command to run
65    /// validate.
66    ///
67    /// # Errors
68    ///
69    /// Will return `Err` if failed to synthesize stack (see [`Terraform::synth`]).
70    ///
71    /// # Panics
72    ///
73    /// Will panic if failed to generate document (see [`Terraform::synth`]).
74    pub fn validate(stack: &Stack) -> std::io::Result<Command> {
75        Self::synth(stack)?;
76        let mut command = Command::new("terraform");
77        let path = format!("{PATH}/{}", stack.name());
78        command.arg(format!("-chdir={}", path));
79        command.arg("validate");
80        Ok(command)
81    }
82
83    /// Will synthesize (see [`Terraform::synth`]). Returns a prepared Terraform command to run
84    /// deploy.
85    ///
86    /// # Errors
87    ///
88    /// Will return `Err` if failed to synthesize stack (see [`Terraform::synth`]).
89    ///
90    /// # Panics
91    ///
92    /// Will panic if failed to generate document (see [`Terraform::synth`]).
93    pub fn apply(stack: &Stack) -> std::io::Result<Command> {
94        Self::synth(stack)?;
95        let mut command = Command::new("terraform");
96        let path = format!("{PATH}/{}", stack.name());
97        command.arg(format!("-chdir={}", path));
98        command.arg("apply");
99        Ok(command)
100    }
101
102    /// Will synthesize (see [`Terraform::synth`]). Returns a prepared Terraform command to run
103    /// destroy.
104    ///
105    /// # Errors
106    ///
107    /// Will return `Err` if failed to synthesize stack (see [`Terraform::synth`]).
108    ///
109    /// # Panics
110    ///
111    /// Will panic if failed to generate document (see [`Terraform::synth`]).
112    pub fn destroy(stack: &Stack) -> std::io::Result<Command> {
113        Self::synth(stack)?;
114        let mut command = Command::new("terraform");
115        let path = format!("{PATH}/{}", stack.name());
116        command.arg(format!("-chdir={}", path));
117        command.arg("destroy");
118        Ok(command)
119    }
120
121    /// Will synthesize (see [`Terraform::synth`]). Returns a prepared Terraform command to run
122    /// plan.
123    ///
124    /// # Errors
125    ///
126    /// Will return `Err` if failed to synthesize stack (see [`Terraform::synth`]).
127    ///
128    /// # Panics
129    ///
130    /// Will panic if failed to generate document (see [`Terraform::synth`]).
131    pub fn plan(stack: &Stack) -> std::io::Result<Command> {
132        Self::synth(stack)?;
133        let mut command = Command::new("terraform");
134        let path = format!("{PATH}/{}", stack.name());
135        command.arg(format!("-chdir={}", path));
136        command.arg("plan");
137        Ok(command)
138    }
139}