Let builders derive existing clusters from metadata

This commit is contained in:
andrussal 2026-03-08 15:25:01 +01:00
parent 6ad6ff33c4
commit ef9428ba48
8 changed files with 78 additions and 15 deletions

View File

@ -20,12 +20,10 @@ async fn compose_attach_mode_queries_node_api_opt_in() -> Result<()> {
Err(error) => return Err(Error::new(error)), Err(error) => return Err(Error::new(error)),
}; };
let attach_source = metadata
.existing_cluster()
.map_err(|err| anyhow!("{err}"))?;
let attached = ScenarioBuilder::deployment_with(|d| d.with_node_count(1)) let attached = ScenarioBuilder::deployment_with(|d| d.with_node_count(1))
.with_run_duration(Duration::from_secs(5)) .with_run_duration(Duration::from_secs(5))
.with_existing_cluster(attach_source) .with_existing_cluster_from(&metadata)
.map_err(|err| anyhow!("{err}"))?
.build()?; .build()?;
let attached_deployer = LbcComposeDeployer::default(); let attached_deployer = LbcComposeDeployer::default();

View File

@ -20,12 +20,10 @@ async fn k8s_attach_mode_queries_node_api_opt_in() -> Result<()> {
Err(error) => return Err(Error::new(error)), Err(error) => return Err(Error::new(error)),
}; };
let attach_source = metadata
.existing_cluster()
.map_err(|err| anyhow!("{err}"))?;
let attached = ScenarioBuilder::deployment_with(|d| d.with_node_count(1)) let attached = ScenarioBuilder::deployment_with(|d| d.with_node_count(1))
.with_run_duration(Duration::from_secs(5)) .with_run_duration(Duration::from_secs(5))
.with_existing_cluster(attach_source) .with_existing_cluster_from(&metadata)
.map_err(|err| anyhow!("{err}"))?
.build()?; .build()?;
let attached_deployer = LbcK8sDeployer::default(); let attached_deployer = LbcK8sDeployer::default();

View File

