Skip to content

Commit

Permalink
Merge pull request #6748 from k8s-infra-cherrypick-robot/cherry-pick-…
Browse files Browse the repository at this point in the history
…6700-to-release-1.2

[release-1.2] 🌱 Migrate more topology tests to Test* CRD
  • Loading branch information
sbueringer authored Jun 27, 2022
2 parents a820278 + b8741a8 commit e41dc69
Show file tree
Hide file tree
Showing 6 changed files with 272 additions and 78 deletions.
22 changes: 11 additions & 11 deletions internal/controllers/topology/cluster/cluster_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -547,19 +547,19 @@ func setupTestEnvForIntegrationTests(ns *corev1.Namespace) (func() error, error)
// Cluster given a skeletal Cluster object and a ClusterClass. The objects include:

// 1) Templates for Machine, Cluster, ControlPlane and Bootstrap.
infrastructureMachineTemplate1 := builder.InfrastructureMachineTemplate(ns.Name, infrastructureMachineTemplateName1).Build()
infrastructureMachineTemplate2 := builder.InfrastructureMachineTemplate(ns.Name, infrastructureMachineTemplateName2).
infrastructureMachineTemplate1 := builder.TestInfrastructureMachineTemplate(ns.Name, infrastructureMachineTemplateName1).Build()
infrastructureMachineTemplate2 := builder.TestInfrastructureMachineTemplate(ns.Name, infrastructureMachineTemplateName2).
WithSpecFields(map[string]interface{}{"spec.template.spec.fakeSetting": true}).
Build()
infrastructureClusterTemplate1 := builder.InfrastructureClusterTemplate(ns.Name, "infraclustertemplate1").
infrastructureClusterTemplate1 := builder.TestInfrastructureClusterTemplate(ns.Name, "infraclustertemplate1").
Build()
infrastructureClusterTemplate2 := builder.InfrastructureClusterTemplate(ns.Name, "infraclustertemplate2").
infrastructureClusterTemplate2 := builder.TestInfrastructureClusterTemplate(ns.Name, "infraclustertemplate2").
WithSpecFields(map[string]interface{}{"spec.template.spec.alteredSetting": true}).
Build()
controlPlaneTemplate := builder.ControlPlaneTemplate(ns.Name, "cp1").
controlPlaneTemplate := builder.TestControlPlaneTemplate(ns.Name, "cp1").
WithInfrastructureMachineTemplate(infrastructureMachineTemplate1).
Build()
bootstrapTemplate := builder.BootstrapTemplate(ns.Name, "bootstraptemplate").Build()
bootstrapTemplate := builder.TestBootstrapTemplate(ns.Name, "bootstraptemplate").Build()

