Skip to content

Commit 2a566f2

Browse files
WIP: CAPI Machine creation validation
1 parent 509ccfd commit 2a566f2

File tree

2 files changed

+103
-0
lines changed

2 files changed

+103
-0
lines changed

manifests/0000_30_cluster-api_09_admission-policies.yaml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,46 @@ data:
400400
- Deny
401401
---
402402
apiVersion: admissionregistration.k8s.io/v1
403+
kind: ValidatingAdmissionPolicyBinding
404+
metadata:
405+
name: openshift-validate-capi-machine-creation
406+
spec:
407+
matchResources:
408+
namespaceSelector:
409+
matchLabels:
410+
kubernetes.io/metadata.name: openshift-cluster-api
411+
paramRef:
412+
namespace: openshift-machine-api
413+
parameterNotFoundAction: Allow
414+
selector: {}
415+
policyName: openshift-validate-capi-machine-creation
416+
validationActions:
417+
- Deny
418+
---
419+
apiVersion: admissionregistration.k8s.io/v1
420+
kind: ValidatingAdmissionPolicy
421+
metadata:
422+
name: openshift-validate-capi-machine-creation
423+
spec:
424+
failurePolicy: Fail
425+
paramKind:
426+
apiVersion: machine.openshift.io/v1beta1
427+
kind: Machine
428+
matchConstraints:
429+
resourceRules:
430+
- apiGroups: ["cluster.x-k8s.io"]
431+
apiVersions: ["v1beta1"]
432+
operations: ["CREATE"]
433+
resources: ["machines"]
434+
# Requests must satisfy every matchCondition to reach the validations
435+
matchConditions:
436+
- name: check-param-match
437+
expression: 'object.metadata.name == params.metadata.name'
438+
# All validations must evaluate to true
439+
validations:
440+
- expression: 'true'
441+
---
442+
apiVersion: admissionregistration.k8s.io/v1
403443
kind: ValidatingAdmissionPolicy
404444
metadata:
405445
name: openshift-prevent-migration-when-machine-updating

pkg/controllers/machinesync/machine_sync_controller_test.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1641,6 +1641,69 @@ var _ = Describe("With a running MachineSync Reconciler", func() {
16411641

16421642
})
16431643

1644+
FContext("Validate creation of CAPI machine ", func() {
1645+
var vapName = "openshift-validate-capi-machine-creation"
1646+
1647+
BeforeEach(func() {
1648+
By("Waiting for VAP to be ready")
1649+
machineVap = &admissionregistrationv1.ValidatingAdmissionPolicy{}
1650+
Eventually(k8sClient.Get(ctx, client.ObjectKey{Name: vapName}, machineVap), timeout).Should(Succeed())
1651+
resourceRules := machineVap.Spec.MatchConstraints.ResourceRules
1652+
Expect(resourceRules).To(HaveLen(1))
1653+
resourceRules[0].Operations = append(resourceRules[0].Operations, admissionregistrationv1.Update)
1654+
Eventually(k.Update(machineVap, func() {
1655+
admissiontestutils.AddSentinelValidation(machineVap)
1656+
// Updating the VAP so that it functions on "UPDATE" as well as "CREATE" only in this test suite to make it easier to test the functionality
1657+
machineVap.Spec.MatchConstraints.ResourceRules = resourceRules
1658+
1659+
})).Should(Succeed())
1660+
1661+
Eventually(k.Object(machineVap), timeout).Should(
1662+
HaveField("Status.ObservedGeneration", BeNumerically(">=", 2)),
1663+
)
1664+
1665+
By("Updating the VAP binding")
1666+
policyBinding = &admissionregistrationv1.ValidatingAdmissionPolicyBinding{}
1667+
Eventually(k8sClient.Get(ctx, client.ObjectKey{
1668+
Name: vapName}, policyBinding), timeout).Should(Succeed())
1669+
1670+
Eventually(k.Update(policyBinding, func() {
1671+
admissiontestutils.UpdateVAPBindingNamespaces(policyBinding, capiNamespace.GetName(), mapiNamespace.GetName())
1672+
}), timeout).Should(Succeed())
1673+
1674+
// Wait until the binding shows the patched values
1675+
Eventually(k.Object(policyBinding), timeout).Should(
1676+
SatisfyAll(
1677+
HaveField("Spec.MatchResources.NamespaceSelector.MatchLabels",
1678+
HaveKeyWithValue("kubernetes.io/metadata.name",
1679+
mapiNamespace.GetName())),
1680+
),
1681+
)
1682+
1683+
By("Creating a throwaway MAPI machine")
1684+
sentinelMachine := mapiMachineBuilder.WithName("sentinel-machine").WithAuthoritativeAPI(mapiv1beta1.MachineAuthorityClusterAPI).Build()
1685+
Eventually(k8sClient.Create(ctx, sentinelMachine), timeout).Should(Succeed())
1686+
1687+
capiSentinelMachine := clusterv1resourcebuilder.Machine().WithName("sentinel-machine").WithNamespace(capiNamespace.Name).Build()
1688+
Eventually(k8sClient.Create(ctx, capiSentinelMachine)).Should(Succeed())
1689+
1690+
Eventually(k.Get(capiSentinelMachine)).Should(Succeed())
1691+
1692+
admissiontestutils.VerifySentinelValidation(k, sentinelMachine, timeout)
1693+
})
1694+
1695+
// The Authoritative API defaults to MachineAPI so we can't test if it's unset.
1696+
It("Foo", func() {
1697+
By("Create the Capi Machine")
1698+
newCapiMachine := clusterv1resourcebuilder.Machine().WithName("validation-machine").WithNamespace(capiNamespace.Name).Build()
1699+
Eventually(k8sClient.Create(ctx, newCapiMachine)).Should(Succeed())
1700+
1701+
By("Create the Mapi Machine")
1702+
newMapiMachine := mapiMachineBuilder.WithName("validation-machine").WithAuthoritativeAPI(mapiv1beta1.MachineAuthorityMachineAPI).Build()
1703+
Eventually(k8sClient.Create(ctx, newMapiMachine), timeout).Should(MatchError(ContainSubstring("with authoritativeAPI=MachineAPI because a Cluster API Machine with the same name already exists.")))
1704+
})
1705+
})
1706+
16441707
Context("Prevent updates to MAPI machine if migrating would be unpredictable", func() {
16451708
BeforeEach(func() {
16461709
By("Waiting for VAP to be ready")

0 commit comments

Comments
 (0)