mirror of
https://github.com/logos-blockchain/logos-blockchain-testing.git
synced 2026-04-11 13:43:08 +00:00
feat(k8s): support config overrides in manual cluster
This commit is contained in:
parent
bf9d923d8c
commit
84cd33bc67
@ -154,22 +154,32 @@ where
|
|||||||
hostnames: &[String],
|
hostnames: &[String],
|
||||||
options: &StartNodeOptions<Self>,
|
options: &StartNodeOptions<Self>,
|
||||||
) -> Result<Option<ArtifactSet>, Self::Error> {
|
) -> Result<Option<ArtifactSet>, Self::Error> {
|
||||||
match &options.peers {
|
let mut config = match &options.peers {
|
||||||
PeerSelection::DefaultLayout => Ok(None),
|
PeerSelection::DefaultLayout => {
|
||||||
|
if options.config_override.is_none() && options.config_patch.is_none() {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
build_static_cluster_node_config::<T>(deployment, node_index, Some(hostnames))?
|
||||||
|
}
|
||||||
PeerSelection::None => {
|
PeerSelection::None => {
|
||||||
let config =
|
build_cluster_node_config_for_indices::<T>(node_index, hostnames, &[])?
|
||||||
build_cluster_node_config_for_indices::<T>(node_index, hostnames, &[])?;
|
|
||||||
let yaml = T::serialize_cluster_node_config(&config)?;
|
|
||||||
Ok(Some(single_config_artifact(yaml)))
|
|
||||||
}
|
}
|
||||||
PeerSelection::Named(names) => {
|
PeerSelection::Named(names) => {
|
||||||
let indices = resolve_named_peer_indices::<T>(deployment, node_index, names)?;
|
let indices = resolve_named_peer_indices::<T>(deployment, node_index, names)?;
|
||||||
let config =
|
build_cluster_node_config_for_indices::<T>(node_index, hostnames, &indices)?
|
||||||
build_cluster_node_config_for_indices::<T>(node_index, hostnames, &indices)?;
|
|
||||||
let yaml = T::serialize_cluster_node_config(&config)?;
|
|
||||||
Ok(Some(single_config_artifact(yaml)))
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(override_config) = options.config_override.clone() {
|
||||||
|
config = override_config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(config_patch) = &options.config_patch {
|
||||||
|
config = config_patch(config).map_err(|source| io::Error::other(source.to_string()))?
|
||||||
|
}
|
||||||
|
|
||||||
|
let yaml = T::serialize_cluster_node_config(&config)?;
|
||||||
|
Ok(Some(single_config_artifact(yaml)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,4 +380,40 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(artifacts.files[0].content, "node=node-1.svc:9000;peers=");
|
assert_eq!(artifacts.files[0].content, "node=node-1.svc:9000;peers=");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn cluster_app_builds_default_layout_patch_override_artifacts() {
|
||||||
|
let deployment = crate::topology::ClusterTopology::new(2);
|
||||||
|
let hostnames = vec!["node-0.svc".to_owned(), "node-1.svc".to_owned()];
|
||||||
|
let options = StartNodeOptions::<DummyClusterApp>::default().create_patch(|mut config| {
|
||||||
|
config.push_str(";patched=true");
|
||||||
|
Ok(config)
|
||||||
|
});
|
||||||
|
|
||||||
|
let artifacts =
|
||||||
|
DummyClusterApp::build_node_artifacts_for_options(&deployment, 1, &hostnames, &options)
|
||||||
|
.expect("override artifacts")
|
||||||
|
.expect("expected override");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
artifacts.files[0].content,
|
||||||
|
"node=node-1.svc:9000;peers=node-0.svc:9000;patched=true"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn cluster_app_prefers_config_override_for_override_artifacts() {
|
||||||
|
let deployment = crate::topology::ClusterTopology::new(2);
|
||||||
|
let hostnames = vec!["node-0.svc".to_owned(), "node-1.svc".to_owned()];
|
||||||
|
let options = StartNodeOptions::<DummyClusterApp>::default()
|
||||||
|
.with_peers(PeerSelection::Named(vec!["node-0".to_owned()]))
|
||||||
|
.with_config_override("override-config".to_owned());
|
||||||
|
|
||||||
|
let artifacts =
|
||||||
|
DummyClusterApp::build_node_artifacts_for_options(&deployment, 1, &hostnames, &options)
|
||||||
|
.expect("override artifacts")
|
||||||
|
.expect("expected override");
|
||||||
|
|
||||||
|
assert_eq!(artifacts.files[0].content, "override-config");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -405,7 +405,7 @@ where
|
|||||||
options: &StartNodeOptions<E>,
|
options: &StartNodeOptions<E>,
|
||||||
) -> Result<(), ManualClusterError> {
|
) -> Result<(), ManualClusterError> {
|
||||||
let Some((service, port)) = E::cfgsync_service(&self.release) else {
|
let Some((service, port)) = E::cfgsync_service(&self.release) else {
|
||||||
return ensure_default_peer_selection(options);
|
return ensure_default_cfgsync_options(options);
|
||||||
};
|
};
|
||||||
|
|
||||||
let hostnames = E::cfgsync_hostnames(&self.release, self.node_count);
|
let hostnames = E::cfgsync_hostnames(&self.release, self.node_count);
|
||||||
@ -417,7 +417,7 @@ where
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
let Some(artifacts) = artifacts else {
|
let Some(artifacts) = artifacts else {
|
||||||
return ensure_default_peer_selection(options);
|
return ensure_default_cfgsync_options(options);
|
||||||
};
|
};
|
||||||
|
|
||||||
let forward = port_forward_service(&self.namespace, &service, port)?;
|
let forward = port_forward_service(&self.namespace, &service, port)?;
|
||||||
@ -614,11 +614,6 @@ async fn wait_for_replicas(
|
|||||||
fn validate_start_options<E: K8sDeployEnv>(
|
fn validate_start_options<E: K8sDeployEnv>(
|
||||||
options: &StartNodeOptions<E>,
|
options: &StartNodeOptions<E>,
|
||||||
) -> Result<(), ManualClusterError> {
|
) -> Result<(), ManualClusterError> {
|
||||||
if options.config_override.is_some() || options.config_patch.is_some() {
|
|
||||||
return Err(ManualClusterError::UnsupportedStartOptions {
|
|
||||||
message: "config overrides/patches are not supported".to_owned(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if options.persist_dir.is_some() || options.snapshot_dir.is_some() {
|
if options.persist_dir.is_some() || options.snapshot_dir.is_some() {
|
||||||
return Err(ManualClusterError::UnsupportedStartOptions {
|
return Err(ManualClusterError::UnsupportedStartOptions {
|
||||||
message: "persist/snapshot directories are not supported".to_owned(),
|
message: "persist/snapshot directories are not supported".to_owned(),
|
||||||
@ -627,18 +622,19 @@ fn validate_start_options<E: K8sDeployEnv>(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ensure_default_peer_selection<E: K8sDeployEnv>(
|
fn ensure_default_cfgsync_options<E: K8sDeployEnv>(
|
||||||
options: &StartNodeOptions<E>,
|
options: &StartNodeOptions<E>,
|
||||||
) -> Result<(), ManualClusterError> {
|
) -> Result<(), ManualClusterError> {
|
||||||
if matches!(
|
let default_peers = matches!(
|
||||||
options.peers,
|
options.peers,
|
||||||
testing_framework_core::scenario::PeerSelection::DefaultLayout
|
testing_framework_core::scenario::PeerSelection::DefaultLayout
|
||||||
) {
|
);
|
||||||
|
if default_peers && options.config_override.is_none() && options.config_patch.is_none() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(ManualClusterError::UnsupportedStartOptions {
|
Err(ManualClusterError::UnsupportedStartOptions {
|
||||||
message: "custom peer selection is not supported".to_owned(),
|
message: "cfgsync override support is not configured for these start options".to_owned(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -758,16 +754,28 @@ mod tests {
|
|||||||
_hostnames: &[String],
|
_hostnames: &[String],
|
||||||
options: &StartNodeOptions<Self>,
|
options: &StartNodeOptions<Self>,
|
||||||
) -> Result<Option<cfgsync_artifacts::ArtifactSet>, Self::Error> {
|
) -> Result<Option<cfgsync_artifacts::ArtifactSet>, Self::Error> {
|
||||||
let peers = match &options.peers {
|
let mut config = match &options.peers {
|
||||||
PeerSelection::DefaultLayout => return Ok(None),
|
PeerSelection::DefaultLayout => {
|
||||||
PeerSelection::None => "none".to_owned(),
|
if options.config_override.is_none() && options.config_patch.is_none() {
|
||||||
PeerSelection::Named(names) => names.join(","),
|
return Ok(None);
|
||||||
|
}
|
||||||
|
format!("node={node_index};peers=default")
|
||||||
|
}
|
||||||
|
PeerSelection::None => format!("node={node_index};peers=none"),
|
||||||
|
PeerSelection::Named(names) => {
|
||||||
|
format!("node={node_index};peers={}", names.join(","))
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
if let Some(override_config) = options.config_override.clone() {
|
||||||
|
config = override_config;
|
||||||
|
}
|
||||||
|
if let Some(config_patch) = &options.config_patch {
|
||||||
|
config = config_patch(config).map_err(|source| {
|
||||||
|
std::io::Error::other(format!("failed to patch dummy config: {source}"))
|
||||||
|
})?;
|
||||||
|
}
|
||||||
Ok(Some(cfgsync_artifacts::ArtifactSet::new(vec![
|
Ok(Some(cfgsync_artifacts::ArtifactSet::new(vec![
|
||||||
cfgsync_artifacts::ArtifactFile::new(
|
cfgsync_artifacts::ArtifactFile::new("/config.yaml".to_string(), config),
|
||||||
"/config.yaml".to_string(),
|
|
||||||
format!("node={node_index};peers={peers}"),
|
|
||||||
),
|
|
||||||
])))
|
])))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -780,21 +788,46 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn validate_start_options_rejects_non_peer_overrides() {
|
fn validate_start_options_accepts_config_overrides() {
|
||||||
|
let override_config =
|
||||||
|
StartNodeOptions::<DummyEnv>::default().with_config_override("override".to_owned());
|
||||||
|
let patched = StartNodeOptions::<DummyEnv>::default().create_patch(|mut config| {
|
||||||
|
config.push_str(";patched");
|
||||||
|
Ok(config)
|
||||||
|
});
|
||||||
|
|
||||||
|
assert!(validate_start_options(&override_config).is_ok());
|
||||||
|
assert!(validate_start_options(&patched).is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn validate_start_options_rejects_persist_and_snapshot_dirs() {
|
||||||
let persist = StartNodeOptions::<DummyEnv>::default()
|
let persist = StartNodeOptions::<DummyEnv>::default()
|
||||||
.with_persist_dir(std::path::PathBuf::from("/tmp/demo"));
|
.with_persist_dir(std::path::PathBuf::from("/tmp/demo"));
|
||||||
|
let snapshot = StartNodeOptions::<DummyEnv>::default()
|
||||||
|
.with_snapshot_dir(std::path::PathBuf::from("/tmp/snapshot"));
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
validate_start_options(&persist),
|
validate_start_options(&persist),
|
||||||
Err(ManualClusterError::UnsupportedStartOptions { .. })
|
Err(ManualClusterError::UnsupportedStartOptions { .. })
|
||||||
));
|
));
|
||||||
|
assert!(matches!(
|
||||||
|
validate_start_options(&snapshot),
|
||||||
|
Err(ManualClusterError::UnsupportedStartOptions { .. })
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ensure_default_peer_selection_rejects_named_peers() {
|
fn ensure_default_cfgsync_options_rejects_non_default_overrides() {
|
||||||
let peers = StartNodeOptions::<DummyEnv>::default()
|
let peers = StartNodeOptions::<DummyEnv>::default()
|
||||||
.with_peers(PeerSelection::Named(vec!["node-0".to_owned()]));
|
.with_peers(PeerSelection::Named(vec!["node-0".to_owned()]));
|
||||||
|
let override_config =
|
||||||
|
StartNodeOptions::<DummyEnv>::default().with_config_override("override".to_owned());
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
ensure_default_peer_selection(&peers),
|
ensure_default_cfgsync_options(&peers),
|
||||||
|
Err(ManualClusterError::UnsupportedStartOptions { .. })
|
||||||
|
));
|
||||||
|
assert!(matches!(
|
||||||
|
ensure_default_cfgsync_options(&override_config),
|
||||||
Err(ManualClusterError::UnsupportedStartOptions { .. })
|
Err(ManualClusterError::UnsupportedStartOptions { .. })
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -817,4 +850,23 @@ mod tests {
|
|||||||
assert_eq!(artifacts.files.len(), 1);
|
assert_eq!(artifacts.files.len(), 1);
|
||||||
assert_eq!(artifacts.files[0].content, "node=1;peers=node-0");
|
assert_eq!(artifacts.files[0].content, "node=1;peers=node-0");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn dummy_env_builds_cfgsync_override_artifacts_for_config_override() {
|
||||||
|
let topology = testing_framework_core::topology::ClusterTopology::new(2);
|
||||||
|
let options =
|
||||||
|
StartNodeOptions::<DummyEnv>::default().with_config_override("override".to_owned());
|
||||||
|
|
||||||
|
let artifacts = DummyEnv::build_cfgsync_override_artifacts(
|
||||||
|
&topology,
|
||||||
|
1,
|
||||||
|
&["node-0".to_owned(), "node-1".to_owned()],
|
||||||
|
&options,
|
||||||
|
)
|
||||||
|
.expect("build override")
|
||||||
|
.expect("expected override");
|
||||||
|
|
||||||
|
assert_eq!(artifacts.files.len(), 1);
|
||||||
|
assert_eq!(artifacts.files[0].content, "override");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user