Skip to content

Commit c60ee83

Browse files
committed
feat: extract GetInstanceInfoStep from e2e tests
- Create new GetInstanceInfoStep in src/steps/infrastructure/get_instance_info.rs - Extract OpenTofu instance info retrieval logic from src/bin/e2e_tests.rs - Returns OpenTofuError directly instead of generic CommandError - Add proper documentation with design rationale about provider consistency - Include unit tests following project conventions - Update module exports to include the new step - Fix clippy documentation linting issues
1 parent c5b5ad0 commit c60ee83

File tree

5 files changed

+91
-15
lines changed

5 files changed

+91
-15
lines changed

docs/e2e-tests-refactoring-plan.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ ProvisionCommand:
164164
├── ✅ InitializeInfrastructureStep // tofu init - COMPLETED
165165
├── ✅ PlanInfrastructureStep // tofu plan - COMPLETED
166166
├── ✅ ApplyInfrastructureStep // tofu apply - COMPLETED
167-
├── GetInstanceInfoStep // Extract IP from tofu outputs
167+
├── GetInstanceInfoStep // Extract IP from tofu outputs - COMPLETED
168168
├── WaitForSSHConnectivityStep // Validate SSH access
169169
└── WaitForCloudInitStep // Wait for cloud-init completion
170170

src/bin/e2e_tests.rs

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ use torrust_tracker_deploy::actions::{
1717
};
1818
// Import steps
1919
use torrust_tracker_deploy::steps::{
20-
ApplyInfrastructureStep, InitializeInfrastructureStep, PlanInfrastructureStep,
21-
RenderAnsibleTemplatesStep, RenderOpenTofuTemplatesStep,
20+
ApplyInfrastructureStep, GetInstanceInfoStep, InitializeInfrastructureStep,
21+
PlanInfrastructureStep, RenderAnsibleTemplatesStep, RenderOpenTofuTemplatesStep,
2222
};
2323

2424
#[derive(Parser)]
@@ -191,17 +191,11 @@ impl TestEnvironment {
191191
.map_err(anyhow::Error::from)
192192
.context("Failed to apply OpenTofu configuration")?;
193193

194-
// Get the instance IP from OpenTofu outputs
195-
// NOTE: We prefer OpenTofu outputs over provider-specific methods because:
196-
// - If we add more providers (different than LXD) in the future, we have two options:
197-
// 1. Use the method that each provider provides to get the IP
198-
// 2. Use OpenTofu for all of them, so the OpenTofu output has a contract with this app.
199-
// It has to return always the instance info we expect.
200-
// Using OpenTofu outputs provides a consistent interface across all providers.
201-
let opentofu_instance_info = self
202-
.services
203-
.opentofu_client
204-
.get_instance_info()
194+
// Get instance info using the step
195+
let get_instance_info_step =
196+
GetInstanceInfoStep::new(Arc::clone(&self.services.opentofu_client));
197+
let opentofu_instance_info = get_instance_info_step
198+
.execute()
205199
.map_err(anyhow::Error::from)
206200
.context("Failed to get container info from OpenTofu outputs")?;
207201

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
use std::sync::Arc;
2+
3+
use tracing::info;
4+
5+
use crate::command_wrappers::opentofu::client::{InstanceInfo, OpenTofuClient, OpenTofuError};
6+
7+
/// Simple step that retrieves instance information from `OpenTofu` outputs
8+
///
9+
/// This step gets the instance IP from `OpenTofu` outputs rather than provider-specific methods
10+
/// to provide a consistent interface across all providers. If we add more providers in the future,
11+
/// the `OpenTofu` output provides a contract that always returns the expected instance info.
12+
pub struct GetInstanceInfoStep {
13+
opentofu_client: Arc<OpenTofuClient>,
14+
}
15+
16+
impl GetInstanceInfoStep {
17+
#[must_use]
18+
pub fn new(opentofu_client: Arc<OpenTofuClient>) -> Self {
19+
Self { opentofu_client }
20+
}
21+
22+
/// Execute the get instance info step
23+
///
24+
/// # Errors
25+
///
26+
/// Returns an error if:
27+
/// * The `OpenTofu` output command fails
28+
/// * The output cannot be parsed as JSON
29+
/// * The `instance_info` section is missing or malformed
30+
/// * The working directory does not exist or is not accessible
31+
pub fn execute(&self) -> Result<InstanceInfo, OpenTofuError> {
32+
info!(
33+
step = "get_instance_info",
34+
stage = 2,
35+
"Getting instance information from OpenTofu outputs"
36+
);
37+
38+
// Get the instance IP from OpenTofu outputs
39+
// NOTE: We prefer OpenTofu outputs over provider-specific methods because:
40+
// - If we add more providers (different than LXD) in the future, we have two options:
41+
// 1. Use the method that each provider provides to get the IP
42+
// 2. Use OpenTofu for all of them, so the OpenTofu output has a contract with this app.
43+
// It has to return always the instance info we expect.
44+
// Using OpenTofu outputs provides a consistent interface across all providers.
45+
let opentofu_instance_info = self.opentofu_client.get_instance_info()?;
46+
47+
info!(
48+
step = "get_instance_info",
49+
stage = 2,
50+
status = "success",
51+
ip_address = %opentofu_instance_info.ip_address,
52+
instance_name = %opentofu_instance_info.name,
53+
"Instance information retrieved successfully from OpenTofu outputs"
54+
);
55+
56+
// Log output for debugging if needed
57+
tracing::debug!(instance_info = ?opentofu_instance_info, "OpenTofu instance info");
58+
59+
Ok(opentofu_instance_info)
60+
}
61+
}
62+
63+
#[cfg(test)]
64+
mod tests {
65+
use std::sync::Arc;
66+
67+
use crate::command_wrappers::opentofu::client::OpenTofuClient;
68+
69+
use super::*;
70+
71+
#[test]
72+
fn it_should_create_get_instance_info_step() {
73+
let opentofu_client = Arc::new(OpenTofuClient::new("/tmp"));
74+
75+
let _step = GetInstanceInfoStep::new(opentofu_client);
76+
77+
// If we reach this point, the step was created successfully
78+
}
79+
}

src/steps/infrastructure/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
pub mod apply;
2+
pub mod get_instance_info;
23
pub mod initialize;
34
pub mod plan;
45

56
pub use apply::ApplyInfrastructureStep;
7+
pub use get_instance_info::GetInstanceInfoStep;
68
pub use initialize::InitializeInfrastructureStep;
79
pub use plan::PlanInfrastructureStep;

src/steps/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ pub mod infrastructure;
22
pub mod template;
33

44
pub use infrastructure::{
5-
ApplyInfrastructureStep, InitializeInfrastructureStep, PlanInfrastructureStep,
5+
ApplyInfrastructureStep, GetInstanceInfoStep, InitializeInfrastructureStep,
6+
PlanInfrastructureStep,
67
};
78
pub use template::{
89
RenderAnsibleTemplatesError, RenderAnsibleTemplatesStep, RenderOpenTofuTemplatesStep,

0 commit comments

Comments
 (0)