Hide raw source storage behind existing-cluster API

This commit is contained in:
andrussal 2026-03-08 14:13:45 +01:00
parent a523024279
commit f18820b8d1
5 changed files with 64 additions and 78 deletions

View File

@ -5,13 +5,14 @@ use tracing::{debug, info};
use super::{ use super::{
Application, DeploymentPolicy, DynError, ExistingCluster, ExternalNodeSource, Application, DeploymentPolicy, DynError, ExistingCluster, ExternalNodeSource,
HttpReadinessRequirement, NodeControlCapability, ObservabilityCapability, ScenarioSources, HttpReadinessRequirement, NodeControlCapability, ObservabilityCapability,
builder_ops::CoreBuilderAccess, builder_ops::CoreBuilderAccess,
expectation::Expectation, expectation::Expectation,
runtime::{ runtime::{
context::RunMetrics, context::RunMetrics,
orchestration::{SourceOrchestrationPlan, SourceOrchestrationPlanError}, orchestration::{SourceOrchestrationPlan, SourceOrchestrationPlanError},
}, },
sources::ScenarioSources,
workload::Workload, workload::Workload,
}; };
use crate::topology::{DeploymentDescriptor, DeploymentProvider, DeploymentSeed, DynTopologyError}; use crate::topology::{DeploymentDescriptor, DeploymentProvider, DeploymentSeed, DynTopologyError};
@ -112,12 +113,6 @@ impl<E: Application, Caps> Scenario<E, Caps> {
self.deployment_policy self.deployment_policy
} }
#[must_use]
#[doc(hidden)]
pub fn sources(&self) -> &ScenarioSources {
&self.sources
}
#[must_use] #[must_use]
pub fn existing_cluster(&self) -> Option<&ExistingCluster> { pub fn existing_cluster(&self) -> Option<&ExistingCluster> {
self.sources.existing_cluster() self.sources.existing_cluster()

View File

@ -51,8 +51,6 @@ 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,
}; };
#[doc(hidden)]
pub use sources::{AttachSource, ScenarioSources};
pub use sources::{ExistingCluster, ExternalNodeSource}; pub use sources::{ExistingCluster, ExternalNodeSource};
pub use workload::Workload; pub use workload::Workload;

View File