// 2) ClusterClass definitions including definitions of MachineDeploymentClasses used inside the ClusterClass.
machineDeploymentClass1 := builder.MachineDeploymentClass(workerClassName1).
Expand Down Expand Up @@ -676,14 +676,14 @@ func assertClusterReconcile(cluster *clusterv1.Cluster) error {

// Check if InfrastructureRef exists and is of the expected Kind and APIVersion.
if err := referenceExistsWithCorrectKindAndAPIVersion(cluster.Spec.InfrastructureRef,
builder.GenericInfrastructureClusterKind,
builder.TestInfrastructureClusterKind,
builder.InfrastructureGroupVersion); err != nil {
return err
}

// Check if ControlPlaneRef exists is of the expected Kind and APIVersion.
if err := referenceExistsWithCorrectKindAndAPIVersion(cluster.Spec.ControlPlaneRef,
builder.GenericControlPlaneKind,
builder.TestControlPlaneKind,
builder.ControlPlaneGroupVersion); err != nil {
return err
}
Expand Down Expand Up @@ -742,7 +742,7 @@ func assertControlPlaneReconcile(cluster *clusterv1.Cluster) error {
return err
}
if err := referenceExistsWithCorrectKindAndAPIVersion(cpInfra,
builder.GenericInfrastructureMachineTemplateKind,
builder.TestInfrastructureMachineTemplateKind,
builder.InfrastructureGroupVersion); err != nil {
return err
}
Expand Down Expand Up @@ -824,7 +824,7 @@ func assertMachineDeploymentsReconcile(cluster *clusterv1.Cluster) error {

// Check if the InfrastructureReference exists.
if err := referenceExistsWithCorrectKindAndAPIVersion(&md.Spec.Template.Spec.InfrastructureRef,
builder.GenericInfrastructureMachineTemplateKind,
builder.TestInfrastructureMachineTemplateKind,
builder.InfrastructureGroupVersion); err != nil {
return err
}
Expand All @@ -836,7 +836,7 @@ func assertMachineDeploymentsReconcile(cluster *clusterv1.Cluster) error {

// Check if the Bootstrap reference has the expected Kind and APIVersion.
if err := referenceExistsWithCorrectKindAndAPIVersion(md.Spec.Template.Spec.Bootstrap.ConfigRef,
builder.GenericBootstrapConfigTemplateKind,
builder.TestBootstrapConfigTemplateKind,
builder.BootstrapGroupVersion); err != nil {
return err
}
Expand Down
10 changes: 10 additions & 0 deletions internal/test/builder/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ var (

func testBootstrapConfigTemplateCRD(gvk schema.GroupVersionKind) *apiextensionsv1.CustomResourceDefinition {
return generateCRD(gvk, map[string]apiextensionsv1.JSONSchemaProps{
"metadata": {
// NOTE: in CRD there is only a partial definition of metadata schema.
// Ref https://github.com/kubernetes-sigs/controller-tools/blob/59485af1c1f6a664655dad49543c474bb4a0d2a2/pkg/crd/gen.go#L185
Type: "object",
},
"spec": {
Type: "object",
Properties: map[string]apiextensionsv1.JSONSchemaProps{
Expand All @@ -67,6 +72,11 @@ func testBootstrapConfigTemplateCRD(gvk schema.GroupVersionKind) *apiextensionsv

func testBootstrapConfigCRD(gvk schema.GroupVersionKind) *apiextensionsv1.CustomResourceDefinition {
return generateCRD(gvk, map[string]apiextensionsv1.JSONSchemaProps{
"metadata": {
// NOTE: in CRD there is only a partial definition of metadata schema.
// Ref https://github.com/kubernetes-sigs/controller-tools/blob/59485af1c1f6a664655dad49543c474bb4a0d2a2/pkg/crd/gen.go#L185
Type: "object",
},
"spec": bootstrapConfigSpecSchema,
"status": {
Type: "object",
Expand Down
102 changes: 102 additions & 0 deletions internal/test/builder/builders.go
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,51 @@ func (i *InfrastructureClusterTemplateBuilder) Build() *unstructured.Unstructure
return obj
}

// TestInfrastructureClusterTemplateBuilder holds the variables needed to build a generic TestInfrastructureClusterTemplate.
// +kubebuilder:object:generate=false
type TestInfrastructureClusterTemplateBuilder struct {
namespace string
name string
specFields map[string]interface{}
}

// TestInfrastructureClusterTemplate returns an TestInfrastructureClusterTemplateBuilder with the given name and namespace.
func TestInfrastructureClusterTemplate(namespace, name string) *TestInfrastructureClusterTemplateBuilder {
return &TestInfrastructureClusterTemplateBuilder{
namespace: namespace,
name: name,
}
}

// WithSpecFields sets a map of spec fields on the unstructured object. The keys in the map represent the path and the value corresponds
// to the value of the spec field.
//
// Note: all the paths should start with "spec."; the path should correspond to a field defined in the CRD.
//
// Example map: map[string]interface{}{
// "spec.version": "v1.2.3",
// }.
func (i *TestInfrastructureClusterTemplateBuilder) WithSpecFields(fields map[string]interface{}) *TestInfrastructureClusterTemplateBuilder {
i.specFields = fields
return i
}

// Build creates a new Unstructured object with the variables passed to the InfrastructureClusterTemplateBuilder.
func (i *TestInfrastructureClusterTemplateBuilder) Build() *unstructured.Unstructured {
obj := &unstructured.Unstructured{}
obj.SetAPIVersion(InfrastructureGroupVersion.String())
obj.SetKind(TestInfrastructureClusterTemplateKind)
obj.SetNamespace(i.namespace)
obj.SetName(i.name)

// Initialize the spec.template.spec to make the object valid in reconciliation.
setSpecFields(obj, map[string]interface{}{"spec.template.spec": map[string]interface{}{}})

setSpecFields(obj, i.specFields)

return obj
}

// ControlPlaneTemplateBuilder holds the variables and objects needed to build a generic ControlPlane template.
// +kubebuilder:object:generate=false
type ControlPlaneTemplateBuilder struct {
Expand Down Expand Up @@ -670,6 +715,63 @@ func (c *ControlPlaneTemplateBuilder) Build() *unstructured.Unstructured {
return obj
}

// TestControlPlaneTemplateBuilder holds the variables and objects needed to build a generic ControlPlane template.
// +kubebuilder:object:generate=false
type TestControlPlaneTemplateBuilder struct {
namespace string
name string
infrastructureMachineTemplate *unstructured.Unstructured
specFields map[string]interface{}
}

// TestControlPlaneTemplate creates a NewControlPlaneTemplate builder with the given name and namespace.
func TestControlPlaneTemplate(namespace, name string) *TestControlPlaneTemplateBuilder {
return &TestControlPlaneTemplateBuilder{
namespace: namespace,
name: name,
}
}

// WithSpecFields sets a map of spec fields on the unstructured object. The keys in the map represent the path and the value corresponds
// to the value of the spec field.
//
// Note: all the paths should start with "spec."; the path should correspond to a field defined in the CRD.
//
// Example map: map[string]interface{}{
// "spec.version": "v1.2.3",
// }.
func (c *TestControlPlaneTemplateBuilder) WithSpecFields(fields map[string]interface{}) *TestControlPlaneTemplateBuilder {
c.specFields = fields
return c
}

// WithInfrastructureMachineTemplate adds the given Unstructured object to the ControlPlaneTemplateBuilder as its InfrastructureMachineTemplate.
func (c *TestControlPlaneTemplateBuilder) WithInfrastructureMachineTemplate(t *unstructured.Unstructured) *TestControlPlaneTemplateBuilder {
c.infrastructureMachineTemplate = t
return c
}

// Build creates an Unstructured object from the variables passed to the ControlPlaneTemplateBuilder.
func (c *TestControlPlaneTemplateBuilder) Build() *unstructured.Unstructured {
obj := &unstructured.Unstructured{}
obj.SetAPIVersion(ControlPlaneGroupVersion.String())
obj.SetKind(TestControlPlaneTemplateKind)
obj.SetNamespace(c.namespace)
obj.SetName(c.name)

// Initialize the spec.template.spec to make the object valid in reconciliation.
setSpecFields(obj, map[string]interface{}{"spec.template.spec": map[string]interface{}{}})

setSpecFields(obj, c.specFields)

if c.infrastructureMachineTemplate != nil {
if err := setNestedRef(obj, c.infrastructureMachineTemplate, "spec", "template", "spec", "machineTemplate", "infrastructureRef"); err != nil {
panic(err)
}
}
return obj
}

// InfrastructureClusterBuilder holds the variables and objects needed to build a generic InfrastructureCluster.
// +kubebuilder:object:generate=false
type InfrastructureClusterBuilder struct {
Expand Down
118 changes: 77 additions & 41 deletions internal/test/builder/controlplane.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,63 +37,47 @@ var (

// TODO: drop generic CRDs in favour of typed test CRDs.

// TestControlPlaneTemplateKind is the Kind for the TestControlPlaneTemplate.
TestControlPlaneTemplateKind = "TestControlPlaneTemplate"
// TestControlPlaneTemplateCRD is a test control plane template CRD.
TestControlPlaneTemplateCRD = testControlPlaneTemplateCRD(ControlPlaneGroupVersion.WithKind(TestControlPlaneTemplateKind))

// TestControlPlaneKind is the Kind for the TestControlPlane.
TestControlPlaneKind = "TestControlPlane"
// TestControlPlaneCRD is a test control plane CRD.
TestControlPlaneCRD = testControlPlaneCRD(ControlPlaneGroupVersion.WithKind(TestControlPlaneKind))
)

func testControlPlaneCRD(gvk schema.GroupVersionKind) *apiextensionsv1.CustomResourceDefinition {
func testControlPlaneTemplateCRD(gvk schema.GroupVersionKind) *apiextensionsv1.CustomResourceDefinition {
return generateCRD(gvk, map[string]apiextensionsv1.JSONSchemaProps{
"metadata": {
// NOTE: in CRD there is only a partial definition of metadata schema.
// Ref https://github.com/kubernetes-sigs/controller-tools/blob/59485af1c1f6a664655dad49543c474bb4a0d2a2/pkg/crd/gen.go#L185
Type: "object",
},
"spec": {
Type: "object",
Properties: map[string]apiextensionsv1.JSONSchemaProps{
// Mandatory field from the Cluster API contract - version support
"version": {
Type: "string",
},
// mandatory field from the Cluster API contract - replicas support
"replicas": {
Type: "integer",
Format: "int32",
},
// mandatory field from the Cluster API contract - using Machines support
"machineTemplate": {
Type: "object",
Properties: map[string]apiextensionsv1.JSONSchemaProps{
"metadata": metadataSchema,
"infrastructureRef": refSchema,
"nodeDeletionTimeout": {Type: "string"},
"nodeDrainTimeout": {Type: "string"},
},
},
// General purpose fields to be used in different test scenario.
"foo": {Type: "string"},
"bar": {Type: "string"},
// Copy of a subset of KCP spec fields to test server side apply on deep nested structs
"kubeadmConfigSpec": {
// Mandatory field from the Cluster API contract
"template": {
Type: "object",
Properties: map[string]apiextensionsv1.JSONSchemaProps{
"clusterConfiguration": {
Type: "object",
Properties: map[string]apiextensionsv1.JSONSchemaProps{
"controllerManager": {
Type: "object",
Properties: map[string]apiextensionsv1.JSONSchemaProps{
"extraArgs": {
Type: "object",
AdditionalProperties: &apiextensionsv1.JSONSchemaPropsOrBool{
Schema: &apiextensionsv1.JSONSchemaProps{Type: "string"},
},
},
},
},
},
},
"spec": controPlaneSpecSchema,
},
},
},
},
})
}

func testControlPlaneCRD(gvk schema.GroupVersionKind) *apiextensionsv1.CustomResourceDefinition {
return generateCRD(gvk, map[string]apiextensionsv1.JSONSchemaProps{
"metadata": {
// NOTE: in CRD there is only a partial definition of metadata schema.
// Ref https://github.com/kubernetes-sigs/controller-tools/blob/59485af1c1f6a664655dad49543c474bb4a0d2a2/pkg/crd/gen.go#L185
Type: "object",
},
"spec": controPlaneSpecSchema,
"status": {
Type: "object",
Properties: map[string]apiextensionsv1.JSONSchemaProps{
Expand All @@ -114,3 +98,55 @@ func testControlPlaneCRD(gvk schema.GroupVersionKind) *apiextensionsv1.CustomRes
},
})
}

var (
controPlaneSpecSchema = apiextensionsv1.JSONSchemaProps{
Type: "object",
Properties: map[string]apiextensionsv1.JSONSchemaProps{
// Mandatory field from the Cluster API contract - version support
"version": {
Type: "string",
},
// mandatory field from the Cluster API contract - replicas support
"replicas": {
Type: "integer",
Format: "int32",
},
// mandatory field from the Cluster API contract - using Machines support
"machineTemplate": {
Type: "object",
Properties: map[string]apiextensionsv1.JSONSchemaProps{
"metadata": metadataSchema,
"infrastructureRef": refSchema,
"nodeDeletionTimeout": {Type: "string"},
"nodeDrainTimeout": {Type: "string"},
},
},
// General purpose fields to be used in different test scenario.
"foo": {Type: "string"},
"bar": {Type: "string"},
// Copy of a subset of KCP spec fields to test server side apply on deep nested structs
"kubeadmConfigSpec": {
Type: "object",
Properties: map[string]apiextensionsv1.JSONSchemaProps{
"clusterConfiguration": {
Type: "object",
Properties: map[string]apiextensionsv1.JSONSchemaProps{
"controllerManager": {
Type: "object",
Properties: map[string]apiextensionsv1.JSONSchemaProps{
"extraArgs": {
Type: "object",
AdditionalProperties: &apiextensionsv1.JSONSchemaPropsOrBool{
Schema: &apiextensionsv1.JSONSchemaProps{Type: "string"},
},
},
},
},
},
},
},
},
},
}
)
Loading

0 comments on commit e41dc69

Please sign in to comment.