Skip to content

Commit

Permalink
Changes to infra template for SSA apply
Browse files Browse the repository at this point in the history
Signed-off-by: Sagar Muchhal <[email protected]>
  • Loading branch information
srm09 committed Aug 30, 2022
1 parent fcc47d3 commit f463ffa
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 56 deletions.
58 changes: 43 additions & 15 deletions apis/v1beta1/vspheremachinetemplate_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,57 +17,85 @@ limitations under the License.
package v1beta1

import (
"context"
"fmt"
"reflect"

apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"sigs.k8s.io/cluster-api/util/topology"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/webhook"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
)

func (r *VSphereMachineTemplate) SetupWebhookWithManager(mgr ctrl.Manager) error {
const machineTemplateImmutableMsg = "VSphereMachineTemplate spec.template.spec field is immutable. Please create a new resource instead."

func (v *VSphereMachineTemplateWebhook) SetupWebhookWithManager(mgr ctrl.Manager) error {
return ctrl.NewWebhookManagedBy(mgr).
For(r).
For(&VSphereMachineTemplate{}).
WithValidator(v).
Complete()
}

// +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1beta1-vspheremachinetemplate,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=vspheremachinetemplates,versions=v1beta1,name=validation.vspheremachinetemplate.infrastructure.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1

var _ webhook.Validator = &VSphereMachineTemplate{}
// VSphereMachineTemplateWebhook implements a custom validation webhook for DockerMachineTemplate.
// +kubebuilder:object:generate=false
type VSphereMachineTemplateWebhook struct{}

var _ webhook.CustomValidator = &VSphereMachineTemplateWebhook{}

// ValidateCreate implements webhook.Validator so a webhook will be registered for the type.
func (r *VSphereMachineTemplate) ValidateCreate() error {
func (v *VSphereMachineTemplateWebhook) ValidateCreate(_ context.Context, raw runtime.Object) error {
obj, ok := raw.(*VSphereMachineTemplate)
if !ok {
return apierrors.NewBadRequest(fmt.Sprintf("expected a VSphereMachineTemplate but got a %T", raw))
}

var allErrs field.ErrorList
spec := r.Spec.Template.Spec
spec := obj.Spec.Template.Spec

if spec.Network.PreferredAPIServerCIDR != "" {
allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "PreferredAPIServerCIDR"), spec.Network.PreferredAPIServerCIDR, "cannot be set, as it will be removed and is no longer used"))
}

if spec.ProviderID != nil {
allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "template", "spec", "providerID"), "cannot be set in templates"))
}

for _, device := range spec.Network.Devices {
if len(device.IPAddrs) != 0 {
allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "template", "spec", "network", "devices", "ipAddrs"), "cannot be set in templates"))
}
}

return aggregateObjErrors(r.GroupVersionKind().GroupKind(), r.Name, allErrs)
return aggregateObjErrors(obj.GroupVersionKind().GroupKind(), obj.Name, allErrs)
}

// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type.
func (r *VSphereMachineTemplate) ValidateUpdate(old runtime.Object) error {
oldVSphereMachineTemplate := old.(*VSphereMachineTemplate) //nolint:forcetypeassert
if !reflect.DeepEqual(r.Spec, oldVSphereMachineTemplate.Spec) {
return field.Forbidden(field.NewPath("spec"), "VSphereMachineTemplateSpec is immutable")
func (v *VSphereMachineTemplateWebhook) ValidateUpdate(ctx context.Context, oldRaw runtime.Object, newRaw runtime.Object) error {
newObj, ok := newRaw.(*VSphereMachineTemplate)
if !ok {
return apierrors.NewBadRequest(fmt.Sprintf("expected a VSphereMachineTemplate but got a %T", newRaw))
}
oldObj, ok := oldRaw.(*VSphereMachineTemplate)
if !ok {
return apierrors.NewBadRequest(fmt.Sprintf("expected a VSphereMachineTemplate but got a %T", oldRaw))
}

return nil
req, err := admission.RequestFromContext(ctx)
if err != nil {
return apierrors.NewBadRequest(fmt.Sprintf("expected a admission.Request inside context: %v", err))
}

var allErrs field.ErrorList
if !topology.ShouldSkipImmutabilityChecks(req, newObj) &&
!reflect.DeepEqual(newObj.Spec.Template.Spec, oldObj.Spec.Template.Spec) {
allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "template", "spec"), newObj, machineTemplateImmutableMsg))
}
return aggregateObjErrors(newObj.GroupVersionKind().GroupKind(), newObj.Name, allErrs)
}

