diff --git a/src/k8s_etcd.rs b/src/k8s_etcd.rs index 8c3dd3c6..e8255856 100644 --- a/src/k8s_etcd.rs +++ b/src/k8s_etcd.rs @@ -1,6 +1,6 @@ use crate::cluster_crypto::locations::K8sResourceLocation; use crate::etcd_encoding; -use anyhow::{bail, Context, Result}; +use anyhow::{bail, ensure, Context, Result}; use etcd_client::{Client as EtcdClient, GetOptions}; use futures_util::future::join_all; use serde_json::Value; @@ -176,6 +176,36 @@ impl InMemoryK8sEtcd { self.deleted_keys.lock().await.insert(key.to_string()); Ok(()) } + + pub(crate) async fn update_member(&self, value: String) -> Result<()> { + let etcd_client = self.etcd_client.as_ref().context("etcd client not configured")?; + + let members_list = etcd_client + .cluster_client() + .member_list() + .await + .context("listing etcd members list")?; + + let members = members_list.members(); + + ensure!( + members.len() == 1, + "single-node must have exactly one etcd member, found {}", + members.len() + ); + + ensure!( + !etcd_client + .cluster_client() + .member_update(members[0].id(), vec![value.clone()]) + .await + .context("updating etcd member")? + .members() + .is_empty(), + "no members in update response" + ); + Ok(()) + } } fn is_too_many_requests_error(delete_response: &std::prelude::v1::Result) -> bool { diff --git a/src/ocp_postprocess/ip_rename.rs b/src/ocp_postprocess/ip_rename.rs index 85859262..560bc29e 100644 --- a/src/ocp_postprocess/ip_rename.rs +++ b/src/ocp_postprocess/ip_rename.rs @@ -83,5 +83,7 @@ async fn fix_etcd_resources(etcd_client: &Arc, ip: &str) -> Res .await .context("fixing oauth apiserver deployment")?; + etcd_rename::fix_etcd_member(etcd_client, ip).await.context("fixing etcd member")?; + Ok(original_ip) } diff --git a/src/ocp_postprocess/ip_rename/etcd_rename.rs b/src/ocp_postprocess/ip_rename/etcd_rename.rs index b07230f0..08a1d0cd 100644 --- a/src/ocp_postprocess/ip_rename/etcd_rename.rs +++ b/src/ocp_postprocess/ip_rename/etcd_rename.rs @@ -6,6 +6,7 @@ use crate::{ use anyhow::{bail, ensure, Context, Result}; use futures_util::future::join_all; use serde_json::Value; +use std::net::Ipv6Addr; use std::sync::Arc; pub(crate) async fn fix_openshift_apiserver_configmap(etcd_client: &Arc, ip: &str) -> Result { @@ -448,6 +449,16 @@ pub(crate) async fn fix_networks_cluster(etcd_client: &Arc, ip: Ok(()) } +pub(crate) async fn fix_etcd_member(etcd_client: &Arc, ip: &str) -> Result<()> { + let mut update = format!("https://{}:2380", ip).to_string(); + if ip.parse::().is_ok() { + update = format!("https://[{}]:2380", ip).to_string(); + } + + etcd_client.update_member(update).await.context("failed to update etcd member")?; + Ok(()) +} + fn replace_etcd_servers(cluster: &mut Value, original_ip: &str, ip: &str) -> Result<()> { let observed_config = cluster.pointer_mut("/spec/observedConfig").context("no /spec/observedConfig")?;