Skip to content

Commit 65775d6

Browse files
committed
refactor: rename container_info output to instance_info in OpenTofu template
- Rename 'container_info' output to 'instance_info' in templates/tofu/lxd/main.tf - Update JSON parser to use new 'instance_info' output name - Add explicit coupling comment in template explaining parser dependency - Update all test cases and documentation to reflect the new output name - Ensure all field names (name, image, status, ip_address) remain consistent This change makes the naming more consistent with the InstanceInfo struct and adds documentation to make the coupling between template and parser explicit.
1 parent 67e2b37 commit 65775d6

File tree

4 files changed

+33
-30
lines changed

4 files changed

+33
-30
lines changed

docs/tofu-lxd-configuration.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ To provision the container:
114114
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
115115
116116
Outputs:
117-
container_info = {
117+
instance_info = {
118118
"image" = "ubuntu:22.04"
119119
"ip_address" = "10.140.190.155"
120120
"name" = "torrust-vm"

src/opentofu/client.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ impl OpenTofuClient {
176176
/// This function will return an error if:
177177
/// * The `OpenTofu` output command fails
178178
/// * The output cannot be parsed as JSON
179-
/// * The `container_info` section is missing or malformed
179+
/// * The `instance_info` section is missing or malformed
180180
pub fn get_instance_info(&self) -> Result<InstanceInfo, OpenTofuError> {
181181
info!(
182182
"Getting OpenTofu outputs from directory: {}",
@@ -189,8 +189,8 @@ impl OpenTofuClient {
189189
Some(&self.working_dir),
190190
)?;
191191

192-
let container_info = OpenTofuJsonParser::parse_container_info(&output)?;
193-
Ok(container_info)
192+
let instance_info = OpenTofuJsonParser::parse_instance_info(&output)?;
193+
Ok(instance_info)
194194
}
195195

196196
/// Get the working directory path
@@ -311,7 +311,7 @@ resource "null_resource" "test" {
311311

312312
let invalid_json = "not valid json";
313313

314-
let parse_error = OpenTofuJsonParser::parse_container_info(invalid_json).unwrap_err();
314+
let parse_error = OpenTofuJsonParser::parse_instance_info(invalid_json).unwrap_err();
315315
let opentofu_error = OpenTofuError::ParseError(parse_error);
316316

317317
assert!(matches!(opentofu_error, OpenTofuError::ParseError(_)));

src/opentofu/json_parser.rs

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -26,45 +26,45 @@ pub enum ParseError {
2626
pub(crate) struct OpenTofuJsonParser;
2727

2828
impl OpenTofuJsonParser {
29-
/// Parse `container_info` from `OpenTofu` JSON output
29+
/// Parse `instance_info` from `OpenTofu` JSON output
3030
///
3131
/// # Arguments
3232
///
3333
/// * `json_output` - JSON string from `tofu output -json` command
3434
///
3535
/// # Returns
3636
///
37-
/// * `Ok(ContainerInfo)` - Parsed container information
37+
/// * `Ok(InstanceInfo)` - Parsed instance information
3838
/// * `Err(ParseError)` - Parsing error
3939
///
4040
/// # Errors
4141
///
4242
/// This function will return an error if:
4343
/// * The JSON cannot be parsed
44-
/// * The `container_info` section is missing
44+
/// * The `instance_info` section is missing
4545
/// * Required fields are missing or have wrong types
46-
pub fn parse_container_info(json_output: &str) -> Result<InstanceInfo, ParseError> {
46+
pub fn parse_instance_info(json_output: &str) -> Result<InstanceInfo, ParseError> {
4747
let outputs: Value =
4848
serde_json::from_str(json_output).map_err(|e| ParseError::JsonError {
4949
message: format!("Failed to parse OpenTofu output as JSON: {e}"),
5050
})?;
5151

52-
let container_info_value = outputs
53-
.get("container_info")
52+
let instance_info_value = outputs
53+
.get("instance_info")
5454
.and_then(|v| v.get("value"))
5555
.ok_or_else(|| ParseError::FieldError {
56-
message: "container_info section not found in OpenTofu outputs".to_string(),
56+
message: "instance_info section not found in OpenTofu outputs".to_string(),
5757
})?;
5858

59-
let image = container_info_value
59+
let image = instance_info_value
6060
.get("image")
6161
.and_then(|v| v.as_str())
6262
.ok_or_else(|| ParseError::FieldError {
6363
message: "image field missing or not a string".to_string(),
6464
})?
6565
.to_string();
6666

67-
let ip_address_str = container_info_value
67+
let ip_address_str = instance_info_value
6868
.get("ip_address")
6969
.and_then(|v| v.as_str())
7070
.ok_or_else(|| ParseError::FieldError {
@@ -75,15 +75,15 @@ impl OpenTofuJsonParser {
7575
message: format!("ip_address field is not a valid IP address: {e}"),
7676
})?;
7777

78-
let name = container_info_value
78+
let name = instance_info_value
7979
.get("name")
8080
.and_then(|v| v.as_str())
8181
.ok_or_else(|| ParseError::FieldError {
8282
message: "name field missing or not a string".to_string(),
8383
})?
8484
.to_string();
8585

86-
let status = container_info_value
86+
let status = instance_info_value
8787
.get("status")
8888
.and_then(|v| v.as_str())
8989
.ok_or_else(|| ParseError::FieldError {
@@ -105,9 +105,9 @@ mod tests {
105105
use super::*;
106106

107107
#[test]
108-
fn it_should_parse_container_info_from_valid_json() {
108+
fn it_should_parse_instance_info_from_valid_json() {
109109
let json_output = r#"{
110-
"container_info": {
110+
"instance_info": {
111111
"value": {
112112
"image": "ubuntu:24.04",
113113
"ip_address": "10.140.190.68",
@@ -117,7 +117,7 @@ mod tests {
117117
}
118118
}"#;
119119

120-
let result = OpenTofuJsonParser::parse_container_info(json_output).unwrap();
120+
let result = OpenTofuJsonParser::parse_instance_info(json_output).unwrap();
121121

122122
assert_eq!(result.image, "ubuntu:24.04");
123123
assert_eq!(
@@ -132,34 +132,34 @@ mod tests {
132132
fn it_should_fail_with_invalid_json() {
133133
let invalid_json = "not valid json";
134134

135-
let result = OpenTofuJsonParser::parse_container_info(invalid_json);
135+
let result = OpenTofuJsonParser::parse_instance_info(invalid_json);
136136

137137
assert!(result.is_err());
138138
assert!(matches!(result.unwrap_err(), ParseError::JsonError { .. }));
139139
}
140140

141141
#[test]
142-
fn it_should_fail_when_container_info_section_missing() {
142+
fn it_should_fail_when_instance_info_section_missing() {
143143
let json_output = r#"{
144144
"other_output": {
145145
"value": "some value"
146146
}
147147
}"#;
148148

149-
let result = OpenTofuJsonParser::parse_container_info(json_output);
149+
let result = OpenTofuJsonParser::parse_instance_info(json_output);
150150

151151
assert!(result.is_err());
152152
let error = result.unwrap_err();
153153
assert!(matches!(error, ParseError::FieldError { .. }));
154154
assert!(error
155155
.to_string()
156-
.contains("container_info section not found"));
156+
.contains("instance_info section not found"));
157157
}
158158

159159
#[test]
160160
fn it_should_fail_when_required_field_missing() {
161161
let json_output = r#"{
162-
"container_info": {
162+
"instance_info": {
163163
"value": {
164164
"image": "ubuntu:24.04",
165165
"ip_address": "10.140.190.68",
@@ -168,7 +168,7 @@ mod tests {
168168
}
169169
}"#;
170170

171-
let result = OpenTofuJsonParser::parse_container_info(json_output);
171+
let result = OpenTofuJsonParser::parse_instance_info(json_output);
172172

173173
assert!(result.is_err());
174174
let error = result.unwrap_err();
@@ -179,7 +179,7 @@ mod tests {
179179
#[test]
180180
fn it_should_fail_when_field_has_wrong_type() {
181181
let json_output = r#"{
182-
"container_info": {
182+
"instance_info": {
183183
"value": {
184184
"image": 123,
185185
"ip_address": "10.140.190.68",
@@ -189,7 +189,7 @@ mod tests {
189189
}
190190
}"#;
191191

192-
let result = OpenTofuJsonParser::parse_container_info(json_output);
192+
let result = OpenTofuJsonParser::parse_instance_info(json_output);
193193

194194
assert!(result.is_err());
195195
let error = result.unwrap_err();
@@ -202,7 +202,7 @@ mod tests {
202202
#[test]
203203
fn it_should_fail_when_ip_address_is_invalid() {
204204
let json_output = r#"{
205-
"container_info": {
205+
"instance_info": {
206206
"value": {
207207
"image": "ubuntu:24.04",
208208
"ip_address": "invalid-ip-address",
@@ -212,7 +212,7 @@ mod tests {
212212
}
213213
}"#;
214214

215-
let result = OpenTofuJsonParser::parse_container_info(json_output);
215+
let result = OpenTofuJsonParser::parse_instance_info(json_output);
216216

217217
assert!(result.is_err());
218218
let error = result.unwrap_err();

templates/tofu/lxd/main.tf

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,10 @@ resource "lxd_instance" "torrust_vm" {
6969
}
7070

7171
# Output information about the container
72-
output "container_info" {
72+
# IMPORTANT: This output is parsed by src/opentofu/json_parser.rs
73+
# The output name "instance_info" and all fields (name, image, status, ip_address)
74+
# are required by the parser and must remain present with these exact names.
75+
output "instance_info" {
7376
description = "Information about the created container"
7477
value = {
7578
name = lxd_instance.torrust_vm.name

0 commit comments

Comments
 (0)