Skip to content

Commit 18c21d4

Browse files
committed
MGMT-21200: Enable dual-stack
1 parent 1984038 commit 18c21d4

File tree

9 files changed

+382
-94
lines changed

9 files changed

+382
-94
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,3 @@
22
/backup/
33
/summary.yaml
44
/summary_redacted.yaml
5-

hack/dummy_config.yaml

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ use_cert_rules:
4242
-----END CERTIFICATE-----
4343
cluster_rename: new-name:foo.com:some-random-infra-id
4444
hostname: test.hostname
45-
ip: 192.168.126.99
45+
ip:
46+
- 192.168.126.99
47+
- 2001:db8::99
4648
# proxy: http://registry.kni-qe-0.lab.eng.rdu2.redhat.com:3128|http://registry.kni-qe-0.lab.eng.rdu2.redhat.com:3130|.cluster.local,.kni-qe-2.lab.eng.rdu2.redhat.com,.svc,127.0.0.1,2620:52:0:11c::/64,2620:52:0:11c::1,2620:52:0:11c::10,2620:52:0:11c::11,2620:52:0:199::/64,api-int.kni-qe-2.lab.eng.rdu2.redhat.com,fd01::/48,fd02::/112,localhost|http://registry.kni-qe-0.lab.eng.rdu2.redhat.com:3128|http://registry.kni-qe-0.lab.eng.rdu2.redhat.com:3130|.cluster.local,.kni-qe-2.lab.eng.rdu2.redhat.com,.svc,127.0.0.1,2620:52:0:11c::/64,2620:52:0:11c::1,2620:52:0:11c::10,2620:52:0:11c::11,2620:52:0:199::/64,api-int.kni-qe-2.lab.eng.rdu2.redhat.com,fd01::/48,fd02::/112,localhost,moreproxy
4749
install_config: |
4850
additionalTrustBundlePolicy: Proxyonly
@@ -69,18 +71,24 @@ install_config: |
6971
clusterNetwork:
7072
- cidr: 10.128.0.0/14
7173
hostPrefix: 23
74+
- cidr: fd01::/48
75+
hostPrefix: 64
7276
machineNetwork:
73-
- cidr: 192.168.126.0/24
77+
- cidr: 192.168.128.0/24
78+
- cidr: 1001:db8::/120
7479
networkType: OVNKubernetes
7580
serviceNetwork:
7681
- 172.30.0.0/16
82+
- fd02::/112
7783
platform:
7884
none: {}
7985
publish: External
8086
pullSecret: ""
8187
sshKey: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDThIOETj6iTvbCaNv15tZg121nWLcwtJuZofc1QS5iAdw8C8fN2R39cSW/ambikl2Fr6YNBBVR3znbtmattOyWyxAOFUfdY0aw0MqZb4LWLf04q6X0KsWIYWaV3ol0KxTzgvX38i/IU42XQfJwMYFE8dQ15TZ7l+FTKKi3SUPXLuy/9CXRfaCDZ2dKMcCkelkTr0KR1HdjiKQ86rMfk9JUbAf7D29aAQq4h1WNnHMM9vnbqN7MW9L8ebn/lCTJjGQ56r0UmurgyIEMt0P+CGp1e4AUNKYsPoYFB0GNwUkr/rB8LeuCOaZcoWdYXlUJaN45GjtCDon56+AoMA9V8tYkV6HqyFwGQjoGKI1cRCHXDJnGyAbMd9OK94TWJmNvtdHkbSURHyw2G7otZpAkRuEvMP0C7R+3JmuxrDA8yaUgWvgccqGcmFl1krClksW6KrAXNlwhZ4QOAMhDrXwwPfOOQoG82zPpg+g9gZQIhkro1Cje4bmWz5z5fiuDloTq1vc=
8288
root@edge-01.edge.lab.eng.rdu2.redhat.com
83-
machine_network_cidr: 192.168.127.0/24
89+
machine_network_cidr:
90+
- 192.168.128.0/24
91+
- 1001:db8::/120
8492
kubeadmin_password_hash: "$2a$10$20Q4iRLy7cWZkjn/D07bF.RZQZonKwstyRGH0qiYbYRkx5Pe4Ztyi"
8593
# proxy_trusted_ca_bundle: 'user-ca-bundle:'
8694
# user_ca_bundle: |

src/config.rs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,15 @@ pub(crate) struct ClusterCustomizations {
4242
pub(crate) files: Vec<ConfigPath>,
4343
pub(crate) cluster_rename: Option<ClusterNamesRename>,
4444
pub(crate) hostname: Option<String>,
45-
pub(crate) ip: Option<String>,
45+
pub(crate) ip: Option<Vec<String>>,
4646
pub(crate) proxy: Option<Proxy>,
4747
pub(crate) install_config: Option<String>,
4848
pub(crate) kubeadmin_password_hash: Option<String>,
4949
#[serde(serialize_with = "redact")]
5050
pub(crate) pull_secret: Option<String>,
5151
pub(crate) user_ca_bundle: Option<String>,
5252
pub(crate) proxy_trusted_ca_bundle: Option<ProxyAdditionalTrustBundle>,
53-
pub(crate) machine_network_cidr: Option<String>,
53+
pub(crate) machine_network_cidr: Option<Vec<String>>,
5454
pub(crate) chrony_config: Option<String>,
5555
}
5656

