-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathget_instance_info.rs
More file actions
130 lines (112 loc) · 4.51 KB
/
Copy pathget_instance_info.rs
File metadata and controls
130 lines (112 loc) · 4.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
//! Instance information retrieval step
//!
//! This module provides the `GetInstanceInfoStep` which retrieves instance
//! information from `OpenTofu` outputs. This step extracts essential instance
//! data like IP addresses and metadata from the infrastructure state.
//!
//! ## Key Features
//!
//! - Instance information extraction from `OpenTofu` state outputs
//! - Provider-agnostic interface through standardized outputs
//! - JSON parsing and data validation
//! - Integration with `OpenTofuClient` for state queries
//!
//! ## Information Retrieval
//!
//! The step uses `tofu output` to retrieve instance information including:
//! - IP addresses for network connectivity
//! - Instance names and identifiers
//! - Status and configuration metadata
//! - Provider-specific details as needed
//!
//! This provides a consistent interface for accessing instance information
//! regardless of the underlying infrastructure provider.
use std::sync::Arc;
use tracing::{info, instrument};
use crate::adapters::tofu::client::{InstanceInfo, OpenTofuClient, OpenTofuError};
use crate::application::traits::CommandProgressListener;
/// Simple step that retrieves instance information from `OpenTofu` outputs
///
/// This step gets the instance IP from `OpenTofu` outputs rather than provider-specific methods
/// to provide a consistent interface across all providers. If we add more providers in the future,
/// the `OpenTofu` output provides a contract that always returns the expected instance info.
pub struct GetInstanceInfoStep {
opentofu_client: Arc<OpenTofuClient>,
}
impl GetInstanceInfoStep {
#[must_use]
pub fn new(opentofu_client: Arc<OpenTofuClient>) -> Self {
Self { opentofu_client }
}
/// Execute the get instance info step
///
/// # Arguments
///
/// * `listener` - Optional progress listener for reporting details
///
/// # Errors
///
/// Returns an error if:
/// * The `OpenTofu` output command fails
/// * The output cannot be parsed as JSON
/// * The `instance_info` section is missing or malformed
/// * The working directory does not exist or is not accessible
#[instrument(
name = "get_instance_info",
skip_all,
fields(step_type = "infrastructure", operation = "info")
)]
pub fn execute(
&self,
listener: Option<&dyn CommandProgressListener>,
) -> Result<InstanceInfo, OpenTofuError> {
info!(
step = "get_instance_info",
"Getting instance information from OpenTofu outputs"
);
if let Some(l) = listener {
l.on_debug(&format!(
"Working directory: {}",
self.opentofu_client.working_dir().display()
));
l.on_debug("Executing: tofu output -json");
}
// Get the instance IP from OpenTofu outputs
// NOTE: We prefer OpenTofu outputs over provider-specific methods because:
// - If we add more providers (different than LXD) in the future, we have two options:
// 1. Use the method that each provider provides to get the IP
// 2. Use OpenTofu for all of them, so the OpenTofu output has a contract with this app.
// It has to return always the instance info we expect.
// Using OpenTofu outputs provides a consistent interface across all providers.
let opentofu_instance_info = self.opentofu_client.get_instance_info()?;
if let Some(l) = listener {
l.on_debug(&format!("Instance name: {}", opentofu_instance_info.name));
l.on_detail(&format!(
"Instance IP: {}",
opentofu_instance_info.ip_address
));
}
info!(
step = "get_instance_info",
status = "success",
ip_address = %opentofu_instance_info.ip_address,
instance_name = %opentofu_instance_info.name,
"Instance information retrieved successfully from OpenTofu outputs"
);
// Log output for debugging if needed
tracing::debug!(instance_info = ?opentofu_instance_info, "OpenTofu instance info");
Ok(opentofu_instance_info)
}
}
#[cfg(test)]
mod tests {
use std::sync::Arc;
use crate::adapters::tofu::client::OpenTofuClient;
use super::*;
#[test]
fn it_should_create_get_instance_info_step() {
let opentofu_client = Arc::new(OpenTofuClient::new("/tmp"));
let _step = GetInstanceInfoStep::new(opentofu_client);
// If we reach this point, the step was created successfully
}
}