@ -5,8 +5,8 @@ use tracing::{debug, info};
use super::{ use super::{
Application, ClusterControlProfile, ClusterMode, DeploymentPolicy, DynError, ExistingCluster, Application, ClusterControlProfile, ClusterMode, DeploymentPolicy, DynError, ExistingCluster,
ExternalNodeSource, HttpReadinessRequirement, NodeControlCapability, ObservabilityCapability, ExternalNodeSource, HttpReadinessRequirement, IntoExistingCluster, NodeControlCapability,
RequiresNodeControl, ObservabilityCapability, RequiresNodeControl,
builder_ops::CoreBuilderAccess, builder_ops::CoreBuilderAccess,
expectation::Expectation, expectation::Expectation,
runtime::{ runtime::{
@ -265,6 +265,16 @@ macro_rules! impl_common_builder_methods {
self.map_core_builder(|builder| builder.with_existing_cluster(cluster)) self.map_core_builder(|builder| builder.with_existing_cluster(cluster))
} }
#[must_use]
pub fn with_existing_cluster_from(
self,
cluster: impl IntoExistingCluster,
) -> Result<Self, DynError> {
let cluster = cluster.into_existing_cluster()?;
Ok(self.with_existing_cluster(cluster))
}
#[must_use] #[must_use]
#[doc(hidden)] #[doc(hidden)]
pub fn with_attach_source(self, attach: ExistingCluster) -> Self { pub fn with_attach_source(self, attach: ExistingCluster) -> Self {
@ -601,6 +611,16 @@ impl<E: Application, Caps> Builder<E, Caps> {
self self
} }
#[must_use]
pub fn with_existing_cluster_from(
self,
cluster: impl IntoExistingCluster,
) -> Result<Self, DynError> {
let cluster = cluster.into_existing_cluster()?;
Ok(self.with_existing_cluster(cluster))
}
#[must_use] #[must_use]
#[doc(hidden)] #[doc(hidden)]
pub fn with_attach_source(self, attach: ExistingCluster) -> Self { pub fn with_attach_source(self, attach: ExistingCluster) -> Self {

View File

@ -54,7 +54,9 @@ pub use runtime::{
wait_for_http_ports_with_host_and_requirement, wait_for_http_ports_with_requirement, wait_for_http_ports_with_host_and_requirement, wait_for_http_ports_with_requirement,
wait_http_readiness, wait_until_stable, wait_http_readiness, wait_until_stable,
}; };
pub use sources::{ClusterControlProfile, ClusterMode, ExistingCluster, ExternalNodeSource}; pub use sources::{
ClusterControlProfile, ClusterMode, ExistingCluster, ExternalNodeSource, IntoExistingCluster,
};
pub use workload::Workload; pub use workload::Workload;
pub use crate::env::Application; pub use crate::env::Application;

View File

@ -2,4 +2,6 @@ mod model;
pub(crate) use model::ScenarioSources; pub(crate) use model::ScenarioSources;
#[doc(hidden)] #[doc(hidden)]
pub use model::{ClusterControlProfile, ClusterMode, ExistingCluster, ExternalNodeSource}; pub use model::{
ClusterControlProfile, ClusterMode, ExistingCluster, ExternalNodeSource, IntoExistingCluster,
};

View File

@ -1,3 +1,5 @@
use crate::scenario::DynError;
/// Typed descriptor for an existing cluster. /// Typed descriptor for an existing cluster.
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
pub struct ExistingCluster { pub struct ExistingCluster {
@ -94,6 +96,23 @@ impl ExistingCluster {
} }
} }
/// Converts a value into an existing-cluster descriptor.
pub trait IntoExistingCluster {
fn into_existing_cluster(self) -> Result<ExistingCluster, DynError>;
}
impl IntoExistingCluster for ExistingCluster {
fn into_existing_cluster(self) -> Result<ExistingCluster, DynError> {
Ok(self)
}
}
impl IntoExistingCluster for &ExistingCluster {
fn into_existing_cluster(self) -> Result<ExistingCluster, DynError> {
Ok(self.clone())
}
}
/// Static external node endpoint that should be included in the runtime /// Static external node endpoint that should be included in the runtime
/// inventory. /// inventory.
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]

View File

@ -9,8 +9,8 @@ use std::marker::PhantomData;
use async_trait::async_trait; use async_trait::async_trait;
use testing_framework_core::scenario::{ use testing_framework_core::scenario::{
CleanupGuard, Deployer, DynError, ExistingCluster, FeedHandle, ObservabilityCapabilityProvider, CleanupGuard, Deployer, DynError, ExistingCluster, FeedHandle, IntoExistingCluster,
RequiresNodeControl, Runner, Scenario, ObservabilityCapabilityProvider, RequiresNodeControl, Runner, Scenario,
}; };
use crate::{env::ComposeDeployEnv, errors::ComposeRunnerError, lifecycle::cleanup::RunnerCleanup}; use crate::{env::ComposeDeployEnv, errors::ComposeRunnerError, lifecycle::cleanup::RunnerCleanup};
@ -100,6 +100,18 @@ impl ComposeDeploymentMetadata {
} }
} }
impl IntoExistingCluster for ComposeDeploymentMetadata {
fn into_existing_cluster(self) -> Result<ExistingCluster, DynError> {
self.existing_cluster()
}
}
impl IntoExistingCluster for &ComposeDeploymentMetadata {
fn into_existing_cluster(self) -> Result<ExistingCluster, DynError> {
self.existing_cluster()
}
}
impl<E: ComposeDeployEnv> Default for ComposeDeployer<E> { impl<E: ComposeDeployEnv> Default for ComposeDeployer<E> {
fn default() -> Self { fn default() -> Self {
Self::new() Self::new()

View File

@ -2,7 +2,7 @@ mod attach_provider;
mod orchestrator; mod orchestrator;
pub use orchestrator::{K8sDeployer, K8sRunnerError}; pub use orchestrator::{K8sDeployer, K8sRunnerError};
use testing_framework_core::scenario::{DynError, ExistingCluster}; use testing_framework_core::scenario::{DynError, ExistingCluster, IntoExistingCluster};
/// Kubernetes deployment metadata returned by k8s-specific deployment APIs. /// Kubernetes deployment metadata returned by k8s-specific deployment APIs.
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
@ -64,3 +64,15 @@ impl K8sDeploymentMetadata {
self.existing_cluster() self.existing_cluster()
} }
} }
impl IntoExistingCluster for K8sDeploymentMetadata {
fn into_existing_cluster(self) -> Result<ExistingCluster, DynError> {
self.existing_cluster()
}
}
impl IntoExistingCluster for &K8sDeploymentMetadata {
fn into_existing_cluster(self) -> Result<ExistingCluster, DynError> {
self.existing_cluster()
}
}