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::{
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<E: Application, Caps> Scenario<E, Caps> {
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()

View File

@ -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;

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.
#[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<Self, SourceOrchestrationPlanError> {
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");

View File

@ -1,5 +1,5 @@
mod model;
pub(crate) use model::ScenarioSources;
#[doc(hidden)]
pub use model::{AttachSource, ScenarioSources};
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)]
pub enum ExistingCluster {
pub struct ExistingCluster {
kind: ExistingClusterKind,
}
#[derive(Clone, Debug, Eq, PartialEq)]
enum ExistingClusterKind {
K8s {
namespace: Option<String>,
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<String>) -> Self {
Self::Compose {
project: None,
services,
Self {
kind: ExistingClusterKind::Compose {
project: None,
services,
},
}
}
#[must_use]
#[doc(hidden)]
pub fn compose_in_project(services: Vec<String>, 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<ExternalNodeSource>,
},
@ -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<ExternalNodeSource>) -> 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 { .. })
}
}