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}