@ -1,4 +1,4 @@
use crate::scenario::{ExistingCluster, ExternalNodeSource, ScenarioSources}; use crate::scenario::{ExistingCluster, ExternalNodeSource, sources::ScenarioSources};
/// Explicit descriptor for managed node sourcing. /// Explicit descriptor for managed node sourcing.
#[derive(Clone, Copy, Debug, Eq, PartialEq)] #[derive(Clone, Copy, Debug, Eq, PartialEq)]
@ -43,7 +43,7 @@ pub enum SourceOrchestrationPlanError {
} }
impl SourceOrchestrationPlan { impl SourceOrchestrationPlan {
pub fn try_from_sources( pub(crate) fn try_from_sources(
sources: &ScenarioSources, sources: &ScenarioSources,
) -> Result<Self, SourceOrchestrationPlanError> { ) -> Result<Self, SourceOrchestrationPlanError> {
let mode = mode_from_sources(sources); let mode = mode_from_sources(sources);
@ -69,12 +69,12 @@ impl SourceOrchestrationPlan {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::{SourceOrchestrationMode, SourceOrchestrationPlan}; use super::{SourceOrchestrationMode, SourceOrchestrationPlan};
use crate::scenario::{ExistingCluster, ScenarioSources}; use crate::scenario::{ExistingCluster, sources::ScenarioSources};
#[test] #[test]
fn attached_sources_are_planned() { fn attached_sources_are_planned() {
let sources = let sources = ScenarioSources::default()
ScenarioSources::attached(ExistingCluster::compose(vec!["node-0".to_string()])); .with_attach(ExistingCluster::compose(vec!["node-0".to_string()]));
let plan = SourceOrchestrationPlan::try_from_sources(&sources) let plan = SourceOrchestrationPlan::try_from_sources(&sources)
.expect("attached sources should build a source orchestration plan"); .expect("attached sources should build a source orchestration plan");

View File

@ -1,5 +1,5 @@
mod model; mod model;
pub(crate) use model::ScenarioSources;
#[doc(hidden)] #[doc(hidden)]
pub use model::{AttachSource, ScenarioSources};
pub use model::{ExistingCluster, ExternalNodeSource}; pub use model::{ExistingCluster, ExternalNodeSource};

View File

@ -1,6 +1,11 @@
/// Typed attach source for existing clusters. /// Typed descriptor for an existing cluster.
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
pub enum ExistingCluster { pub struct ExistingCluster {
kind: ExistingClusterKind,
}
#[derive(Clone, Debug, Eq, PartialEq)]
enum ExistingClusterKind {
K8s { K8s {
namespace: Option<String>, namespace: Option<String>,
label_selector: String, label_selector: String,
@ -13,73 +18,86 @@ pub enum ExistingCluster {
impl ExistingCluster { impl ExistingCluster {
#[must_use] #[must_use]
#[doc(hidden)]
pub fn k8s(label_selector: String) -> Self { pub fn k8s(label_selector: String) -> Self {
Self::K8s { Self {
namespace: None, kind: ExistingClusterKind::K8s {
label_selector, namespace: None,
label_selector,
},
} }
} }
#[must_use] #[must_use]
#[doc(hidden)]
pub fn k8s_in_namespace(label_selector: String, namespace: String) -> Self { pub fn k8s_in_namespace(label_selector: String, namespace: String) -> Self {
Self::K8s { Self {
namespace: Some(namespace), kind: ExistingClusterKind::K8s {
label_selector, namespace: Some(namespace),
label_selector,
},
} }
} }
#[must_use] #[must_use]
#[doc(hidden)]
pub fn compose(services: Vec<String>) -> Self { pub fn compose(services: Vec<String>) -> Self {
Self::Compose { Self {
project: None, kind: ExistingClusterKind::Compose {
services, project: None,
services,
},
} }
} }
#[must_use] #[must_use]
#[doc(hidden)]
pub fn compose_in_project(services: Vec<String>, project: String) -> Self { pub fn compose_in_project(services: Vec<String>, project: String) -> Self {
Self::Compose { Self {
project: Some(project), kind: ExistingClusterKind::Compose {
services, project: Some(project),
services,
},
} }
} }
#[must_use] #[must_use]
#[doc(hidden)]
pub fn compose_project(&self) -> Option<&str> { pub fn compose_project(&self) -> Option<&str> {
match self { match &self.kind {
Self::Compose { project, .. } => project.as_deref(), ExistingClusterKind::Compose { project, .. } => project.as_deref(),
Self::K8s { .. } => None, ExistingClusterKind::K8s { .. } => None,
} }
} }
#[must_use] #[must_use]
#[doc(hidden)]
pub fn compose_services(&self) -> Option<&[String]> { pub fn compose_services(&self) -> Option<&[String]> {
match self { match &self.kind {
Self::Compose { services, .. } => Some(services), ExistingClusterKind::Compose { services, .. } => Some(services),
Self::K8s { .. } => None, ExistingClusterKind::K8s { .. } => None,
} }
} }
#[must_use] #[must_use]
#[doc(hidden)]
pub fn k8s_namespace(&self) -> Option<&str> { pub fn k8s_namespace(&self) -> Option<&str> {
match self { match &self.kind {
Self::K8s { namespace, .. } => namespace.as_deref(), ExistingClusterKind::K8s { namespace, .. } => namespace.as_deref(),
Self::Compose { .. } => None, ExistingClusterKind::Compose { .. } => None,
} }
} }
#[must_use] #[must_use]
#[doc(hidden)]
pub fn k8s_label_selector(&self) -> Option<&str> { pub fn k8s_label_selector(&self) -> Option<&str> {
match self { match &self.kind {
Self::K8s { label_selector, .. } => Some(label_selector), ExistingClusterKind::K8s { label_selector, .. } => Some(label_selector),
Self::Compose { .. } => None, ExistingClusterKind::Compose { .. } => None,
} }
} }
} }
#[doc(hidden)]
pub type AttachSource = ExistingCluster;
/// 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)]
@ -108,7 +126,7 @@ impl ExternalNodeSource {
/// Source model that makes invalid managed+attached combinations /// Source model that makes invalid managed+attached combinations
/// unrepresentable by type. /// unrepresentable by type.
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
pub enum ScenarioSources { pub(crate) enum ScenarioSources {
Managed { Managed {
external: Vec<ExternalNodeSource>, external: Vec<ExternalNodeSource>,
}, },
@ -131,27 +149,7 @@ impl Default for ScenarioSources {
impl ScenarioSources { impl ScenarioSources {
#[must_use] #[must_use]
pub const fn managed() -> Self { pub(crate) fn with_external_node(mut self, node: ExternalNodeSource) -> 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<ExternalNodeSource>) -> Self {
Self::ExternalOnly { external }
}
#[must_use]
pub fn with_external_node(mut self, node: ExternalNodeSource) -> Self {
match &mut self { match &mut self {
Self::Managed { external } Self::Managed { external }
| Self::Attached { external, .. } | Self::Attached { external, .. }
@ -162,21 +160,21 @@ impl ScenarioSources {
} }
#[must_use] #[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(); let external = self.external_nodes().to_vec();
Self::Attached { attach, external } Self::Attached { attach, external }
} }
#[must_use] #[must_use]
pub fn into_external_only(self) -> Self { pub(crate) fn into_external_only(self) -> Self {
let external = self.external_nodes().to_vec(); let external = self.external_nodes().to_vec();
Self::ExternalOnly { external } Self::ExternalOnly { external }
} }
#[must_use] #[must_use]
pub fn existing_cluster(&self) -> Option<&AttachSource> { pub(crate) fn existing_cluster(&self) -> Option<&ExistingCluster> {
match self { match self {
Self::Attached { attach, .. } => Some(attach), Self::Attached { attach, .. } => Some(attach),
Self::Managed { .. } | Self::ExternalOnly { .. } => None, Self::Managed { .. } | Self::ExternalOnly { .. } => None,
@ -184,7 +182,7 @@ impl ScenarioSources {
} }
#[must_use] #[must_use]
pub fn external_nodes(&self) -> &[ExternalNodeSource] { pub(crate) fn external_nodes(&self) -> &[ExternalNodeSource] {
match self { match self {
Self::Managed { external } Self::Managed { external }
| Self::Attached { external, .. } | Self::Attached { external, .. }
@ -193,22 +191,17 @@ impl ScenarioSources {
} }
#[must_use] #[must_use]
pub const fn is_managed(&self) -> bool { pub(crate) const fn is_managed(&self) -> bool {
matches!(self, Self::Managed { .. }) matches!(self, Self::Managed { .. })
} }
#[must_use] #[must_use]
pub const fn is_attached(&self) -> bool { pub(crate) const fn uses_existing_cluster(&self) -> bool {
matches!(self, Self::Attached { .. }) matches!(self, Self::Attached { .. })
} }
#[must_use] #[must_use]
pub const fn uses_existing_cluster(&self) -> bool { pub(crate) const fn is_external_only(&self) -> bool {
self.is_attached()
}
#[must_use]
pub const fn is_external_only(&self) -> bool {
matches!(self, Self::ExternalOnly { .. }) matches!(self, Self::ExternalOnly { .. })
} }
} }