// ValidateDelete implements webhook.Validator so a webhook will be registered for the type.
func (r *VSphereMachineTemplate) ValidateDelete() error {
func (v *VSphereMachineTemplateWebhook) ValidateDelete(_ context.Context, _ runtime.Object) error {
return nil
}
13 changes: 8 additions & 5 deletions apis/v1beta1/vspheremachinetemplate_webhooks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package v1beta1

import (
"context"
"testing"

. "github.com/onsi/gomega"
Expand Down Expand Up @@ -54,7 +55,8 @@ func TestVSphereMachineTemplate_ValidateCreate(t *testing.T) {
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
err := tc.vsphereMachine.ValidateCreate()
webhook := &VSphereMachineTemplateWebhook{}
err := webhook.ValidateCreate(context.TODO(), tc.vsphereMachine)
if tc.wantErr {
g.Expect(err).To(HaveOccurred())
} else {
Expand Down Expand Up @@ -96,7 +98,8 @@ func TestVSphereMachineTemplate_ValidateUpdate(t *testing.T) {
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
err := tc.vsphereMachine.ValidateUpdate(tc.oldVSphereMachine)
webhook := &VSphereMachineTemplateWebhook{}
err := webhook.ValidateUpdate(context.TODO(), tc.oldVSphereMachine, tc.vsphereMachine)
if tc.wantErr {
g.Expect(err).To(HaveOccurred())
} else {
Expand All @@ -107,7 +110,7 @@ func TestVSphereMachineTemplate_ValidateUpdate(t *testing.T) {
}

func createVSphereMachineTemplate(server string, providerID *string, preferredAPIServerCIDR string, ips []string) *VSphereMachineTemplate {
VSphereMachineTemplate := &VSphereMachineTemplate{
vsphereMachineTemplate := &VSphereMachineTemplate{
Spec: VSphereMachineTemplateSpec{
Template: VSphereMachineTemplateResource{
Spec: VSphereMachineSpec{
Expand All @@ -124,9 +127,9 @@ func createVSphereMachineTemplate(server string, providerID *string, preferredAP
},
}
for _, ip := range ips {
VSphereMachineTemplate.Spec.Template.Spec.Network.Devices = append(VSphereMachineTemplate.Spec.Template.Spec.Network.Devices, NetworkDeviceSpec{
vsphereMachineTemplate.Spec.Template.Spec.Network.Devices = append(vsphereMachineTemplate.Spec.Template.Spec.Network.Devices, NetworkDeviceSpec{
IPAddrs: []string{ip},
})
}
return VSphereMachineTemplate
return vsphereMachineTemplate
}
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ func setupVAPIControllers(ctx *context.ControllerManagerContext, mgr ctrlmgr.Man
return err
}

if err := (&v1beta1.VSphereMachineTemplate{}).SetupWebhookWithManager(mgr); err != nil {
if err := (&v1beta1.VSphereMachineTemplateWebhook{}).SetupWebhookWithManager(mgr); err != nil {
return err
}
if err := (&v1beta1.VSphereMachineTemplateList{}).SetupWebhookWithManager(mgr); err != nil {
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/capv_clusterclass_quickstart_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (
capi_e2e "sigs.k8s.io/cluster-api/test/e2e"
)

var _ = Describe("ClusterClass Creation using Cluster API quick-start test", func() {
var _ = Describe("ClusterClass Creation using Cluster API quick-start test [PR-Blocking] [ClusterClass]", func() {
Byf("Creating single-node control plane with one worker node")
capi_e2e.QuickStartSpec(ctx, func() capi_e2e.QuickStartSpecInput {
return capi_e2e.QuickStartSpecInput{
Expand Down
49 changes: 49 additions & 0 deletions test/e2e/clusterclass_changes_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
Copyright 2022 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package e2e

import (
. "github.com/onsi/ginkgo"
capie2e "sigs.k8s.io/cluster-api/test/e2e"
)

// TODO(srm09): Add the ModifyMachineDeploymentInfrastructureMachineTemplateFields to the test below
// once it is available in CAPI v.1.2.x release line.
var _ = Describe("When testing ClusterClass changes [ClusterClass]", func() {
capie2e.ClusterClassChangesSpec(ctx, func() capie2e.ClusterClassChangesSpecInput {
return capie2e.ClusterClassChangesSpecInput{
E2EConfig: e2eConfig,
ClusterctlConfigPath: clusterctlConfigPath,
BootstrapClusterProxy: bootstrapClusterProxy,
ArtifactFolder: artifactFolder,
SkipCleanup: skipCleanup,
Flavor: "topology",
// ModifyControlPlaneFields are the ControlPlane fields which will be set on the
// ControlPlaneTemplate of the ClusterClass after the initial Cluster creation.
// The test verifies that these fields are rolled out to the ControlPlane.
ModifyControlPlaneFields: map[string]interface{}{
"spec.machineTemplate.nodeDrainTimeout": "10s",
},
// ModifyMachineDeploymentBootstrapConfigTemplateFields are the fields which will be set on the
// BootstrapConfigTemplate of all MachineDeploymentClasses of the ClusterClass after the initial Cluster creation.
// The test verifies that these fields are rolled out to the MachineDeployments.
ModifyMachineDeploymentBootstrapConfigTemplateFields: map[string]interface{}{
"spec.template.spec.verbosity": int64(4),
},
}
})
})
18 changes: 9 additions & 9 deletions test/e2e/config/vsphere-ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
# For creating local images, run ./hack/e2e.sh

images:
- name: k8s.gcr.io/cluster-api/cluster-api-controller:v1.1.5
- name: k8s.gcr.io/cluster-api/cluster-api-controller:v1.2.1
loadBehavior: tryLoad
- name: k8s.gcr.io/cluster-api/kubeadm-bootstrap-controller:v1.1.5
- name: k8s.gcr.io/cluster-api/kubeadm-bootstrap-controller:v1.2.1
loadBehavior: tryLoad
- name: k8s.gcr.io/cluster-api/kubeadm-control-plane-controller:v1.1.5
- name: k8s.gcr.io/cluster-api/kubeadm-control-plane-controller:v1.2.1
loadBehavior: tryLoad
- name: gcr.io/k8s-staging-cluster-api/capv-manager:e2e
loadBehavior: mustLoad
Expand Down Expand Up @@ -46,9 +46,9 @@ providers:
replacements:
- old: "imagePullPolicy: Always"
new: "imagePullPolicy: IfNotPresent"
- name: v1.1.5
- name: v1.2.1
# Use manifest from source files
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.1.5/core-components.yaml"
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.2.1/core-components.yaml"
type: "url"
files:
- sourcePath: "../data/shared/metadata.yaml"
Expand Down Expand Up @@ -77,9 +77,9 @@ providers:
replacements:
- old: "imagePullPolicy: Always"
new: "imagePullPolicy: IfNotPresent"
- name: v1.1.5
- name: v1.2.1
# Use manifest from source files
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.1.5/bootstrap-components.yaml"
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.2.1/bootstrap-components.yaml"
type: "url"
files:
- sourcePath: "../data/shared/metadata.yaml"
Expand Down Expand Up @@ -108,9 +108,9 @@ providers:
replacements:
- old: "imagePullPolicy: Always"
new: "imagePullPolicy: IfNotPresent"
- name: v1.1.5
- name: v1.2.1
# Use manifest from source files
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.1.5/control-plane-components.yaml"
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.2.1/control-plane-components.yaml"
type: "url"
files:
- sourcePath: "../data/shared/metadata.yaml"
Expand Down
18 changes: 9 additions & 9 deletions test/e2e/config/vsphere-dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
# - from the CAPV repository root, `make e2e` to build the vsphere provider image and run e2e tests.

images:
- name: k8s.gcr.io/cluster-api/cluster-api-controller:v1.1.5
- name: k8s.gcr.io/cluster-api/cluster-api-controller:v1.2.1
loadBehavior: tryLoad
- name: k8s.gcr.io/cluster-api/kubeadm-bootstrap-controller:v1.1.5
- name: k8s.gcr.io/cluster-api/kubeadm-bootstrap-controller:v1.2.1
loadBehavior: tryLoad
- name: k8s.gcr.io/cluster-api/kubeadm-control-plane-controller:v1.1.5
- name: k8s.gcr.io/cluster-api/kubeadm-control-plane-controller:v1.2.1
loadBehavior: tryLoad
- name: gcr.io/k8s-staging-cluster-api/capv-manager:e2e
loadBehavior: mustLoad
Expand Down Expand Up @@ -49,9 +49,9 @@ providers:
replacements:
- old: "imagePullPolicy: Always"
new: "imagePullPolicy: IfNotPresent"
- name: v1.1.5
- name: v1.2.1
# Use manifest from source files
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.1.5/core-components.yaml"
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.2.1/core-components.yaml"
type: "url"
contract: v1beta1
files:
Expand Down Expand Up @@ -81,9 +81,9 @@ providers:
replacements:
- old: "imagePullPolicy: Always"
new: "imagePullPolicy: IfNotPresent"
- name: v1.1.5
- name: v1.2.1
# Use manifest from source files
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.1.5/bootstrap-components.yaml"
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.2.1/bootstrap-components.yaml"
type: "url"
contract: "v1beta1"
files:
Expand Down Expand Up @@ -113,9 +113,9 @@ providers:
replacements:
- old: "imagePullPolicy: Always"
new: "imagePullPolicy: IfNotPresent"
- name: v1.1.5
- name: v1.2.1
# Use manifest from source files
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.1.5/control-plane-components.yaml"
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.2.1/control-plane-components.yaml"
type: "url"
files:
- sourcePath: "../data/shared/metadata.yaml"
Expand Down
17 changes: 1 addition & 16 deletions test/helpers/envtest.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,37 +150,22 @@ func NewTestEnvironment() *TestEnvironment {
if err := (&infrav1.VSphereMachine{}).SetupWebhookWithManager(mgr); err != nil {
return err
}
if err := (&infrav1.VSphereMachineList{}).SetupWebhookWithManager(mgr); err != nil {
return err
}

if err := (&infrav1.VSphereMachineTemplate{}).SetupWebhookWithManager(mgr); err != nil {
return err
}
if err := (&infrav1.VSphereMachineTemplateList{}).SetupWebhookWithManager(mgr); err != nil {
if err := (&infrav1.VSphereMachineTemplateWebhook{}).SetupWebhookWithManager(mgr); err != nil {
return err
}

if err := (&infrav1.VSphereVM{}).SetupWebhookWithManager(mgr); err != nil {
return err
}
if err := (&infrav1.VSphereVMList{}).SetupWebhookWithManager(mgr); err != nil {
return err
}

if err := (&infrav1.VSphereDeploymentZone{}).SetupWebhookWithManager(mgr); err != nil {
return err
}
if err := (&infrav1.VSphereDeploymentZoneList{}).SetupWebhookWithManager(mgr); err != nil {
return err
}

if err := (&infrav1.VSphereFailureDomain{}).SetupWebhookWithManager(mgr); err != nil {
return err
}
if err := (&infrav1.VSphereFailureDomainList{}).SetupWebhookWithManager(mgr); err != nil {
return err
}

return nil
}
Expand Down

0 comments on commit f463ffa

Please sign in to comment.