From 4bd732638ad4acffac37e8b5091ad7120088cfba Mon Sep 17 00:00:00 2001 From: Jona Neef Date: Fri, 7 Aug 2026 17:50:36 +0200 Subject: [PATCH] refac(gcp): drop the pre-multi-DC environment mirrors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The migration to DataCenters is complete: no step reads the top-level ControlPlaneNodes, CephNodes, GatewayIP, PublicGatewayIP or SshProxyIP fields of CodesphereEnvironment any more. So mirrorPrimaryDataCenter has nothing left to serve and goes away, along with the eight call sites that kept it up to date. The fields themselves stay, read-only: ensureDataCenters still adopts them into the primary data center, which is what makes an infra file written by an OMS from before multi-DC support usable for cleanup and restart-vms. They are no longer written, so a fresh infra file describes its data centers only under "datacenters" — omitempty keeps the obsolete keys out of it instead of writing them empty. Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: Jona Neef --- internal/bootstrap/gcp/datacenter.go | 28 ++++--------------- internal/bootstrap/gcp/gce.go | 2 -- internal/bootstrap/gcp/gce_test.go | 4 +-- internal/bootstrap/gcp/gcp.go | 19 ++++++------- internal/bootstrap/gcp/gcp_test.go | 19 +++++++------ internal/bootstrap/gcp/infrafile.go | 1 - internal/bootstrap/gcp/install_config.go | 6 ---- internal/bootstrap/gcp/install_config_test.go | 2 +- internal/bootstrap/gcp/multi_dc_test.go | 13 --------- 9 files changed, 28 insertions(+), 66 deletions(-) diff --git a/internal/bootstrap/gcp/datacenter.go b/internal/bootstrap/gcp/datacenter.go index b1380596e..d91fb1e4d 100644 --- a/internal/bootstrap/gcp/datacenter.go +++ b/internal/bootstrap/gcp/datacenter.go @@ -69,9 +69,10 @@ func (b *GCPBootstrapper) ensureConfigManagers() { } } -// adoptLegacyEnvFields moves state that a caller supplied through the deprecated top-level -// environment fields into the primary data center. Infra files written before multi-DC support -// carry the primary data center's nodes and IPs there. +// adoptLegacyEnvFields moves state that reached the environment through the fields the primary +// data center's state lived in before multi-DC support into the primary data center itself. This +// is the only place those fields are still read: infra files written by an earlier OMS carry the +// nodes and IPs there, and cleanup and restart-vms have to keep working with them. func (b *GCPBootstrapper) adoptLegacyEnvFields() { primary := b.Env.DataCenters[0] if len(primary.ControlPlaneNodes) == 0 { @@ -91,7 +92,7 @@ func (b *GCPBootstrapper) adoptLegacyEnvFields() { } if primary.SSHProxyIP == "" { - primary.SSHProxyIP = b.Env.SshProxyIP + primary.SSHProxyIP = b.Env.SSHProxyIP } if primary.InstallConfig == nil { @@ -104,25 +105,6 @@ func (b *GCPBootstrapper) adoptLegacyEnvFields() { } } -// mirrorPrimaryDataCenter projects the primary data center's state back onto the top-level -// environment fields it lived in before multi-DC support. The steps that still read those fields -// keep working while they are migrated one by one, and the infra file keeps the shape an earlier -// OMS wrote. The projection is one-way and never read back into a DataCenter. -func (b *GCPBootstrapper) mirrorPrimaryDataCenter() { - if len(b.Env.DataCenters) == 0 { - return - } - - primary := b.primaryDC() - b.Env.ControlPlaneNodes = primary.ControlPlaneNodes - b.Env.CephNodes = primary.CephNodes - b.Env.GatewayIP = primary.GatewayIP - b.Env.PublicGatewayIP = primary.PublicGatewayIP - b.Env.SshProxyIP = primary.SSHProxyIP - b.Env.InstallConfig = primary.InstallConfig - b.Env.ExistingConfigUsed = primary.ExistingConfigUsed -} - // newDataCenter builds one data center, deriving its resource names, file paths and domains // from the environment and the data-center suffix. func newDataCenter(env *CodesphereEnvironment, id int, suffix string, newICG func() installer.InstallConfigManager) *datacenter.DataCenter { diff --git a/internal/bootstrap/gcp/gce.go b/internal/bootstrap/gcp/gce.go index 0d267be6a..247d987bb 100644 --- a/internal/bootstrap/gcp/gce.go +++ b/internal/bootstrap/gcp/gce.go @@ -199,8 +199,6 @@ func (b *GCPBootstrapper) EnsureComputeInstances() error { }) } - b.mirrorPrimaryDataCenter() - return nil } diff --git a/internal/bootstrap/gcp/gce_test.go b/internal/bootstrap/gcp/gce_test.go index 3ef77bd20..2848915db 100644 --- a/internal/bootstrap/gcp/gce_test.go +++ b/internal/bootstrap/gcp/gce_test.go @@ -652,8 +652,8 @@ var _ = Describe("GCE", func() { err := bs.EnsureComputeInstances() Expect(err).NotTo(HaveOccurred()) - Expect(len(bs.Env.ControlPlaneNodes)).To(Equal(3)) - Expect(len(bs.Env.CephNodes)).To(Equal(3)) + Expect(len(bs.Env.DataCenters[0].ControlPlaneNodes)).To(Equal(3)) + Expect(len(bs.Env.DataCenters[0].CephNodes)).To(Equal(3)) Expect(bs.Env.PostgreSQLNode).NotTo(BeNil()) Expect(bs.Env.Jumpbox).NotTo(BeNil()) }) diff --git a/internal/bootstrap/gcp/gcp.go b/internal/bootstrap/gcp/gcp.go index 6e2a8743f..0c8619b41 100644 --- a/internal/bootstrap/gcp/gcp.go +++ b/internal/bootstrap/gcp/gcp.go @@ -197,11 +197,12 @@ type CodesphereEnvironment struct { // DNSRecords records the DNS records the bootstrap created, so cleanup deletes exactly // those instead of recomputing the list. DNSRecords []DNSRecordName `json:"dns_records,omitempty"` - // ControlPlaneNodes and CephNodes are where the primary data center's nodes lived before - // multi-DC support. The steps that have not been migrated to DataCenters yet still use - // them, and infra files written by an earlier OMS carry the nodes here. - ControlPlaneNodes []*node.Node `json:"control_plane_nodes"` - CephNodes []*node.Node `json:"ceph_nodes"` + // ControlPlaneNodes, CephNodes, GatewayIP, PublicGatewayIP and SSHProxyIP are where the + // primary data center's nodes and addresses lived before multi-DC support. Nothing writes + // them any more; they are only read, by ensureDataCenters, so an infra file written by an + // earlier OMS still yields a usable primary data center. + ControlPlaneNodes []*node.Node `json:"control_plane_nodes,omitempty"` + CephNodes []*node.Node `json:"ceph_nodes,omitempty"` // ContainerRegistryURL is the resolved registry server all data centers pull images from. ContainerRegistryURL string `json:"container_registry_url,omitempty"` RegistryUsername string `json:"-"` @@ -215,9 +216,9 @@ type CodesphereEnvironment struct { SpotVMs bool `json:"spot_vms"` WriteConfig bool `json:"-"` RecoverConfig bool `json:"-"` - GatewayIP string `json:"gateway_ip"` - PublicGatewayIP string `json:"public_gateway_ip"` - SshProxyIP string `json:"ssh_proxy_ip"` + GatewayIP string `json:"gateway_ip,omitempty"` + PublicGatewayIP string `json:"public_gateway_ip,omitempty"` + SSHProxyIP string `json:"ssh_proxy_ip,omitempty"` RegistryType RegistryType `json:"registry_type"` GitHubPAT string `json:"-"` GitHubAppName string `json:"-"` @@ -943,8 +944,6 @@ func (b *GCPBootstrapper) EnsureGatewayIPAddresses() error { } } - b.mirrorPrimaryDataCenter() - return nil } diff --git a/internal/bootstrap/gcp/gcp_test.go b/internal/bootstrap/gcp/gcp_test.go index 833603888..90a5e651e 100644 --- a/internal/bootstrap/gcp/gcp_test.go +++ b/internal/bootstrap/gcp/gcp_test.go @@ -271,8 +271,9 @@ var _ = Describe("GCP Bootstrapper", func() { // Verify nodes are properly set in the environment Expect(bs.Env.Jumpbox).NotTo(BeNil()) Expect(bs.Env.PostgreSQLNode).NotTo(BeNil()) - Expect(bs.Env.CephNodes).To(HaveLen(3)) - Expect(bs.Env.ControlPlaneNodes).To(HaveLen(3)) + primary := bs.Env.DataCenters[0] + Expect(primary.CephNodes).To(HaveLen(3)) + Expect(primary.ControlPlaneNodes).To(HaveLen(3)) // Verify mock returns expected values Expect(bs.Env.Jumpbox.GetName()).To(Equal("jumpbox")) @@ -283,19 +284,19 @@ var _ = Describe("GCP Bootstrapper", func() { Expect(bs.Env.PostgreSQLNode.GetExternalIP()).To(Equal("1.2.3.4")) Expect(bs.Env.PostgreSQLNode.GetInternalIP()).To(Equal("10.0.0.1")) - for _, cephNode := range bs.Env.CephNodes { + for _, cephNode := range primary.CephNodes { Expect(cephNode.GetName()).To(MatchRegexp("ceph-\\d+")) Expect(cephNode.GetExternalIP()).To(Equal("1.2.3.4")) Expect(cephNode.GetInternalIP()).To(Equal("10.0.0.1")) } - for _, cpNode := range bs.Env.ControlPlaneNodes { + for _, cpNode := range primary.ControlPlaneNodes { Expect(cpNode.GetName()).To(MatchRegexp("k0s-\\d+")) Expect(cpNode.GetExternalIP()).To(Equal("1.2.3.4")) Expect(cpNode.GetInternalIP()).To(Equal("10.0.0.1")) } - Expect(len(bs.Env.InstallConfig.Codesphere.ManagedServices)).To(Equal(5)) + Expect(len(primary.InstallConfig.Codesphere.ManagedServices)).To(Equal(5)) }) }) @@ -1142,9 +1143,11 @@ var _ = Describe("GCP Bootstrapper", func() { err := bs.EnsureGatewayIPAddresses() Expect(err).NotTo(HaveOccurred()) - Expect(bs.Env.GatewayIP).To(Equal("1.1.1.1")) - Expect(bs.Env.PublicGatewayIP).To(Equal("2.2.2.2")) - Expect(bs.Env.SshProxyIP).To(Equal("3.3.3.3")) + + primary := bs.Env.DataCenters[0] + Expect(primary.GatewayIP).To(Equal("1.1.1.1")) + Expect(primary.PublicGatewayIP).To(Equal("2.2.2.2")) + Expect(primary.SSHProxyIP).To(Equal("3.3.3.3")) }) }) diff --git a/internal/bootstrap/gcp/infrafile.go b/internal/bootstrap/gcp/infrafile.go index e9e77bfd8..b675f4620 100644 --- a/internal/bootstrap/gcp/infrafile.go +++ b/internal/bootstrap/gcp/infrafile.go @@ -44,7 +44,6 @@ func (b *GCPBootstrapper) WriteInfraFile() error { // The steps that still write the top-level node and IP fields are migrated to DataCenters // one by one, so keep both in sync until the last one is. - b.mirrorPrimaryDataCenter() envBytes, err := json.MarshalIndent(b.Env, "", " ") if err != nil { diff --git a/internal/bootstrap/gcp/install_config.go b/internal/bootstrap/gcp/install_config.go index 6018550b4..671bdb27f 100644 --- a/internal/bootstrap/gcp/install_config.go +++ b/internal/bootstrap/gcp/install_config.go @@ -75,8 +75,6 @@ func (b *GCPBootstrapper) ensureInstallConfig(dc *datacenter.DataCenter) error { // A secondary data center without a config of its own is left unset here, so // seedSecondaryDataCenter can derive it from the primary data center instead of the profile. - b.mirrorPrimaryDataCenter() - return nil } @@ -501,8 +499,6 @@ func (b *GCPBootstrapper) updateInstallConfig(dc *datacenter.DataCenter) error { return fmt.Errorf("failed to copy secrets file to jumpbox: %w", err) } - b.mirrorPrimaryDataCenter() - return nil } @@ -780,8 +776,6 @@ func (b *GCPBootstrapper) ensureSecrets(dc *datacenter.DataCenter) error { if dc.IsPrimary() { b.Env.Secrets = dc.ConfigManager.GetVault() } - - b.mirrorPrimaryDataCenter() return nil } diff --git a/internal/bootstrap/gcp/install_config_test.go b/internal/bootstrap/gcp/install_config_test.go index 1231b0a18..f10f5903a 100644 --- a/internal/bootstrap/gcp/install_config_test.go +++ b/internal/bootstrap/gcp/install_config_test.go @@ -320,7 +320,7 @@ var _ = Describe("Installconfig & Secrets", func() { }) Describe("Valid UpdateInstallConfig", func() { It("updates config and writes files", func() { - csEnv.SshProxyIP = "3.3.3.3" + csEnv.SSHProxyIP = "3.3.3.3" icg.EXPECT().GenerateSecrets().Return(nil) icg.EXPECT().WriteInstallConfig("fake-config-file", true).Return(nil) diff --git a/internal/bootstrap/gcp/multi_dc_test.go b/internal/bootstrap/gcp/multi_dc_test.go index 5ccc1d31e..8283461d8 100644 --- a/internal/bootstrap/gcp/multi_dc_test.go +++ b/internal/bootstrap/gcp/multi_dc_test.go @@ -304,19 +304,6 @@ var _ = Describe("Multi-DC bootstrap", func() { Expect(bs.InstallK0s()).To(Succeed()) }) - It("mirrors the primary data center onto the legacy infra file fields", func() { - expectBootstrapMocks("test-project-12345") - - Expect(bs.Bootstrap()).To(Succeed()) - - primary := bs.Env.DataCenters[0] - Expect(bs.Env.ControlPlaneNodes).To(Equal(primary.ControlPlaneNodes)) - Expect(bs.Env.CephNodes).To(Equal(primary.CephNodes)) - Expect(bs.Env.GatewayIP).To(Equal(primary.GatewayIP)) - Expect(bs.Env.PublicGatewayIP).To(Equal(primary.PublicGatewayIP)) - Expect(bs.Env.SshProxyIP).To(Equal(primary.SSHProxyIP)) - }) - Describe("validateMultiDC", func() { DescribeTable("rejects flag combinations it cannot satisfy", func(mutate func(), wantErr string) {