Skip to content

Commit 38d7255

Browse files
WIP: fixups
1 parent 2d0b6f4 commit 38d7255

File tree

2 files changed

+334
-7
lines changed

2 files changed

+334
-7
lines changed

manifests/0000_30_cluster-api_09_admission-policies.yaml

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ data:
534534
expression: oldObject.spec.authoritativeAPI != object.spec.authoritativeAPI
535535
536536
- name: capiInfraReady
537-
expression: params.status?.infrastructureReady == true
537+
expression: params.?status.?infrastructureReady.orValue(false)
538538
539539
- name: capiDeleting
540540
expression: has(params.metadata.deletionTimestamp)
@@ -545,17 +545,13 @@ data:
545545
- name: block-when-not-infraReady
546546
expression: >
547547
!(variables.authAPIChanged && !variables.capiInfraReady)
548-
message: |
549-
spec.authoritativeAPI may only be updated when the Cluster API Machine’s
550-
status.infrastructureReady is true.
548+
message: "spec.authoritativeAPI may only be updated when the Cluster API Machine's status.infrastructureReady is true."
551549
552550
# Don't allow changing the AuthoritativeAPI if the CAPI Machine mirror is deleting
553551
- name: block-when-capi-deleting
554552
expression: >
555553
!(variables.authAPIChanged && variables.capiDeleting)
556-
message: |
557-
spec.authoritativeAPI cannot be modified while the corresponding
558-
CAPI Machine is being deleted (metadata.deletionTimestamp is set).
554+
message: "spec.authoritativeAPI cannot be modified while the corresponding CAPI Machine is being deleted (metadata.deletionTimestamp is set)."
559555
---
560556
apiVersion: v1
561557
kind: ConfigMap

pkg/controllers/machinesync/machine_sync_controller_test.go

Lines changed: 331 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1876,6 +1876,337 @@ var _ = Describe("With a running MachineSync Reconciler", func() {
18761876
})
18771877
})
18781878

