@@ -115,4 +115,53 @@ struct TestK8sRunSerial {
115115 #expect( server1 != server2)
116116 }
117117 }
118+
119+ @Test func testRestartAfterAddressRotation( ) async throws {
120+ try await ContainerFixture . with { f in
121+ let name = " k8s- \( f. testID) "
122+ let bumper = " \( name) -bumper "
123+ f. addCleanup { try f. doRemoveIfExists ( bumper, force: true , ignoreFailure: true ) }
124+ f. addCleanup { _ = try ? f. run ( [ " k8s " , " delete " , " --name " , name] ) }
125+
126+ try f. restoreWarmupImage ( . kindestNodeV1_35_5)
127+ try f. run ( [ " k8s " , " create " , " --name " , name] ) . check ( )
128+
129+ let originalAddress = try f. run ( [ " exec " , name, " cat " , " /kind/old-ipv4 " ] )
130+ try originalAddress. check ( )
131+ #expect( try f. run ( [ " exec " , name, " test " , " -f " , " /kind/kubeadm.conf " ] ) . status == 0 )
132+ try f. run ( [
133+ " exec " , name, " grep " , " -F " , " controlPlaneEndpoint: 127.0.0.1:6443 " , " /kind/kubeadm.conf " ,
134+ ] ) . check ( )
135+
136+ try f. run ( [ " stop " , name] ) . check ( )
137+ // Advance the rotating allocator while the node is stopped so its
138+ // restart cannot accidentally reuse the same address.
139+ try f. restoreWarmupImage ( . alpine320)
140+ try f. run ( [
141+ " run " , " --name " , bumper, " -d " , WarmupImage . alpine320. rawValue,
142+ " sleep " , " infinity " ,
143+ ] ) . check ( )
144+
145+ let restart = try f. run ( [ " k8s " , " start " , " --name " , name] )
146+ if restart. status != 0 {
147+ print ( " [k8s-run] restart stderr: \( restart. error) " )
148+ f. dumpNodeDiagnostics ( node: name)
149+ }
150+ try restart. check ( )
151+
152+ let rotatedAddress = try f. run ( [ " exec " , name, " cat " , " /kind/old-ipv4 " ] )
153+ try rotatedAddress. check ( )
154+ let originalIP = originalAddress. output. trimmingCharacters ( in: . whitespacesAndNewlines)
155+ let rotatedIP = rotatedAddress. output. trimmingCharacters ( in: . whitespacesAndNewlines)
156+ print ( " [k8s-run] restart rotated address \( originalIP) -> \( rotatedIP) " )
157+ #expect( originalIP != rotatedIP)
158+ #expect( try f. getContainerStatus ( name) == " running " )
159+ try f. run ( [
160+ " exec " , name, " grep " , " -F " , " advertiseAddress: \( rotatedIP) " , " /kind/kubeadm.conf " ,
161+ ] ) . check ( )
162+ try f. run ( [
163+ " exec " , name, " kubectl " , " wait " , " --for=condition=Ready " , " node " , " --all " , " --timeout=30s " ,
164+ ] ) . check ( )
165+ }
166+ }
118167}
0 commit comments