From f18820b8d1009117bc44b4939bfd72b7cfbedc2d Mon Sep 17 00:00:00 2001 From: andrussal Date: Sun, 8 Mar 2026 14:13:45 +0100 Subject: [PATCH] Hide raw source storage behind existing-cluster API --- .../core/src/scenario/definition.rs | 9 +- testing-framework/core/src/scenario/mod.rs | 2 - .../source_orchestration_plan.rs | 10 +- .../core/src/scenario/sources/mod.rs | 2 +- .../core/src/scenario/sources/model.rs | 119 +++++++++--------- 5 files changed, 64 insertions(+), 78 deletions(-) diff --git a/testing-framework/core/src/scenario/definition.rs b/testing-framework/core/src/scenario/definition.rs index fe6dad3..0eea6f2 100644 --- a/testing-framework/core/src/scenario/definition.rs +++ b/testing-framework/core/src/scenario/definition.rs @@ -5,13 +5,14 @@ use tracing::{debug, info}; use super::{ Application, DeploymentPolicy, DynError, ExistingCluster, ExternalNodeSource, - HttpReadinessRequirement, NodeControlCapability, ObservabilityCapability, ScenarioSources, + HttpReadinessRequirement, NodeControlCapability, ObservabilityCapability, builder_ops::CoreBuilderAccess, expectation::Expectation, runtime::{ context::RunMetrics, orchestration::{SourceOrchestrationPlan, SourceOrchestrationPlanError}, }, + sources::ScenarioSources, workload::Workload, }; use crate::topology::{DeploymentDescriptor, DeploymentProvider, DeploymentSeed, DynTopologyError}; @@ -112,12 +113,6 @@ impl Scenario { self.deployment_policy } - #[must_use] - #[doc(hidden)] - pub fn sources(&self) -> &ScenarioSources { - &self.sources - } - #[must_use] pub fn existing_cluster(&self) -> Option<&ExistingCluster> { self.sources.existing_cluster() diff --git a/testing-framework/core/src/scenario/mod.rs b/testing-framework/core/src/scenario/mod.rs index 5fcd013..ca358a5 100644 --- a/testing-framework/core/src/scenario/mod.rs +++ b/testing-framework/core/src/scenario/mod.rs @@ -51,8 +51,6 @@ pub use runtime::{ wait_for_http_ports_with_host_and_requirement, wait_for_http_ports_with_requirement, wait_http_readiness, wait_until_stable, }; -#[doc(hidden)] -pub use sources::{AttachSource, ScenarioSources}; pub use sources::{ExistingCluster, ExternalNodeSource}; pub use workload::Workload; diff --git a/testing-framework/core/src/scenario/runtime/orchestration/source_orchestration_plan.rs b/testing-framework/core/src/scenario/runtime/orchestration/source_orchestration_plan.rs index 2c10958..c9c99f9 100644 --- a/testing-framework/core/src/scenario/runtime/orchestration/source_orchestration_plan.rs +++ b/testing-framework/core/src/scenario/runtime/orchestration/source_orchestration_plan.rs @@ -1,4 +1,4 @@ -use crate::scenario::{ExistingCluster, ExternalNodeSource, ScenarioSources}; +use crate::scenario::{ExistingCluster, ExternalNodeSource, sources::ScenarioSources}; /// Explicit descriptor for managed node sourcing. #[derive(Clone, Copy, Debug, Eq, PartialEq)] @@ -43,7 +43,7 @@ pub enum SourceOrchestrationPlanError { } impl SourceOrchestrationPlan { - pub fn try_from_sources( + pub(crate) fn try_from_sources( sources: &ScenarioSources, ) -> Result { let mode = mode_from_sources(sources); @@ -69,12 +69,12 @@ impl SourceOrchestrationPlan { #[cfg(test)] mod tests { use super::{SourceOrchestrationMode, SourceOrchestrationPlan}; - use crate::scenario::{ExistingCluster, ScenarioSources}; + use crate::scenario::{ExistingCluster, sources::ScenarioSources}; #[test] fn attached_sources_are_planned() { - let sources = - ScenarioSources::attached(ExistingCluster::compose(vec!["node-0".to_string()])); + let sources = ScenarioSources::default() + .with_attach(ExistingCluster::compose(vec!["node-0".to_string()])); let plan = SourceOrchestrationPlan::try_from_sources(&sources) .expect("attached sources should build a source orchestration plan"); diff --git a/testing-framework/core/src/scenario/sources/mod.rs b/testing-framework/core/src/scenario/sources/mod.rs index 15ddbf0..506a8aa 100644 --- a/testing-framework/core/src/scenario/sources/mod.rs +++ b/testing-framework/core/src/scenario/sources/mod.rs @@ -1,5 +1,5 @@ mod model; +pub(crate) use model::ScenarioSources; #[doc(hidden)] -pub use model::{AttachSource, ScenarioSources}; pub use model::{ExistingCluster, ExternalNodeSource}; diff --git a/testing-framework/core/src/scenario/sources/model.rs b/testing-framework/core/src/scenario/sources/model.rs index 8e62419..566e2ee 100644 --- a/testing-framework/core/src/scenario/sources/model.rs +++ b/testing-framework/core/src/scenario/sources/model.rs @@ -1,6 +1,11 @@ -/// Typed attach source for existing clusters. +/// Typed descriptor for an existing cluster. #[derive(Clone, Debug, Eq, PartialEq)] -pub enum ExistingCluster { +pub struct ExistingCluster { + kind: ExistingClusterKind, +} + +#[derive(Clone, Debug, Eq, PartialEq)] +enum ExistingClusterKind { K8s { namespace: Option, label_selector: String, @@ -13,73 +18,86 @@ pub enum ExistingCluster { impl ExistingCluster { #[must_use] + #[doc(hidden)] pub fn k8s(label_selector: String) -> Self { - Self::K8s { - namespace: None, - label_selector, + Self { + kind: ExistingClusterKind::K8s { + namespace: None, + label_selector, + }, } } #[must_use] + #[doc(hidden)] pub fn k8s_in_namespace(label_selector: String, namespace: String) -> Self { - Self::K8s { - namespace: Some(namespace), - label_selector, + Self { + kind: ExistingClusterKind::K8s { + namespace: Some(namespace), + label_selector, + }, } } #[must_use] + #[doc(hidden)] pub fn compose(services: Vec) -> Self { - Self::Compose { - project: None, - services, + Self { + kind: ExistingClusterKind::Compose { + project: None, + services, + }, } } #[must_use] + #[doc(hidden)] pub fn compose_in_project(services: Vec, project: String) -> Self { - Self::Compose { - project: Some(project), - services, + Self { + kind: ExistingClusterKind::Compose { + project: Some(project), + services, + }, } } #[must_use] + #[doc(hidden)] pub fn compose_project(&self) -> Option<&str> { - match self { - Self::Compose { project, .. } => project.as_deref(), - Self::K8s { .. } => None, + match &self.kind { + ExistingClusterKind::Compose { project, .. } => project.as_deref(), + ExistingClusterKind::K8s { .. } => None, } } #[must_use] + #[doc(hidden)] pub fn compose_services(&self) -> Option<&[String]> { - match self { - Self::Compose { services, .. } => Some(services), - Self::K8s { .. } => None, + match &self.kind { + ExistingClusterKind::Compose { services, .. } => Some(services), + ExistingClusterKind::K8s { .. } => None, } } #[must_use] + #[doc(hidden)] pub fn k8s_namespace(&self) -> Option<&str> { - match self { - Self::K8s { namespace, .. } => namespace.as_deref(), - Self::Compose { .. } => None, + match &self.kind { + ExistingClusterKind::K8s { namespace, .. } => namespace.as_deref(), + ExistingClusterKind::Compose { .. } => None, } } #[must_use] + #[doc(hidden)] pub fn k8s_label_selector(&self) -> Option<&str> { - match self { - Self::K8s { label_selector, .. } => Some(label_selector), - Self::Compose { .. } => None, + match &self.kind { + ExistingClusterKind::K8s { label_selector, .. } => Some(label_selector), + ExistingClusterKind::Compose { .. } => None, } } } -#[doc(hidden)] -pub type AttachSource = ExistingCluster; - /// Static external node endpoint that should be included in the runtime /// inventory. #[derive(Clone, Debug, Eq, PartialEq)] @@ -108,7 +126,7 @@ impl ExternalNodeSource { /// Source model that makes invalid managed+attached combinations /// unrepresentable by type. #[derive(Clone, Debug, Eq, PartialEq)] -pub enum ScenarioSources { +pub(crate) enum ScenarioSources { Managed { external: Vec, }, @@ -131,27 +149,7 @@ impl Default for ScenarioSources { impl ScenarioSources { #[must_use] - pub const fn managed() -> Self { - Self::Managed { - external: Vec::new(), - } - } - - #[must_use] - pub fn attached(attach: ExistingCluster) -> Self { - Self::Attached { - attach, - external: Vec::new(), - } - } - - #[must_use] - pub fn external_only(external: Vec) -> Self { - Self::ExternalOnly { external } - } - - #[must_use] - pub fn with_external_node(mut self, node: ExternalNodeSource) -> Self { + pub(crate) fn with_external_node(mut self, node: ExternalNodeSource) -> Self { match &mut self { Self::Managed { external } | Self::Attached { external, .. } @@ -162,21 +160,21 @@ impl ScenarioSources { } #[must_use] - pub fn with_attach(self, attach: ExistingCluster) -> Self { + pub(crate) fn with_attach(self, attach: ExistingCluster) -> Self { let external = self.external_nodes().to_vec(); Self::Attached { attach, external } } #[must_use] - pub fn into_external_only(self) -> Self { + pub(crate) fn into_external_only(self) -> Self { let external = self.external_nodes().to_vec(); Self::ExternalOnly { external } } #[must_use] - pub fn existing_cluster(&self) -> Option<&AttachSource> { + pub(crate) fn existing_cluster(&self) -> Option<&ExistingCluster> { match self { Self::Attached { attach, .. } => Some(attach), Self::Managed { .. } | Self::ExternalOnly { .. } => None, @@ -184,7 +182,7 @@ impl ScenarioSources { } #[must_use] - pub fn external_nodes(&self) -> &[ExternalNodeSource] { + pub(crate) fn external_nodes(&self) -> &[ExternalNodeSource] { match self { Self::Managed { external } | Self::Attached { external, .. } @@ -193,22 +191,17 @@ impl ScenarioSources { } #[must_use] - pub const fn is_managed(&self) -> bool { + pub(crate) const fn is_managed(&self) -> bool { matches!(self, Self::Managed { .. }) } #[must_use] - pub const fn is_attached(&self) -> bool { + pub(crate) const fn uses_existing_cluster(&self) -> bool { matches!(self, Self::Attached { .. }) } #[must_use] - pub const fn uses_existing_cluster(&self) -> bool { - self.is_attached() - } - - #[must_use] - pub const fn is_external_only(&self) -> bool { + pub(crate) const fn is_external_only(&self) -> bool { matches!(self, Self::ExternalOnly { .. }) } }