1879+
Context("when validating MAPI authoritativeAPI transitions", func() {
1880+
const vapName = "mapi-authapi-transition-requires-capi-ready"
1881+
1882+
BeforeEach(func() {
1883+
By("Waiting for VAP to be ready")
1884+
machineVap = &admissionregistrationv1.ValidatingAdmissionPolicy{}
1885+
Eventually(k8sClient.Get(ctx, client.ObjectKey{Name: vapName}, machineVap), timeout).Should(Succeed())
1886+
Eventually(k.Update(machineVap, func() {
1887+
admissiontestutils.AddSentinelValidation(machineVap)
1888+
})).Should(Succeed())
1889+
1890+
Eventually(k.Object(machineVap), timeout).Should(
1891+
HaveField("Status.ObservedGeneration", BeNumerically(">=", 2)),
1892+
)
1893+
1894+
By("Updating the VAP binding")
1895+
policyBinding = &admissionregistrationv1.ValidatingAdmissionPolicyBinding{}
1896+
Eventually(k8sClient.Get(ctx, client.ObjectKey{
1897+
Name: vapName}, policyBinding), timeout).Should(Succeed())
1898+
1899+
Eventually(k.Update(policyBinding, func() {
1900+
// paramNamespace=capiNamespace (CAPI resources are params)
1901+
// targetNamespace=mapiNamespace (MAPI resources are validated)
1902+
admissiontestutils.UpdateVAPBindingNamespaces(policyBinding, capiNamespace.GetName(), mapiNamespace.GetName())
1903+
}), timeout).Should(Succeed())
1904+
1905+
Eventually(k.Object(policyBinding), timeout).Should(
1906+
SatisfyAll(
1907+
HaveField("Spec.MatchResources.NamespaceSelector.MatchLabels",
1908+
HaveKeyWithValue("kubernetes.io/metadata.name",
1909+
mapiNamespace.GetName())),
1910+
),
1911+
)
1912+
1913+
By("Creating sentinel Machine pair for VAP verification")
1914+
sentinelCapiMachine := clusterv1resourcebuilder.Machine().
1915+
WithNamespace(capiNamespace.Name).
1916+
WithName("sentinel-machine").
1917+
Build()
1918+
Eventually(k8sClient.Create(ctx, sentinelCapiMachine)).Should(Succeed())
1919+
1920+
sentinelMapiMachine := machinev1resourcebuilder.Machine().
1921+
WithNamespace(mapiNamespace.Name).
1922+
WithName("sentinel-machine").
1923+
WithAuthoritativeAPI(mapiv1beta1.MachineAuthorityMachineAPI).
1924+
Build()
1925+
Eventually(k8sClient.Create(ctx, sentinelMapiMachine), timeout).Should(Succeed())
1926+
1927+
admissiontestutils.VerifySentinelValidation(k, sentinelMapiMachine, timeout)
1928+
})
1929+
1930+
Context("when validating infrastructure readiness", func() {
1931+
Context("when infrastructure is not ready", func() {
1932+
It("should deny authoritativeAPI change when infrastructureReady is false", func() {
1933+
By("Creating CAPI Machine with infrastructureReady=false")
1934+
Eventually(k.UpdateStatus(capiMachine, func() {
1935+
capiMachine.Status.InfrastructureReady = false
1936+
})).Should(Succeed())
1937+
1938+
By("Setting MAPI machine AuthoritativeAPI to MachineAPI")
1939+
Eventually(k.UpdateStatus(mapiMachine, func() {
1940+
mapiMachine.Status.AuthoritativeAPI = mapiv1beta1.MachineAuthorityMachineAPI
1941+
})).Should(Succeed())
1942+
1943+
By("Attempting to change authoritativeAPI to ClusterAPI")
1944+
Eventually(k.Update(mapiMachine, func() {
1945+
mapiMachine.Spec.AuthoritativeAPI = mapiv1beta1.MachineAuthorityClusterAPI
1946+
}), timeout).Should(MatchError(ContainSubstring("status.infrastructureReady is true")))
1947+
})
1948+
1949+
It("should deny authoritativeAPI change when infrastructureReady is missing", func() {
1950+
By("CAPI Machine was created in BeforeEach without setting infrastructureReady")
1951+
1952+
By("Setting MAPI machine AuthoritativeAPI to MachineAPI")
1953+
Eventually(k.UpdateStatus(mapiMachine, func() {
1954+
mapiMachine.Status.AuthoritativeAPI = mapiv1beta1.MachineAuthorityMachineAPI
1955+
})).Should(Succeed())
1956+
1957+
By("Attempting to change authoritativeAPI to ClusterAPI")
1958+
Eventually(k.Update(mapiMachine, func() {
1959+
mapiMachine.Spec.AuthoritativeAPI = mapiv1beta1.MachineAuthorityClusterAPI
1960+
}), timeout).Should(MatchError(ContainSubstring("status.infrastructureReady is true")))
1961+
})
1962+
1963+
It("should deny authoritativeAPI change when status field doesn't exist", func() {
1964+
By("CAPI Machine was created in BeforeEach without status")
1965+
1966+
By("Setting MAPI machine AuthoritativeAPI to MachineAPI")
1967+
Eventually(k.UpdateStatus(mapiMachine, func() {
1968+
mapiMachine.Status.AuthoritativeAPI = mapiv1beta1.MachineAuthorityMachineAPI
1969+
})).Should(Succeed())
1970+
1971+
By("Attempting to change authoritativeAPI to ClusterAPI")
1972+
Eventually(k.Update(mapiMachine, func() {
1973+
mapiMachine.Spec.AuthoritativeAPI = mapiv1beta1.MachineAuthorityClusterAPI
1974+
}), timeout).Should(MatchError(ContainSubstring("status.infrastructureReady is true")))
1975+
})
1976+
})
1977+
1978+
Context("when infrastructure is ready", func() {
1979+
It("should allow authoritativeAPI change when infrastructureReady is true", func() {
1980+
By("Creating CAPI Machine with infrastructureReady=true")
1981+
Eventually(k.UpdateStatus(capiMachine, func() {
1982+
capiMachine.Status.InfrastructureReady = true
1983+
})).Should(Succeed())
1984+
1985+
By("Setting MAPI machine AuthoritativeAPI to MachineAPI")
1986+
Eventually(k.UpdateStatus(mapiMachine, func() {
1987+
mapiMachine.Status.AuthoritativeAPI = mapiv1beta1.MachineAuthorityMachineAPI
1988+
})).Should(Succeed())
1989+
1990+
By("Changing authoritativeAPI to ClusterAPI")
1991+
Eventually(k.Update(mapiMachine, func() {
1992+
mapiMachine.Spec.AuthoritativeAPI = mapiv1beta1.MachineAuthorityClusterAPI
1993+
}), timeout).Should(Succeed())
1994+
})
1995+
})
1996+
})
1997+
1998+
Context("when validating deletion state", func() {
1999+
Context("when CAPI Machine is deleting", func() {
2000+
It("should deny authoritativeAPI change when deletionTimestamp is set", func() {
2001+
By("Creating CAPI Machine with infrastructureReady=true")
2002+
Eventually(k.UpdateStatus(capiMachine, func() {
2003+
capiMachine.Status.InfrastructureReady = true
2004+
})).Should(Succeed())
2005+
2006+
By("Adding finalizer and deleting CAPI Machine to set deletionTimestamp")
2007+
Eventually(k.Update(capiMachine, func() {
2008+
capiMachine.Finalizers = append(capiMachine.Finalizers, "test-finalizer")
2009+
})).Should(Succeed())
2010+
2011+
Eventually(k8sClient.Delete(ctx, capiMachine)).Should(Succeed())
2012+
2013+
By("Waiting for deletion timestamp to be set")
2014+
Eventually(k.Object(capiMachine)).Should(SatisfyAll(
2015+
HaveField("DeletionTimestamp", Not(BeNil())),
2016+
))
2017+
2018+
By("Setting MAPI machine AuthoritativeAPI to MachineAPI")
2019+
Eventually(k.UpdateStatus(mapiMachine, func() {
2020+
mapiMachine.Status.AuthoritativeAPI = mapiv1beta1.MachineAuthorityMachineAPI
2021+
})).Should(Succeed())
2022+
2023+
By("Attempting to change authoritativeAPI to ClusterAPI")
2024+
Eventually(k.Update(mapiMachine, func() {
2025+
mapiMachine.Spec.AuthoritativeAPI = mapiv1beta1.MachineAuthorityClusterAPI
2026+
}), timeout).Should(MatchError(ContainSubstring("CAPI Machine is being deleted")))
2027+
})
2028+
})
2029+
2030+
Context("when CAPI Machine is not deleting", func() {
2031+
It("should allow authoritativeAPI change when deletionTimestamp is not set", func() {
2032+
By("Creating CAPI Machine with infrastructureReady=true and no deletionTimestamp")
2033+
Eventually(k.UpdateStatus(capiMachine, func() {
2034+
capiMachine.Status.InfrastructureReady = true
2035+
})).Should(Succeed())
2036+
2037+
By("Setting MAPI machine AuthoritativeAPI to MachineAPI")
2038+
Eventually(k.UpdateStatus(mapiMachine, func() {
2039+
mapiMachine.Status.AuthoritativeAPI = mapiv1beta1.MachineAuthorityMachineAPI
2040+
})).Should(Succeed())
2041+
2042+
By("Changing authoritativeAPI to ClusterAPI")
2043+
Eventually(k.Update(mapiMachine, func() {
2044+
mapiMachine.Spec.AuthoritativeAPI = mapiv1beta1.MachineAuthorityClusterAPI
2045+
}), timeout).Should(Succeed())
2046+
})
2047+
})
2048+
})
2049+
2050+
Context("when validating mixed states", func() {
2051+
It("should deny authoritativeAPI change when infrastructureReady is true but deleting", func() {
2052+
By("Creating CAPI Machine with infrastructureReady=true")
2053+
Eventually(k.UpdateStatus(capiMachine, func() {
2054+
capiMachine.Status.InfrastructureReady = true
2055+
})).Should(Succeed())
2056+
2057+
By("Adding finalizer and deleting CAPI Machine to set deletionTimestamp")
2058+
Eventually(k.Update(capiMachine, func() {
2059+
capiMachine.Finalizers = append(capiMachine.Finalizers, "test-finalizer")
2060+
})).Should(Succeed())
2061+
2062+
Eventually(k8sClient.Delete(ctx, capiMachine)).Should(Succeed())
2063+
2064+
By("Waiting for deletion timestamp to be set")
2065+
Eventually(k.Object(capiMachine)).Should(SatisfyAll(
2066+
HaveField("DeletionTimestamp", Not(BeNil())),
2067+
))
2068+
2069+
By("Setting MAPI machine AuthoritativeAPI to MachineAPI")
2070+
Eventually(k.UpdateStatus(mapiMachine, func() {
2071+
mapiMachine.Status.AuthoritativeAPI = mapiv1beta1.MachineAuthorityMachineAPI
2072+
})).Should(Succeed())
2073+
2074+
By("Attempting to change authoritativeAPI to ClusterAPI")
2075+
Eventually(k.Update(mapiMachine, func() {
2076+
mapiMachine.Spec.AuthoritativeAPI = mapiv1beta1.MachineAuthorityClusterAPI
2077+
}), timeout).Should(MatchError(ContainSubstring("CAPI Machine is being deleted")))
2078+
})
2079+
2080+
It("should deny authoritativeAPI change when infrastructureReady is false but not deleting", func() {
2081+
By("Creating CAPI Machine with infrastructureReady=false")
2082+
Eventually(k.UpdateStatus(capiMachine, func() {
2083+
capiMachine.Status.InfrastructureReady = false
2084+
})).Should(Succeed())
2085+
2086+
By("Setting MAPI machine AuthoritativeAPI to MachineAPI")
2087+
Eventually(k.UpdateStatus(mapiMachine, func() {
2088+
mapiMachine.Status.AuthoritativeAPI = mapiv1beta1.MachineAuthorityMachineAPI
2089+
})).Should(Succeed())
2090+
2091+
By("Attempting to change authoritativeAPI to ClusterAPI")
2092+
Eventually(k.Update(mapiMachine, func() {
2093+
mapiMachine.Spec.AuthoritativeAPI = mapiv1beta1.MachineAuthorityClusterAPI
2094+
}), timeout).Should(MatchError(ContainSubstring("status.infrastructureReady is true")))
2095+
})
2096+
})
2097+
2098+
Context("when testing VAP trigger conditions", func() {
2099+
Context("when changing non-authoritativeAPI fields", func() {
2100+
It("should allow updating labels without changing authoritativeAPI", func() {
2101+
By("Creating CAPI Machine with infrastructureReady=false")
2102+
Eventually(k.UpdateStatus(capiMachine, func() {
2103+
capiMachine.Status.InfrastructureReady = false
2104+
})).Should(Succeed())
2105+
2106+
By("Setting MAPI machine AuthoritativeAPI to MachineAPI")
2107+
Eventually(k.UpdateStatus(mapiMachine, func() {
2108+
mapiMachine.Status.AuthoritativeAPI = mapiv1beta1.MachineAuthorityMachineAPI
2109+
})).Should(Succeed())
2110+
2111+
By("Updating labels without changing authoritativeAPI")
2112+
Eventually(k.Update(mapiMachine, func() {
2113+
if mapiMachine.Labels == nil {
2114+
mapiMachine.Labels = make(map[string]string)
2115+
}
2116+
mapiMachine.Labels["test-label"] = "test-value"
2117+
}), timeout).Should(Succeed())
2118+
})
2119+
2120+
It("should allow updating annotations without changing authoritativeAPI", func() {
2121+
By("Adding finalizer and deleting CAPI Machine to set deletionTimestamp")
2122+
Eventually(k.Update(capiMachine, func() {
2123+
capiMachine.Finalizers = append(capiMachine.Finalizers, "test-finalizer")
2124+
})).Should(Succeed())
2125+
2126+
Eventually(k8sClient.Delete(ctx, capiMachine)).Should(Succeed())
2127+
2128+
By("Waiting for deletion timestamp to be set")
2129+
Eventually(k.Object(capiMachine)).Should(SatisfyAll(
2130+
HaveField("DeletionTimestamp", Not(BeNil())),
2131+
))
2132+
2133+
By("Setting MAPI machine AuthoritativeAPI to MachineAPI")
2134+
Eventually(k.UpdateStatus(mapiMachine, func() {
2135+
mapiMachine.Status.AuthoritativeAPI = mapiv1beta1.MachineAuthorityMachineAPI
2136+
})).Should(Succeed())
2137+
2138+
By("Updating annotations without changing authoritativeAPI")
2139+
Eventually(k.Update(mapiMachine, func() {
2140+
if mapiMachine.Annotations == nil {
2141+
mapiMachine.Annotations = make(map[string]string)
2142+
}
2143+
mapiMachine.Annotations["test-annotation"] = "test-value"
2144+
}), timeout).Should(Succeed())
2145+
})
2146+
2147+
It("should allow updating spec fields without changing authoritativeAPI", func() {
2148+
By("CAPI Machine was created without infrastructureReady")
2149+
2150+
By("Setting MAPI machine AuthoritativeAPI to MachineAPI")
2151+
Eventually(k.UpdateStatus(mapiMachine, func() {
2152+
mapiMachine.Status.AuthoritativeAPI = mapiv1beta1.MachineAuthorityMachineAPI
2153+
})).Should(Succeed())
2154+
2155+
By("Updating spec.objectMeta.labels without changing authoritativeAPI")
2156+
Eventually(k.Update(mapiMachine, func() {
2157+
mapiMachine.Spec.ObjectMeta.Labels = map[string]string{"new-label": "new-value"}
2158+
}), timeout).Should(Succeed())
2159+
})
2160+
})
2161+
2162+
Context("when CAPI Machine parameter is not found", func() {
2163+
It("should allow authoritativeAPI change when CAPI Machine does not exist", func() {
2164+
By("Creating a new MAPI Machine without CAPI counterpart")
2165+
newMapiMachine := machinev1resourcebuilder.Machine().
2166+
WithNamespace(mapiNamespace.Name).
2167+
WithName("no-capi-equivalent").
2168+
WithAuthoritativeAPI(mapiv1beta1.MachineAuthorityMachineAPI).
2169+
Build()
2170+
Eventually(k8sClient.Create(ctx, newMapiMachine)).Should(Succeed())
2171+
2172+
By("Setting AuthoritativeAPI to MachineAPI")
2173+
Eventually(k.UpdateStatus(newMapiMachine, func() {
2174+
newMapiMachine.Status.AuthoritativeAPI = mapiv1beta1.MachineAuthorityMachineAPI
2175+
})).Should(Succeed())
2176+
2177+
By("Changing authoritativeAPI to ClusterAPI")
2178+
Eventually(k.Update(newMapiMachine, func() {
2179+
newMapiMachine.Spec.AuthoritativeAPI = mapiv1beta1.MachineAuthorityClusterAPI
2180+
}), timeout).Should(Succeed())
2181+
})
2182+
2183+
})
2184+
})
2185+
2186+
Context("when testing edge cases", func() {
2187+
Context("when CAPI Machine is in various states", func() {
2188+
2189+
2190+
It("should deny authoritativeAPI change when CAPI Machine is provisioning", func() {
2191+
By("Creating CAPI Machine with infrastructureReady=false and no deletionTimestamp")
2192+
Eventually(k.UpdateStatus(capiMachine, func() {
2193+
capiMachine.Status.InfrastructureReady = false
2194+
})).Should(Succeed())
2195+
2196+
By("Setting MAPI machine AuthoritativeAPI to MachineAPI")
2197+
Eventually(k.UpdateStatus(mapiMachine, func() {
2198+
mapiMachine.Status.AuthoritativeAPI = mapiv1beta1.MachineAuthorityMachineAPI
2199+
})).Should(Succeed())
2200+
2201+
By("Attempting to change authoritativeAPI to ClusterAPI")
2202+
Eventually(k.Update(mapiMachine, func() {
2203+
mapiMachine.Spec.AuthoritativeAPI = mapiv1beta1.MachineAuthorityClusterAPI
2204+
}), timeout).Should(MatchError(ContainSubstring("status.infrastructureReady is true")))
2205+
})
2206+
})
2207+
})
2208+
})
2209+
18792210
})
18802211
})
18812212

0 commit comments

Comments
 (0)