@@ -223,7 +223,17 @@ impl RecertConfig {
223223
None => None,
224224
};
225225
let ip = match value.remove("ip") {
226-
Some(value) => Some(value.as_str().context("ip must be a string")?.to_string()),
226+
Some(value) => {
227+
if let Some(array) = value.as_array() {
228+
// Handle array of IPs for dual stack
229+
Some(array.iter().map(|v| -> Result<String, anyhow::Error> { Ok(v.as_str().context("ip array element must be a string")?.to_string()) }).collect::<Result<Vec<_>, _>>()?)
230+
} else if let Some(single_ip) = value.as_str() {
231+
// Handle single IP for backward compatibility
232+
Some(vec![single_ip.to_string()])
233+
} else {
234+
anyhow::bail!("ip must be a string or array of strings");
235+
}
236+
},
227237
None => None,
228238
};
229239
let pull_secret = match value.remove("pull_secret") {
@@ -261,7 +271,17 @@ impl RecertConfig {
261271
None => None,
262272
};
263273
let machine_network_cidr = match value.remove("machine_network_cidr") {
264-
Some(value) => Some(value.as_str().context("machine_network_cidr must be a string")?.to_string()),
274+
Some(value) => {
275+
if let Some(array) = value.as_array() {
276+
// Handle array of CIDRs for dual stack
277+
Some(array.iter().map(|v| -> Result<String, anyhow::Error> { Ok(v.as_str().context("machine_network_cidr array element must be a string")?.to_string()) }).collect::<Result<Vec<_>, _>>()?)
278+
} else if let Some(single_cidr) = value.as_str() {
279+
// Handle single CIDR for backward compatibility
280+
Some(vec![single_cidr.to_string()])
281+
} else {
282+
anyhow::bail!("machine_network_cidr must be a string or array of strings");
283+
}
284+
},
265285
None => None,
266286
};
267287
let chrony_config = match value.remove("chrony_config") {
@@ -429,14 +449,14 @@ impl RecertConfig {
429449
},
430450
cluster_rename: cli.cluster_rename,
431451
hostname: cli.hostname,
432-
ip: cli.ip,
452+
ip: if cli.ip.is_empty() { None } else { Some(cli.ip) },
433453
proxy: cli.proxy,
434454
install_config: cli.install_config,
435455
kubeadmin_password_hash: cli.kubeadmin_password_hash,
436456
pull_secret: cli.pull_secret,
437457
user_ca_bundle: cli.user_ca_bundle,
438458
proxy_trusted_ca_bundle: cli.proxy_trusted_ca_bundle,
439-
machine_network_cidr: cli.machine_network_cidr,
459+
machine_network_cidr: if cli.machine_network_cidr.is_empty() { None } else { Some(cli.machine_network_cidr) },
440460
chrony_config: cli.chrony_config,
441461
},
442462
encryption_customizations: EncryptionCustomizations {

src/config/cli.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,9 @@ pub(crate) struct Cli {
9797
pub(crate) hostname: Option<String>,
9898

9999
/// If given, the cluster resources that include the IP address will be modified to use this
100-
/// one instead.
100+
/// one instead. For dual stack, provide multiple IP addresses (IPv4 first).
101101
#[clap(long)]
102-
pub(crate) ip: Option<String>,
102+
pub(crate) ip: Vec<String>,
103103

104104
/// If given, the cluster's HTTP proxy configuration will be modified to use this one instead.
105105
#[clap(long, value_parser = Proxy::parse)]
@@ -150,10 +150,11 @@ pub(crate) struct Cli {
150150

151151
/// The CIDR of the machine network. If given, the machine network CIDR which appears in the
152152
/// install-config found in the cluster-config-v1 configmaps will be modified to use this
153-
/// machine CIDR. WARNING: If a different machine network CIDR is stated in the
153+
/// machine CIDR. For dual stack, provide multiple IPv4 and IPv6 CIDRs (IPv4 first).
154+
/// WARNING: If a different machine network CIDR is stated in the
154155
/// --install-config parameter, it might overwrite the one given here.
155156
#[clap(long)]
156-
pub(crate) machine_network_cidr: Option<String>,
157+
pub(crate) machine_network_cidr: Vec<String>,
157158

158159
/// If given, the cluster resources that include chrony.config be modified to have this value.
159160
#[clap(long)]

src/etcd_encoding.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use super::protobuf_gen::{
55
admissionregistration::v1::{MutatingWebhookConfiguration, ValidatingWebhookConfiguration},
66
apps::v1::{ControllerRevision, DaemonSet, Deployment, StatefulSet},
77
batch::v1::{CronJob, Job},
8-
core::v1::{ConfigMap, Secret},
8+
core::v1::{ConfigMap, Node, Secret},
99
},
1010
apimachinery::pkg::runtime::{TypeMeta, Unknown},
1111
},
@@ -56,6 +56,7 @@ k8s_type!(JobWithMeta, Job);
5656
k8s_type!(CronJobWithMeta, CronJob);
5757
k8s_type!(StatefulSetWithMeta, StatefulSet);
5858
k8s_type!(ConfigMapWithMeta, ConfigMap);
59+
k8s_type!(NodeWithMeta, Node);
5960
k8s_type!(SecretWithMeta, Secret);
6061
k8s_type!(ValidatingWebhookConfigurationWithMeta, ValidatingWebhookConfiguration);
6162
k8s_type!(MutatingWebhookConfigurationWithMeta, MutatingWebhookConfiguration);
@@ -86,6 +87,7 @@ pub(crate) async fn decode(data: &[u8]) -> Result<Vec<u8>> {
8687
"StatefulSet" => serde_json::to_vec(&StatefulSetWithMeta::try_from(unknown)?)?,
8788
"DaemonSet" => serde_json::to_vec(&DaemonsSetWithMeta::try_from(unknown)?)?,
8889
"ConfigMap" => serde_json::to_vec(&ConfigMapWithMeta::try_from(unknown)?)?,
90+
"Node" => serde_json::to_vec(&NodeWithMeta::try_from(unknown)?)?,
8991
"Secret" => serde_json::to_vec(&SecretWithMeta::try_from(unknown)?)?,
9092
"ValidatingWebhookConfiguration" => serde_json::to_vec(&ValidatingWebhookConfigurationWithMeta::try_from(unknown)?)?,
9193
"MutatingWebhookConfiguration" => serde_json::to_vec(&MutatingWebhookConfigurationWithMeta::try_from(unknown)?)?,

src/ocp_postprocess.rs

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,16 @@ async fn run_cluster_customizations(
152152
.context("renaming cluster")?;
153153
}
154154

155-
if let Some(ip) = &cluster_customizations.ip {
156-
ip_rename(in_memory_etcd_client, ip, dirs, files).await.context("renaming IP")?;
155+
if let Some(ips) = &cluster_customizations.ip {
156+
if ips.len() == 1 {
157+
log::info!("Processing single IP: {}", ips[0]);
158+
ip_rename(in_memory_etcd_client, &ips[0], dirs, files).await.context(format!("renaming IP {}", ips[0]))?;
159+
} else if ips.len() == 2 {
160+
log::info!("Processing dual-stack IPs: {}", ips.join(", "));
161+
ip_rename_dual_stack(in_memory_etcd_client, ips, dirs, files).await.context("renaming dual-stack IPs")?;
162+
} else {
163+
log::warn!("No IPs were provided, skipping IP rename");
164+
}
157165
}
158166

159167
if let Some(hostname) = &cluster_customizations.hostname {
@@ -196,8 +204,10 @@ async fn run_cluster_customizations(
196204
.await
197205
.context("renaming additional trust bundle")?;
198206

199-
if let Some(machine_network_cidr) = &cluster_customizations.machine_network_cidr {
200-
fix_machine_network_cidr(in_memory_etcd_client, machine_network_cidr, dirs, files)
207+
if let Some(machine_network_cidrs) = &cluster_customizations.machine_network_cidr {
208+
let combined_cidrs = machine_network_cidrs.join(",");
209+
log::info!("Processing machine network CIDRs: {}", combined_cidrs);
210+
fix_machine_network_cidr(in_memory_etcd_client, &combined_cidrs, dirs, files)
201211
.await
202212
.context("fixing machine network CIDR")?;
203213
}
@@ -913,6 +923,19 @@ pub(crate) async fn ip_rename(
913923
Ok(())
914924
}
915925

926+
pub(crate) async fn ip_rename_dual_stack(
927+
in_memory_etcd_client: &Arc<InMemoryK8sEtcd>,
928+
ips: &[String],
929+
dirs: &[ConfigPath],
930+
files: &[ConfigPath],
931+
) -> Result<()> {
932+
let etcd_client = in_memory_etcd_client;
933+
934+
ip_rename::rename_all_dual_stack(etcd_client, ips, dirs, files).await.context("renaming all dual stack")?;
935+
936+
Ok(())
937+
}
938+
916939
pub(crate) async fn pull_secret_rename(
917940
in_memory_etcd_client: &Arc<InMemoryK8sEtcd>,
918941
pull_secret: &str,

0 commit comments

Comments
 (0)