terraform_wrapper/commands/
destroy.rs1use crate::Terraform;
2use crate::command::TerraformCommand;
3use crate::error::Result;
4use crate::exec::{self, CommandOutput};
5
6#[derive(Debug, Clone, Default)]
25pub struct DestroyCommand {
26 auto_approve: bool,
27 vars: Vec<(String, String)>,
28 var_files: Vec<String>,
29 targets: Vec<String>,
30 lock: Option<bool>,
31 lock_timeout: Option<String>,
32 parallelism: Option<u32>,
33 json: bool,
34 raw_args: Vec<String>,
35}
36
37impl DestroyCommand {
38 #[must_use]
40 pub fn new() -> Self {
41 Self::default()
42 }
43
44 #[must_use]
46 pub fn auto_approve(mut self) -> Self {
47 self.auto_approve = true;
48 self
49 }
50
51 #[must_use]
53 pub fn var(mut self, name: &str, value: &str) -> Self {
54 self.vars.push((name.to_string(), value.to_string()));
55 self
56 }
57
58 #[must_use]
60 pub fn var_file(mut self, path: &str) -> Self {
61 self.var_files.push(path.to_string());
62 self
63 }
64
65 #[must_use]
67 pub fn target(mut self, resource: &str) -> Self {
68 self.targets.push(resource.to_string());
69 self
70 }
71
72 #[must_use]
74 pub fn lock(mut self, enabled: bool) -> Self {
75 self.lock = Some(enabled);
76 self
77 }
78
79 #[must_use]
81 pub fn lock_timeout(mut self, timeout: &str) -> Self {
82 self.lock_timeout = Some(timeout.to_string());
83 self
84 }
85
86 #[must_use]
88 pub fn parallelism(mut self, n: u32) -> Self {
89 self.parallelism = Some(n);
90 self
91 }
92
93 #[must_use]
95 pub fn json(mut self) -> Self {
96 self.json = true;
97 self
98 }
99
100 #[must_use]
102 pub fn arg(mut self, arg: impl Into<String>) -> Self {
103 self.raw_args.push(arg.into());
104 self
105 }
106}
107
108impl TerraformCommand for DestroyCommand {
109 type Output = CommandOutput;
110
111 fn args(&self) -> Vec<String> {
112 let mut args = vec!["destroy".to_string()];
113 if self.auto_approve {
114 args.push("-auto-approve".to_string());
115 }
116 for (name, value) in &self.vars {
117 args.push(format!("-var={name}={value}"));
118 }
119 for file in &self.var_files {
120 args.push(format!("-var-file={file}"));
121 }
122 for target in &self.targets {
123 args.push(format!("-target={target}"));
124 }
125 if let Some(lock) = self.lock {
126 args.push(format!("-lock={lock}"));
127 }
128 if let Some(ref timeout) = self.lock_timeout {
129 args.push(format!("-lock-timeout={timeout}"));
130 }
131 if let Some(n) = self.parallelism {
132 args.push(format!("-parallelism={n}"));
133 }
134 if self.json {
135 args.push("-json".to_string());
136 }
137 args.extend(self.raw_args.clone());
138 args
139 }
140
141 fn supports_input(&self) -> bool {
142 true
143 }
144
145 async fn execute(&self, tf: &Terraform) -> Result<CommandOutput> {
146 exec::run_terraform(tf, self.prepare_args(tf)).await
147 }
148}
149
150#[cfg(test)]
151mod tests {
152 use super::*;
153
154 #[test]
155 fn default_args() {
156 let cmd = DestroyCommand::new();
157 assert_eq!(cmd.args(), vec!["destroy"]);
158 }
159
160 #[test]
161 fn auto_approve_with_targets() {
162 let cmd = DestroyCommand::new()
163 .auto_approve()
164 .target("module.vpc")
165 .var("region", "us-west-2")
166 .json();
167 let args = cmd.args();
168 assert_eq!(args[0], "destroy");
169 assert!(args.contains(&"-auto-approve".to_string()));
170 assert!(args.contains(&"-target=module.vpc".to_string()));
171 assert!(args.contains(&"-var=region=us-west-2".to_string()));
172 assert!(args.contains(&"-json".to_string()));
173 }
174}