tfparser_core/ir/
terragrunt.rs1use std::{path::Path, sync::Arc};
9
10use serde::{Deserialize, Serialize};
11use typed_builder::TypedBuilder;
12
13use crate::{
14 diagnostic::Diagnostic,
15 ir::{AccountId, AttributeMap, Map, Region, Span},
16};
17
18#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, TypedBuilder)]
20#[non_exhaustive]
21#[serde(rename_all = "camelCase")]
22#[builder(field_defaults(setter(into)))]
23pub struct IncludePath {
24 #[serde(with = "crate::ir::path_serde::arc_path")]
26 pub path: Arc<Path>,
27 #[builder(default)]
29 pub label: Option<Arc<str>>,
30 pub span: Span,
32}
33
34#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TypedBuilder)]
37#[non_exhaustive]
38#[serde(rename_all = "camelCase")]
39#[builder(field_defaults(setter(into)))]
40pub struct GenerateBlock {
41 pub label: Arc<str>,
43 #[serde(with = "crate::ir::path_serde::arc_path")]
45 pub path: Arc<Path>,
46 pub if_exists: Arc<str>,
48 pub contents: Arc<str>,
50 pub span: Span,
52}
53
54#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TypedBuilder)]
56#[non_exhaustive]
57#[serde(rename_all = "camelCase")]
58#[builder(field_defaults(setter(into)))]
59pub struct DependencyBlock {
60 pub name: Arc<str>,
62 #[serde(with = "crate::ir::path_serde::arc_path")]
64 pub config_path: Arc<Path>,
65 #[builder(default)]
67 pub mock_outputs: AttributeMap,
68 pub span: Span,
70}
71
72#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TypedBuilder)]
79#[non_exhaustive]
80#[serde(rename_all = "camelCase")]
81#[builder(field_defaults(setter(into)))]
82pub struct StateBackend {
83 pub kind: Arc<str>,
85 pub attributes: AttributeMap,
87 #[builder(default)]
89 pub state_account_id: Option<AccountId>,
90 #[builder(default)]
92 pub state_region: Option<Region>,
93 pub span: Span,
95}
96
97#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TypedBuilder)]
99#[non_exhaustive]
100#[serde(rename_all = "camelCase")]
101#[builder(field_defaults(setter(into)))]
102pub struct TerragruntConfig {
103 #[serde(with = "crate::ir::path_serde::arc_path")]
105 pub component_dir: Arc<Path>,
106
107 #[builder(default)]
110 pub effective_locals: Map,
111
112 #[builder(default)]
114 pub inputs: Map,
115
116 #[builder(default)]
118 pub includes: Vec<IncludePath>,
119
120 #[builder(default)]
122 pub generates: Vec<GenerateBlock>,
123
124 #[builder(default)]
126 pub dependencies: Vec<DependencyBlock>,
127
128 #[builder(default)]
131 pub state_backend: Option<StateBackend>,
132
133 #[builder(default)]
135 pub diagnostics: Vec<Diagnostic>,
136}
137
138#[cfg(test)]
139#[allow(clippy::unwrap_used)]
140mod tests {
141 use std::path::PathBuf;
142
143 use super::*;
144 use crate::ir::Span;
145
146 #[test]
147 fn test_should_build_minimal_terragrunt_config() {
148 let cfg = TerragruntConfig::builder()
149 .component_dir(Arc::<Path>::from(PathBuf::from("/repo/services/x")))
150 .build();
151 assert!(cfg.effective_locals.is_empty());
152 assert!(cfg.includes.is_empty());
153 }
154
155 #[test]
156 fn test_should_serde_round_trip_generate_block() {
157 let g = GenerateBlock {
158 label: Arc::<str>::from("backend"),
159 path: Arc::<Path>::from(PathBuf::from("generated_backend.tf")),
160 if_exists: Arc::<str>::from("overwrite_terragrunt"),
161 contents: Arc::<str>::from("terraform { backend \"s3\" {} }"),
162 span: Span::synthetic(),
163 };
164 let json = serde_json::to_string(&g).unwrap();
165 let back: GenerateBlock = serde_json::from_str(&json).unwrap();
166 assert_eq!(g, back);
167 }
168}