Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions manifests/0000_30_cluster-api_09_admission-policies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,46 @@ data:
- Deny
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
name: openshift-validate-capi-machine-creation
spec:
matchResources:
namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: openshift-cluster-api
paramRef:
namespace: openshift-machine-api
parameterNotFoundAction: Allow
selector: {}
policyName: openshift-validate-capi-machine-creation
validationActions:
- Deny
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: openshift-validate-capi-machine-creation
spec:
failurePolicy: Fail
paramKind:
apiVersion: machine.openshift.io/v1beta1
kind: Machine
matchConstraints:
resourceRules:
- apiGroups: ["cluster.x-k8s.io"]
apiVersions: ["v1beta1"]
operations: ["CREATE"]
resources: ["machines"]
# Requests must satisfy every matchCondition to reach the validations
matchConditions:
- name: check-param-match
expression: 'object.metadata.name == params.metadata.name'
# All validations must evaluate to true
validations:
- expression: 'true'
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: openshift-prevent-migration-when-machine-updating
Expand Down
63 changes: 63 additions & 0 deletions pkg/controllers/machinesync/machine_sync_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1641,6 +1641,69 @@ var _ = Describe("With a running MachineSync Reconciler", func() {

})

FContext("Validate creation of CAPI machine ", func() {
var vapName = "openshift-validate-capi-machine-creation"

BeforeEach(func() {
By("Waiting for VAP to be ready")
machineVap = &admissionregistrationv1.ValidatingAdmissionPolicy{}
Eventually(k8sClient.Get(ctx, client.ObjectKey{Name: vapName}, machineVap), timeout).Should(Succeed())
resourceRules := machineVap.Spec.MatchConstraints.ResourceRules
Expect(resourceRules).To(HaveLen(1))
resourceRules[0].Operations = append(resourceRules[0].Operations, admissionregistrationv1.Update)
Eventually(k.Update(machineVap, func() {
admissiontestutils.AddSentinelValidation(machineVap)
// 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
machineVap.Spec.MatchConstraints.ResourceRules = resourceRules

})).Should(Succeed())

Eventually(k.Object(machineVap), timeout).Should(
HaveField("Status.ObservedGeneration", BeNumerically(">=", 2)),
)

By("Updating the VAP binding")
policyBinding = &admissionregistrationv1.ValidatingAdmissionPolicyBinding{}
Eventually(k8sClient.Get(ctx, client.ObjectKey{
Name: vapName}, policyBinding), timeout).Should(Succeed())

Eventually(k.Update(policyBinding, func() {
admissiontestutils.UpdateVAPBindingNamespaces(policyBinding, capiNamespace.GetName(), mapiNamespace.GetName())
}), timeout).Should(Succeed())

// Wait until the binding shows the patched values
Eventually(k.Object(policyBinding), timeout).Should(
SatisfyAll(
HaveField("Spec.MatchResources.NamespaceSelector.MatchLabels",
HaveKeyWithValue("kubernetes.io/metadata.name",
mapiNamespace.GetName())),
),
)

By("Creating a throwaway MAPI machine")
sentinelMachine := mapiMachineBuilder.WithName("sentinel-machine").WithAuthoritativeAPI(mapiv1beta1.MachineAuthorityClusterAPI).Build()
Eventually(k8sClient.Create(ctx, sentinelMachine), timeout).Should(Succeed())

capiSentinelMachine := clusterv1resourcebuilder.Machine().WithName("sentinel-machine").WithNamespace(capiNamespace.Name).Build()
Eventually(k8sClient.Create(ctx, capiSentinelMachine)).Should(Succeed())

Eventually(k.Get(capiSentinelMachine)).Should(Succeed())

admissiontestutils.VerifySentinelValidation(k, sentinelMachine, timeout)
})

// The Authoritative API defaults to MachineAPI so we can't test if it's unset.
It("Foo", func() {
By("Create the Capi Machine")
newCapiMachine := clusterv1resourcebuilder.Machine().WithName("validation-machine").WithNamespace(capiNamespace.Name).Build()
Eventually(k8sClient.Create(ctx, newCapiMachine)).Should(Succeed())

By("Create the Mapi Machine")
newMapiMachine := mapiMachineBuilder.WithName("validation-machine").WithAuthoritativeAPI(mapiv1beta1.MachineAuthorityMachineAPI).Build()
Eventually(k8sClient.Create(ctx, newMapiMachine), timeout).Should(MatchError(ContainSubstring("with authoritativeAPI=MachineAPI because a Cluster API Machine with the same name already exists.")))
})
})

Context("Prevent updates to MAPI machine if migrating would be unpredictable", func() {
BeforeEach(func() {
By("Waiting for VAP to be ready")
Expand Down