From 5622424dd762539fb00ed455a29f966a7ff08c6b Mon Sep 17 00:00:00 2001 From: Sagar Muchhal Date: Thu, 14 Jan 2021 13:44:04 -0800 Subject: [PATCH] Generate v1alpha4 types and conversions Signed-off-by: Sagar Muchhal --- Makefile | 2 +- PROJECT | 22 +- api/v1alpha3/conversion_test.go | 44 + api/v1alpha3/doc.go | 1 + api/v1alpha3/groupversion_info.go | 3 + .../haproxyloadbalancer_conversion.go | 31 +- api/v1alpha3/haproxyloadbalancer_types.go | 1 - api/v1alpha3/vspherecluster_conversion.go | 31 +- api/v1alpha3/vspherecluster_types.go | 1 - api/v1alpha3/vspheremachine_conversion.go | 31 +- api/v1alpha3/vspheremachine_types.go | 1 - .../vspheremachinetemplate_conversion.go | 28 +- api/v1alpha3/vspheremachinetemplate_types.go | 1 - api/v1alpha3/vspherevm_conversion.go | 31 +- api/v1alpha3/vspherevm_types.go | 1 - api/v1alpha3/zz_generated.conversion.go | 1532 +++++++++++++++++ api/v1alpha4/cloudprovider_encoding.go | 273 +++ api/v1alpha4/cloudprovider_encoding_test.go | 725 ++++++++ api/v1alpha4/cloudprovider_types.go | 253 +++ api/v1alpha4/condition_consts.go | 106 ++ api/v1alpha4/doc.go | 20 + api/v1alpha4/groupversion_info.go | 41 + .../haproxyloadbalancer_conversion.go | 23 + api/v1alpha4/haproxyloadbalancer_types.go | 89 + api/v1alpha4/haproxyloadbalancer_webhook.go | 27 + .../haproxyloadbalancerlist_webhook.go | 27 + api/v1alpha4/types.go | 342 ++++ api/v1alpha4/vspherecluster_conversion.go | 23 + api/v1alpha4/vspherecluster_types.go | 110 ++ api/v1alpha4/vspherecluster_webhook.go | 53 + api/v1alpha4/vspherecluster_webhook_test.go | 71 + api/v1alpha4/vsphereclusterlist_webhook.go | 27 + api/v1alpha4/vspheremachine_conversion.go | 23 + api/v1alpha4/vspheremachine_types.go | 132 ++ api/v1alpha4/vspheremachine_webhook.go | 96 ++ api/v1alpha4/vspheremachine_webhook_test.go | 127 ++ api/v1alpha4/vspheremachinelist_webhook.go | 27 + .../vspheremachinetemplate_conversion.go | 23 + api/v1alpha4/vspheremachinetemplate_types.go | 51 + .../vspheremachinetemplate_webhook.go | 73 + .../vspheremachinetemplate_webhooks_test.go | 132 ++ .../vspheremachinetemplatelist_webhook.go | 27 + api/v1alpha4/vspherevm_conversion.go | 23 + api/v1alpha4/vspherevm_types.go | 156 ++ api/v1alpha4/vspherevm_webhook.go | 100 ++ api/v1alpha4/vspherevm_webhook_test.go | 135 ++ api/v1alpha4/vspherevmlist_webhook.go | 27 + api/v1alpha4/webhooks.go | 35 + api/v1alpha4/zz_generated.deepcopy.go | 936 ++++++++++ ...cluster.x-k8s.io_haproxyloadbalancers.yaml | 278 +++ ...ture.cluster.x-k8s.io_vsphereclusters.yaml | 131 +- ...ture.cluster.x-k8s.io_vspheremachines.yaml | 143 +- ...ster.x-k8s.io_vspheremachinetemplates.yaml | 185 +- ...structure.cluster.x-k8s.io_vspherevms.yaml | 406 +++++ config/webhook/manifests.yaml | 80 + main.go | 33 +- 56 files changed, 7134 insertions(+), 216 deletions(-) create mode 100644 api/v1alpha3/conversion_test.go create mode 100644 api/v1alpha3/zz_generated.conversion.go create mode 100644 api/v1alpha4/cloudprovider_encoding.go create mode 100644 api/v1alpha4/cloudprovider_encoding_test.go create mode 100644 api/v1alpha4/cloudprovider_types.go create mode 100644 api/v1alpha4/condition_consts.go create mode 100644 api/v1alpha4/doc.go create mode 100644 api/v1alpha4/groupversion_info.go create mode 100644 api/v1alpha4/haproxyloadbalancer_conversion.go create mode 100644 api/v1alpha4/haproxyloadbalancer_types.go create mode 100644 api/v1alpha4/haproxyloadbalancer_webhook.go create mode 100644 api/v1alpha4/haproxyloadbalancerlist_webhook.go create mode 100644 api/v1alpha4/types.go create mode 100644 api/v1alpha4/vspherecluster_conversion.go create mode 100644 api/v1alpha4/vspherecluster_types.go create mode 100644 api/v1alpha4/vspherecluster_webhook.go create mode 100644 api/v1alpha4/vspherecluster_webhook_test.go create mode 100644 api/v1alpha4/vsphereclusterlist_webhook.go create mode 100644 api/v1alpha4/vspheremachine_conversion.go create mode 100644 api/v1alpha4/vspheremachine_types.go create mode 100644 api/v1alpha4/vspheremachine_webhook.go create mode 100644 api/v1alpha4/vspheremachine_webhook_test.go create mode 100644 api/v1alpha4/vspheremachinelist_webhook.go create mode 100644 api/v1alpha4/vspheremachinetemplate_conversion.go create mode 100644 api/v1alpha4/vspheremachinetemplate_types.go create mode 100644 api/v1alpha4/vspheremachinetemplate_webhook.go create mode 100644 api/v1alpha4/vspheremachinetemplate_webhooks_test.go create mode 100644 api/v1alpha4/vspheremachinetemplatelist_webhook.go create mode 100644 api/v1alpha4/vspherevm_conversion.go create mode 100644 api/v1alpha4/vspherevm_types.go create mode 100644 api/v1alpha4/vspherevm_webhook.go create mode 100644 api/v1alpha4/vspherevm_webhook_test.go create mode 100644 api/v1alpha4/vspherevmlist_webhook.go create mode 100644 api/v1alpha4/webhooks.go create mode 100644 api/v1alpha4/zz_generated.deepcopy.go diff --git a/Makefile b/Makefile index 9ec7e98abf..460e418a1c 100644 --- a/Makefile +++ b/Makefile @@ -202,7 +202,7 @@ generate-go: $(CONTROLLER_GEN) $(CONVERSION_GEN) ## Runs Go related generate tar object:headerFile=./hack/boilerplate/boilerplate.generatego.txt $(CONVERSION_GEN) \ - --input-dirs=./api/v1alpha2 \ + --input-dirs=./api/v1alpha3 \ --output-file-base=zz_generated.conversion \ --go-header-file=./hack/boilerplate/boilerplate.generatego.txt diff --git a/PROJECT b/PROJECT index 25252e90fb..e098d80eb5 100644 --- a/PROJECT +++ b/PROJECT @@ -2,15 +2,6 @@ version: "2" domain: cluster.x-k8s.io repo: sigs.k8s.io/cluster-api-provider-vsphere resources: -- group: infrastructure - version: v1alpha2 - kind: VSphereCluster -- group: infrastructure - version: v1alpha2 - kind: VSphereMachine -- group: infrastructure - version: v1alpha2 - kind: VSphereMachineTemplate - group: infrastructure version: v1alpha3 kind: VSphereCluster @@ -26,4 +17,15 @@ resources: - group: infrastructure version: v1alpha3 kind: HAProxyLoadBalancer - + - group: infrastructure + version: v1alpha4 + kind: VSphereCluster + - group: infrastructure + version: v1alpha4 + kind: VSphereMachine + - group: infrastructure + version: v1alpha4 + kind: VSphereMachineTemplate + - group: infrastructure + version: v1alpha4 + kind: VSphereVM diff --git a/api/v1alpha3/conversion_test.go b/api/v1alpha3/conversion_test.go new file mode 100644 index 0000000000..3a6449cb0f --- /dev/null +++ b/api/v1alpha3/conversion_test.go @@ -0,0 +1,44 @@ +/* +Copyright 2020 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 v1alpha3 + +import ( + "testing" + + . "github.com/onsi/gomega" + + "k8s.io/apimachinery/pkg/runtime" + utilconversion "sigs.k8s.io/cluster-api/util/conversion" + + nextver "sigs.k8s.io/cluster-api-provider-vsphere/api/v1alpha4" +) + +func TestFuzzyConversion(t *testing.T) { + g := NewWithT(t) + scheme := runtime.NewScheme() + g.Expect(AddToScheme(scheme)).To(Succeed()) + g.Expect(nextver.AddToScheme(scheme)).To(Succeed()) + + t.Run("for VSphereCluster", utilconversion.FuzzTestFunc(scheme, &nextver.VSphereCluster{}, &VSphereCluster{})) + t.Run("for VSphereCluster", utilconversion.FuzzTestFunc(scheme, &nextver.VSphereClusterList{}, &VSphereClusterList{})) + t.Run("for VSphereMachine", utilconversion.FuzzTestFunc(scheme, &nextver.VSphereMachine{}, &VSphereMachine{})) + t.Run("for VSphereMachineList", utilconversion.FuzzTestFunc(scheme, &nextver.VSphereMachineList{}, &VSphereMachineList{})) + t.Run("for VSphereMachineTemplate", utilconversion.FuzzTestFunc(scheme, &nextver.VSphereMachineTemplate{}, &VSphereMachineTemplate{})) + t.Run("for VSphereMachineTemplateList", utilconversion.FuzzTestFunc(scheme, &nextver.VSphereMachineTemplateList{}, &VSphereMachineTemplateList{})) + t.Run("for VSphereVM", utilconversion.FuzzTestFunc(scheme, &nextver.VSphereVM{}, &VSphereVM{})) + t.Run("for VSphereVMList", utilconversion.FuzzTestFunc(scheme, &nextver.VSphereVMList{}, &VSphereVMList{})) +} diff --git a/api/v1alpha3/doc.go b/api/v1alpha3/doc.go index cd52f2806a..747f2b8bb0 100644 --- a/api/v1alpha3/doc.go +++ b/api/v1alpha3/doc.go @@ -17,4 +17,5 @@ limitations under the License. // Package v1alpha3 contains API Schema definitions for the infrastructure v1alpha3 API group // +kubebuilder:object:generate=true // +groupName=infrastructure.cluster.x-k8s.io +// +k8s:conversion-gen=sigs.k8s.io/cluster-api-provider-vsphere/api/v1alpha4 package v1alpha3 diff --git a/api/v1alpha3/groupversion_info.go b/api/v1alpha3/groupversion_info.go index fd739f1287..e7ed37e4a1 100644 --- a/api/v1alpha3/groupversion_info.go +++ b/api/v1alpha3/groupversion_info.go @@ -38,4 +38,7 @@ var ( // AddToScheme adds the types in this group-version to the given scheme. AddToScheme = SchemeBuilder.AddToScheme + + // localSchemeBuilder is used for type conversions. + localSchemeBuilder = SchemeBuilder.SchemeBuilder ) diff --git a/api/v1alpha3/haproxyloadbalancer_conversion.go b/api/v1alpha3/haproxyloadbalancer_conversion.go index 8c556d3b7e..d91b8244ee 100644 --- a/api/v1alpha3/haproxyloadbalancer_conversion.go +++ b/api/v1alpha3/haproxyloadbalancer_conversion.go @@ -16,8 +16,31 @@ limitations under the License. package v1alpha3 -// Hub marks HAProxyLoadBalancer as a conversion hub. -func (*HAProxyLoadBalancer) Hub() {} +import ( + infrav1alpha4 "sigs.k8s.io/cluster-api-provider-vsphere/api/v1alpha4" + "sigs.k8s.io/controller-runtime/pkg/conversion" +) -// Hub marks HAProxyLoadBalancerList as a conversion hub. -func (*HAProxyLoadBalancerList) Hub() {} +// ConvertTo converts this HAProxyLoadBalancer to the Hub version (v1alpha4). +func (src *HAProxyLoadBalancer) ConvertTo(dstRaw conversion.Hub) error { // nolint + dst := dstRaw.(*infrav1alpha4.HAProxyLoadBalancer) + return Convert_v1alpha3_HAProxyLoadBalancer_To_v1alpha4_HAProxyLoadBalancer(src, dst, nil) +} + +// ConvertFrom converts from the Hub version (v1alpha4) to this HAProxyLoadBalancer. +func (dst *HAProxyLoadBalancer) ConvertFrom(srcRaw conversion.Hub) error { // nolint + src := srcRaw.(*infrav1alpha4.HAProxyLoadBalancer) + return Convert_v1alpha4_HAProxyLoadBalancer_To_v1alpha3_HAProxyLoadBalancer(src, dst, nil) +} + +// ConvertTo converts this HAProxyLoadBalancerList to the Hub version (v1alpha4). +func (src *HAProxyLoadBalancerList) ConvertTo(dstRaw conversion.Hub) error { // nolint + dst := dstRaw.(*infrav1alpha4.HAProxyLoadBalancerList) + return Convert_v1alpha3_HAProxyLoadBalancerList_To_v1alpha4_HAProxyLoadBalancerList(src, dst, nil) +} + +// ConvertFrom converts this VSphereVM to the Hub version (v1alpha4). +func (dst *HAProxyLoadBalancerList) ConvertFrom(srcRaw conversion.Hub) error { // nolint + src := srcRaw.(*infrav1alpha4.HAProxyLoadBalancerList) + return Convert_v1alpha4_HAProxyLoadBalancerList_To_v1alpha3_HAProxyLoadBalancerList(src, dst, nil) +} diff --git a/api/v1alpha3/haproxyloadbalancer_types.go b/api/v1alpha3/haproxyloadbalancer_types.go index 3dea400bbb..b97dca3510 100644 --- a/api/v1alpha3/haproxyloadbalancer_types.go +++ b/api/v1alpha3/haproxyloadbalancer_types.go @@ -62,7 +62,6 @@ type HAProxyLoadBalancerStatus struct { // +kubebuilder:object:root=true // +kubebuilder:resource:path=haproxyloadbalancers,scope=Namespaced -// +kubebuilder:storageversion // +kubebuilder:subresource:status // HAProxyLoadBalancer is the Schema for the haproxyloadbalancers API diff --git a/api/v1alpha3/vspherecluster_conversion.go b/api/v1alpha3/vspherecluster_conversion.go index 73374b2f2b..5a5d5d595a 100644 --- a/api/v1alpha3/vspherecluster_conversion.go +++ b/api/v1alpha3/vspherecluster_conversion.go @@ -16,8 +16,31 @@ limitations under the License. package v1alpha3 -// Hub marks VSphereCluster as a conversion hub. -func (*VSphereCluster) Hub() {} +import ( + infrav1alpha4 "sigs.k8s.io/cluster-api-provider-vsphere/api/v1alpha4" + "sigs.k8s.io/controller-runtime/pkg/conversion" +) -// Hub marks VSphereClusterList as a conversion hub. -func (*VSphereClusterList) Hub() {} +// ConvertTo converts this VSphereCluster to the Hub version (v1alpha4). +func (src *VSphereCluster) ConvertTo(dstRaw conversion.Hub) error { // nolint + dst := dstRaw.(*infrav1alpha4.VSphereCluster) + return Convert_v1alpha3_VSphereCluster_To_v1alpha4_VSphereCluster(src, dst, nil) +} + +// ConvertFrom converts from the Hub version (v1alpha4) to this VSphereCluster. +func (dst *VSphereCluster) ConvertFrom(srcRaw conversion.Hub) error { // nolint + src := srcRaw.(*infrav1alpha4.VSphereCluster) + return Convert_v1alpha4_VSphereCluster_To_v1alpha3_VSphereCluster(src, dst, nil) +} + +// ConvertTo converts this VSphereClusterList to the Hub version (v1alpha4). +func (src *VSphereClusterList) ConvertTo(dstRaw conversion.Hub) error { // nolint + dst := dstRaw.(*infrav1alpha4.VSphereClusterList) + return Convert_v1alpha3_VSphereClusterList_To_v1alpha4_VSphereClusterList(src, dst, nil) +} + +// ConvertFrom converts this VSphereVM to the Hub version (v1alpha4). +func (dst *VSphereClusterList) ConvertFrom(srcRaw conversion.Hub) error { // nolint + src := srcRaw.(*infrav1alpha4.VSphereClusterList) + return Convert_v1alpha4_VSphereClusterList_To_v1alpha3_VSphereClusterList(src, dst, nil) +} diff --git a/api/v1alpha3/vspherecluster_types.go b/api/v1alpha3/vspherecluster_types.go index cade8639cb..b5492b8e8a 100644 --- a/api/v1alpha3/vspherecluster_types.go +++ b/api/v1alpha3/vspherecluster_types.go @@ -76,7 +76,6 @@ type VSphereClusterStatus struct { // +kubebuilder:object:root=true // +kubebuilder:resource:path=vsphereclusters,scope=Namespaced,categories=cluster-api -// +kubebuilder:storageversion // +kubebuilder:subresource:status // VSphereCluster is the Schema for the vsphereclusters API diff --git a/api/v1alpha3/vspheremachine_conversion.go b/api/v1alpha3/vspheremachine_conversion.go index 4169cc9292..8863bab13e 100644 --- a/api/v1alpha3/vspheremachine_conversion.go +++ b/api/v1alpha3/vspheremachine_conversion.go @@ -16,8 +16,31 @@ limitations under the License. package v1alpha3 -// Hub marks VSphereMachine as a conversion hub. -func (*VSphereMachine) Hub() {} +import ( + infrav1alpha4 "sigs.k8s.io/cluster-api-provider-vsphere/api/v1alpha4" + "sigs.k8s.io/controller-runtime/pkg/conversion" +) -// Hub marks VSphereMachineList as a conversion hub. -func (*VSphereMachineList) Hub() {} +// ConvertTo converts this VSphereMachine to the Hub version (v1alpha4). +func (src *VSphereMachine) ConvertTo(dstRaw conversion.Hub) error { // nolint + dst := dstRaw.(*infrav1alpha4.VSphereMachine) + return Convert_v1alpha3_VSphereMachine_To_v1alpha4_VSphereMachine(src, dst, nil) +} + +// ConvertFrom converts from the Hub version (v1alpha4) to this VSphereMachine. +func (dst *VSphereMachine) ConvertFrom(srcRaw conversion.Hub) error { // nolint + src := srcRaw.(*infrav1alpha4.VSphereMachine) + return Convert_v1alpha4_VSphereMachine_To_v1alpha3_VSphereMachine(src, dst, nil) +} + +// ConvertTo converts this VSphereMachineList to the Hub version (v1alpha4). +func (src *VSphereMachineList) ConvertTo(dstRaw conversion.Hub) error { // nolint + dst := dstRaw.(*infrav1alpha4.VSphereMachineList) + return Convert_v1alpha3_VSphereMachineList_To_v1alpha4_VSphereMachineList(src, dst, nil) +} + +// ConvertFrom converts from the Hub version (v1alpha4) to this VSphereMachineList. +func (dst *VSphereMachineList) ConvertFrom(srcRaw conversion.Hub) error { // nolint + src := srcRaw.(*infrav1alpha4.VSphereMachineList) + return Convert_v1alpha4_VSphereMachineList_To_v1alpha3_VSphereMachineList(src, dst, nil) +} diff --git a/api/v1alpha3/vspheremachine_types.go b/api/v1alpha3/vspheremachine_types.go index 2b907ea6c7..da240ebb79 100644 --- a/api/v1alpha3/vspheremachine_types.go +++ b/api/v1alpha3/vspheremachine_types.go @@ -98,7 +98,6 @@ type VSphereMachineStatus struct { // +kubebuilder:object:root=true // +kubebuilder:resource:path=vspheremachines,scope=Namespaced,categories=cluster-api -// +kubebuilder:storageversion // +kubebuilder:subresource:status // VSphereMachine is the Schema for the vspheremachines API diff --git a/api/v1alpha3/vspheremachinetemplate_conversion.go b/api/v1alpha3/vspheremachinetemplate_conversion.go index 383eaf37b9..43e4bbbe75 100644 --- a/api/v1alpha3/vspheremachinetemplate_conversion.go +++ b/api/v1alpha3/vspheremachinetemplate_conversion.go @@ -16,8 +16,28 @@ limitations under the License. package v1alpha3 -// Hub marks VSphereMachineTemplate as a conversion hub. -func (*VSphereMachineTemplate) Hub() {} +import ( + infrav1alpha4 "sigs.k8s.io/cluster-api-provider-vsphere/api/v1alpha4" + "sigs.k8s.io/controller-runtime/pkg/conversion" +) -// Hub marks VSphereMachineTemplateList as a conversion hub. -func (*VSphereMachineTemplateList) Hub() {} +// ConvertTo +func (src *VSphereMachineTemplate) ConvertTo(dstRaw conversion.Hub) error { // nolint + dst := dstRaw.(*infrav1alpha4.VSphereMachineTemplate) + return Convert_v1alpha3_VSphereMachineTemplate_To_v1alpha4_VSphereMachineTemplate(src, dst, nil) +} + +func (dst *VSphereMachineTemplate) ConvertFrom(srcRaw conversion.Hub) error { // nolint + src := srcRaw.(*infrav1alpha4.VSphereMachineTemplate) + return Convert_v1alpha4_VSphereMachineTemplate_To_v1alpha3_VSphereMachineTemplate(src, dst, nil) +} + +func (src *VSphereMachineTemplateList) ConvertTo(dstRaw conversion.Hub) error { // nolint + dst := dstRaw.(*infrav1alpha4.VSphereMachineTemplateList) + return Convert_v1alpha3_VSphereMachineTemplateList_To_v1alpha4_VSphereMachineTemplateList(src, dst, nil) +} + +func (dst *VSphereMachineTemplateList) ConvertFrom(srcRaw conversion.Hub) error { // nolint + src := srcRaw.(*infrav1alpha4.VSphereMachineTemplateList) + return Convert_v1alpha4_VSphereMachineTemplateList_To_v1alpha3_VSphereMachineTemplateList(src, dst, nil) +} diff --git a/api/v1alpha3/vspheremachinetemplate_types.go b/api/v1alpha3/vspheremachinetemplate_types.go index ace8ca6304..2ee59ef70c 100644 --- a/api/v1alpha3/vspheremachinetemplate_types.go +++ b/api/v1alpha3/vspheremachinetemplate_types.go @@ -27,7 +27,6 @@ type VSphereMachineTemplateSpec struct { // +kubebuilder:object:root=true // +kubebuilder:resource:path=vspheremachinetemplates,scope=Namespaced,categories=cluster-api -// +kubebuilder:storageversion // VSphereMachineTemplate is the Schema for the vspheremachinetemplates API type VSphereMachineTemplate struct { diff --git a/api/v1alpha3/vspherevm_conversion.go b/api/v1alpha3/vspherevm_conversion.go index 2fc6deac6e..d83b0c28cd 100644 --- a/api/v1alpha3/vspherevm_conversion.go +++ b/api/v1alpha3/vspherevm_conversion.go @@ -16,8 +16,31 @@ limitations under the License. package v1alpha3 -// Hub marks VSphereVM as a conversion hub. -func (*VSphereVM) Hub() {} +import ( + infrav1alpha4 "sigs.k8s.io/cluster-api-provider-vsphere/api/v1alpha4" + "sigs.k8s.io/controller-runtime/pkg/conversion" +) -// Hub marks VSphereVMList as a conversion hub. -func (*VSphereVMList) Hub() {} +// ConvertTo converts this VSphereVM to the Hub version (v1alpha4). +func (src *VSphereVM) ConvertTo(dstRaw conversion.Hub) error { // nolint + dst := dstRaw.(*infrav1alpha4.VSphereVM) + return Convert_v1alpha3_VSphereVM_To_v1alpha4_VSphereVM(src, dst, nil) +} + +// ConvertFrom converts from the Hub version (v1alpha4) to this VSphereVM. +func (dst *VSphereVM) ConvertFrom(srcRaw conversion.Hub) error { // nolint + src := srcRaw.(*infrav1alpha4.VSphereVM) + return Convert_v1alpha4_VSphereVM_To_v1alpha3_VSphereVM(src, dst, nil) +} + +// ConvertTo converts this VSphereVMList to the Hub version (v1alpha4). +func (src *VSphereVMList) ConvertTo(dstRaw conversion.Hub) error { // nolint + dst := dstRaw.(*infrav1alpha4.VSphereVMList) + return Convert_v1alpha3_VSphereVMList_To_v1alpha4_VSphereVMList(src, dst, nil) +} + +// ConvertFrom converts this VSphereVM to the Hub version (v1alpha4). +func (dst *VSphereVMList) ConvertFrom(srcRaw conversion.Hub) error { // nolint + src := srcRaw.(*infrav1alpha4.VSphereVMList) + return Convert_v1alpha4_VSphereVMList_To_v1alpha3_VSphereVMList(src, dst, nil) +} diff --git a/api/v1alpha3/vspherevm_types.go b/api/v1alpha3/vspherevm_types.go index 29a4ad0d0d..c3bd0df889 100644 --- a/api/v1alpha3/vspherevm_types.go +++ b/api/v1alpha3/vspherevm_types.go @@ -122,7 +122,6 @@ type VSphereVMStatus struct { // +kubebuilder:object:root=true // +kubebuilder:resource:path=vspherevms,scope=Namespaced -// +kubebuilder:storageversion // +kubebuilder:subresource:status // VSphereVM is the Schema for the vspherevms API diff --git a/api/v1alpha3/zz_generated.conversion.go b/api/v1alpha3/zz_generated.conversion.go new file mode 100644 index 0000000000..7253ca4654 --- /dev/null +++ b/api/v1alpha3/zz_generated.conversion.go @@ -0,0 +1,1532 @@ +// +build !ignore_autogenerated + +/* +Copyright 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. +*/ + +// Code generated by conversion-gen. DO NOT EDIT. + +package v1alpha3 + +import ( + unsafe "unsafe" + + v1 "k8s.io/api/core/v1" + conversion "k8s.io/apimachinery/pkg/conversion" + runtime "k8s.io/apimachinery/pkg/runtime" + v1alpha4 "sigs.k8s.io/cluster-api-provider-vsphere/api/v1alpha4" + apiv1alpha3 "sigs.k8s.io/cluster-api/api/v1alpha3" + errors "sigs.k8s.io/cluster-api/errors" +) + +func init() { + localSchemeBuilder.Register(RegisterConversions) +} + +// RegisterConversions adds conversion functions to the given scheme. +// Public to allow building arbitrary schemes. +func RegisterConversions(s *runtime.Scheme) error { + if err := s.AddGeneratedConversionFunc((*APIEndpoint)(nil), (*v1alpha4.APIEndpoint)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_APIEndpoint_To_v1alpha4_APIEndpoint(a.(*APIEndpoint), b.(*v1alpha4.APIEndpoint), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.APIEndpoint)(nil), (*APIEndpoint)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_APIEndpoint_To_v1alpha3_APIEndpoint(a.(*v1alpha4.APIEndpoint), b.(*APIEndpoint), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*CPICloudConfig)(nil), (*v1alpha4.CPICloudConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_CPICloudConfig_To_v1alpha4_CPICloudConfig(a.(*CPICloudConfig), b.(*v1alpha4.CPICloudConfig), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.CPICloudConfig)(nil), (*CPICloudConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_CPICloudConfig_To_v1alpha3_CPICloudConfig(a.(*v1alpha4.CPICloudConfig), b.(*CPICloudConfig), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*CPIConfig)(nil), (*v1alpha4.CPIConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_CPIConfig_To_v1alpha4_CPIConfig(a.(*CPIConfig), b.(*v1alpha4.CPIConfig), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.CPIConfig)(nil), (*CPIConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_CPIConfig_To_v1alpha3_CPIConfig(a.(*v1alpha4.CPIConfig), b.(*CPIConfig), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*CPIDiskConfig)(nil), (*v1alpha4.CPIDiskConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_CPIDiskConfig_To_v1alpha4_CPIDiskConfig(a.(*CPIDiskConfig), b.(*v1alpha4.CPIDiskConfig), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.CPIDiskConfig)(nil), (*CPIDiskConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_CPIDiskConfig_To_v1alpha3_CPIDiskConfig(a.(*v1alpha4.CPIDiskConfig), b.(*CPIDiskConfig), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*CPIGlobalConfig)(nil), (*v1alpha4.CPIGlobalConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_CPIGlobalConfig_To_v1alpha4_CPIGlobalConfig(a.(*CPIGlobalConfig), b.(*v1alpha4.CPIGlobalConfig), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.CPIGlobalConfig)(nil), (*CPIGlobalConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_CPIGlobalConfig_To_v1alpha3_CPIGlobalConfig(a.(*v1alpha4.CPIGlobalConfig), b.(*CPIGlobalConfig), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*CPILabelConfig)(nil), (*v1alpha4.CPILabelConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_CPILabelConfig_To_v1alpha4_CPILabelConfig(a.(*CPILabelConfig), b.(*v1alpha4.CPILabelConfig), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.CPILabelConfig)(nil), (*CPILabelConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_CPILabelConfig_To_v1alpha3_CPILabelConfig(a.(*v1alpha4.CPILabelConfig), b.(*CPILabelConfig), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*CPINetworkConfig)(nil), (*v1alpha4.CPINetworkConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_CPINetworkConfig_To_v1alpha4_CPINetworkConfig(a.(*CPINetworkConfig), b.(*v1alpha4.CPINetworkConfig), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.CPINetworkConfig)(nil), (*CPINetworkConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_CPINetworkConfig_To_v1alpha3_CPINetworkConfig(a.(*v1alpha4.CPINetworkConfig), b.(*CPINetworkConfig), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*CPIProviderConfig)(nil), (*v1alpha4.CPIProviderConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_CPIProviderConfig_To_v1alpha4_CPIProviderConfig(a.(*CPIProviderConfig), b.(*v1alpha4.CPIProviderConfig), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.CPIProviderConfig)(nil), (*CPIProviderConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_CPIProviderConfig_To_v1alpha3_CPIProviderConfig(a.(*v1alpha4.CPIProviderConfig), b.(*CPIProviderConfig), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*CPIStorageConfig)(nil), (*v1alpha4.CPIStorageConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_CPIStorageConfig_To_v1alpha4_CPIStorageConfig(a.(*CPIStorageConfig), b.(*v1alpha4.CPIStorageConfig), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.CPIStorageConfig)(nil), (*CPIStorageConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_CPIStorageConfig_To_v1alpha3_CPIStorageConfig(a.(*v1alpha4.CPIStorageConfig), b.(*CPIStorageConfig), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*CPIVCenterConfig)(nil), (*v1alpha4.CPIVCenterConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_CPIVCenterConfig_To_v1alpha4_CPIVCenterConfig(a.(*CPIVCenterConfig), b.(*v1alpha4.CPIVCenterConfig), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.CPIVCenterConfig)(nil), (*CPIVCenterConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_CPIVCenterConfig_To_v1alpha3_CPIVCenterConfig(a.(*v1alpha4.CPIVCenterConfig), b.(*CPIVCenterConfig), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*CPIWorkspaceConfig)(nil), (*v1alpha4.CPIWorkspaceConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_CPIWorkspaceConfig_To_v1alpha4_CPIWorkspaceConfig(a.(*CPIWorkspaceConfig), b.(*v1alpha4.CPIWorkspaceConfig), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.CPIWorkspaceConfig)(nil), (*CPIWorkspaceConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_CPIWorkspaceConfig_To_v1alpha3_CPIWorkspaceConfig(a.(*v1alpha4.CPIWorkspaceConfig), b.(*CPIWorkspaceConfig), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*HAProxyLoadBalancer)(nil), (*v1alpha4.HAProxyLoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_HAProxyLoadBalancer_To_v1alpha4_HAProxyLoadBalancer(a.(*HAProxyLoadBalancer), b.(*v1alpha4.HAProxyLoadBalancer), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.HAProxyLoadBalancer)(nil), (*HAProxyLoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_HAProxyLoadBalancer_To_v1alpha3_HAProxyLoadBalancer(a.(*v1alpha4.HAProxyLoadBalancer), b.(*HAProxyLoadBalancer), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*HAProxyLoadBalancerList)(nil), (*v1alpha4.HAProxyLoadBalancerList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_HAProxyLoadBalancerList_To_v1alpha4_HAProxyLoadBalancerList(a.(*HAProxyLoadBalancerList), b.(*v1alpha4.HAProxyLoadBalancerList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.HAProxyLoadBalancerList)(nil), (*HAProxyLoadBalancerList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_HAProxyLoadBalancerList_To_v1alpha3_HAProxyLoadBalancerList(a.(*v1alpha4.HAProxyLoadBalancerList), b.(*HAProxyLoadBalancerList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*HAProxyLoadBalancerSpec)(nil), (*v1alpha4.HAProxyLoadBalancerSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_HAProxyLoadBalancerSpec_To_v1alpha4_HAProxyLoadBalancerSpec(a.(*HAProxyLoadBalancerSpec), b.(*v1alpha4.HAProxyLoadBalancerSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.HAProxyLoadBalancerSpec)(nil), (*HAProxyLoadBalancerSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_HAProxyLoadBalancerSpec_To_v1alpha3_HAProxyLoadBalancerSpec(a.(*v1alpha4.HAProxyLoadBalancerSpec), b.(*HAProxyLoadBalancerSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*HAProxyLoadBalancerStatus)(nil), (*v1alpha4.HAProxyLoadBalancerStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_HAProxyLoadBalancerStatus_To_v1alpha4_HAProxyLoadBalancerStatus(a.(*HAProxyLoadBalancerStatus), b.(*v1alpha4.HAProxyLoadBalancerStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.HAProxyLoadBalancerStatus)(nil), (*HAProxyLoadBalancerStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_HAProxyLoadBalancerStatus_To_v1alpha3_HAProxyLoadBalancerStatus(a.(*v1alpha4.HAProxyLoadBalancerStatus), b.(*HAProxyLoadBalancerStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*NetworkDeviceSpec)(nil), (*v1alpha4.NetworkDeviceSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_NetworkDeviceSpec_To_v1alpha4_NetworkDeviceSpec(a.(*NetworkDeviceSpec), b.(*v1alpha4.NetworkDeviceSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.NetworkDeviceSpec)(nil), (*NetworkDeviceSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_NetworkDeviceSpec_To_v1alpha3_NetworkDeviceSpec(a.(*v1alpha4.NetworkDeviceSpec), b.(*NetworkDeviceSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*NetworkRouteSpec)(nil), (*v1alpha4.NetworkRouteSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_NetworkRouteSpec_To_v1alpha4_NetworkRouteSpec(a.(*NetworkRouteSpec), b.(*v1alpha4.NetworkRouteSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.NetworkRouteSpec)(nil), (*NetworkRouteSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_NetworkRouteSpec_To_v1alpha3_NetworkRouteSpec(a.(*v1alpha4.NetworkRouteSpec), b.(*NetworkRouteSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*NetworkSpec)(nil), (*v1alpha4.NetworkSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_NetworkSpec_To_v1alpha4_NetworkSpec(a.(*NetworkSpec), b.(*v1alpha4.NetworkSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.NetworkSpec)(nil), (*NetworkSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_NetworkSpec_To_v1alpha3_NetworkSpec(a.(*v1alpha4.NetworkSpec), b.(*NetworkSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*NetworkStatus)(nil), (*v1alpha4.NetworkStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_NetworkStatus_To_v1alpha4_NetworkStatus(a.(*NetworkStatus), b.(*v1alpha4.NetworkStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.NetworkStatus)(nil), (*NetworkStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_NetworkStatus_To_v1alpha3_NetworkStatus(a.(*v1alpha4.NetworkStatus), b.(*NetworkStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*SSHUser)(nil), (*v1alpha4.SSHUser)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_SSHUser_To_v1alpha4_SSHUser(a.(*SSHUser), b.(*v1alpha4.SSHUser), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.SSHUser)(nil), (*SSHUser)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_SSHUser_To_v1alpha3_SSHUser(a.(*v1alpha4.SSHUser), b.(*SSHUser), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*UnmarshalINIOptions)(nil), (*v1alpha4.UnmarshalINIOptions)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_UnmarshalINIOptions_To_v1alpha4_UnmarshalINIOptions(a.(*UnmarshalINIOptions), b.(*v1alpha4.UnmarshalINIOptions), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.UnmarshalINIOptions)(nil), (*UnmarshalINIOptions)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_UnmarshalINIOptions_To_v1alpha3_UnmarshalINIOptions(a.(*v1alpha4.UnmarshalINIOptions), b.(*UnmarshalINIOptions), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*VSphereCluster)(nil), (*v1alpha4.VSphereCluster)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_VSphereCluster_To_v1alpha4_VSphereCluster(a.(*VSphereCluster), b.(*v1alpha4.VSphereCluster), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.VSphereCluster)(nil), (*VSphereCluster)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_VSphereCluster_To_v1alpha3_VSphereCluster(a.(*v1alpha4.VSphereCluster), b.(*VSphereCluster), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*VSphereClusterList)(nil), (*v1alpha4.VSphereClusterList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_VSphereClusterList_To_v1alpha4_VSphereClusterList(a.(*VSphereClusterList), b.(*v1alpha4.VSphereClusterList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.VSphereClusterList)(nil), (*VSphereClusterList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_VSphereClusterList_To_v1alpha3_VSphereClusterList(a.(*v1alpha4.VSphereClusterList), b.(*VSphereClusterList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*VSphereClusterSpec)(nil), (*v1alpha4.VSphereClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_VSphereClusterSpec_To_v1alpha4_VSphereClusterSpec(a.(*VSphereClusterSpec), b.(*v1alpha4.VSphereClusterSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.VSphereClusterSpec)(nil), (*VSphereClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_VSphereClusterSpec_To_v1alpha3_VSphereClusterSpec(a.(*v1alpha4.VSphereClusterSpec), b.(*VSphereClusterSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*VSphereClusterStatus)(nil), (*v1alpha4.VSphereClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_VSphereClusterStatus_To_v1alpha4_VSphereClusterStatus(a.(*VSphereClusterStatus), b.(*v1alpha4.VSphereClusterStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.VSphereClusterStatus)(nil), (*VSphereClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_VSphereClusterStatus_To_v1alpha3_VSphereClusterStatus(a.(*v1alpha4.VSphereClusterStatus), b.(*VSphereClusterStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*VSphereMachine)(nil), (*v1alpha4.VSphereMachine)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_VSphereMachine_To_v1alpha4_VSphereMachine(a.(*VSphereMachine), b.(*v1alpha4.VSphereMachine), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.VSphereMachine)(nil), (*VSphereMachine)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_VSphereMachine_To_v1alpha3_VSphereMachine(a.(*v1alpha4.VSphereMachine), b.(*VSphereMachine), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*VSphereMachineList)(nil), (*v1alpha4.VSphereMachineList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_VSphereMachineList_To_v1alpha4_VSphereMachineList(a.(*VSphereMachineList), b.(*v1alpha4.VSphereMachineList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.VSphereMachineList)(nil), (*VSphereMachineList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_VSphereMachineList_To_v1alpha3_VSphereMachineList(a.(*v1alpha4.VSphereMachineList), b.(*VSphereMachineList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*VSphereMachineSpec)(nil), (*v1alpha4.VSphereMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_VSphereMachineSpec_To_v1alpha4_VSphereMachineSpec(a.(*VSphereMachineSpec), b.(*v1alpha4.VSphereMachineSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.VSphereMachineSpec)(nil), (*VSphereMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_VSphereMachineSpec_To_v1alpha3_VSphereMachineSpec(a.(*v1alpha4.VSphereMachineSpec), b.(*VSphereMachineSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*VSphereMachineStatus)(nil), (*v1alpha4.VSphereMachineStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_VSphereMachineStatus_To_v1alpha4_VSphereMachineStatus(a.(*VSphereMachineStatus), b.(*v1alpha4.VSphereMachineStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.VSphereMachineStatus)(nil), (*VSphereMachineStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_VSphereMachineStatus_To_v1alpha3_VSphereMachineStatus(a.(*v1alpha4.VSphereMachineStatus), b.(*VSphereMachineStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*VSphereMachineTemplate)(nil), (*v1alpha4.VSphereMachineTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_VSphereMachineTemplate_To_v1alpha4_VSphereMachineTemplate(a.(*VSphereMachineTemplate), b.(*v1alpha4.VSphereMachineTemplate), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.VSphereMachineTemplate)(nil), (*VSphereMachineTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_VSphereMachineTemplate_To_v1alpha3_VSphereMachineTemplate(a.(*v1alpha4.VSphereMachineTemplate), b.(*VSphereMachineTemplate), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*VSphereMachineTemplateList)(nil), (*v1alpha4.VSphereMachineTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_VSphereMachineTemplateList_To_v1alpha4_VSphereMachineTemplateList(a.(*VSphereMachineTemplateList), b.(*v1alpha4.VSphereMachineTemplateList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.VSphereMachineTemplateList)(nil), (*VSphereMachineTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_VSphereMachineTemplateList_To_v1alpha3_VSphereMachineTemplateList(a.(*v1alpha4.VSphereMachineTemplateList), b.(*VSphereMachineTemplateList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*VSphereMachineTemplateResource)(nil), (*v1alpha4.VSphereMachineTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_VSphereMachineTemplateResource_To_v1alpha4_VSphereMachineTemplateResource(a.(*VSphereMachineTemplateResource), b.(*v1alpha4.VSphereMachineTemplateResource), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.VSphereMachineTemplateResource)(nil), (*VSphereMachineTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_VSphereMachineTemplateResource_To_v1alpha3_VSphereMachineTemplateResource(a.(*v1alpha4.VSphereMachineTemplateResource), b.(*VSphereMachineTemplateResource), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*VSphereMachineTemplateSpec)(nil), (*v1alpha4.VSphereMachineTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_VSphereMachineTemplateSpec_To_v1alpha4_VSphereMachineTemplateSpec(a.(*VSphereMachineTemplateSpec), b.(*v1alpha4.VSphereMachineTemplateSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.VSphereMachineTemplateSpec)(nil), (*VSphereMachineTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_VSphereMachineTemplateSpec_To_v1alpha3_VSphereMachineTemplateSpec(a.(*v1alpha4.VSphereMachineTemplateSpec), b.(*VSphereMachineTemplateSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*VSphereVM)(nil), (*v1alpha4.VSphereVM)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_VSphereVM_To_v1alpha4_VSphereVM(a.(*VSphereVM), b.(*v1alpha4.VSphereVM), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.VSphereVM)(nil), (*VSphereVM)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_VSphereVM_To_v1alpha3_VSphereVM(a.(*v1alpha4.VSphereVM), b.(*VSphereVM), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*VSphereVMList)(nil), (*v1alpha4.VSphereVMList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_VSphereVMList_To_v1alpha4_VSphereVMList(a.(*VSphereVMList), b.(*v1alpha4.VSphereVMList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.VSphereVMList)(nil), (*VSphereVMList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_VSphereVMList_To_v1alpha3_VSphereVMList(a.(*v1alpha4.VSphereVMList), b.(*VSphereVMList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*VSphereVMSpec)(nil), (*v1alpha4.VSphereVMSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_VSphereVMSpec_To_v1alpha4_VSphereVMSpec(a.(*VSphereVMSpec), b.(*v1alpha4.VSphereVMSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.VSphereVMSpec)(nil), (*VSphereVMSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_VSphereVMSpec_To_v1alpha3_VSphereVMSpec(a.(*v1alpha4.VSphereVMSpec), b.(*VSphereVMSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*VSphereVMStatus)(nil), (*v1alpha4.VSphereVMStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_VSphereVMStatus_To_v1alpha4_VSphereVMStatus(a.(*VSphereVMStatus), b.(*v1alpha4.VSphereVMStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.VSphereVMStatus)(nil), (*VSphereVMStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_VSphereVMStatus_To_v1alpha3_VSphereVMStatus(a.(*v1alpha4.VSphereVMStatus), b.(*VSphereVMStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*VirtualMachine)(nil), (*v1alpha4.VirtualMachine)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_VirtualMachine_To_v1alpha4_VirtualMachine(a.(*VirtualMachine), b.(*v1alpha4.VirtualMachine), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.VirtualMachine)(nil), (*VirtualMachine)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_VirtualMachine_To_v1alpha3_VirtualMachine(a.(*v1alpha4.VirtualMachine), b.(*VirtualMachine), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*VirtualMachineCloneSpec)(nil), (*v1alpha4.VirtualMachineCloneSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_VirtualMachineCloneSpec_To_v1alpha4_VirtualMachineCloneSpec(a.(*VirtualMachineCloneSpec), b.(*v1alpha4.VirtualMachineCloneSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha4.VirtualMachineCloneSpec)(nil), (*VirtualMachineCloneSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_VirtualMachineCloneSpec_To_v1alpha3_VirtualMachineCloneSpec(a.(*v1alpha4.VirtualMachineCloneSpec), b.(*VirtualMachineCloneSpec), scope) + }); err != nil { + return err + } + return nil +} + +func autoConvert_v1alpha3_APIEndpoint_To_v1alpha4_APIEndpoint(in *APIEndpoint, out *v1alpha4.APIEndpoint, s conversion.Scope) error { + out.Host = in.Host + out.Port = in.Port + return nil +} + +// Convert_v1alpha3_APIEndpoint_To_v1alpha4_APIEndpoint is an autogenerated conversion function. +func Convert_v1alpha3_APIEndpoint_To_v1alpha4_APIEndpoint(in *APIEndpoint, out *v1alpha4.APIEndpoint, s conversion.Scope) error { + return autoConvert_v1alpha3_APIEndpoint_To_v1alpha4_APIEndpoint(in, out, s) +} + +func autoConvert_v1alpha4_APIEndpoint_To_v1alpha3_APIEndpoint(in *v1alpha4.APIEndpoint, out *APIEndpoint, s conversion.Scope) error { + out.Host = in.Host + out.Port = in.Port + return nil +} + +// Convert_v1alpha4_APIEndpoint_To_v1alpha3_APIEndpoint is an autogenerated conversion function. +func Convert_v1alpha4_APIEndpoint_To_v1alpha3_APIEndpoint(in *v1alpha4.APIEndpoint, out *APIEndpoint, s conversion.Scope) error { + return autoConvert_v1alpha4_APIEndpoint_To_v1alpha3_APIEndpoint(in, out, s) +} + +func autoConvert_v1alpha3_CPICloudConfig_To_v1alpha4_CPICloudConfig(in *CPICloudConfig, out *v1alpha4.CPICloudConfig, s conversion.Scope) error { + out.ControllerImage = in.ControllerImage + out.ExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ExtraArgs)) + return nil +} + +// Convert_v1alpha3_CPICloudConfig_To_v1alpha4_CPICloudConfig is an autogenerated conversion function. +func Convert_v1alpha3_CPICloudConfig_To_v1alpha4_CPICloudConfig(in *CPICloudConfig, out *v1alpha4.CPICloudConfig, s conversion.Scope) error { + return autoConvert_v1alpha3_CPICloudConfig_To_v1alpha4_CPICloudConfig(in, out, s) +} + +func autoConvert_v1alpha4_CPICloudConfig_To_v1alpha3_CPICloudConfig(in *v1alpha4.CPICloudConfig, out *CPICloudConfig, s conversion.Scope) error { + out.ControllerImage = in.ControllerImage + out.ExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ExtraArgs)) + return nil +} + +// Convert_v1alpha4_CPICloudConfig_To_v1alpha3_CPICloudConfig is an autogenerated conversion function. +func Convert_v1alpha4_CPICloudConfig_To_v1alpha3_CPICloudConfig(in *v1alpha4.CPICloudConfig, out *CPICloudConfig, s conversion.Scope) error { + return autoConvert_v1alpha4_CPICloudConfig_To_v1alpha3_CPICloudConfig(in, out, s) +} + +func autoConvert_v1alpha3_CPIConfig_To_v1alpha4_CPIConfig(in *CPIConfig, out *v1alpha4.CPIConfig, s conversion.Scope) error { + if err := Convert_v1alpha3_CPIGlobalConfig_To_v1alpha4_CPIGlobalConfig(&in.Global, &out.Global, s); err != nil { + return err + } + out.VCenter = *(*map[string]v1alpha4.CPIVCenterConfig)(unsafe.Pointer(&in.VCenter)) + if err := Convert_v1alpha3_CPINetworkConfig_To_v1alpha4_CPINetworkConfig(&in.Network, &out.Network, s); err != nil { + return err + } + if err := Convert_v1alpha3_CPIDiskConfig_To_v1alpha4_CPIDiskConfig(&in.Disk, &out.Disk, s); err != nil { + return err + } + if err := Convert_v1alpha3_CPIWorkspaceConfig_To_v1alpha4_CPIWorkspaceConfig(&in.Workspace, &out.Workspace, s); err != nil { + return err + } + if err := Convert_v1alpha3_CPILabelConfig_To_v1alpha4_CPILabelConfig(&in.Labels, &out.Labels, s); err != nil { + return err + } + if err := Convert_v1alpha3_CPIProviderConfig_To_v1alpha4_CPIProviderConfig(&in.ProviderConfig, &out.ProviderConfig, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha3_CPIConfig_To_v1alpha4_CPIConfig is an autogenerated conversion function. +func Convert_v1alpha3_CPIConfig_To_v1alpha4_CPIConfig(in *CPIConfig, out *v1alpha4.CPIConfig, s conversion.Scope) error { + return autoConvert_v1alpha3_CPIConfig_To_v1alpha4_CPIConfig(in, out, s) +} + +func autoConvert_v1alpha4_CPIConfig_To_v1alpha3_CPIConfig(in *v1alpha4.CPIConfig, out *CPIConfig, s conversion.Scope) error { + if err := Convert_v1alpha4_CPIGlobalConfig_To_v1alpha3_CPIGlobalConfig(&in.Global, &out.Global, s); err != nil { + return err + } + out.VCenter = *(*map[string]CPIVCenterConfig)(unsafe.Pointer(&in.VCenter)) + if err := Convert_v1alpha4_CPINetworkConfig_To_v1alpha3_CPINetworkConfig(&in.Network, &out.Network, s); err != nil { + return err + } + if err := Convert_v1alpha4_CPIDiskConfig_To_v1alpha3_CPIDiskConfig(&in.Disk, &out.Disk, s); err != nil { + return err + } + if err := Convert_v1alpha4_CPIWorkspaceConfig_To_v1alpha3_CPIWorkspaceConfig(&in.Workspace, &out.Workspace, s); err != nil { + return err + } + if err := Convert_v1alpha4_CPILabelConfig_To_v1alpha3_CPILabelConfig(&in.Labels, &out.Labels, s); err != nil { + return err + } + if err := Convert_v1alpha4_CPIProviderConfig_To_v1alpha3_CPIProviderConfig(&in.ProviderConfig, &out.ProviderConfig, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha4_CPIConfig_To_v1alpha3_CPIConfig is an autogenerated conversion function. +func Convert_v1alpha4_CPIConfig_To_v1alpha3_CPIConfig(in *v1alpha4.CPIConfig, out *CPIConfig, s conversion.Scope) error { + return autoConvert_v1alpha4_CPIConfig_To_v1alpha3_CPIConfig(in, out, s) +} + +func autoConvert_v1alpha3_CPIDiskConfig_To_v1alpha4_CPIDiskConfig(in *CPIDiskConfig, out *v1alpha4.CPIDiskConfig, s conversion.Scope) error { + out.SCSIControllerType = in.SCSIControllerType + return nil +} + +// Convert_v1alpha3_CPIDiskConfig_To_v1alpha4_CPIDiskConfig is an autogenerated conversion function. +func Convert_v1alpha3_CPIDiskConfig_To_v1alpha4_CPIDiskConfig(in *CPIDiskConfig, out *v1alpha4.CPIDiskConfig, s conversion.Scope) error { + return autoConvert_v1alpha3_CPIDiskConfig_To_v1alpha4_CPIDiskConfig(in, out, s) +} + +func autoConvert_v1alpha4_CPIDiskConfig_To_v1alpha3_CPIDiskConfig(in *v1alpha4.CPIDiskConfig, out *CPIDiskConfig, s conversion.Scope) error { + out.SCSIControllerType = in.SCSIControllerType + return nil +} + +// Convert_v1alpha4_CPIDiskConfig_To_v1alpha3_CPIDiskConfig is an autogenerated conversion function. +func Convert_v1alpha4_CPIDiskConfig_To_v1alpha3_CPIDiskConfig(in *v1alpha4.CPIDiskConfig, out *CPIDiskConfig, s conversion.Scope) error { + return autoConvert_v1alpha4_CPIDiskConfig_To_v1alpha3_CPIDiskConfig(in, out, s) +} + +func autoConvert_v1alpha3_CPIGlobalConfig_To_v1alpha4_CPIGlobalConfig(in *CPIGlobalConfig, out *v1alpha4.CPIGlobalConfig, s conversion.Scope) error { + out.Insecure = in.Insecure + out.RoundTripperCount = in.RoundTripperCount + out.Username = in.Username + out.Password = in.Password + out.SecretName = in.SecretName + out.SecretNamespace = in.SecretNamespace + out.Port = in.Port + out.CAFile = in.CAFile + out.Thumbprint = in.Thumbprint + out.Datacenters = in.Datacenters + out.ServiceAccount = in.ServiceAccount + out.SecretsDirectory = in.SecretsDirectory + out.APIDisable = (*bool)(unsafe.Pointer(in.APIDisable)) + out.APIBindPort = in.APIBindPort + out.ClusterID = in.ClusterID + return nil +} + +// Convert_v1alpha3_CPIGlobalConfig_To_v1alpha4_CPIGlobalConfig is an autogenerated conversion function. +func Convert_v1alpha3_CPIGlobalConfig_To_v1alpha4_CPIGlobalConfig(in *CPIGlobalConfig, out *v1alpha4.CPIGlobalConfig, s conversion.Scope) error { + return autoConvert_v1alpha3_CPIGlobalConfig_To_v1alpha4_CPIGlobalConfig(in, out, s) +} + +func autoConvert_v1alpha4_CPIGlobalConfig_To_v1alpha3_CPIGlobalConfig(in *v1alpha4.CPIGlobalConfig, out *CPIGlobalConfig, s conversion.Scope) error { + out.Insecure = in.Insecure + out.RoundTripperCount = in.RoundTripperCount + out.Username = in.Username + out.Password = in.Password + out.SecretName = in.SecretName + out.SecretNamespace = in.SecretNamespace + out.Port = in.Port + out.CAFile = in.CAFile + out.Thumbprint = in.Thumbprint + out.Datacenters = in.Datacenters + out.ServiceAccount = in.ServiceAccount + out.SecretsDirectory = in.SecretsDirectory + out.APIDisable = (*bool)(unsafe.Pointer(in.APIDisable)) + out.APIBindPort = in.APIBindPort + out.ClusterID = in.ClusterID + return nil +} + +// Convert_v1alpha4_CPIGlobalConfig_To_v1alpha3_CPIGlobalConfig is an autogenerated conversion function. +func Convert_v1alpha4_CPIGlobalConfig_To_v1alpha3_CPIGlobalConfig(in *v1alpha4.CPIGlobalConfig, out *CPIGlobalConfig, s conversion.Scope) error { + return autoConvert_v1alpha4_CPIGlobalConfig_To_v1alpha3_CPIGlobalConfig(in, out, s) +} + +func autoConvert_v1alpha3_CPILabelConfig_To_v1alpha4_CPILabelConfig(in *CPILabelConfig, out *v1alpha4.CPILabelConfig, s conversion.Scope) error { + out.Zone = in.Zone + out.Region = in.Region + return nil +} + +// Convert_v1alpha3_CPILabelConfig_To_v1alpha4_CPILabelConfig is an autogenerated conversion function. +func Convert_v1alpha3_CPILabelConfig_To_v1alpha4_CPILabelConfig(in *CPILabelConfig, out *v1alpha4.CPILabelConfig, s conversion.Scope) error { + return autoConvert_v1alpha3_CPILabelConfig_To_v1alpha4_CPILabelConfig(in, out, s) +} + +func autoConvert_v1alpha4_CPILabelConfig_To_v1alpha3_CPILabelConfig(in *v1alpha4.CPILabelConfig, out *CPILabelConfig, s conversion.Scope) error { + out.Zone = in.Zone + out.Region = in.Region + return nil +} + +// Convert_v1alpha4_CPILabelConfig_To_v1alpha3_CPILabelConfig is an autogenerated conversion function. +func Convert_v1alpha4_CPILabelConfig_To_v1alpha3_CPILabelConfig(in *v1alpha4.CPILabelConfig, out *CPILabelConfig, s conversion.Scope) error { + return autoConvert_v1alpha4_CPILabelConfig_To_v1alpha3_CPILabelConfig(in, out, s) +} + +func autoConvert_v1alpha3_CPINetworkConfig_To_v1alpha4_CPINetworkConfig(in *CPINetworkConfig, out *v1alpha4.CPINetworkConfig, s conversion.Scope) error { + out.Name = in.Name + return nil +} + +// Convert_v1alpha3_CPINetworkConfig_To_v1alpha4_CPINetworkConfig is an autogenerated conversion function. +func Convert_v1alpha3_CPINetworkConfig_To_v1alpha4_CPINetworkConfig(in *CPINetworkConfig, out *v1alpha4.CPINetworkConfig, s conversion.Scope) error { + return autoConvert_v1alpha3_CPINetworkConfig_To_v1alpha4_CPINetworkConfig(in, out, s) +} + +func autoConvert_v1alpha4_CPINetworkConfig_To_v1alpha3_CPINetworkConfig(in *v1alpha4.CPINetworkConfig, out *CPINetworkConfig, s conversion.Scope) error { + out.Name = in.Name + return nil +} + +// Convert_v1alpha4_CPINetworkConfig_To_v1alpha3_CPINetworkConfig is an autogenerated conversion function. +func Convert_v1alpha4_CPINetworkConfig_To_v1alpha3_CPINetworkConfig(in *v1alpha4.CPINetworkConfig, out *CPINetworkConfig, s conversion.Scope) error { + return autoConvert_v1alpha4_CPINetworkConfig_To_v1alpha3_CPINetworkConfig(in, out, s) +} + +func autoConvert_v1alpha3_CPIProviderConfig_To_v1alpha4_CPIProviderConfig(in *CPIProviderConfig, out *v1alpha4.CPIProviderConfig, s conversion.Scope) error { + out.Cloud = (*v1alpha4.CPICloudConfig)(unsafe.Pointer(in.Cloud)) + out.Storage = (*v1alpha4.CPIStorageConfig)(unsafe.Pointer(in.Storage)) + return nil +} + +// Convert_v1alpha3_CPIProviderConfig_To_v1alpha4_CPIProviderConfig is an autogenerated conversion function. +func Convert_v1alpha3_CPIProviderConfig_To_v1alpha4_CPIProviderConfig(in *CPIProviderConfig, out *v1alpha4.CPIProviderConfig, s conversion.Scope) error { + return autoConvert_v1alpha3_CPIProviderConfig_To_v1alpha4_CPIProviderConfig(in, out, s) +} + +func autoConvert_v1alpha4_CPIProviderConfig_To_v1alpha3_CPIProviderConfig(in *v1alpha4.CPIProviderConfig, out *CPIProviderConfig, s conversion.Scope) error { + out.Cloud = (*CPICloudConfig)(unsafe.Pointer(in.Cloud)) + out.Storage = (*CPIStorageConfig)(unsafe.Pointer(in.Storage)) + return nil +} + +// Convert_v1alpha4_CPIProviderConfig_To_v1alpha3_CPIProviderConfig is an autogenerated conversion function. +func Convert_v1alpha4_CPIProviderConfig_To_v1alpha3_CPIProviderConfig(in *v1alpha4.CPIProviderConfig, out *CPIProviderConfig, s conversion.Scope) error { + return autoConvert_v1alpha4_CPIProviderConfig_To_v1alpha3_CPIProviderConfig(in, out, s) +} + +func autoConvert_v1alpha3_CPIStorageConfig_To_v1alpha4_CPIStorageConfig(in *CPIStorageConfig, out *v1alpha4.CPIStorageConfig, s conversion.Scope) error { + out.ControllerImage = in.ControllerImage + out.NodeDriverImage = in.NodeDriverImage + out.AttacherImage = in.AttacherImage + out.ProvisionerImage = in.ProvisionerImage + out.MetadataSyncerImage = in.MetadataSyncerImage + out.LivenessProbeImage = in.LivenessProbeImage + out.RegistrarImage = in.RegistrarImage + return nil +} + +// Convert_v1alpha3_CPIStorageConfig_To_v1alpha4_CPIStorageConfig is an autogenerated conversion function. +func Convert_v1alpha3_CPIStorageConfig_To_v1alpha4_CPIStorageConfig(in *CPIStorageConfig, out *v1alpha4.CPIStorageConfig, s conversion.Scope) error { + return autoConvert_v1alpha3_CPIStorageConfig_To_v1alpha4_CPIStorageConfig(in, out, s) +} + +func autoConvert_v1alpha4_CPIStorageConfig_To_v1alpha3_CPIStorageConfig(in *v1alpha4.CPIStorageConfig, out *CPIStorageConfig, s conversion.Scope) error { + out.ControllerImage = in.ControllerImage + out.NodeDriverImage = in.NodeDriverImage + out.AttacherImage = in.AttacherImage + out.ProvisionerImage = in.ProvisionerImage + out.MetadataSyncerImage = in.MetadataSyncerImage + out.LivenessProbeImage = in.LivenessProbeImage + out.RegistrarImage = in.RegistrarImage + return nil +} + +// Convert_v1alpha4_CPIStorageConfig_To_v1alpha3_CPIStorageConfig is an autogenerated conversion function. +func Convert_v1alpha4_CPIStorageConfig_To_v1alpha3_CPIStorageConfig(in *v1alpha4.CPIStorageConfig, out *CPIStorageConfig, s conversion.Scope) error { + return autoConvert_v1alpha4_CPIStorageConfig_To_v1alpha3_CPIStorageConfig(in, out, s) +} + +func autoConvert_v1alpha3_CPIVCenterConfig_To_v1alpha4_CPIVCenterConfig(in *CPIVCenterConfig, out *v1alpha4.CPIVCenterConfig, s conversion.Scope) error { + out.Username = in.Username + out.Password = in.Password + out.Port = in.Port + out.Datacenters = in.Datacenters + out.RoundTripperCount = in.RoundTripperCount + out.Thumbprint = in.Thumbprint + return nil +} + +// Convert_v1alpha3_CPIVCenterConfig_To_v1alpha4_CPIVCenterConfig is an autogenerated conversion function. +func Convert_v1alpha3_CPIVCenterConfig_To_v1alpha4_CPIVCenterConfig(in *CPIVCenterConfig, out *v1alpha4.CPIVCenterConfig, s conversion.Scope) error { + return autoConvert_v1alpha3_CPIVCenterConfig_To_v1alpha4_CPIVCenterConfig(in, out, s) +} + +func autoConvert_v1alpha4_CPIVCenterConfig_To_v1alpha3_CPIVCenterConfig(in *v1alpha4.CPIVCenterConfig, out *CPIVCenterConfig, s conversion.Scope) error { + out.Username = in.Username + out.Password = in.Password + out.Port = in.Port + out.Datacenters = in.Datacenters + out.RoundTripperCount = in.RoundTripperCount + out.Thumbprint = in.Thumbprint + return nil +} + +// Convert_v1alpha4_CPIVCenterConfig_To_v1alpha3_CPIVCenterConfig is an autogenerated conversion function. +func Convert_v1alpha4_CPIVCenterConfig_To_v1alpha3_CPIVCenterConfig(in *v1alpha4.CPIVCenterConfig, out *CPIVCenterConfig, s conversion.Scope) error { + return autoConvert_v1alpha4_CPIVCenterConfig_To_v1alpha3_CPIVCenterConfig(in, out, s) +} + +func autoConvert_v1alpha3_CPIWorkspaceConfig_To_v1alpha4_CPIWorkspaceConfig(in *CPIWorkspaceConfig, out *v1alpha4.CPIWorkspaceConfig, s conversion.Scope) error { + out.Server = in.Server + out.Datacenter = in.Datacenter + out.Folder = in.Folder + out.Datastore = in.Datastore + out.ResourcePool = in.ResourcePool + return nil +} + +// Convert_v1alpha3_CPIWorkspaceConfig_To_v1alpha4_CPIWorkspaceConfig is an autogenerated conversion function. +func Convert_v1alpha3_CPIWorkspaceConfig_To_v1alpha4_CPIWorkspaceConfig(in *CPIWorkspaceConfig, out *v1alpha4.CPIWorkspaceConfig, s conversion.Scope) error { + return autoConvert_v1alpha3_CPIWorkspaceConfig_To_v1alpha4_CPIWorkspaceConfig(in, out, s) +} + +func autoConvert_v1alpha4_CPIWorkspaceConfig_To_v1alpha3_CPIWorkspaceConfig(in *v1alpha4.CPIWorkspaceConfig, out *CPIWorkspaceConfig, s conversion.Scope) error { + out.Server = in.Server + out.Datacenter = in.Datacenter + out.Folder = in.Folder + out.Datastore = in.Datastore + out.ResourcePool = in.ResourcePool + return nil +} + +// Convert_v1alpha4_CPIWorkspaceConfig_To_v1alpha3_CPIWorkspaceConfig is an autogenerated conversion function. +func Convert_v1alpha4_CPIWorkspaceConfig_To_v1alpha3_CPIWorkspaceConfig(in *v1alpha4.CPIWorkspaceConfig, out *CPIWorkspaceConfig, s conversion.Scope) error { + return autoConvert_v1alpha4_CPIWorkspaceConfig_To_v1alpha3_CPIWorkspaceConfig(in, out, s) +} + +func autoConvert_v1alpha3_HAProxyLoadBalancer_To_v1alpha4_HAProxyLoadBalancer(in *HAProxyLoadBalancer, out *v1alpha4.HAProxyLoadBalancer, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha3_HAProxyLoadBalancerSpec_To_v1alpha4_HAProxyLoadBalancerSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1alpha3_HAProxyLoadBalancerStatus_To_v1alpha4_HAProxyLoadBalancerStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha3_HAProxyLoadBalancer_To_v1alpha4_HAProxyLoadBalancer is an autogenerated conversion function. +func Convert_v1alpha3_HAProxyLoadBalancer_To_v1alpha4_HAProxyLoadBalancer(in *HAProxyLoadBalancer, out *v1alpha4.HAProxyLoadBalancer, s conversion.Scope) error { + return autoConvert_v1alpha3_HAProxyLoadBalancer_To_v1alpha4_HAProxyLoadBalancer(in, out, s) +} + +func autoConvert_v1alpha4_HAProxyLoadBalancer_To_v1alpha3_HAProxyLoadBalancer(in *v1alpha4.HAProxyLoadBalancer, out *HAProxyLoadBalancer, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha4_HAProxyLoadBalancerSpec_To_v1alpha3_HAProxyLoadBalancerSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1alpha4_HAProxyLoadBalancerStatus_To_v1alpha3_HAProxyLoadBalancerStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha4_HAProxyLoadBalancer_To_v1alpha3_HAProxyLoadBalancer is an autogenerated conversion function. +func Convert_v1alpha4_HAProxyLoadBalancer_To_v1alpha3_HAProxyLoadBalancer(in *v1alpha4.HAProxyLoadBalancer, out *HAProxyLoadBalancer, s conversion.Scope) error { + return autoConvert_v1alpha4_HAProxyLoadBalancer_To_v1alpha3_HAProxyLoadBalancer(in, out, s) +} + +func autoConvert_v1alpha3_HAProxyLoadBalancerList_To_v1alpha4_HAProxyLoadBalancerList(in *HAProxyLoadBalancerList, out *v1alpha4.HAProxyLoadBalancerList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]v1alpha4.HAProxyLoadBalancer)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_v1alpha3_HAProxyLoadBalancerList_To_v1alpha4_HAProxyLoadBalancerList is an autogenerated conversion function. +func Convert_v1alpha3_HAProxyLoadBalancerList_To_v1alpha4_HAProxyLoadBalancerList(in *HAProxyLoadBalancerList, out *v1alpha4.HAProxyLoadBalancerList, s conversion.Scope) error { + return autoConvert_v1alpha3_HAProxyLoadBalancerList_To_v1alpha4_HAProxyLoadBalancerList(in, out, s) +} + +func autoConvert_v1alpha4_HAProxyLoadBalancerList_To_v1alpha3_HAProxyLoadBalancerList(in *v1alpha4.HAProxyLoadBalancerList, out *HAProxyLoadBalancerList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]HAProxyLoadBalancer)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_v1alpha4_HAProxyLoadBalancerList_To_v1alpha3_HAProxyLoadBalancerList is an autogenerated conversion function. +func Convert_v1alpha4_HAProxyLoadBalancerList_To_v1alpha3_HAProxyLoadBalancerList(in *v1alpha4.HAProxyLoadBalancerList, out *HAProxyLoadBalancerList, s conversion.Scope) error { + return autoConvert_v1alpha4_HAProxyLoadBalancerList_To_v1alpha3_HAProxyLoadBalancerList(in, out, s) +} + +func autoConvert_v1alpha3_HAProxyLoadBalancerSpec_To_v1alpha4_HAProxyLoadBalancerSpec(in *HAProxyLoadBalancerSpec, out *v1alpha4.HAProxyLoadBalancerSpec, s conversion.Scope) error { + if err := Convert_v1alpha3_VirtualMachineCloneSpec_To_v1alpha4_VirtualMachineCloneSpec(&in.VirtualMachineConfiguration, &out.VirtualMachineConfiguration, s); err != nil { + return err + } + out.User = (*v1alpha4.SSHUser)(unsafe.Pointer(in.User)) + return nil +} + +// Convert_v1alpha3_HAProxyLoadBalancerSpec_To_v1alpha4_HAProxyLoadBalancerSpec is an autogenerated conversion function. +func Convert_v1alpha3_HAProxyLoadBalancerSpec_To_v1alpha4_HAProxyLoadBalancerSpec(in *HAProxyLoadBalancerSpec, out *v1alpha4.HAProxyLoadBalancerSpec, s conversion.Scope) error { + return autoConvert_v1alpha3_HAProxyLoadBalancerSpec_To_v1alpha4_HAProxyLoadBalancerSpec(in, out, s) +} + +func autoConvert_v1alpha4_HAProxyLoadBalancerSpec_To_v1alpha3_HAProxyLoadBalancerSpec(in *v1alpha4.HAProxyLoadBalancerSpec, out *HAProxyLoadBalancerSpec, s conversion.Scope) error { + if err := Convert_v1alpha4_VirtualMachineCloneSpec_To_v1alpha3_VirtualMachineCloneSpec(&in.VirtualMachineConfiguration, &out.VirtualMachineConfiguration, s); err != nil { + return err + } + out.User = (*SSHUser)(unsafe.Pointer(in.User)) + return nil +} + +// Convert_v1alpha4_HAProxyLoadBalancerSpec_To_v1alpha3_HAProxyLoadBalancerSpec is an autogenerated conversion function. +func Convert_v1alpha4_HAProxyLoadBalancerSpec_To_v1alpha3_HAProxyLoadBalancerSpec(in *v1alpha4.HAProxyLoadBalancerSpec, out *HAProxyLoadBalancerSpec, s conversion.Scope) error { + return autoConvert_v1alpha4_HAProxyLoadBalancerSpec_To_v1alpha3_HAProxyLoadBalancerSpec(in, out, s) +} + +func autoConvert_v1alpha3_HAProxyLoadBalancerStatus_To_v1alpha4_HAProxyLoadBalancerStatus(in *HAProxyLoadBalancerStatus, out *v1alpha4.HAProxyLoadBalancerStatus, s conversion.Scope) error { + out.Ready = in.Ready + out.Address = in.Address + return nil +} + +// Convert_v1alpha3_HAProxyLoadBalancerStatus_To_v1alpha4_HAProxyLoadBalancerStatus is an autogenerated conversion function. +func Convert_v1alpha3_HAProxyLoadBalancerStatus_To_v1alpha4_HAProxyLoadBalancerStatus(in *HAProxyLoadBalancerStatus, out *v1alpha4.HAProxyLoadBalancerStatus, s conversion.Scope) error { + return autoConvert_v1alpha3_HAProxyLoadBalancerStatus_To_v1alpha4_HAProxyLoadBalancerStatus(in, out, s) +} + +func autoConvert_v1alpha4_HAProxyLoadBalancerStatus_To_v1alpha3_HAProxyLoadBalancerStatus(in *v1alpha4.HAProxyLoadBalancerStatus, out *HAProxyLoadBalancerStatus, s conversion.Scope) error { + out.Ready = in.Ready + out.Address = in.Address + return nil +} + +// Convert_v1alpha4_HAProxyLoadBalancerStatus_To_v1alpha3_HAProxyLoadBalancerStatus is an autogenerated conversion function. +func Convert_v1alpha4_HAProxyLoadBalancerStatus_To_v1alpha3_HAProxyLoadBalancerStatus(in *v1alpha4.HAProxyLoadBalancerStatus, out *HAProxyLoadBalancerStatus, s conversion.Scope) error { + return autoConvert_v1alpha4_HAProxyLoadBalancerStatus_To_v1alpha3_HAProxyLoadBalancerStatus(in, out, s) +} + +func autoConvert_v1alpha3_NetworkDeviceSpec_To_v1alpha4_NetworkDeviceSpec(in *NetworkDeviceSpec, out *v1alpha4.NetworkDeviceSpec, s conversion.Scope) error { + out.NetworkName = in.NetworkName + out.DeviceName = in.DeviceName + out.DHCP4 = in.DHCP4 + out.DHCP6 = in.DHCP6 + out.Gateway4 = in.Gateway4 + out.Gateway6 = in.Gateway6 + out.IPAddrs = *(*[]string)(unsafe.Pointer(&in.IPAddrs)) + out.MTU = (*int64)(unsafe.Pointer(in.MTU)) + out.MACAddr = in.MACAddr + out.Nameservers = *(*[]string)(unsafe.Pointer(&in.Nameservers)) + out.Routes = *(*[]v1alpha4.NetworkRouteSpec)(unsafe.Pointer(&in.Routes)) + out.SearchDomains = *(*[]string)(unsafe.Pointer(&in.SearchDomains)) + return nil +} + +// Convert_v1alpha3_NetworkDeviceSpec_To_v1alpha4_NetworkDeviceSpec is an autogenerated conversion function. +func Convert_v1alpha3_NetworkDeviceSpec_To_v1alpha4_NetworkDeviceSpec(in *NetworkDeviceSpec, out *v1alpha4.NetworkDeviceSpec, s conversion.Scope) error { + return autoConvert_v1alpha3_NetworkDeviceSpec_To_v1alpha4_NetworkDeviceSpec(in, out, s) +} + +func autoConvert_v1alpha4_NetworkDeviceSpec_To_v1alpha3_NetworkDeviceSpec(in *v1alpha4.NetworkDeviceSpec, out *NetworkDeviceSpec, s conversion.Scope) error { + out.NetworkName = in.NetworkName + out.DeviceName = in.DeviceName + out.DHCP4 = in.DHCP4 + out.DHCP6 = in.DHCP6 + out.Gateway4 = in.Gateway4 + out.Gateway6 = in.Gateway6 + out.IPAddrs = *(*[]string)(unsafe.Pointer(&in.IPAddrs)) + out.MTU = (*int64)(unsafe.Pointer(in.MTU)) + out.MACAddr = in.MACAddr + out.Nameservers = *(*[]string)(unsafe.Pointer(&in.Nameservers)) + out.Routes = *(*[]NetworkRouteSpec)(unsafe.Pointer(&in.Routes)) + out.SearchDomains = *(*[]string)(unsafe.Pointer(&in.SearchDomains)) + return nil +} + +// Convert_v1alpha4_NetworkDeviceSpec_To_v1alpha3_NetworkDeviceSpec is an autogenerated conversion function. +func Convert_v1alpha4_NetworkDeviceSpec_To_v1alpha3_NetworkDeviceSpec(in *v1alpha4.NetworkDeviceSpec, out *NetworkDeviceSpec, s conversion.Scope) error { + return autoConvert_v1alpha4_NetworkDeviceSpec_To_v1alpha3_NetworkDeviceSpec(in, out, s) +} + +func autoConvert_v1alpha3_NetworkRouteSpec_To_v1alpha4_NetworkRouteSpec(in *NetworkRouteSpec, out *v1alpha4.NetworkRouteSpec, s conversion.Scope) error { + out.To = in.To + out.Via = in.Via + out.Metric = in.Metric + return nil +} + +// Convert_v1alpha3_NetworkRouteSpec_To_v1alpha4_NetworkRouteSpec is an autogenerated conversion function. +func Convert_v1alpha3_NetworkRouteSpec_To_v1alpha4_NetworkRouteSpec(in *NetworkRouteSpec, out *v1alpha4.NetworkRouteSpec, s conversion.Scope) error { + return autoConvert_v1alpha3_NetworkRouteSpec_To_v1alpha4_NetworkRouteSpec(in, out, s) +} + +func autoConvert_v1alpha4_NetworkRouteSpec_To_v1alpha3_NetworkRouteSpec(in *v1alpha4.NetworkRouteSpec, out *NetworkRouteSpec, s conversion.Scope) error { + out.To = in.To + out.Via = in.Via + out.Metric = in.Metric + return nil +} + +// Convert_v1alpha4_NetworkRouteSpec_To_v1alpha3_NetworkRouteSpec is an autogenerated conversion function. +func Convert_v1alpha4_NetworkRouteSpec_To_v1alpha3_NetworkRouteSpec(in *v1alpha4.NetworkRouteSpec, out *NetworkRouteSpec, s conversion.Scope) error { + return autoConvert_v1alpha4_NetworkRouteSpec_To_v1alpha3_NetworkRouteSpec(in, out, s) +} + +func autoConvert_v1alpha3_NetworkSpec_To_v1alpha4_NetworkSpec(in *NetworkSpec, out *v1alpha4.NetworkSpec, s conversion.Scope) error { + out.Devices = *(*[]v1alpha4.NetworkDeviceSpec)(unsafe.Pointer(&in.Devices)) + out.Routes = *(*[]v1alpha4.NetworkRouteSpec)(unsafe.Pointer(&in.Routes)) + out.PreferredAPIServerCIDR = in.PreferredAPIServerCIDR + return nil +} + +// Convert_v1alpha3_NetworkSpec_To_v1alpha4_NetworkSpec is an autogenerated conversion function. +func Convert_v1alpha3_NetworkSpec_To_v1alpha4_NetworkSpec(in *NetworkSpec, out *v1alpha4.NetworkSpec, s conversion.Scope) error { + return autoConvert_v1alpha3_NetworkSpec_To_v1alpha4_NetworkSpec(in, out, s) +} + +func autoConvert_v1alpha4_NetworkSpec_To_v1alpha3_NetworkSpec(in *v1alpha4.NetworkSpec, out *NetworkSpec, s conversion.Scope) error { + out.Devices = *(*[]NetworkDeviceSpec)(unsafe.Pointer(&in.Devices)) + out.Routes = *(*[]NetworkRouteSpec)(unsafe.Pointer(&in.Routes)) + out.PreferredAPIServerCIDR = in.PreferredAPIServerCIDR + return nil +} + +// Convert_v1alpha4_NetworkSpec_To_v1alpha3_NetworkSpec is an autogenerated conversion function. +func Convert_v1alpha4_NetworkSpec_To_v1alpha3_NetworkSpec(in *v1alpha4.NetworkSpec, out *NetworkSpec, s conversion.Scope) error { + return autoConvert_v1alpha4_NetworkSpec_To_v1alpha3_NetworkSpec(in, out, s) +} + +func autoConvert_v1alpha3_NetworkStatus_To_v1alpha4_NetworkStatus(in *NetworkStatus, out *v1alpha4.NetworkStatus, s conversion.Scope) error { + out.Connected = in.Connected + out.IPAddrs = *(*[]string)(unsafe.Pointer(&in.IPAddrs)) + out.MACAddr = in.MACAddr + out.NetworkName = in.NetworkName + return nil +} + +// Convert_v1alpha3_NetworkStatus_To_v1alpha4_NetworkStatus is an autogenerated conversion function. +func Convert_v1alpha3_NetworkStatus_To_v1alpha4_NetworkStatus(in *NetworkStatus, out *v1alpha4.NetworkStatus, s conversion.Scope) error { + return autoConvert_v1alpha3_NetworkStatus_To_v1alpha4_NetworkStatus(in, out, s) +} + +func autoConvert_v1alpha4_NetworkStatus_To_v1alpha3_NetworkStatus(in *v1alpha4.NetworkStatus, out *NetworkStatus, s conversion.Scope) error { + out.Connected = in.Connected + out.IPAddrs = *(*[]string)(unsafe.Pointer(&in.IPAddrs)) + out.MACAddr = in.MACAddr + out.NetworkName = in.NetworkName + return nil +} + +// Convert_v1alpha4_NetworkStatus_To_v1alpha3_NetworkStatus is an autogenerated conversion function. +func Convert_v1alpha4_NetworkStatus_To_v1alpha3_NetworkStatus(in *v1alpha4.NetworkStatus, out *NetworkStatus, s conversion.Scope) error { + return autoConvert_v1alpha4_NetworkStatus_To_v1alpha3_NetworkStatus(in, out, s) +} + +func autoConvert_v1alpha3_SSHUser_To_v1alpha4_SSHUser(in *SSHUser, out *v1alpha4.SSHUser, s conversion.Scope) error { + out.Name = in.Name + out.AuthorizedKeys = *(*[]string)(unsafe.Pointer(&in.AuthorizedKeys)) + return nil +} + +// Convert_v1alpha3_SSHUser_To_v1alpha4_SSHUser is an autogenerated conversion function. +func Convert_v1alpha3_SSHUser_To_v1alpha4_SSHUser(in *SSHUser, out *v1alpha4.SSHUser, s conversion.Scope) error { + return autoConvert_v1alpha3_SSHUser_To_v1alpha4_SSHUser(in, out, s) +} + +func autoConvert_v1alpha4_SSHUser_To_v1alpha3_SSHUser(in *v1alpha4.SSHUser, out *SSHUser, s conversion.Scope) error { + out.Name = in.Name + out.AuthorizedKeys = *(*[]string)(unsafe.Pointer(&in.AuthorizedKeys)) + return nil +} + +// Convert_v1alpha4_SSHUser_To_v1alpha3_SSHUser is an autogenerated conversion function. +func Convert_v1alpha4_SSHUser_To_v1alpha3_SSHUser(in *v1alpha4.SSHUser, out *SSHUser, s conversion.Scope) error { + return autoConvert_v1alpha4_SSHUser_To_v1alpha3_SSHUser(in, out, s) +} + +func autoConvert_v1alpha3_UnmarshalINIOptions_To_v1alpha4_UnmarshalINIOptions(in *UnmarshalINIOptions, out *v1alpha4.UnmarshalINIOptions, s conversion.Scope) error { + out.WarnAsFatal = in.WarnAsFatal + return nil +} + +// Convert_v1alpha3_UnmarshalINIOptions_To_v1alpha4_UnmarshalINIOptions is an autogenerated conversion function. +func Convert_v1alpha3_UnmarshalINIOptions_To_v1alpha4_UnmarshalINIOptions(in *UnmarshalINIOptions, out *v1alpha4.UnmarshalINIOptions, s conversion.Scope) error { + return autoConvert_v1alpha3_UnmarshalINIOptions_To_v1alpha4_UnmarshalINIOptions(in, out, s) +} + +func autoConvert_v1alpha4_UnmarshalINIOptions_To_v1alpha3_UnmarshalINIOptions(in *v1alpha4.UnmarshalINIOptions, out *UnmarshalINIOptions, s conversion.Scope) error { + out.WarnAsFatal = in.WarnAsFatal + return nil +} + +// Convert_v1alpha4_UnmarshalINIOptions_To_v1alpha3_UnmarshalINIOptions is an autogenerated conversion function. +func Convert_v1alpha4_UnmarshalINIOptions_To_v1alpha3_UnmarshalINIOptions(in *v1alpha4.UnmarshalINIOptions, out *UnmarshalINIOptions, s conversion.Scope) error { + return autoConvert_v1alpha4_UnmarshalINIOptions_To_v1alpha3_UnmarshalINIOptions(in, out, s) +} + +func autoConvert_v1alpha3_VSphereCluster_To_v1alpha4_VSphereCluster(in *VSphereCluster, out *v1alpha4.VSphereCluster, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha3_VSphereClusterSpec_To_v1alpha4_VSphereClusterSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1alpha3_VSphereClusterStatus_To_v1alpha4_VSphereClusterStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha3_VSphereCluster_To_v1alpha4_VSphereCluster is an autogenerated conversion function. +func Convert_v1alpha3_VSphereCluster_To_v1alpha4_VSphereCluster(in *VSphereCluster, out *v1alpha4.VSphereCluster, s conversion.Scope) error { + return autoConvert_v1alpha3_VSphereCluster_To_v1alpha4_VSphereCluster(in, out, s) +} + +func autoConvert_v1alpha4_VSphereCluster_To_v1alpha3_VSphereCluster(in *v1alpha4.VSphereCluster, out *VSphereCluster, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha4_VSphereClusterSpec_To_v1alpha3_VSphereClusterSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1alpha4_VSphereClusterStatus_To_v1alpha3_VSphereClusterStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha4_VSphereCluster_To_v1alpha3_VSphereCluster is an autogenerated conversion function. +func Convert_v1alpha4_VSphereCluster_To_v1alpha3_VSphereCluster(in *v1alpha4.VSphereCluster, out *VSphereCluster, s conversion.Scope) error { + return autoConvert_v1alpha4_VSphereCluster_To_v1alpha3_VSphereCluster(in, out, s) +} + +func autoConvert_v1alpha3_VSphereClusterList_To_v1alpha4_VSphereClusterList(in *VSphereClusterList, out *v1alpha4.VSphereClusterList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]v1alpha4.VSphereCluster)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_v1alpha3_VSphereClusterList_To_v1alpha4_VSphereClusterList is an autogenerated conversion function. +func Convert_v1alpha3_VSphereClusterList_To_v1alpha4_VSphereClusterList(in *VSphereClusterList, out *v1alpha4.VSphereClusterList, s conversion.Scope) error { + return autoConvert_v1alpha3_VSphereClusterList_To_v1alpha4_VSphereClusterList(in, out, s) +} + +func autoConvert_v1alpha4_VSphereClusterList_To_v1alpha3_VSphereClusterList(in *v1alpha4.VSphereClusterList, out *VSphereClusterList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]VSphereCluster)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_v1alpha4_VSphereClusterList_To_v1alpha3_VSphereClusterList is an autogenerated conversion function. +func Convert_v1alpha4_VSphereClusterList_To_v1alpha3_VSphereClusterList(in *v1alpha4.VSphereClusterList, out *VSphereClusterList, s conversion.Scope) error { + return autoConvert_v1alpha4_VSphereClusterList_To_v1alpha3_VSphereClusterList(in, out, s) +} + +func autoConvert_v1alpha3_VSphereClusterSpec_To_v1alpha4_VSphereClusterSpec(in *VSphereClusterSpec, out *v1alpha4.VSphereClusterSpec, s conversion.Scope) error { + out.Server = in.Server + out.Insecure = (*bool)(unsafe.Pointer(in.Insecure)) + out.Thumbprint = in.Thumbprint + if err := Convert_v1alpha3_CPIConfig_To_v1alpha4_CPIConfig(&in.CloudProviderConfiguration, &out.CloudProviderConfiguration, s); err != nil { + return err + } + if err := Convert_v1alpha3_APIEndpoint_To_v1alpha4_APIEndpoint(&in.ControlPlaneEndpoint, &out.ControlPlaneEndpoint, s); err != nil { + return err + } + out.LoadBalancerRef = (*v1.ObjectReference)(unsafe.Pointer(in.LoadBalancerRef)) + return nil +} + +// Convert_v1alpha3_VSphereClusterSpec_To_v1alpha4_VSphereClusterSpec is an autogenerated conversion function. +func Convert_v1alpha3_VSphereClusterSpec_To_v1alpha4_VSphereClusterSpec(in *VSphereClusterSpec, out *v1alpha4.VSphereClusterSpec, s conversion.Scope) error { + return autoConvert_v1alpha3_VSphereClusterSpec_To_v1alpha4_VSphereClusterSpec(in, out, s) +} + +func autoConvert_v1alpha4_VSphereClusterSpec_To_v1alpha3_VSphereClusterSpec(in *v1alpha4.VSphereClusterSpec, out *VSphereClusterSpec, s conversion.Scope) error { + out.Server = in.Server + out.Insecure = (*bool)(unsafe.Pointer(in.Insecure)) + out.Thumbprint = in.Thumbprint + if err := Convert_v1alpha4_CPIConfig_To_v1alpha3_CPIConfig(&in.CloudProviderConfiguration, &out.CloudProviderConfiguration, s); err != nil { + return err + } + if err := Convert_v1alpha4_APIEndpoint_To_v1alpha3_APIEndpoint(&in.ControlPlaneEndpoint, &out.ControlPlaneEndpoint, s); err != nil { + return err + } + out.LoadBalancerRef = (*v1.ObjectReference)(unsafe.Pointer(in.LoadBalancerRef)) + return nil +} + +// Convert_v1alpha4_VSphereClusterSpec_To_v1alpha3_VSphereClusterSpec is an autogenerated conversion function. +func Convert_v1alpha4_VSphereClusterSpec_To_v1alpha3_VSphereClusterSpec(in *v1alpha4.VSphereClusterSpec, out *VSphereClusterSpec, s conversion.Scope) error { + return autoConvert_v1alpha4_VSphereClusterSpec_To_v1alpha3_VSphereClusterSpec(in, out, s) +} + +func autoConvert_v1alpha3_VSphereClusterStatus_To_v1alpha4_VSphereClusterStatus(in *VSphereClusterStatus, out *v1alpha4.VSphereClusterStatus, s conversion.Scope) error { + out.Ready = in.Ready + out.Conditions = *(*apiv1alpha3.Conditions)(unsafe.Pointer(&in.Conditions)) + return nil +} + +// Convert_v1alpha3_VSphereClusterStatus_To_v1alpha4_VSphereClusterStatus is an autogenerated conversion function. +func Convert_v1alpha3_VSphereClusterStatus_To_v1alpha4_VSphereClusterStatus(in *VSphereClusterStatus, out *v1alpha4.VSphereClusterStatus, s conversion.Scope) error { + return autoConvert_v1alpha3_VSphereClusterStatus_To_v1alpha4_VSphereClusterStatus(in, out, s) +} + +func autoConvert_v1alpha4_VSphereClusterStatus_To_v1alpha3_VSphereClusterStatus(in *v1alpha4.VSphereClusterStatus, out *VSphereClusterStatus, s conversion.Scope) error { + out.Ready = in.Ready + out.Conditions = *(*apiv1alpha3.Conditions)(unsafe.Pointer(&in.Conditions)) + return nil +} + +// Convert_v1alpha4_VSphereClusterStatus_To_v1alpha3_VSphereClusterStatus is an autogenerated conversion function. +func Convert_v1alpha4_VSphereClusterStatus_To_v1alpha3_VSphereClusterStatus(in *v1alpha4.VSphereClusterStatus, out *VSphereClusterStatus, s conversion.Scope) error { + return autoConvert_v1alpha4_VSphereClusterStatus_To_v1alpha3_VSphereClusterStatus(in, out, s) +} + +func autoConvert_v1alpha3_VSphereMachine_To_v1alpha4_VSphereMachine(in *VSphereMachine, out *v1alpha4.VSphereMachine, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha3_VSphereMachineSpec_To_v1alpha4_VSphereMachineSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1alpha3_VSphereMachineStatus_To_v1alpha4_VSphereMachineStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha3_VSphereMachine_To_v1alpha4_VSphereMachine is an autogenerated conversion function. +func Convert_v1alpha3_VSphereMachine_To_v1alpha4_VSphereMachine(in *VSphereMachine, out *v1alpha4.VSphereMachine, s conversion.Scope) error { + return autoConvert_v1alpha3_VSphereMachine_To_v1alpha4_VSphereMachine(in, out, s) +} + +func autoConvert_v1alpha4_VSphereMachine_To_v1alpha3_VSphereMachine(in *v1alpha4.VSphereMachine, out *VSphereMachine, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha4_VSphereMachineSpec_To_v1alpha3_VSphereMachineSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1alpha4_VSphereMachineStatus_To_v1alpha3_VSphereMachineStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha4_VSphereMachine_To_v1alpha3_VSphereMachine is an autogenerated conversion function. +func Convert_v1alpha4_VSphereMachine_To_v1alpha3_VSphereMachine(in *v1alpha4.VSphereMachine, out *VSphereMachine, s conversion.Scope) error { + return autoConvert_v1alpha4_VSphereMachine_To_v1alpha3_VSphereMachine(in, out, s) +} + +func autoConvert_v1alpha3_VSphereMachineList_To_v1alpha4_VSphereMachineList(in *VSphereMachineList, out *v1alpha4.VSphereMachineList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]v1alpha4.VSphereMachine)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_v1alpha3_VSphereMachineList_To_v1alpha4_VSphereMachineList is an autogenerated conversion function. +func Convert_v1alpha3_VSphereMachineList_To_v1alpha4_VSphereMachineList(in *VSphereMachineList, out *v1alpha4.VSphereMachineList, s conversion.Scope) error { + return autoConvert_v1alpha3_VSphereMachineList_To_v1alpha4_VSphereMachineList(in, out, s) +} + +func autoConvert_v1alpha4_VSphereMachineList_To_v1alpha3_VSphereMachineList(in *v1alpha4.VSphereMachineList, out *VSphereMachineList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]VSphereMachine)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_v1alpha4_VSphereMachineList_To_v1alpha3_VSphereMachineList is an autogenerated conversion function. +func Convert_v1alpha4_VSphereMachineList_To_v1alpha3_VSphereMachineList(in *v1alpha4.VSphereMachineList, out *VSphereMachineList, s conversion.Scope) error { + return autoConvert_v1alpha4_VSphereMachineList_To_v1alpha3_VSphereMachineList(in, out, s) +} + +func autoConvert_v1alpha3_VSphereMachineSpec_To_v1alpha4_VSphereMachineSpec(in *VSphereMachineSpec, out *v1alpha4.VSphereMachineSpec, s conversion.Scope) error { + if err := Convert_v1alpha3_VirtualMachineCloneSpec_To_v1alpha4_VirtualMachineCloneSpec(&in.VirtualMachineCloneSpec, &out.VirtualMachineCloneSpec, s); err != nil { + return err + } + out.ProviderID = (*string)(unsafe.Pointer(in.ProviderID)) + return nil +} + +// Convert_v1alpha3_VSphereMachineSpec_To_v1alpha4_VSphereMachineSpec is an autogenerated conversion function. +func Convert_v1alpha3_VSphereMachineSpec_To_v1alpha4_VSphereMachineSpec(in *VSphereMachineSpec, out *v1alpha4.VSphereMachineSpec, s conversion.Scope) error { + return autoConvert_v1alpha3_VSphereMachineSpec_To_v1alpha4_VSphereMachineSpec(in, out, s) +} + +func autoConvert_v1alpha4_VSphereMachineSpec_To_v1alpha3_VSphereMachineSpec(in *v1alpha4.VSphereMachineSpec, out *VSphereMachineSpec, s conversion.Scope) error { + if err := Convert_v1alpha4_VirtualMachineCloneSpec_To_v1alpha3_VirtualMachineCloneSpec(&in.VirtualMachineCloneSpec, &out.VirtualMachineCloneSpec, s); err != nil { + return err + } + out.ProviderID = (*string)(unsafe.Pointer(in.ProviderID)) + return nil +} + +// Convert_v1alpha4_VSphereMachineSpec_To_v1alpha3_VSphereMachineSpec is an autogenerated conversion function. +func Convert_v1alpha4_VSphereMachineSpec_To_v1alpha3_VSphereMachineSpec(in *v1alpha4.VSphereMachineSpec, out *VSphereMachineSpec, s conversion.Scope) error { + return autoConvert_v1alpha4_VSphereMachineSpec_To_v1alpha3_VSphereMachineSpec(in, out, s) +} + +func autoConvert_v1alpha3_VSphereMachineStatus_To_v1alpha4_VSphereMachineStatus(in *VSphereMachineStatus, out *v1alpha4.VSphereMachineStatus, s conversion.Scope) error { + out.Ready = in.Ready + out.Addresses = *(*[]apiv1alpha3.MachineAddress)(unsafe.Pointer(&in.Addresses)) + out.Network = *(*[]v1alpha4.NetworkStatus)(unsafe.Pointer(&in.Network)) + out.FailureReason = (*errors.MachineStatusError)(unsafe.Pointer(in.FailureReason)) + out.FailureMessage = (*string)(unsafe.Pointer(in.FailureMessage)) + out.Conditions = *(*apiv1alpha3.Conditions)(unsafe.Pointer(&in.Conditions)) + return nil +} + +// Convert_v1alpha3_VSphereMachineStatus_To_v1alpha4_VSphereMachineStatus is an autogenerated conversion function. +func Convert_v1alpha3_VSphereMachineStatus_To_v1alpha4_VSphereMachineStatus(in *VSphereMachineStatus, out *v1alpha4.VSphereMachineStatus, s conversion.Scope) error { + return autoConvert_v1alpha3_VSphereMachineStatus_To_v1alpha4_VSphereMachineStatus(in, out, s) +} + +func autoConvert_v1alpha4_VSphereMachineStatus_To_v1alpha3_VSphereMachineStatus(in *v1alpha4.VSphereMachineStatus, out *VSphereMachineStatus, s conversion.Scope) error { + out.Ready = in.Ready + out.Addresses = *(*[]apiv1alpha3.MachineAddress)(unsafe.Pointer(&in.Addresses)) + out.Network = *(*[]NetworkStatus)(unsafe.Pointer(&in.Network)) + out.FailureReason = (*errors.MachineStatusError)(unsafe.Pointer(in.FailureReason)) + out.FailureMessage = (*string)(unsafe.Pointer(in.FailureMessage)) + out.Conditions = *(*apiv1alpha3.Conditions)(unsafe.Pointer(&in.Conditions)) + return nil +} + +// Convert_v1alpha4_VSphereMachineStatus_To_v1alpha3_VSphereMachineStatus is an autogenerated conversion function. +func Convert_v1alpha4_VSphereMachineStatus_To_v1alpha3_VSphereMachineStatus(in *v1alpha4.VSphereMachineStatus, out *VSphereMachineStatus, s conversion.Scope) error { + return autoConvert_v1alpha4_VSphereMachineStatus_To_v1alpha3_VSphereMachineStatus(in, out, s) +} + +func autoConvert_v1alpha3_VSphereMachineTemplate_To_v1alpha4_VSphereMachineTemplate(in *VSphereMachineTemplate, out *v1alpha4.VSphereMachineTemplate, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha3_VSphereMachineTemplateSpec_To_v1alpha4_VSphereMachineTemplateSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha3_VSphereMachineTemplate_To_v1alpha4_VSphereMachineTemplate is an autogenerated conversion function. +func Convert_v1alpha3_VSphereMachineTemplate_To_v1alpha4_VSphereMachineTemplate(in *VSphereMachineTemplate, out *v1alpha4.VSphereMachineTemplate, s conversion.Scope) error { + return autoConvert_v1alpha3_VSphereMachineTemplate_To_v1alpha4_VSphereMachineTemplate(in, out, s) +} + +func autoConvert_v1alpha4_VSphereMachineTemplate_To_v1alpha3_VSphereMachineTemplate(in *v1alpha4.VSphereMachineTemplate, out *VSphereMachineTemplate, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha4_VSphereMachineTemplateSpec_To_v1alpha3_VSphereMachineTemplateSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha4_VSphereMachineTemplate_To_v1alpha3_VSphereMachineTemplate is an autogenerated conversion function. +func Convert_v1alpha4_VSphereMachineTemplate_To_v1alpha3_VSphereMachineTemplate(in *v1alpha4.VSphereMachineTemplate, out *VSphereMachineTemplate, s conversion.Scope) error { + return autoConvert_v1alpha4_VSphereMachineTemplate_To_v1alpha3_VSphereMachineTemplate(in, out, s) +} + +func autoConvert_v1alpha3_VSphereMachineTemplateList_To_v1alpha4_VSphereMachineTemplateList(in *VSphereMachineTemplateList, out *v1alpha4.VSphereMachineTemplateList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]v1alpha4.VSphereMachineTemplate)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_v1alpha3_VSphereMachineTemplateList_To_v1alpha4_VSphereMachineTemplateList is an autogenerated conversion function. +func Convert_v1alpha3_VSphereMachineTemplateList_To_v1alpha4_VSphereMachineTemplateList(in *VSphereMachineTemplateList, out *v1alpha4.VSphereMachineTemplateList, s conversion.Scope) error { + return autoConvert_v1alpha3_VSphereMachineTemplateList_To_v1alpha4_VSphereMachineTemplateList(in, out, s) +} + +func autoConvert_v1alpha4_VSphereMachineTemplateList_To_v1alpha3_VSphereMachineTemplateList(in *v1alpha4.VSphereMachineTemplateList, out *VSphereMachineTemplateList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]VSphereMachineTemplate)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_v1alpha4_VSphereMachineTemplateList_To_v1alpha3_VSphereMachineTemplateList is an autogenerated conversion function. +func Convert_v1alpha4_VSphereMachineTemplateList_To_v1alpha3_VSphereMachineTemplateList(in *v1alpha4.VSphereMachineTemplateList, out *VSphereMachineTemplateList, s conversion.Scope) error { + return autoConvert_v1alpha4_VSphereMachineTemplateList_To_v1alpha3_VSphereMachineTemplateList(in, out, s) +} + +func autoConvert_v1alpha3_VSphereMachineTemplateResource_To_v1alpha4_VSphereMachineTemplateResource(in *VSphereMachineTemplateResource, out *v1alpha4.VSphereMachineTemplateResource, s conversion.Scope) error { + if err := Convert_v1alpha3_VSphereMachineSpec_To_v1alpha4_VSphereMachineSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha3_VSphereMachineTemplateResource_To_v1alpha4_VSphereMachineTemplateResource is an autogenerated conversion function. +func Convert_v1alpha3_VSphereMachineTemplateResource_To_v1alpha4_VSphereMachineTemplateResource(in *VSphereMachineTemplateResource, out *v1alpha4.VSphereMachineTemplateResource, s conversion.Scope) error { + return autoConvert_v1alpha3_VSphereMachineTemplateResource_To_v1alpha4_VSphereMachineTemplateResource(in, out, s) +} + +func autoConvert_v1alpha4_VSphereMachineTemplateResource_To_v1alpha3_VSphereMachineTemplateResource(in *v1alpha4.VSphereMachineTemplateResource, out *VSphereMachineTemplateResource, s conversion.Scope) error { + if err := Convert_v1alpha4_VSphereMachineSpec_To_v1alpha3_VSphereMachineSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha4_VSphereMachineTemplateResource_To_v1alpha3_VSphereMachineTemplateResource is an autogenerated conversion function. +func Convert_v1alpha4_VSphereMachineTemplateResource_To_v1alpha3_VSphereMachineTemplateResource(in *v1alpha4.VSphereMachineTemplateResource, out *VSphereMachineTemplateResource, s conversion.Scope) error { + return autoConvert_v1alpha4_VSphereMachineTemplateResource_To_v1alpha3_VSphereMachineTemplateResource(in, out, s) +} + +func autoConvert_v1alpha3_VSphereMachineTemplateSpec_To_v1alpha4_VSphereMachineTemplateSpec(in *VSphereMachineTemplateSpec, out *v1alpha4.VSphereMachineTemplateSpec, s conversion.Scope) error { + if err := Convert_v1alpha3_VSphereMachineTemplateResource_To_v1alpha4_VSphereMachineTemplateResource(&in.Template, &out.Template, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha3_VSphereMachineTemplateSpec_To_v1alpha4_VSphereMachineTemplateSpec is an autogenerated conversion function. +func Convert_v1alpha3_VSphereMachineTemplateSpec_To_v1alpha4_VSphereMachineTemplateSpec(in *VSphereMachineTemplateSpec, out *v1alpha4.VSphereMachineTemplateSpec, s conversion.Scope) error { + return autoConvert_v1alpha3_VSphereMachineTemplateSpec_To_v1alpha4_VSphereMachineTemplateSpec(in, out, s) +} + +func autoConvert_v1alpha4_VSphereMachineTemplateSpec_To_v1alpha3_VSphereMachineTemplateSpec(in *v1alpha4.VSphereMachineTemplateSpec, out *VSphereMachineTemplateSpec, s conversion.Scope) error { + if err := Convert_v1alpha4_VSphereMachineTemplateResource_To_v1alpha3_VSphereMachineTemplateResource(&in.Template, &out.Template, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha4_VSphereMachineTemplateSpec_To_v1alpha3_VSphereMachineTemplateSpec is an autogenerated conversion function. +func Convert_v1alpha4_VSphereMachineTemplateSpec_To_v1alpha3_VSphereMachineTemplateSpec(in *v1alpha4.VSphereMachineTemplateSpec, out *VSphereMachineTemplateSpec, s conversion.Scope) error { + return autoConvert_v1alpha4_VSphereMachineTemplateSpec_To_v1alpha3_VSphereMachineTemplateSpec(in, out, s) +} + +func autoConvert_v1alpha3_VSphereVM_To_v1alpha4_VSphereVM(in *VSphereVM, out *v1alpha4.VSphereVM, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha3_VSphereVMSpec_To_v1alpha4_VSphereVMSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1alpha3_VSphereVMStatus_To_v1alpha4_VSphereVMStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha3_VSphereVM_To_v1alpha4_VSphereVM is an autogenerated conversion function. +func Convert_v1alpha3_VSphereVM_To_v1alpha4_VSphereVM(in *VSphereVM, out *v1alpha4.VSphereVM, s conversion.Scope) error { + return autoConvert_v1alpha3_VSphereVM_To_v1alpha4_VSphereVM(in, out, s) +} + +func autoConvert_v1alpha4_VSphereVM_To_v1alpha3_VSphereVM(in *v1alpha4.VSphereVM, out *VSphereVM, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha4_VSphereVMSpec_To_v1alpha3_VSphereVMSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1alpha4_VSphereVMStatus_To_v1alpha3_VSphereVMStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha4_VSphereVM_To_v1alpha3_VSphereVM is an autogenerated conversion function. +func Convert_v1alpha4_VSphereVM_To_v1alpha3_VSphereVM(in *v1alpha4.VSphereVM, out *VSphereVM, s conversion.Scope) error { + return autoConvert_v1alpha4_VSphereVM_To_v1alpha3_VSphereVM(in, out, s) +} + +func autoConvert_v1alpha3_VSphereVMList_To_v1alpha4_VSphereVMList(in *VSphereVMList, out *v1alpha4.VSphereVMList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]v1alpha4.VSphereVM)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_v1alpha3_VSphereVMList_To_v1alpha4_VSphereVMList is an autogenerated conversion function. +func Convert_v1alpha3_VSphereVMList_To_v1alpha4_VSphereVMList(in *VSphereVMList, out *v1alpha4.VSphereVMList, s conversion.Scope) error { + return autoConvert_v1alpha3_VSphereVMList_To_v1alpha4_VSphereVMList(in, out, s) +} + +func autoConvert_v1alpha4_VSphereVMList_To_v1alpha3_VSphereVMList(in *v1alpha4.VSphereVMList, out *VSphereVMList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]VSphereVM)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_v1alpha4_VSphereVMList_To_v1alpha3_VSphereVMList is an autogenerated conversion function. +func Convert_v1alpha4_VSphereVMList_To_v1alpha3_VSphereVMList(in *v1alpha4.VSphereVMList, out *VSphereVMList, s conversion.Scope) error { + return autoConvert_v1alpha4_VSphereVMList_To_v1alpha3_VSphereVMList(in, out, s) +} + +func autoConvert_v1alpha3_VSphereVMSpec_To_v1alpha4_VSphereVMSpec(in *VSphereVMSpec, out *v1alpha4.VSphereVMSpec, s conversion.Scope) error { + if err := Convert_v1alpha3_VirtualMachineCloneSpec_To_v1alpha4_VirtualMachineCloneSpec(&in.VirtualMachineCloneSpec, &out.VirtualMachineCloneSpec, s); err != nil { + return err + } + out.BootstrapRef = (*v1.ObjectReference)(unsafe.Pointer(in.BootstrapRef)) + out.BiosUUID = in.BiosUUID + return nil +} + +// Convert_v1alpha3_VSphereVMSpec_To_v1alpha4_VSphereVMSpec is an autogenerated conversion function. +func Convert_v1alpha3_VSphereVMSpec_To_v1alpha4_VSphereVMSpec(in *VSphereVMSpec, out *v1alpha4.VSphereVMSpec, s conversion.Scope) error { + return autoConvert_v1alpha3_VSphereVMSpec_To_v1alpha4_VSphereVMSpec(in, out, s) +} + +func autoConvert_v1alpha4_VSphereVMSpec_To_v1alpha3_VSphereVMSpec(in *v1alpha4.VSphereVMSpec, out *VSphereVMSpec, s conversion.Scope) error { + if err := Convert_v1alpha4_VirtualMachineCloneSpec_To_v1alpha3_VirtualMachineCloneSpec(&in.VirtualMachineCloneSpec, &out.VirtualMachineCloneSpec, s); err != nil { + return err + } + out.BootstrapRef = (*v1.ObjectReference)(unsafe.Pointer(in.BootstrapRef)) + out.BiosUUID = in.BiosUUID + return nil +} + +// Convert_v1alpha4_VSphereVMSpec_To_v1alpha3_VSphereVMSpec is an autogenerated conversion function. +func Convert_v1alpha4_VSphereVMSpec_To_v1alpha3_VSphereVMSpec(in *v1alpha4.VSphereVMSpec, out *VSphereVMSpec, s conversion.Scope) error { + return autoConvert_v1alpha4_VSphereVMSpec_To_v1alpha3_VSphereVMSpec(in, out, s) +} + +func autoConvert_v1alpha3_VSphereVMStatus_To_v1alpha4_VSphereVMStatus(in *VSphereVMStatus, out *v1alpha4.VSphereVMStatus, s conversion.Scope) error { + out.Ready = in.Ready + out.Addresses = *(*[]string)(unsafe.Pointer(&in.Addresses)) + out.CloneMode = v1alpha4.CloneMode(in.CloneMode) + out.Snapshot = in.Snapshot + out.TaskRef = in.TaskRef + out.Network = *(*[]v1alpha4.NetworkStatus)(unsafe.Pointer(&in.Network)) + out.FailureReason = (*errors.MachineStatusError)(unsafe.Pointer(in.FailureReason)) + out.FailureMessage = (*string)(unsafe.Pointer(in.FailureMessage)) + out.Conditions = *(*apiv1alpha3.Conditions)(unsafe.Pointer(&in.Conditions)) + return nil +} + +// Convert_v1alpha3_VSphereVMStatus_To_v1alpha4_VSphereVMStatus is an autogenerated conversion function. +func Convert_v1alpha3_VSphereVMStatus_To_v1alpha4_VSphereVMStatus(in *VSphereVMStatus, out *v1alpha4.VSphereVMStatus, s conversion.Scope) error { + return autoConvert_v1alpha3_VSphereVMStatus_To_v1alpha4_VSphereVMStatus(in, out, s) +} + +func autoConvert_v1alpha4_VSphereVMStatus_To_v1alpha3_VSphereVMStatus(in *v1alpha4.VSphereVMStatus, out *VSphereVMStatus, s conversion.Scope) error { + out.Ready = in.Ready + out.Addresses = *(*[]string)(unsafe.Pointer(&in.Addresses)) + out.CloneMode = CloneMode(in.CloneMode) + out.Snapshot = in.Snapshot + out.TaskRef = in.TaskRef + out.Network = *(*[]NetworkStatus)(unsafe.Pointer(&in.Network)) + out.FailureReason = (*errors.MachineStatusError)(unsafe.Pointer(in.FailureReason)) + out.FailureMessage = (*string)(unsafe.Pointer(in.FailureMessage)) + out.Conditions = *(*apiv1alpha3.Conditions)(unsafe.Pointer(&in.Conditions)) + return nil +} + +// Convert_v1alpha4_VSphereVMStatus_To_v1alpha3_VSphereVMStatus is an autogenerated conversion function. +func Convert_v1alpha4_VSphereVMStatus_To_v1alpha3_VSphereVMStatus(in *v1alpha4.VSphereVMStatus, out *VSphereVMStatus, s conversion.Scope) error { + return autoConvert_v1alpha4_VSphereVMStatus_To_v1alpha3_VSphereVMStatus(in, out, s) +} + +func autoConvert_v1alpha3_VirtualMachine_To_v1alpha4_VirtualMachine(in *VirtualMachine, out *v1alpha4.VirtualMachine, s conversion.Scope) error { + out.Name = in.Name + out.BiosUUID = in.BiosUUID + out.State = v1alpha4.VirtualMachineState(in.State) + out.Network = *(*[]v1alpha4.NetworkStatus)(unsafe.Pointer(&in.Network)) + return nil +} + +// Convert_v1alpha3_VirtualMachine_To_v1alpha4_VirtualMachine is an autogenerated conversion function. +func Convert_v1alpha3_VirtualMachine_To_v1alpha4_VirtualMachine(in *VirtualMachine, out *v1alpha4.VirtualMachine, s conversion.Scope) error { + return autoConvert_v1alpha3_VirtualMachine_To_v1alpha4_VirtualMachine(in, out, s) +} + +func autoConvert_v1alpha4_VirtualMachine_To_v1alpha3_VirtualMachine(in *v1alpha4.VirtualMachine, out *VirtualMachine, s conversion.Scope) error { + out.Name = in.Name + out.BiosUUID = in.BiosUUID + out.State = VirtualMachineState(in.State) + out.Network = *(*[]NetworkStatus)(unsafe.Pointer(&in.Network)) + return nil +} + +// Convert_v1alpha4_VirtualMachine_To_v1alpha3_VirtualMachine is an autogenerated conversion function. +func Convert_v1alpha4_VirtualMachine_To_v1alpha3_VirtualMachine(in *v1alpha4.VirtualMachine, out *VirtualMachine, s conversion.Scope) error { + return autoConvert_v1alpha4_VirtualMachine_To_v1alpha3_VirtualMachine(in, out, s) +} + +func autoConvert_v1alpha3_VirtualMachineCloneSpec_To_v1alpha4_VirtualMachineCloneSpec(in *VirtualMachineCloneSpec, out *v1alpha4.VirtualMachineCloneSpec, s conversion.Scope) error { + out.Template = in.Template + out.CloneMode = v1alpha4.CloneMode(in.CloneMode) + out.Snapshot = in.Snapshot + out.Server = in.Server + out.Thumbprint = in.Thumbprint + out.Datacenter = in.Datacenter + out.Folder = in.Folder + out.Datastore = in.Datastore + out.StoragePolicyName = in.StoragePolicyName + out.ResourcePool = in.ResourcePool + if err := Convert_v1alpha3_NetworkSpec_To_v1alpha4_NetworkSpec(&in.Network, &out.Network, s); err != nil { + return err + } + out.NumCPUs = in.NumCPUs + out.NumCoresPerSocket = in.NumCoresPerSocket + out.MemoryMiB = in.MemoryMiB + out.DiskGiB = in.DiskGiB + out.CustomVMXKeys = *(*map[string]string)(unsafe.Pointer(&in.CustomVMXKeys)) + return nil +} + +// Convert_v1alpha3_VirtualMachineCloneSpec_To_v1alpha4_VirtualMachineCloneSpec is an autogenerated conversion function. +func Convert_v1alpha3_VirtualMachineCloneSpec_To_v1alpha4_VirtualMachineCloneSpec(in *VirtualMachineCloneSpec, out *v1alpha4.VirtualMachineCloneSpec, s conversion.Scope) error { + return autoConvert_v1alpha3_VirtualMachineCloneSpec_To_v1alpha4_VirtualMachineCloneSpec(in, out, s) +} + +func autoConvert_v1alpha4_VirtualMachineCloneSpec_To_v1alpha3_VirtualMachineCloneSpec(in *v1alpha4.VirtualMachineCloneSpec, out *VirtualMachineCloneSpec, s conversion.Scope) error { + out.Template = in.Template + out.CloneMode = CloneMode(in.CloneMode) + out.Snapshot = in.Snapshot + out.Server = in.Server + out.Thumbprint = in.Thumbprint + out.Datacenter = in.Datacenter + out.Folder = in.Folder + out.Datastore = in.Datastore + out.StoragePolicyName = in.StoragePolicyName + out.ResourcePool = in.ResourcePool + if err := Convert_v1alpha4_NetworkSpec_To_v1alpha3_NetworkSpec(&in.Network, &out.Network, s); err != nil { + return err + } + out.NumCPUs = in.NumCPUs + out.NumCoresPerSocket = in.NumCoresPerSocket + out.MemoryMiB = in.MemoryMiB + out.DiskGiB = in.DiskGiB + out.CustomVMXKeys = *(*map[string]string)(unsafe.Pointer(&in.CustomVMXKeys)) + return nil +} + +// Convert_v1alpha4_VirtualMachineCloneSpec_To_v1alpha3_VirtualMachineCloneSpec is an autogenerated conversion function. +func Convert_v1alpha4_VirtualMachineCloneSpec_To_v1alpha3_VirtualMachineCloneSpec(in *v1alpha4.VirtualMachineCloneSpec, out *VirtualMachineCloneSpec, s conversion.Scope) error { + return autoConvert_v1alpha4_VirtualMachineCloneSpec_To_v1alpha3_VirtualMachineCloneSpec(in, out, s) +} diff --git a/api/v1alpha4/cloudprovider_encoding.go b/api/v1alpha4/cloudprovider_encoding.go new file mode 100644 index 0000000000..1da7bf3026 --- /dev/null +++ b/api/v1alpha4/cloudprovider_encoding.go @@ -0,0 +1,273 @@ +/* +Copyright 2021 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 v1alpha4 + +import ( + "bytes" + "fmt" + "io" + "reflect" + "regexp" + "sort" + "strings" + + "github.com/pkg/errors" + gcfg "gopkg.in/gcfg.v1" +) + +const gcfgTag = "gcfg" + +var iniEscapeChars = regexp.MustCompile(`([\\"])`) + +// MarshalINI marshals the cloud provider configuration to INI-style +// configuration data. +func (c *CPIConfig) MarshalINI() ([]byte, error) { + if c == nil { + return nil, errors.New("config is nil") + } + + buf := &bytes.Buffer{} + + // Get the reflected type and value of the CPIConfig object. + configValue := reflect.ValueOf(*c) + configType := reflect.TypeOf(*c) + + for sectionIndex := 0; sectionIndex < configValue.NumField(); sectionIndex++ { + sectionType := configType.Field(sectionIndex) + sectionValue := configValue.Field(sectionIndex) + + // Get the value of the gcfg tag to help determine the section + // name and whether to omit an empty value. Also ignore fields without the gcfg tag + sectionName, omitEmpty, hasTag := parseGcfgTag(sectionType) + if !hasTag { + continue + } + + // Do not marshal a section if it is empty. + if omitEmpty && isEmpty(sectionValue) { + continue + } + + switch sectionValue.Kind() { + case reflect.Map: + keys := sectionValue.MapKeys() + sort.Slice(keys, func(i, j int) bool { + return keys[i].String() < keys[j].String() + }) + + for _, key := range keys { + sectionNameKey, sectionValue := key, sectionValue.MapIndex(key) + sectionName := fmt.Sprintf(`%s "%v"`, sectionName, sectionNameKey.String()) + if err := c.marshalINISectionProperties(buf, sectionValue, sectionName); err != nil { + return nil, err + } + } + default: + if err := c.marshalINISectionProperties(buf, sectionValue, sectionName); err != nil { + return nil, err + } + } + } + + return buf.Bytes(), nil +} + +func (c *CPIConfig) marshalINISectionProperties( + out io.Writer, + sectionValue reflect.Value, + sectionName string) error { + + switch sectionValue.Kind() { + case reflect.Interface, reflect.Ptr: + return c.marshalINISectionProperties(out, sectionValue.Elem(), sectionName) + } + + fmt.Fprintf(out, "[%s]\n", sectionName) + + sectionType := sectionValue.Type() + for propertyIndex := 0; propertyIndex < sectionType.NumField(); propertyIndex++ { + propertyType := sectionType.Field(propertyIndex) + propertyValue := sectionValue.Field(propertyIndex) + + // Get the value of the gcfg tag to help determine the property + // name and whether to omit an empty value. + propertyName, omitEmpty, hasTag := parseGcfgTag(propertyType) + if !hasTag { + continue + } + + // Do not marshal a property if it is empty. + if omitEmpty && isEmpty(propertyValue) { + continue + } + + switch propertyValue.Kind() { + case reflect.Interface, reflect.Ptr: + propertyValue = propertyValue.Elem() + } + + fmt.Fprintf(out, "%s", propertyName) + if propertyValue.IsValid() { + rawVal := fmt.Sprintf("%v", propertyValue.Interface()) + val := iniEscapeChars.ReplaceAllString(rawVal, "\\$1") + val = strings.ReplaceAll(val, "\t", "\\t") + if propertyValue.Kind() == reflect.String { + val = "\"" + val + "\"" + } + fmt.Fprintf(out, " = %s\n", val) + } + } + + fmt.Fprintf(out, "\n") + + return nil +} + +func parseGcfgTag(field reflect.StructField) (string, bool, bool) { + name := field.Name + omitEmpty := false + hasTag := false + + if tagVal, ok := field.Tag.Lookup(gcfgTag); ok { + hasTag = true + tagParts := strings.Split(tagVal, ",") + lenTagParts := len(tagParts) + if lenTagParts > 0 { + tagName := tagParts[0] + if len(tagName) > 0 && tagName != "-" { + name = tagName + } + } + if lenTagParts > 1 { + omitEmpty = tagParts[1] == "omitempty" + } + } + + return name, omitEmpty, hasTag +} + +// UnmarshalINIOptions defines the options used to influence how INI data is +// unmarshalled. +// +// +kubebuilder:object:generate=false +type UnmarshalINIOptions struct { + // WarnAsFatal indicates that warnings that occur when unmarshalling INI + // data should be treated as fatal errors. + WarnAsFatal bool +} + +// UnmarshalINIOptionFunc is used to set unmarshal options. +// +// +kubebuilder:object:generate=false +type UnmarshalINIOptionFunc func(*UnmarshalINIOptions) + +// WarnAsFatal sets the option to treat warnings as fatal errors when +// unmarshalling INI data. +func WarnAsFatal(opts *UnmarshalINIOptions) { + opts.WarnAsFatal = true +} + +// UnmarshalINI unmarshals the cloud provider configuration from INI-style +// configuration data. +func (c *CPIConfig) UnmarshalINI(data []byte, optFuncs ...UnmarshalINIOptionFunc) error { + opts := &UnmarshalINIOptions{} + for _, setOpts := range optFuncs { + setOpts(opts) + } + var config unmarshallableConfig + if err := gcfg.ReadStringInto(&config, string(data)); err != nil { + if opts.WarnAsFatal { + return err + } + if err := gcfg.FatalOnly(err); err != nil { + return err + } + } + c.Global = config.Global + c.Network = config.Network + c.Disk = config.Disk + c.Workspace = config.Workspace + c.Labels = config.Labels + c.VCenter = map[string]CPIVCenterConfig{} + for k, v := range config.VCenter { + c.VCenter[k] = *v + } + return nil +} + +// IsEmpty returns true if an object is its empty value or if a struct, all of +// its fields are their empty values. +func IsEmpty(obj interface{}) bool { + return isEmpty(reflect.ValueOf(obj)) +} + +// IsNotEmpty returns true when IsEmpty returns false. +func IsNotEmpty(obj interface{}) bool { + return !IsEmpty(obj) +} + +// isEmpty returns true if an object's fields are all set to their empty values. +func isEmpty(val reflect.Value) bool { + switch val.Kind() { + + case reflect.Interface, reflect.Ptr: + return val.IsNil() || isEmpty(val.Elem()) + + case reflect.Struct: + structIsEmpty := true + for fieldIndex := 0; fieldIndex < val.NumField(); fieldIndex++ { + if structIsEmpty = isEmpty(val.Field(fieldIndex)); !structIsEmpty { + break + } + } + return structIsEmpty + + case reflect.Array, reflect.String: + return val.Len() == 0 + + case reflect.Bool: + return !val.Bool() + + case reflect.Map, reflect.Slice: + return val.IsNil() || val.Len() == 0 + + case reflect.Float32, reflect.Float64: + return val.Float() == 0 + + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return val.Int() == 0 + + default: + panic(errors.Errorf("invalid kind: %s", val.Kind())) + } +} + +// MarshalCloudProviderArgs marshals the cloud provider arguments for passing +// into a pod spec +func (cpic *CPICloudConfig) MarshalCloudProviderArgs() []string { + args := []string{ + "--v=2", + "--cloud-provider=vsphere", + "--cloud-config=/etc/cloud/vsphere.conf", + } + if cpic.ExtraArgs != nil { + for k, v := range cpic.ExtraArgs { + args = append(args, fmt.Sprintf("--%s=%s", k, v)) + } + } + return args +} diff --git a/api/v1alpha4/cloudprovider_encoding_test.go b/api/v1alpha4/cloudprovider_encoding_test.go new file mode 100644 index 0000000000..0ee0c91b68 --- /dev/null +++ b/api/v1alpha4/cloudprovider_encoding_test.go @@ -0,0 +1,725 @@ +/* +Copyright 2021 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 v1alpha4_test + +import ( + "fmt" + "testing" + + "sigs.k8s.io/cluster-api-provider-vsphere/api/v1alpha4" + + "github.com/onsi/gomega" + "github.com/pkg/errors" +) + +var unmarshalWarnAsFatal = []v1alpha4.UnmarshalINIOptionFunc{v1alpha4.WarnAsFatal} + +func errDeprecated(section, key string) error { + return errors.Errorf("warning:\ncan't store data at section \"%s\", variable \"%s\"\n", section, key) +} + +type codecTestCase struct { + testName string + iniString string + configObj v1alpha4.CPIConfig + expectedError error + unmarshalOptions []v1alpha4.UnmarshalINIOptionFunc +} + +func TestMarshalINI(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + testcases := []codecTestCase{ + { + testName: "Username and password in global section", + iniString: `[Global] +user = "user" +password = "password" +datacenters = "us-west" +cluster-id = "cluster-namespace/cluster-name" + +[VirtualCenter "0.0.0.0"] + +[Workspace] +server = "0.0.0.0" +datacenter = "us-west" +folder = "kubernetes" +default-datastore = "default" + +`, + configObj: v1alpha4.CPIConfig{ + Global: v1alpha4.CPIGlobalConfig{ + Username: "user", + Password: "password", + Datacenters: "us-west", + ClusterID: "cluster-namespace/cluster-name", + }, + VCenter: map[string]v1alpha4.CPIVCenterConfig{ + "0.0.0.0": {}, + }, + Workspace: v1alpha4.CPIWorkspaceConfig{ + Server: "0.0.0.0", + Datacenter: "us-west", + Folder: "kubernetes", + Datastore: "default", + }, + }, + }, + { + testName: "Username and password in vCenter section", + iniString: `[Global] +insecure-flag = true +port = "443" +datacenters = "us-west" + +[VirtualCenter "0.0.0.0"] +user = "user" +password = "password" + +[Workspace] +server = "0.0.0.0" +datacenter = "us-west" +folder = "kubernetes" + +`, + configObj: v1alpha4.CPIConfig{ + Global: v1alpha4.CPIGlobalConfig{ + Port: "443", + Insecure: true, + Datacenters: "us-west", + }, + VCenter: map[string]v1alpha4.CPIVCenterConfig{ + "0.0.0.0": { + Username: "user", + Password: "password", + }, + }, + Workspace: v1alpha4.CPIWorkspaceConfig{ + Server: "0.0.0.0", + Datacenter: "us-west", + Folder: "kubernetes", + }, + }, + }, + { + testName: "SecretName and SecretNamespace", + iniString: `[Global] +secret-name = "vccreds" +secret-namespace = "kube-system" +datacenters = "us-west" + +[VirtualCenter "0.0.0.0"] + +[Workspace] +server = "0.0.0.0" +datacenter = "us-west" +folder = "kubernetes" + +`, + configObj: v1alpha4.CPIConfig{ + Global: v1alpha4.CPIGlobalConfig{ + SecretName: "vccreds", + SecretNamespace: "kube-system", + Datacenters: "us-west", + }, + VCenter: map[string]v1alpha4.CPIVCenterConfig{ + "0.0.0.0": {}, + }, + Workspace: v1alpha4.CPIWorkspaceConfig{ + Server: "0.0.0.0", + Datacenter: "us-west", + Folder: "kubernetes", + }, + }, + }, + { + testName: "SecretName and SecretNamespace with Username missing", + iniString: `[Global] +insecure-flag = true +secret-name = "vccreds" +secret-namespace = "kube-system" +port = "443" +datacenters = "us-west" + +[VirtualCenter "0.0.0.0"] +password = "password" + +[Workspace] +server = "0.0.0.0" +datacenter = "us-west" +folder = "kubernetes" + +`, + configObj: v1alpha4.CPIConfig{ + Global: v1alpha4.CPIGlobalConfig{ + Port: "443", + Insecure: true, + SecretName: "vccreds", + SecretNamespace: "kube-system", + Datacenters: "us-west", + }, + VCenter: map[string]v1alpha4.CPIVCenterConfig{ + "0.0.0.0": { + Password: "password", + }, + }, + Workspace: v1alpha4.CPIWorkspaceConfig{ + Server: "0.0.0.0", + Datacenter: "us-west", + Folder: "kubernetes", + }, + }, + }, + { + testName: "Multiple virtual centers with different thumbprints", + iniString: `[Global] +user = "user" +password = "password" +datacenters = "us-west" + +[VirtualCenter "0.0.0.0"] +thumbprint = "thumbprint:0" + +[VirtualCenter "1.1.1.1"] +thumbprint = "thumbprint:1" + +[VirtualCenter "no_thumbprint"] + +[Workspace] +server = "0.0.0.0" +datacenter = "us-west" +folder = "kubernetes" + +`, + configObj: v1alpha4.CPIConfig{ + Global: v1alpha4.CPIGlobalConfig{ + Username: "user", + Password: "password", + Datacenters: "us-west", + }, + VCenter: map[string]v1alpha4.CPIVCenterConfig{ + "0.0.0.0": { + Thumbprint: "thumbprint:0", + }, + "no_thumbprint": {}, + "1.1.1.1": { + Thumbprint: "thumbprint:1", + }, + }, + Workspace: v1alpha4.CPIWorkspaceConfig{ + Server: "0.0.0.0", + Datacenter: "us-west", + Folder: "kubernetes", + }, + }, + }, + { + testName: "Multiple vCenters using global CA cert", + iniString: `[Global] +secret-name = "vccreds" +secret-namespace = "kube-system" +ca-file = "/some/path/to/my/trusted/ca.pem" +datacenters = "us-west" + +[VirtualCenter "0.0.0.0"] + +[VirtualCenter "1.1.1.1"] + +[Workspace] +server = "0.0.0.0" +datacenter = "us-west" +folder = "kubernetes" + +`, + configObj: v1alpha4.CPIConfig{ + Global: v1alpha4.CPIGlobalConfig{ + Datacenters: "us-west", + SecretName: "vccreds", + SecretNamespace: "kube-system", + CAFile: "/some/path/to/my/trusted/ca.pem", + }, + VCenter: map[string]v1alpha4.CPIVCenterConfig{ + "0.0.0.0": {}, + "1.1.1.1": {}, + }, + Workspace: v1alpha4.CPIWorkspaceConfig{ + Server: "0.0.0.0", + Datacenter: "us-west", + Folder: "kubernetes", + }, + ProviderConfig: v1alpha4.CPIProviderConfig{ + Cloud: &v1alpha4.CPICloudConfig{ + ControllerImage: "test", + }, + }, + }, + }, + } + + for _, tc := range testcases { + tc := tc + t.Run(tc.testName, func(t *testing.T) { + buf, err := tc.configObj.MarshalINI() + if err != nil { + if tc.expectedError == nil { + g.Expect(err).ShouldNot( + gomega.HaveOccurred(), + "unexpected error when marshalling data") + } else { + g.Expect(err.Error()).Should( + gomega.Equal(tc.expectedError.Error()), + "unexpected error when marshalling data") + } + } + + g.Expect(string(buf)).To(gomega.Equal(tc.iniString), + "marshalled config does not match") + }) + } +} + +func TestUnmarshalINI(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + deprecatedTestCases := []codecTestCase{ + { + testName: "Global server is deprecated", + iniString: ` + [Global] + server = "deprecated" + `, + expectedError: errDeprecated("Global", "server"), + unmarshalOptions: unmarshalWarnAsFatal, + }, + { + testName: "Global datacenter is deprecated", + iniString: ` + [Global] + datacenter = "deprecated" + `, + expectedError: errDeprecated("Global", "datacenter"), + unmarshalOptions: unmarshalWarnAsFatal, + }, + { + + testName: "Global datastore is deprecated", + iniString: ` + [Global] + datastore = "deprecated" + `, + expectedError: errDeprecated("Global", "datastore"), + unmarshalOptions: unmarshalWarnAsFatal, + }, + { + testName: "Global working-dir is deprecated", + iniString: ` + [Global] + working-dir = "deprecated" + `, + expectedError: errDeprecated("Global", "working-dir"), + unmarshalOptions: unmarshalWarnAsFatal, + }, + { + testName: "Global vm-name is deprecated", + iniString: ` + [Global] + vm-name = "deprecated" + `, + expectedError: errDeprecated("Global", "vm-name"), + unmarshalOptions: unmarshalWarnAsFatal, + }, + { + testName: "Global vm-uuid is deprecated", + iniString: ` + [Global] + vm-uuid = "deprecated" + `, + expectedError: errDeprecated("Global", "vm-uuid"), + unmarshalOptions: unmarshalWarnAsFatal, + }, + } + + testcases := []codecTestCase{ + { + testName: "Username and password in global section", + iniString: ` + [Global] + user = "user" + password = "password" + datacenters = "us-west" + cluster-id = "cluster-namespace/cluster-name" + + [VirtualCenter "0.0.0.0"] + + [Workspace] + server = "0.0.0.0" + datacenter = "us-west" + folder = "kubernetes" + default-datastore = "default" + `, + configObj: v1alpha4.CPIConfig{ + Global: v1alpha4.CPIGlobalConfig{ + Username: "user", + Password: "password", + Datacenters: "us-west", + ClusterID: "cluster-namespace/cluster-name", + }, + VCenter: map[string]v1alpha4.CPIVCenterConfig{ + "0.0.0.0": {}, + }, + Workspace: v1alpha4.CPIWorkspaceConfig{ + Server: "0.0.0.0", + Datacenter: "us-west", + Folder: "kubernetes", + Datastore: "default", + }, + }, + }, + { + testName: "Username and password in vCenter section", + iniString: ` + [Global] + port = "443" + insecure-flag = true + datacenters = "us-west" + + [VirtualCenter "0.0.0.0"] + user = "user" + password = "password" + + [Workspace] + server = 0.0.0.0 + datacenter = "us-west" + folder = "kubernetes" + `, + configObj: v1alpha4.CPIConfig{ + Global: v1alpha4.CPIGlobalConfig{ + Port: "443", + Insecure: true, + Datacenters: "us-west", + }, + VCenter: map[string]v1alpha4.CPIVCenterConfig{ + "0.0.0.0": { + Username: "user", + Password: "password", + }, + }, + Workspace: v1alpha4.CPIWorkspaceConfig{ + Server: "0.0.0.0", + Datacenter: "us-west", + Folder: "kubernetes", + }, + }, + }, + { + testName: "NetBIOS style AD username and password in vCenter section", + iniString: ` + [Global] + port = "443" + insecure-flag = true + datacenters = "us-west" + + [VirtualCenter "0.0.0.0"] + user = "domain\\user" + password = "password" + + [Workspace] + server = 0.0.0.0 + datacenter = "us-west" + folder = "kubernetes" + `, + configObj: v1alpha4.CPIConfig{ + Global: v1alpha4.CPIGlobalConfig{ + Port: "443", + Insecure: true, + Datacenters: "us-west", + }, + VCenter: map[string]v1alpha4.CPIVCenterConfig{ + "0.0.0.0": { + Username: "domain\\user", + Password: "password", + }, + }, + Workspace: v1alpha4.CPIWorkspaceConfig{ + Server: "0.0.0.0", + Datacenter: "us-west", + Folder: "kubernetes", + }, + }, + }, + { + testName: "SecretName and SecretNamespace", + iniString: ` + [Global] + secret-name = "vccreds" + secret-namespace = "kube-system" + datacenters = "us-west" + + [VirtualCenter "0.0.0.0"] + + [Workspace] + server = "0.0.0.0" + datacenter = "us-west" + folder = "kubernetes" + `, + configObj: v1alpha4.CPIConfig{ + Global: v1alpha4.CPIGlobalConfig{ + SecretName: "vccreds", + SecretNamespace: "kube-system", + Datacenters: "us-west", + }, + VCenter: map[string]v1alpha4.CPIVCenterConfig{ + "0.0.0.0": {}, + }, + Workspace: v1alpha4.CPIWorkspaceConfig{ + Server: "0.0.0.0", + Datacenter: "us-west", + Folder: "kubernetes", + }, + }, + }, + { + testName: "SecretName and SecretNamespace with Username missing", + iniString: ` + [Global] + port = "443" + insecure-flag = true + datacenters = "us-west" + secret-name = "vccreds" + secret-namespace = "kube-system" + + [VirtualCenter "0.0.0.0"] + password = "password" + + [Workspace] + server = "0.0.0.0" + datacenter = "us-west" + folder = "kubernetes" + `, + configObj: v1alpha4.CPIConfig{ + Global: v1alpha4.CPIGlobalConfig{ + Port: "443", + Insecure: true, + SecretName: "vccreds", + SecretNamespace: "kube-system", + Datacenters: "us-west", + }, + VCenter: map[string]v1alpha4.CPIVCenterConfig{ + "0.0.0.0": { + Password: "password", + }, + }, + Workspace: v1alpha4.CPIWorkspaceConfig{ + Server: "0.0.0.0", + Datacenter: "us-west", + Folder: "kubernetes", + }, + }, + }, + { + testName: "Multiple virtual centers with different thumbprints", + iniString: ` + [Global] + user = "user" + password = "password" + datacenters = "us-west" + + [VirtualCenter "0.0.0.0"] + thumbprint = "thumbprint:0" + + [VirtualCenter "no_thumbprint"] + + [VirtualCenter "1.1.1.1"] + thumbprint = "thumbprint:1" + + [Workspace] + server = "0.0.0.0" + datacenter = "us-west" + folder = "kubernetes" + `, + configObj: v1alpha4.CPIConfig{ + Global: v1alpha4.CPIGlobalConfig{ + Username: "user", + Password: "password", + Datacenters: "us-west", + }, + VCenter: map[string]v1alpha4.CPIVCenterConfig{ + "0.0.0.0": { + Thumbprint: "thumbprint:0", + }, + "no_thumbprint": {}, + "1.1.1.1": { + Thumbprint: "thumbprint:1", + }, + }, + Workspace: v1alpha4.CPIWorkspaceConfig{ + Server: "0.0.0.0", + Datacenter: "us-west", + Folder: "kubernetes", + }, + }, + }, + { + testName: "Multiple vCenters using global CA cert", + iniString: ` + [Global] + datacenters = "us-west" + secret-name = "vccreds" + secret-namespace = "kube-system" + ca-file = "/some/path/to/my/trusted/ca.pem" + + [VirtualCenter "0.0.0.0"] + [VirtualCenter "1.1.1.1"] + + [Workspace] + server = "0.0.0.0" + datacenter = "us-west" + folder = "kubernetes" + `, + configObj: v1alpha4.CPIConfig{ + Global: v1alpha4.CPIGlobalConfig{ + Datacenters: "us-west", + SecretName: "vccreds", + SecretNamespace: "kube-system", + CAFile: "/some/path/to/my/trusted/ca.pem", + }, + VCenter: map[string]v1alpha4.CPIVCenterConfig{ + "0.0.0.0": {}, + "1.1.1.1": {}, + }, + Workspace: v1alpha4.CPIWorkspaceConfig{ + Server: "0.0.0.0", + Datacenter: "us-west", + Folder: "kubernetes", + }, + }, + }, + } + + testCases := append( + testcases, + deprecatedTestCases..., + ) + + for _, tc := range testCases { + tc := tc + t.Run(tc.testName, func(t *testing.T) { + var actualConfig v1alpha4.CPIConfig + + if err := actualConfig.UnmarshalINI( + []byte(tc.iniString), + tc.unmarshalOptions...); err != nil { + + if tc.expectedError == nil { + g.Expect(err).ShouldNot( + gomega.HaveOccurred(), + "unexpected error when unmarshalling data") + } else { + g.Expect(err.Error()).Should( + gomega.Equal(tc.expectedError.Error()), + "unexpected error when unmarshalling data") + } + } + + g.Expect(actualConfig).Should( + gomega.Equal(tc.configObj), + "actual config does not match expected config") + }) + } +} + +type passwordTestCase struct { + testName string + iniEncodedString string + expectedString string +} + +func TestPasswords(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + testCases := []passwordTestCase{ + { + testName: "password contains backslash", + iniEncodedString: "pass\\\\word", + expectedString: "pass\\word", + }, + { + testName: "password contains quotation mark", + iniEncodedString: "pass\\\"word", + expectedString: "pass\"word", + }, + { + testName: "password contains tab", + iniEncodedString: "pass\\tword", + expectedString: "pass\tword", + }, + { + testName: "password contains allowed characters for Microsoft Active Directory including Unicode", + iniEncodedString: "0123456789abczABCZ~!@#$%^&*_-+=`|\\\\(){}[]:;\\\"'<>,.?/€Пассворд密码🌟", + expectedString: "0123456789abczABCZ~!@#$%^&*_-+=`|\\(){}[]:;\"'<>,.?/€Пассворд密码🌟", + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.testName, func(t *testing.T) { + var actualConfig v1alpha4.CPIConfig + + iniString := ` + [Global] + port = "443" + insecure-flag = true + datacenters = "us-west" + + [VirtualCenter "0.0.0.0"] + user = "user" + password = "%s" + + [Workspace] + server = 0.0.0.0 + datacenter = "us-west" + folder = "kubernetes" +` + expectedConfig := v1alpha4.CPIConfig{ + Global: v1alpha4.CPIGlobalConfig{ + Port: "443", + Insecure: true, + Datacenters: "us-west", + }, + VCenter: map[string]v1alpha4.CPIVCenterConfig{ + "0.0.0.0": { + Username: "user", + Password: tc.expectedString, + }, + }, + Workspace: v1alpha4.CPIWorkspaceConfig{ + Server: "0.0.0.0", + Datacenter: "us-west", + Folder: "kubernetes", + }, + } + + err := actualConfig.UnmarshalINI([]byte(fmt.Sprintf(iniString, tc.iniEncodedString))) + g.Expect(err).ToNot(gomega.HaveOccurred()) + + g.Expect(actualConfig).Should( + gomega.Equal(expectedConfig), + "actual config does not match expected config") + }) + } + +} diff --git a/api/v1alpha4/cloudprovider_types.go b/api/v1alpha4/cloudprovider_types.go new file mode 100644 index 0000000000..4cc62e33ed --- /dev/null +++ b/api/v1alpha4/cloudprovider_types.go @@ -0,0 +1,253 @@ +/* +Copyright 2021 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. +*/ + +// cloudprovider_types contains API types for the vSphere cloud provider. +// The configuration may be unmarshalled from an INI-style configuration using +// the "gopkg.in/gcfg.v1" package. +// +// The configuration may be marshalled to an INI-style configuration using a Go +// template. +// +// The "gopkg.in/go-ini/ini.v1" package was investigated, but it does not +// support reflecting a struct with a field of type "map[string]TYPE" to INI. +package v1alpha4 + +// CPIConfig is the vSphere cloud provider's configuration. +// DEPRECATED: will be removed in v1alpha4 +type CPIConfig struct { + // Global is the vSphere cloud provider's global configuration. + // +optional + Global CPIGlobalConfig `gcfg:"Global,omitempty" json:"global,omitempty"` + + // VCenter is a list of vCenter configurations. + // +optional + VCenter map[string]CPIVCenterConfig `gcfg:"VirtualCenter,omitempty" json:"virtualCenter,omitempty"` + + // Network is the vSphere cloud provider's network configuration. + // +optional + Network CPINetworkConfig `gcfg:"Network,omitempty" json:"network,omitempty"` + + // Disk is the vSphere cloud provider's disk configuration. + // +optional + Disk CPIDiskConfig `gcfg:"Disk,omitempty" json:"disk,omitempty"` + + // Workspace is the vSphere cloud provider's workspace configuration. + // +optional + Workspace CPIWorkspaceConfig `gcfg:"Workspace,omitempty" json:"workspace,omitempty"` + + // Labels is the vSphere cloud provider's zone and region configuration. + // +optional + Labels CPILabelConfig `gcfg:"Labels,omitempty" json:"labels,omitempty"` + + // CPIProviderConfig contains extra information used to configure the + // vSphere cloud provider. + ProviderConfig CPIProviderConfig `json:"providerConfig,omitempty"` +} + +// CPIProviderConfig defines any extra information used to configure +// the vSphere external cloud provider +type CPIProviderConfig struct { + Cloud *CPICloudConfig `json:"cloud,omitempty"` + Storage *CPIStorageConfig `json:"storage,omitempty"` +} + +type CPICloudConfig struct { + ControllerImage string `json:"controllerImage,omitempty"` + // ExtraArgs passes through extra arguments to the cloud provider. + // The arguments here are passed to the cloud provider daemonset specification + // +optional + ExtraArgs map[string]string `json:"extraArgs,omitempty"` +} + +type CPIStorageConfig struct { + ControllerImage string `json:"controllerImage,omitempty"` + NodeDriverImage string `json:"nodeDriverImage,omitempty"` + AttacherImage string `json:"attacherImage,omitempty"` + ProvisionerImage string `json:"provisionerImage,omitempty"` + MetadataSyncerImage string `json:"metadataSyncerImage,omitempty"` + LivenessProbeImage string `json:"livenessProbeImage,omitempty"` + RegistrarImage string `json:"registrarImage,omitempty"` +} + +// unmarshallableConfig is used to unmarshal the INI data using the gcfg +// package. The package requires fields with map types use *Values. However, +// kubebuilder v2 won't generate CRDs for map types with *Values. +type unmarshallableConfig struct { + Global CPIGlobalConfig `gcfg:"Global,omitempty"` + VCenter map[string]*CPIVCenterConfig `gcfg:"VirtualCenter,omitempty"` + Network CPINetworkConfig `gcfg:"Network,omitempty"` + Disk CPIDiskConfig `gcfg:"Disk,omitempty"` + Workspace CPIWorkspaceConfig `gcfg:"Workspace,omitempty"` + Labels CPILabelConfig `gcfg:"Labels,omitempty"` +} + +// CPIGlobalConfig is the vSphere cloud provider's global configuration. +type CPIGlobalConfig struct { + // Insecure is a flag that disables TLS peer verification. + // +optional + Insecure bool `gcfg:"insecure-flag,omitempty" json:"insecure,omitempty"` + + // RoundTripperCount specifies the SOAP round tripper count + // (retries = RoundTripper - 1) + // +optional + RoundTripperCount int32 `gcfg:"soap-roundtrip-count,omitempty" json:"roundTripperCount,omitempty"` + + // Username is the username used to access a vSphere endpoint. + // +optional + Username string `gcfg:"user,omitempty" json:"username,omitempty"` + + // Password is the password used to access a vSphere endpoint. + // +optional + Password string `gcfg:"password,omitempty" json:"password,omitempty"` + + // SecretName is the name of the Kubernetes secret in which the vSphere + // credentials are located. + // +optional + SecretName string `gcfg:"secret-name,omitempty" json:"secretName,omitempty"` + + // SecretNamespace is the namespace for SecretName. + // +optional + SecretNamespace string `gcfg:"secret-namespace,omitempty" json:"secretNamespace,omitempty"` + + // Port is the port on which the vSphere endpoint is listening. + // Defaults to 443. + // +optional + Port string `gcfg:"port,omitempty" json:"port,omitempty"` + + // CAFile Specifies the path to a CA certificate in PEM format. + // If not configured, the system's CA certificates will be used. + // +optional + CAFile string `gcfg:"ca-file,omitempty" json:"caFile,omitempty"` + + // Thumbprint is the cryptographic thumbprint of the vSphere endpoint's + // certificate. + // +optional + Thumbprint string `gcfg:"thumbprint,omitempty" json:"thumbprint,omitempty"` + + // Datacenters is a CSV string of the datacenters in which VMs are located. + // +optional + Datacenters string `gcfg:"datacenters,omitempty" json:"datacenters,omitempty"` + + // ServiceAccount is the Kubernetes service account used to launch the cloud + // controller manager. + // Defaults to cloud-controller-manager. + // +optional + ServiceAccount string `gcfg:"service-account,omitempty" json:"serviceAccount,omitempty"` + + // SecretsDirectory is a directory in which secrets may be found. This + // may used in the event that: + // 1. It is not desirable to use the K8s API to watch changes to secrets + // 2. The cloud controller manager is not running in a K8s environment, + // such as DC/OS. For example, the container storage interface (CSI) is + // container orcehstrator (CO) agnostic, and should support non-K8s COs. + // Defaults to /etc/cloud/credentials. + // +optional + SecretsDirectory string `gcfg:"secrets-directory,omitempty" json:"secretsDirectory,omitempty"` + + // APIDisable disables the vSphere cloud controller manager API. + // Defaults to true. + // +optional + APIDisable *bool `gcfg:"api-disable,omitempty" json:"apiDisable,omitempty"` + + // APIBindPort configures the vSphere cloud controller manager API port. + // Defaults to 43001. + // +optional + APIBindPort string `gcfg:"api-binding,omitempty" json:"apiBindPort,omitempty"` + + // ClusterID is a unique identifier for a cluster used by the vSphere CSI driver (CNS) + // NOTE: This field is set internally by CAPV and should not be set by any other consumer of this API + ClusterID string `gcfg:"cluster-id,omitempty" json:"-"` +} + +// CPIVCenterConfig is a vSphere cloud provider's vCenter configuration. +type CPIVCenterConfig struct { + // Username is the username used to access a vSphere endpoint. + // +optional + Username string `gcfg:"user,omitempty" json:"username,omitempty"` + + // Password is the password used to access a vSphere endpoint. + // +optional + Password string `gcfg:"password,omitempty" json:"password,omitempty"` + + // Port is the port on which the vSphere endpoint is listening. + // Defaults to 443. + // +optional + Port string `gcfg:"port,omitempty" json:"port,omitempty"` + + // Datacenters is a CSV string of the datacenters in which VMs are located. + // +optional + Datacenters string `gcfg:"datacenters,omitempty" json:"datacenters,omitempty"` + + // RoundTripperCount specifies the SOAP round tripper count + // (retries = RoundTripper - 1) + // +optional + RoundTripperCount int32 `gcfg:"soap-roundtrip-count,omitempty" json:"roundTripperCount,omitempty"` + + // Thumbprint is the cryptographic thumbprint of the vSphere endpoint's + // certificate. + // +optional + Thumbprint string `gcfg:"thumbprint,omitempty" json:"thumbprint,omitempty"` +} + +// CPINetworkConfig is the network configuration for the vSphere cloud provider. +type CPINetworkConfig struct { + // Name is the name of the network to which VMs are connected. + // +optional + Name string `gcfg:"public-network,omitempty" json:"name,omitempty"` +} + +// CPIDiskConfig defines the disk configuration for the vSphere cloud provider. +type CPIDiskConfig struct { + // SCSIControllerType defines SCSI controller to be used. + // +optional + SCSIControllerType string `gcfg:"scsicontrollertype,omitempty" json:"scsiControllerType,omitempty"` +} + +// CPIWorkspaceConfig defines a workspace configuration for the vSphere cloud +// provider. +type CPIWorkspaceConfig struct { + // Server is the IP address or FQDN of the vSphere endpoint. + // +optional + Server string `gcfg:"server,omitempty" json:"server,omitempty"` + + // Datacenter is the datacenter in which VMs are created/located. + // +optional + Datacenter string `gcfg:"datacenter,omitempty" json:"datacenter,omitempty"` + + // Folder is the folder in which VMs are created/located. + // +optional + Folder string `gcfg:"folder,omitempty" json:"folder,omitempty"` + + // Datastore is the datastore in which VMs are created/located. + // +optional + Datastore string `gcfg:"default-datastore,omitempty" json:"datastore,omitempty"` + + // ResourcePool is the resource pool in which VMs are created/located. + // +optional + ResourcePool string `gcfg:"resourcepool-path,omitempty" json:"resourcePool,omitempty"` +} + +// CPILabelConfig defines the categories and tags which correspond to built-in +// node labels, zone and region. +type CPILabelConfig struct { + // Zone is the zone in which VMs are created/located. + // +optional + Zone string `gcfg:"zone,omitempty" json:"zone,omitempty"` + + // Region is the region in which VMs are created/located. + // +optional + Region string `gcfg:"region,omitempty" json:"region,omitempty"` +} diff --git a/api/v1alpha4/condition_consts.go b/api/v1alpha4/condition_consts.go new file mode 100644 index 0000000000..6060d309e7 --- /dev/null +++ b/api/v1alpha4/condition_consts.go @@ -0,0 +1,106 @@ +/* +Copyright 2021 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 v1alpha4 + +import clusterv1 "sigs.k8s.io/cluster-api/api/v1alpha3" + +// Conditions and condition Reasons for the VSphereCluster object. + +const ( + // LoadBalancerAvailableCondition documents the status of the VSphereCluster load balancer. + LoadBalancerAvailableCondition clusterv1.ConditionType = "LoadBalancerAvailable" + + // LoadBalancerProvisioningReason (Severity=Info) documents a VSphereCluster provisioning a load balancer. + LoadBalancerProvisioningReason = "LoadBalancerProvisioning" + + // LoadBalancerProvisioningReason (Severity=Warning) documents a VSphereCluster controller detecting + // while provisioning the load balancer; those kind of errors are usually transient and failed provisioning + // are automatically re-tried by the controller. + LoadBalancerProvisioningFailedReason = "LoadBalancerProvisioningFailed" + + // CCMAvailableCondition documents the status of the VSphereCluster cloud controller manager addon. + CCMAvailableCondition clusterv1.ConditionType = "CCMAvailable" + + // CCMProvisioningFailedReason (Severity=Warning) documents a VSphereCluster controller detecting + // while installing the cloud controller manager addon; those kind of errors are usually transient + // the operation is automatically re-tried by the controller. + CCMProvisioningFailedReason = "CCMProvisioningFailed" + + // CSIAvailableCondition documents the status of the VSphereCluster container storage interface addon. + CSIAvailableCondition clusterv1.ConditionType = "CSIAvailable" + + // CSIProvisioningFailedReason (Severity=Warning) documents a VSphereCluster controller detecting + // while installing the container storage interface addon; those kind of errors are usually transient + // the operation is automatically re-tried by the controller. + CSIProvisioningFailedReason = "CSIProvisioningFailed" + + // VCenterAvailableCondition documents the connectivity with vcenter + // for a given VSphereCluster + VCenterAvailableCondition clusterv1.ConditionType = "VCenterAvailable" + + // VCenterUnreachableReason (Severity=Error) documents a VSphereCluster controller detecting + // issues with VCenter reachability; + VCenterUnreachableReason = "VCenterUnreachable" +) + +// Conditions and condition Reasons for the VSphereMachine and the VSphereVM object. +// +// NOTE: VSphereMachine wraps a VMSphereVM, some we are using a unique set of conditions and reasons in order +// to ensure a consistent UX; differences between the two objects will be highlighted in the comments. + +const ( + // VMProvisionedCondition documents the status of the provisioning of a VSphereMachine and its underlying VSphereVM. + VMProvisionedCondition clusterv1.ConditionType = "VMProvisioned" + + // WaitingForClusterInfrastructureReason (Severity=Info) documents a VSphereMachine waiting for the cluster + // infrastructure to be ready before starting the provisioning process. + // + // NOTE: This reason does not apply to VSphereVM (this state happens before the VSphereVM is actually created). + WaitingForClusterInfrastructureReason = "WaitingForClusterInfrastructure" + + // WaitingForBootstrapDataReason (Severity=Info) documents a VSphereMachine waiting for the bootstrap + // script to be ready before starting the provisioning process. + // + // NOTE: This reason does not apply to VSphereVM (this state happens before the VSphereVM is actually created). + WaitingForBootstrapDataReason = "WaitingForBootstrapData" + + // CloningReason documents (Severity=Info) a VSphereMachine/VSphereVM currently executing the clone operation. + CloningReason = "Cloning" + + // CloningFailedReason (Severity=Warning) documents a VSphereMachine/VSphereVM controller detecting + // an error while provisioning; those kind of errors are usually transient and failed provisioning + // are automatically re-tried by the controller. + CloningFailedReason = "CloningFailed" + + // PoweringOnReason documents (Severity=Info) a VSphereMachine/VSphereVM currently executing the power on sequence. + PoweringOnReason = "PoweringOn" + + // PoweringOnFailedReason (Severity=Warning) documents a VSphereMachine/VSphereVM controller detecting + // an error while powering on; those kind of errors are usually transient and failed provisioning + // are automatically re-tried by the controller. + PoweringOnFailedReason = "PoweringOnFailed" + + // TaskFailure (Severity=Warning) documents a VSphereMachine/VSphere task failure; the reconcile look will automatically + // retry the operation, but a user intervention might be required to fix the problem. + TaskFailure = "TaskFailure" + + // WaitingForNetworkAddressesReason (Severity=Info) documents a VSphereMachine waiting for the the machine network + // settings to be reported after machine being powered on. + // + // NOTE: This reason does not apply to VSphereVM (this state happens after the VSphereVM is in ready state). + WaitingForNetworkAddressesReason = "WaitingForNetworkAddresses" +) diff --git a/api/v1alpha4/doc.go b/api/v1alpha4/doc.go new file mode 100644 index 0000000000..9c7b07e946 --- /dev/null +++ b/api/v1alpha4/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2021 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 v1alpha4 contains API Schema definitions for the infrastructure v1alpha4 API group +// +kubebuilder:object:generate=true +// +groupName=infrastructure.cluster.x-k8s.io +package v1alpha4 diff --git a/api/v1alpha4/groupversion_info.go b/api/v1alpha4/groupversion_info.go new file mode 100644 index 0000000000..3f36ce0173 --- /dev/null +++ b/api/v1alpha4/groupversion_info.go @@ -0,0 +1,41 @@ +/* +Copyright 2021 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 v1alpha4 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +const ( + // Version is the API version. + Version = "v1alpha4" + + // GroupName is the name of the API group. + GroupName = "infrastructure.cluster.x-k8s.io" +) + +var ( + // GroupVersion is group version used to register these objects + GroupVersion = schema.GroupVersion{Group: GroupName, Version: Version} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) diff --git a/api/v1alpha4/haproxyloadbalancer_conversion.go b/api/v1alpha4/haproxyloadbalancer_conversion.go new file mode 100644 index 0000000000..207b9ec3da --- /dev/null +++ b/api/v1alpha4/haproxyloadbalancer_conversion.go @@ -0,0 +1,23 @@ +/* +Copyright 2019 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 v1alpha4 + +// Hub marks HAProxyLoadBalancer as a conversion hub. +func (*HAProxyLoadBalancer) Hub() {} + +// Hub marks HAProxyLoadBalancerList as a conversion hub. +func (*HAProxyLoadBalancerList) Hub() {} diff --git a/api/v1alpha4/haproxyloadbalancer_types.go b/api/v1alpha4/haproxyloadbalancer_types.go new file mode 100644 index 0000000000..9fd5f6233f --- /dev/null +++ b/api/v1alpha4/haproxyloadbalancer_types.go @@ -0,0 +1,89 @@ +/* +Copyright 2021 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 v1alpha4 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const ( + // HAProxyLoadBalancerFinalizer allows a reconciler to clean up + // resources associated with an HAProxyLoadBalancer before removing + // it from the API server. + HAProxyLoadBalancerFinalizer = "haproxyloadbalancer.infrastructure.cluster.x-k8s.io" +) + +// HAProxyLoadBalancerSpec defines the desired state of HAProxyLoadBalancer. +type HAProxyLoadBalancerSpec struct { + // VirtualMachineConfiguration is information used to deploy a load balancer + // VM. + VirtualMachineConfiguration VirtualMachineCloneSpec `json:"virtualMachineConfiguration"` + + // SSHUser specifies the name of a user that is granted remote access to the + // deployed VM. + // +optional + User *SSHUser `json:"user,omitempty"` +} + +// HAProxyLoadBalancerStatus defines the observed state of HAProxyLoadBalancer. +type HAProxyLoadBalancerStatus struct { + // Ready indicates whether or not the load balancer is ready. + // + // This field is required as part of the Portable Load Balancer model and is + // inspected via an unstructured reader by other controllers to determine + // the status of the load balancer. + // + // +optional + Ready bool `json:"ready,omitempty"` + + // Address is the IP address or DNS name of the load balancer. + // + // This field is required as part of the Portable Load Balancer model and is + // inspected via an unstructured reader by other controllers to determine + // the status of the load balancer. + // + // +optional + Address string `json:"address,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:resource:path=haproxyloadbalancers,scope=Namespaced +// +kubebuilder:storageversion +// +kubebuilder:subresource:status + +// HAProxyLoadBalancer is the Schema for the haproxyloadbalancers API +// DEPRECATED: will be removed in v1alpha4 +type HAProxyLoadBalancer struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec HAProxyLoadBalancerSpec `json:"spec,omitempty"` + Status HAProxyLoadBalancerStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// HAProxyLoadBalancerList contains a list of HAProxyLoadBalancer +type HAProxyLoadBalancerList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []HAProxyLoadBalancer `json:"items"` +} + +func init() { + SchemeBuilder.Register(&HAProxyLoadBalancer{}, &HAProxyLoadBalancerList{}) +} diff --git a/api/v1alpha4/haproxyloadbalancer_webhook.go b/api/v1alpha4/haproxyloadbalancer_webhook.go new file mode 100644 index 0000000000..fe978fe11a --- /dev/null +++ b/api/v1alpha4/haproxyloadbalancer_webhook.go @@ -0,0 +1,27 @@ +/* +Copyright 2021 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 v1alpha4 + +import ( + ctrl "sigs.k8s.io/controller-runtime" +) + +func (r *HAProxyLoadBalancer) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} diff --git a/api/v1alpha4/haproxyloadbalancerlist_webhook.go b/api/v1alpha4/haproxyloadbalancerlist_webhook.go new file mode 100644 index 0000000000..fcc9a4fd00 --- /dev/null +++ b/api/v1alpha4/haproxyloadbalancerlist_webhook.go @@ -0,0 +1,27 @@ +/* +Copyright 2021 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 v1alpha4 + +import ( + ctrl "sigs.k8s.io/controller-runtime" +) + +func (r *HAProxyLoadBalancerList) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} diff --git a/api/v1alpha4/types.go b/api/v1alpha4/types.go new file mode 100644 index 0000000000..2e686c5ea5 --- /dev/null +++ b/api/v1alpha4/types.go @@ -0,0 +1,342 @@ +/* +Copyright 2018 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 v1alpha4 + +import ( + "fmt" +) + +const ( + // AnnotationClusterInfrastructureReady indicates the cluster's + // infrastructure sources are ready and machines may be created. + AnnotationClusterInfrastructureReady = "vsphere.infrastructure.cluster.x-k8s.io/infrastructure-ready" + + // AnnotationControlPlaneReady indicates the cluster's control plane is + // ready. + AnnotationControlPlaneReady = "vsphere.infrastructure.cluster.x-k8s.io/control-plane-ready" + + // ValueReady is the ready value for *Ready annotations. + ValueReady = "true" +) + +// CloneMode is the type of clone operation used to clone a VM from a template. +type CloneMode string + +const ( + // FullClone indicates a VM will have no relationship to the source of the + // clone operation once the operation is complete. This is the safest clone + // mode, but it is not the fastest. + FullClone CloneMode = "fullClone" + + // LinkedClone means resulting VMs will be dependent upon the snapshot of + // the source VM/template from which the VM was cloned. This is the fastest + // clone mode, but it also prevents expanding a VMs disk beyond the size of + // the source VM/template. + LinkedClone CloneMode = "linkedClone" +) + +// VirtualMachineCloneSpec is information used to clone a virtual machine. +type VirtualMachineCloneSpec struct { + // Template is the name or inventory path of the template used to clone + // the virtual machine. + // +kubebuilder:validation:MinLength=1 + Template string `json:"template"` + + // CloneMode specifies the type of clone operation. + // The LinkedClone mode is only support for templates that have at least + // one snapshot. If the template has no snapshots, then CloneMode defaults + // to FullClone. + // When LinkedClone mode is enabled the DiskGiB field is ignored as it is + // not possible to expand disks of linked clones. + // Defaults to LinkedClone, but fails gracefully to FullClone if the source + // of the clone operation has no snapshots. + // +optional + CloneMode CloneMode `json:"cloneMode,omitempty"` + + // Snapshot is the name of the snapshot from which to create a linked clone. + // This field is ignored if LinkedClone is not enabled. + // Defaults to the source's current snapshot. + // +optional + Snapshot string `json:"snapshot,omitempty"` + + // Server is the IP address or FQDN of the vSphere server on which + // the virtual machine is created/located. + // +optional + Server string `json:"server,omitempty"` + + // Thumbprint is the colon-separated SHA-1 checksum of the given vCenter server's host certificate + // When this is set to empty, this VirtualMachine would be created + // without TLS certificate validation of the communication between Cluster API Provider vSphere + // and the VMware vCenter server. + // +optional + Thumbprint string `json:"thumbprint,omitempty"` + + // Datacenter is the name or inventory path of the datacenter in which the + // virtual machine is created/located. + // +optional + Datacenter string `json:"datacenter,omitempty"` + + // Folder is the name or inventory path of the folder in which the + // virtual machine is created/located. + // +optional + Folder string `json:"folder,omitempty"` + + // Datastore is the name or inventory path of the datastore in which the + // virtual machine is created/located. + // +optional + Datastore string `json:"datastore,omitempty"` + + // StoragePolicyName of the storage policy to use with this + // Virtual Machine + // +optional + StoragePolicyName string `json:"storagePolicyName,omitempty"` + + // ResourcePool is the name or inventory path of the resource pool in which + // the virtual machine is created/located. + // +optional + ResourcePool string `json:"resourcePool,omitempty"` + + // Network is the network configuration for this machine's VM. + Network NetworkSpec `json:"network"` + + // NumCPUs is the number of virtual processors in a virtual machine. + // Defaults to the eponymous property value in the template from which the + // virtual machine is cloned. + // +optional + NumCPUs int32 `json:"numCPUs,omitempty"` + // NumCPUs is the number of cores among which to distribute CPUs in this + // virtual machine. + // Defaults to the eponymous property value in the template from which the + // virtual machine is cloned. + // +optional + NumCoresPerSocket int32 `json:"numCoresPerSocket,omitempty"` + // MemoryMiB is the size of a virtual machine's memory, in MiB. + // Defaults to the eponymous property value in the template from which the + // virtual machine is cloned. + // +optional + MemoryMiB int64 `json:"memoryMiB,omitempty"` + // DiskGiB is the size of a virtual machine's disk, in GiB. + // Defaults to the eponymous property value in the template from which the + // virtual machine is cloned. + // +optional + DiskGiB int32 `json:"diskGiB,omitempty"` + // CustomVMXKeys is a dictionary of advanced VMX options that can be set on VM + // Defaults to empty map + // +optional + CustomVMXKeys map[string]string `json:"customVMXKeys,omitempty"` +} + +// VSphereMachineTemplateResource describes the data needed to create a VSphereMachine from a template +type VSphereMachineTemplateResource struct { + // Spec is the specification of the desired behavior of the machine. + Spec VSphereMachineSpec `json:"spec"` +} + +// VSphereMachineProviderConditionType is a valid value for VSphereMachineProviderCondition.Type +type VSphereMachineProviderConditionType string + +// Valid conditions for an VSphere machine instance +const ( + // MachineCreated indicates whether the machine has been created or not. If not, + // it should include a reason and message for the failure. + MachineCreated VSphereMachineProviderConditionType = "MachineCreated" +) + +// APIEndpoint represents a reachable Kubernetes API endpoint. +type APIEndpoint struct { + // The hostname on which the API server is serving. + Host string `json:"host"` + + // The port on which the API server is serving. + Port int32 `json:"port"` +} + +// IsZero returns true if either the host or the port are zero values. +func (v APIEndpoint) IsZero() bool { + return v.Host == "" || v.Port == 0 +} + +// String returns a formatted version HOST:PORT of this APIEndpoint. +func (v APIEndpoint) String() string { + return fmt.Sprintf("%s:%d", v.Host, v.Port) +} + +// NetworkSpec defines the virtual machine's network configuration. +type NetworkSpec struct { + // Devices is the list of network devices used by the virtual machine. + // TODO(akutz) Make sure at least one network matches the + // ClusterSpec.CloudProviderConfiguration.Network.Name + Devices []NetworkDeviceSpec `json:"devices"` + + // Routes is a list of optional, static routes applied to the virtual + // machine. + // +optional + Routes []NetworkRouteSpec `json:"routes,omitempty"` + + // PreferredAPIServeCIDR is the preferred CIDR for the Kubernetes API + // server endpoint on this machine + // +optional + PreferredAPIServerCIDR string `json:"preferredAPIServerCidr,omitempty"` +} + +// NetworkDeviceSpec defines the network configuration for a virtual machine's +// network device. +type NetworkDeviceSpec struct { + // NetworkName is the name of the vSphere network to which the device + // will be connected. + NetworkName string `json:"networkName"` + + // DeviceName may be used to explicitly assign a name to the network device + // as it exists in the guest operating system. + // +optional + DeviceName string `json:"deviceName,omitempty"` + + // DHCP4 is a flag that indicates whether or not to use DHCP for IPv4 + // on this device. + // If true then IPAddrs should not contain any IPv4 addresses. + // +optional + DHCP4 bool `json:"dhcp4,omitempty"` + + // DHCP6 is a flag that indicates whether or not to use DHCP for IPv6 + // on this device. + // If true then IPAddrs should not contain any IPv6 addresses. + // +optional + DHCP6 bool `json:"dhcp6,omitempty"` + + // Gateway4 is the IPv4 gateway used by this device. + // Required when DHCP4 is false. + // +optional + Gateway4 string `json:"gateway4,omitempty"` + + // Gateway4 is the IPv4 gateway used by this device. + // Required when DHCP6 is false. + // +optional + Gateway6 string `json:"gateway6,omitempty"` + + // IPAddrs is a list of one or more IPv4 and/or IPv6 addresses to assign + // to this device. + // Required when DHCP4 and DHCP6 are both false. + // +optional + IPAddrs []string `json:"ipAddrs,omitempty"` + + // MTU is the device’s Maximum Transmission Unit size in bytes. + // +optional + MTU *int64 `json:"mtu,omitempty"` + + // MACAddr is the MAC address used by this device. + // It is generally a good idea to omit this field and allow a MAC address + // to be generated. + // Please note that this value must use the VMware OUI to work with the + // in-tree vSphere cloud provider. + // +optional + MACAddr string `json:"macAddr,omitempty"` + + // Nameservers is a list of IPv4 and/or IPv6 addresses used as DNS + // nameservers. + // Please note that Linux allows only three nameservers (https://linux.die.net/man/5/resolv.conf). + // +optional + Nameservers []string `json:"nameservers,omitempty"` + + // Routes is a list of optional, static routes applied to the device. + // +optional + Routes []NetworkRouteSpec `json:"routes,omitempty"` + + // SearchDomains is a list of search domains used when resolving IP + // addresses with DNS. + // +optional + SearchDomains []string `json:"searchDomains,omitempty"` +} + +// NetworkRouteSpec defines a static network route. +type NetworkRouteSpec struct { + // To is an IPv4 or IPv6 address. + To string `json:"to"` + // Via is an IPv4 or IPv6 address. + Via string `json:"via"` + // Metric is the weight/priority of the route. + Metric int32 `json:"metric"` +} + +// NetworkStatus provides information about one of a VM's networks. +type NetworkStatus struct { + // Connected is a flag that indicates whether this network is currently + // connected to the VM. + Connected bool `json:"connected,omitempty"` + + // IPAddrs is one or more IP addresses reported by vm-tools. + // +optional + IPAddrs []string `json:"ipAddrs,omitempty"` + + // MACAddr is the MAC address of the network device. + MACAddr string `json:"macAddr"` + + // NetworkName is the name of the network. + // +optional + NetworkName string `json:"networkName,omitempty"` +} + +// VirtualMachineState describes the state of a VM. +type VirtualMachineState string + +const ( + // VirtualMachineStateNotFound is the string representing a VM that + // cannot be located. + VirtualMachineStateNotFound VirtualMachineState = "notfound" + + // VirtualMachineStatePending is the string representing a VM with an in-flight task. + VirtualMachineStatePending = "pending" + + // VirtualMachineStateReady is the string representing a powered-on VM with reported IP addresses. + VirtualMachineStateReady = "ready" +) + +// VirtualMachinePowerState describe the power state of a VM +type VirtualMachinePowerState string + +const ( + // VirtualMachinePowerStatePoweredOn is the string representing a VM in powered on state + VirtualMachinePowerStatePoweredOn VirtualMachinePowerState = "poweredOn" + + // VirtualMachinePowerStatePoweredOff is the string representing a VM in powered off state + VirtualMachinePowerStatePoweredOff = "poweredOff" + + // VirtualMachinePowerStateSuspended is the string representing a VM in suspended state + VirtualMachinePowerStateSuspended = "suspended" +) + +// VirtualMachine represents data about a vSphere virtual machine object. +type VirtualMachine struct { + // Name is the VM's name. + Name string `json:"name"` + + // BiosUUID is the VM's BIOS UUID. + BiosUUID string `json:"biosUUID"` + + // State is the VM's state. + State VirtualMachineState `json:"state"` + + // Network is the status of the VM's network devices. + Network []NetworkStatus `json:"network"` +} + +// SSHUser is granted remote access to a system. +type SSHUser struct { + // Name is the name of the SSH user. + Name string `json:"name"` + // AuthorizedKeys is one or more public SSH keys that grant remote access. + AuthorizedKeys []string `json:"authorizedKeys"` +} diff --git a/api/v1alpha4/vspherecluster_conversion.go b/api/v1alpha4/vspherecluster_conversion.go new file mode 100644 index 0000000000..bdaf2fc971 --- /dev/null +++ b/api/v1alpha4/vspherecluster_conversion.go @@ -0,0 +1,23 @@ +/* +Copyright 2021 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 v1alpha4 + +// Hub marks VSphereCluster as a conversion hub. +func (*VSphereCluster) Hub() {} + +// Hub marks VSphereClusterList as a conversion hub. +func (*VSphereClusterList) Hub() {} diff --git a/api/v1alpha4/vspherecluster_types.go b/api/v1alpha4/vspherecluster_types.go new file mode 100644 index 0000000000..f6d494d3fb --- /dev/null +++ b/api/v1alpha4/vspherecluster_types.go @@ -0,0 +1,110 @@ +/* +Copyright 2021 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 v1alpha4 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + clusterv1 "sigs.k8s.io/cluster-api/api/v1alpha3" +) + +const ( + // ClusterFinalizer allows ReconcileVSphereCluster to clean up vSphere + // resources associated with VSphereCluster before removing it from the + // API server. + ClusterFinalizer = "vspherecluster.infrastructure.cluster.x-k8s.io" +) + +// VSphereClusterSpec defines the desired state of VSphereCluster +type VSphereClusterSpec struct { + // Server is the address of the vSphere endpoint. + Server string `json:"server,omitempty"` + + // Insecure is a flag that controls whether or not to validate the + // vSphere server's certificate. + // DEPRECATED: will be removed in v1alpha4 + // +optional + Insecure *bool `json:"insecure,omitempty"` + + // Thumbprint is the colon-separated SHA-1 checksum of the given vCenter server's host certificate + // When provided, Insecure should not be set to true + // +optional + Thumbprint string `json:"thumbprint,omitempty"` + + // CloudProviderConfiguration holds the cluster-wide configuration for the + // DEPRECATED: will be removed in v1alpha4 + // vSphere cloud provider. + CloudProviderConfiguration CPIConfig `json:"cloudProviderConfiguration,omitempty"` + + // ControlPlaneEndpoint represents the endpoint used to communicate with the control plane. + // +optional + ControlPlaneEndpoint APIEndpoint `json:"controlPlaneEndpoint"` + + // LoadBalancerRef may be used to enable a control plane load balancer + // for this cluster. + // When a LoadBalancerRef is provided, the VSphereCluster.Status.Ready field + // will not be true until the referenced resource is Status.Ready and has a + // non-empty Status.Address value. + // DEPRECATED: will be removed in v1alpha4 + // +optional + LoadBalancerRef *corev1.ObjectReference `json:"loadBalancerRef,omitempty"` +} + +// VSphereClusterStatus defines the observed state of VSphereClusterSpec +type VSphereClusterStatus struct { + // +optional + Ready bool `json:"ready,omitempty"` + + // Conditions defines current service state of the VSphereCluster. + // +optional + Conditions clusterv1.Conditions `json:"conditions,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:resource:path=vsphereclusters,scope=Namespaced,categories=cluster-api +// +kubebuilder:storageversion +// +kubebuilder:subresource:status + +// VSphereCluster is the Schema for the vsphereclusters API +type VSphereCluster struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec VSphereClusterSpec `json:"spec,omitempty"` + Status VSphereClusterStatus `json:"status,omitempty"` +} + +func (m *VSphereCluster) GetConditions() clusterv1.Conditions { + return m.Status.Conditions +} + +func (m *VSphereCluster) SetConditions(conditions clusterv1.Conditions) { + m.Status.Conditions = conditions +} + +// +kubebuilder:object:root=true + +// VSphereClusterList contains a list of VSphereCluster +type VSphereClusterList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []VSphereCluster `json:"items"` +} + +func init() { + SchemeBuilder.Register(&VSphereCluster{}, &VSphereClusterList{}) +} diff --git a/api/v1alpha4/vspherecluster_webhook.go b/api/v1alpha4/vspherecluster_webhook.go new file mode 100644 index 0000000000..5efee3a3db --- /dev/null +++ b/api/v1alpha4/vspherecluster_webhook.go @@ -0,0 +1,53 @@ +/* +Copyright 2021 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 v1alpha4 + +import ( + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/validation/field" + ctrl "sigs.k8s.io/controller-runtime" +) + +func (r *VSphereCluster) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} + +// +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1alpha4-vspherecluster,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=vsphereclusters,versions=v1alpha4,name=validation.vspherecluster.infrastructure.x-k8s.io,sideEffects=None + +// ValidateCreate implements webhook.Validator so a webhook will be registered for the type +func (r *VSphereCluster) ValidateCreate() error { + var allErrs field.ErrorList + spec := r.Spec + + if spec.Thumbprint != "" && spec.Insecure != nil && *spec.Insecure { + allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "Insecure"), spec.Insecure, "cannot be set to true at the same time as .spec.Thumbprint")) + } + + return aggregateObjErrors(r.GroupVersionKind().GroupKind(), r.Name, allErrs) +} + +// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type +func (r *VSphereCluster) ValidateUpdate(old runtime.Object) error { + return nil +} + +// ValidateDelete implements webhook.Validator so a webhook will be registered for the type +func (r *VSphereCluster) ValidateDelete() error { + return nil +} diff --git a/api/v1alpha4/vspherecluster_webhook_test.go b/api/v1alpha4/vspherecluster_webhook_test.go new file mode 100644 index 0000000000..53c8a5323d --- /dev/null +++ b/api/v1alpha4/vspherecluster_webhook_test.go @@ -0,0 +1,71 @@ +/* +Copyright 2021 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 v1alpha4 + +import ( + "testing" + + . "github.com/onsi/gomega" +) + +//nolint +func TestVSphereCluster_ValidateCreate(t *testing.T) { + + g := NewWithT(t) + tests := []struct { + name string + vsphereCluster *VSphereCluster + wantErr bool + }{ + { + name: "insecure true with empty thumbprint", + vsphereCluster: createVSphereCluster("foo.com", true, ""), + wantErr: false, + }, + { + name: "insecure false with non-empty thumbprint", + vsphereCluster: createVSphereCluster("foo.com", false, "thumprint:foo"), + wantErr: false, + }, + { + name: "insecure true with non-empty thumbprint", + vsphereCluster: createVSphereCluster("foo.com", true, "thumprint:foo"), + wantErr: true, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + err := tc.vsphereCluster.ValidateCreate() + if tc.wantErr { + g.Expect(err).To(HaveOccurred()) + } else { + g.Expect(err).NotTo(HaveOccurred()) + } + }) + } +} + +func createVSphereCluster(server string, insecure bool, thumbprint string) *VSphereCluster { + vsphereCluster := &VSphereCluster{ + Spec: VSphereClusterSpec{ + Server: server, + Insecure: &insecure, + Thumbprint: thumbprint, + }, + } + return vsphereCluster +} diff --git a/api/v1alpha4/vsphereclusterlist_webhook.go b/api/v1alpha4/vsphereclusterlist_webhook.go new file mode 100644 index 0000000000..2dec7f9189 --- /dev/null +++ b/api/v1alpha4/vsphereclusterlist_webhook.go @@ -0,0 +1,27 @@ +/* +Copyright 2021 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 v1alpha4 + +import ( + ctrl "sigs.k8s.io/controller-runtime" +) + +func (r *VSphereClusterList) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} diff --git a/api/v1alpha4/vspheremachine_conversion.go b/api/v1alpha4/vspheremachine_conversion.go new file mode 100644 index 0000000000..97f28684f7 --- /dev/null +++ b/api/v1alpha4/vspheremachine_conversion.go @@ -0,0 +1,23 @@ +/* +Copyright 2021 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 v1alpha4 + +// Hub marks VSphereMachine as a conversion hub. +func (*VSphereMachine) Hub() {} + +// Hub marks VSphereMachineList as a conversion hub. +func (*VSphereMachineList) Hub() {} diff --git a/api/v1alpha4/vspheremachine_types.go b/api/v1alpha4/vspheremachine_types.go new file mode 100644 index 0000000000..ce2e411dbb --- /dev/null +++ b/api/v1alpha4/vspheremachine_types.go @@ -0,0 +1,132 @@ +/* +Copyright 2021 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 v1alpha4 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + clusterv1 "sigs.k8s.io/cluster-api/api/v1alpha3" + "sigs.k8s.io/cluster-api/errors" +) + +const ( + // MachineFinalizer allows ReconcileVSphereMachine to clean up VSphere + // resources associated with VSphereMachine before removing it from the + // API Server. + MachineFinalizer = "vspheremachine.infrastructure.cluster.x-k8s.io" +) + +// VSphereMachineSpec defines the desired state of VSphereMachine +type VSphereMachineSpec struct { + VirtualMachineCloneSpec `json:",inline"` + + // ProviderID is the virtual machine's BIOS UUID formated as + // vsphere://12345678-1234-1234-1234-123456789abc + // +optional + ProviderID *string `json:"providerID,omitempty"` +} + +// VSphereMachineStatus defines the observed state of VSphereMachine +type VSphereMachineStatus struct { + // Ready is true when the provider resource is ready. + // +optional + Ready bool `json:"ready"` + + // Addresses contains the VSphere instance associated addresses. + Addresses []clusterv1.MachineAddress `json:"addresses,omitempty"` + + // Network returns the network status for each of the machine's configured + // network interfaces. + // +optional + Network []NetworkStatus `json:"network,omitempty"` + + // FailureReason will be set in the event that there is a terminal problem + // reconciling the Machine and will contain a succinct value suitable + // for machine interpretation. + // + // This field should not be set for transitive errors that a controller + // faces that are expected to be fixed automatically over + // time (like service outages), but instead indicate that something is + // fundamentally wrong with the Machine's spec or the configuration of + // the controller, and that manual intervention is required. Examples + // of terminal errors would be invalid combinations of settings in the + // spec, values that are unsupported by the controller, or the + // responsible controller itself being critically misconfigured. + // + // Any transient errors that occur during the reconciliation of Machines + // can be added as events to the Machine object and/or logged in the + // controller's output. + // +optional + FailureReason *errors.MachineStatusError `json:"failureReason,omitempty"` + + // FailureMessage will be set in the event that there is a terminal problem + // reconciling the Machine and will contain a more verbose string suitable + // for logging and human consumption. + // + // This field should not be set for transitive errors that a controller + // faces that are expected to be fixed automatically over + // time (like service outages), but instead indicate that something is + // fundamentally wrong with the Machine's spec or the configuration of + // the controller, and that manual intervention is required. Examples + // of terminal errors would be invalid combinations of settings in the + // spec, values that are unsupported by the controller, or the + // responsible controller itself being critically misconfigured. + // + // Any transient errors that occur during the reconciliation of Machines + // can be added as events to the Machine object and/or logged in the + // controller's output. + // +optional + FailureMessage *string `json:"failureMessage,omitempty"` + + // Conditions defines current service state of the VSphereMachine. + // +optional + Conditions clusterv1.Conditions `json:"conditions,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:resource:path=vspheremachines,scope=Namespaced,categories=cluster-api +// +kubebuilder:storageversion +// +kubebuilder:subresource:status + +// VSphereMachine is the Schema for the vspheremachines API +type VSphereMachine struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec VSphereMachineSpec `json:"spec,omitempty"` + Status VSphereMachineStatus `json:"status,omitempty"` +} + +func (m *VSphereMachine) GetConditions() clusterv1.Conditions { + return m.Status.Conditions +} + +func (m *VSphereMachine) SetConditions(conditions clusterv1.Conditions) { + m.Status.Conditions = conditions +} + +// +kubebuilder:object:root=true + +// VSphereMachineList contains a list of VSphereMachine +type VSphereMachineList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []VSphereMachine `json:"items"` +} + +func init() { + SchemeBuilder.Register(&VSphereMachine{}, &VSphereMachineList{}) +} diff --git a/api/v1alpha4/vspheremachine_webhook.go b/api/v1alpha4/vspheremachine_webhook.go new file mode 100644 index 0000000000..099ff1c2f2 --- /dev/null +++ b/api/v1alpha4/vspheremachine_webhook.go @@ -0,0 +1,96 @@ +/* +Copyright 2021 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 v1alpha4 + +import ( + "fmt" + "net" + "reflect" + + "github.com/pkg/errors" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/validation/field" + ctrl "sigs.k8s.io/controller-runtime" +) + +func (r *VSphereMachine) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} + +// +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1alpha4-vspheremachine,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=vspheremachines,versions=v1alpha4,name=validation.vspheremachine.infrastructure.x-k8s.io,sideEffects=None + +// ValidateCreate implements webhook.Validator so a webhook will be registered for the type +func (r *VSphereMachine) ValidateCreate() error { + var allErrs field.ErrorList + spec := r.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")) + } + + for i, device := range spec.Network.Devices { + for j, ip := range device.IPAddrs { + if _, _, err := net.ParseCIDR(ip); err != nil { + allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "network", fmt.Sprintf("devices[%d]", i), fmt.Sprintf("ipAddrs[%d]", j)), ip, "ip addresses should be in the CIDR format")) + } + } + } + + return aggregateObjErrors(r.GroupVersionKind().GroupKind(), r.Name, allErrs) +} + +// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type +func (r *VSphereMachine) ValidateUpdate(old runtime.Object) error { + newVSphereMachine, err := runtime.DefaultUnstructuredConverter.ToUnstructured(r) + if err != nil { + return apierrors.NewInternalError(errors.Wrap(err, "failed to convert new VSphereMachine to unstructured object")) + } + oldVSphereMachine, err := runtime.DefaultUnstructuredConverter.ToUnstructured(old) + if err != nil { + return apierrors.NewInternalError(errors.Wrap(err, "failed to convert old VSphereMachine to unstructured object")) + } + + var allErrs field.ErrorList + + newVSphereMachineSpec := newVSphereMachine["spec"].(map[string]interface{}) + oldVSphereMachineSpec := oldVSphereMachine["spec"].(map[string]interface{}) + + // allow changes to providerID + delete(oldVSphereMachineSpec, "providerID") + delete(newVSphereMachineSpec, "providerID") + + newVSphereMachineNetwork := newVSphereMachineSpec["network"].(map[string]interface{}) + oldVSphereMachineNetwork := oldVSphereMachineSpec["network"].(map[string]interface{}) + + // allow changes to the devices + delete(oldVSphereMachineNetwork, "devices") + delete(newVSphereMachineNetwork, "devices") + + if !reflect.DeepEqual(oldVSphereMachineSpec, newVSphereMachineSpec) { + allErrs = append(allErrs, field.Forbidden(field.NewPath("spec"), "cannot be modified")) + } + + return aggregateObjErrors(r.GroupVersionKind().GroupKind(), r.Name, allErrs) +} + +// ValidateDelete implements webhook.Validator so a webhook will be registered for the type +func (r *VSphereMachine) ValidateDelete() error { + return nil +} diff --git a/api/v1alpha4/vspheremachine_webhook_test.go b/api/v1alpha4/vspheremachine_webhook_test.go new file mode 100644 index 0000000000..9af4e13d6f --- /dev/null +++ b/api/v1alpha4/vspheremachine_webhook_test.go @@ -0,0 +1,127 @@ +/* +Copyright 2021 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 v1alpha4 + +import ( + "testing" + + . "github.com/onsi/gomega" +) + +var ( + someProviderID = "vsphere://42305f0b-dad7-1d3d-5727-0eaffffffffc" +) + +//nolint +func TestVSphereMachine_ValidateCreate(t *testing.T) { + + g := NewWithT(t) + tests := []struct { + name string + vsphereMachine *VSphereMachine + wantErr bool + }{ + { + name: "preferredAPIServerCIDR set on creation ", + vsphereMachine: createVSphereMachine("foo.com", nil, "192.168.0.1/32", []string{}), + wantErr: true, + }, + { + name: "IPs are not in CIDR format", + vsphereMachine: createVSphereMachine("foo.com", nil, "", []string{"192.168.0.1/32", "192.168.0.3"}), + wantErr: true, + }, + { + name: "successful VSphereMachine creation", + vsphereMachine: createVSphereMachine("foo.com", nil, "", []string{"192.168.0.1/32", "192.168.0.3/32"}), + wantErr: false, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + err := tc.vsphereMachine.ValidateCreate() + if tc.wantErr { + g.Expect(err).To(HaveOccurred()) + } else { + g.Expect(err).NotTo(HaveOccurred()) + } + }) + } +} + +//nolint +func TestVSphereMachine_ValidateUpdate(t *testing.T) { + + g := NewWithT(t) + + tests := []struct { + name string + oldVSphereMachine *VSphereMachine + vsphereMachine *VSphereMachine + wantErr bool + }{ + { + name: "ProviderID can be updated", + oldVSphereMachine: createVSphereMachine("foo.com", nil, "", []string{"192.168.0.1/32"}), + vsphereMachine: createVSphereMachine("foo.com", &someProviderID, "", []string{"192.168.0.1/32"}), + wantErr: false, + }, + { + name: "updating ips can be done", + oldVSphereMachine: createVSphereMachine("foo.com", nil, "", []string{"192.168.0.1/32"}), + vsphereMachine: createVSphereMachine("foo.com", &someProviderID, "", []string{"192.168.0.1/32", "192.168.0.10/32"}), + wantErr: false, + }, + { + name: "updating server cannot be done", + oldVSphereMachine: createVSphereMachine("foo.com", nil, "", []string{"192.168.0.1/32"}), + vsphereMachine: createVSphereMachine("bar.com", &someProviderID, "", []string{"192.168.0.1/32", "192.168.0.10/32"}), + wantErr: true, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + err := tc.vsphereMachine.ValidateUpdate(tc.oldVSphereMachine) + if tc.wantErr { + g.Expect(err).To(HaveOccurred()) + } else { + g.Expect(err).NotTo(HaveOccurred()) + } + }) + } +} + +func createVSphereMachine(server string, providerID *string, preferredAPIServerCIDR string, ips []string) *VSphereMachine { + VSphereMachine := &VSphereMachine{ + Spec: VSphereMachineSpec{ + ProviderID: providerID, + VirtualMachineCloneSpec: VirtualMachineCloneSpec{ + Server: server, + Network: NetworkSpec{ + PreferredAPIServerCIDR: preferredAPIServerCIDR, + Devices: []NetworkDeviceSpec{}, + }, + }, + }, + } + for _, ip := range ips { + VSphereMachine.Spec.Network.Devices = append(VSphereMachine.Spec.Network.Devices, NetworkDeviceSpec{ + IPAddrs: []string{ip}, + }) + } + return VSphereMachine +} diff --git a/api/v1alpha4/vspheremachinelist_webhook.go b/api/v1alpha4/vspheremachinelist_webhook.go new file mode 100644 index 0000000000..21e8610c6b --- /dev/null +++ b/api/v1alpha4/vspheremachinelist_webhook.go @@ -0,0 +1,27 @@ +/* +Copyright 2021 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 v1alpha4 + +import ( + ctrl "sigs.k8s.io/controller-runtime" +) + +func (r *VSphereMachineList) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} diff --git a/api/v1alpha4/vspheremachinetemplate_conversion.go b/api/v1alpha4/vspheremachinetemplate_conversion.go new file mode 100644 index 0000000000..03bc5c33c0 --- /dev/null +++ b/api/v1alpha4/vspheremachinetemplate_conversion.go @@ -0,0 +1,23 @@ +/* +Copyright 2021 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 v1alpha4 + +// Hub marks VSphereMachineTemplate as a conversion hub. +func (*VSphereMachineTemplate) Hub() {} + +// Hub marks VSphereMachineTemplateList as a conversion hub. +func (*VSphereMachineTemplateList) Hub() {} diff --git a/api/v1alpha4/vspheremachinetemplate_types.go b/api/v1alpha4/vspheremachinetemplate_types.go new file mode 100644 index 0000000000..5d731eda63 --- /dev/null +++ b/api/v1alpha4/vspheremachinetemplate_types.go @@ -0,0 +1,51 @@ +/* +Copyright 2021 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 v1alpha4 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// VSphereMachineTemplateSpec defines the desired state of VSphereMachineTemplate +type VSphereMachineTemplateSpec struct { + Template VSphereMachineTemplateResource `json:"template"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:resource:path=vspheremachinetemplates,scope=Namespaced,categories=cluster-api +// +kubebuilder:storageversion + +// VSphereMachineTemplate is the Schema for the vspheremachinetemplates API +type VSphereMachineTemplate struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec VSphereMachineTemplateSpec `json:"spec,omitempty"` +} + +// +kubebuilder:object:root=true + +// VSphereMachineTemplateList contains a list of VSphereMachineTemplate +type VSphereMachineTemplateList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []VSphereMachineTemplate `json:"items"` +} + +func init() { + SchemeBuilder.Register(&VSphereMachineTemplate{}, &VSphereMachineTemplateList{}) +} diff --git a/api/v1alpha4/vspheremachinetemplate_webhook.go b/api/v1alpha4/vspheremachinetemplate_webhook.go new file mode 100644 index 0000000000..e8187e181c --- /dev/null +++ b/api/v1alpha4/vspheremachinetemplate_webhook.go @@ -0,0 +1,73 @@ +/* +Copyright 2021 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 v1alpha4 + +import ( + "reflect" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/validation/field" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/webhook" +) + +func (r *VSphereMachineTemplate) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} + +// +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1alpha4-vspheremachinetemplate,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=vspheremachinetemplates,versions=v1alpha4,name=validation.vspheremachinetemplate.infrastructure.x-k8s.io,sideEffects=None + +var _ webhook.Validator = &VSphereMachineTemplate{} + +// ValidateCreate implements webhook.Validator so a webhook will be registered for the type +func (r *VSphereMachineTemplate) ValidateCreate() error { + var allErrs field.ErrorList + spec := r.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) +} + +// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type +func (r *VSphereMachineTemplate) ValidateUpdate(old runtime.Object) error { + oldVSphereMachineTemplate := old.(*VSphereMachineTemplate) + if !reflect.DeepEqual(r.Spec, oldVSphereMachineTemplate.Spec) { + return field.Forbidden(field.NewPath("spec"), "VSphereMachineTemplateSpec is immutable") + } + + return nil +} + +// ValidateDelete implements webhook.Validator so a webhook will be registered for the type +func (r *VSphereMachineTemplate) ValidateDelete() error { + return nil +} diff --git a/api/v1alpha4/vspheremachinetemplate_webhooks_test.go b/api/v1alpha4/vspheremachinetemplate_webhooks_test.go new file mode 100644 index 0000000000..4a46daa0a2 --- /dev/null +++ b/api/v1alpha4/vspheremachinetemplate_webhooks_test.go @@ -0,0 +1,132 @@ +/* +Copyright 2021 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 v1alpha4 + +import ( + "testing" + + . "github.com/onsi/gomega" +) + +//nolint +func TestVSphereMachineTemplate_ValidateCreate(t *testing.T) { + + g := NewWithT(t) + tests := []struct { + name string + vsphereMachine *VSphereMachineTemplate + wantErr bool + }{ + { + name: "preferredAPIServerCIDR set on creation ", + vsphereMachine: createVSphereMachineTemplate("foo.com", nil, "192.168.0.1/32", []string{}), + wantErr: true, + }, + { + name: "ProviderID set on creation", + vsphereMachine: createVSphereMachineTemplate("foo.com", &someProviderID, "", []string{}), + wantErr: true, + }, + { + name: "IPs are not in CIDR format", + vsphereMachine: createVSphereMachineTemplate("foo.com", nil, "", []string{"192.168.0.1/32", "192.168.0.3"}), + wantErr: true, + }, + { + name: "successful VSphereMachine creation", + vsphereMachine: createVSphereMachineTemplate("foo.com", nil, "", []string{"192.168.0.1/32", "192.168.0.3/32"}), + wantErr: true, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + err := tc.vsphereMachine.ValidateCreate() + if tc.wantErr { + g.Expect(err).To(HaveOccurred()) + } else { + g.Expect(err).NotTo(HaveOccurred()) + } + }) + } +} + +//nolint +func TestVSphereMachineTemplate_ValidateUpdate(t *testing.T) { + + g := NewWithT(t) + + tests := []struct { + name string + oldVSphereMachine *VSphereMachineTemplate + vsphereMachine *VSphereMachineTemplate + wantErr bool + }{ + { + name: "ProviderID cannot be updated", + oldVSphereMachine: createVSphereMachineTemplate("foo.com", nil, "", []string{"192.168.0.1/32"}), + vsphereMachine: createVSphereMachineTemplate("foo.com", &someProviderID, "", []string{"192.168.0.1/32"}), + wantErr: true, + }, + { + name: "updating ips cannot be done", + oldVSphereMachine: createVSphereMachineTemplate("foo.com", nil, "", []string{"192.168.0.1/32"}), + vsphereMachine: createVSphereMachineTemplate("foo.com", &someProviderID, "", []string{"192.168.0.1/32", "192.168.0.10/32"}), + wantErr: true, + }, + { + name: "updating server cannot be done", + oldVSphereMachine: createVSphereMachineTemplate("foo.com", nil, "", []string{"192.168.0.1/32"}), + vsphereMachine: createVSphereMachineTemplate("baz.com", &someProviderID, "", []string{"192.168.0.1/32", "192.168.0.10/32"}), + wantErr: true, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + err := tc.vsphereMachine.ValidateUpdate(tc.oldVSphereMachine) + if tc.wantErr { + g.Expect(err).To(HaveOccurred()) + } else { + g.Expect(err).NotTo(HaveOccurred()) + } + }) + } +} + +func createVSphereMachineTemplate(server string, providerID *string, preferredAPIServerCIDR string, ips []string) *VSphereMachineTemplate { + VSphereMachineTemplate := &VSphereMachineTemplate{ + Spec: VSphereMachineTemplateSpec{ + Template: VSphereMachineTemplateResource{ + Spec: VSphereMachineSpec{ + ProviderID: providerID, + VirtualMachineCloneSpec: VirtualMachineCloneSpec{ + Server: server, + Network: NetworkSpec{ + PreferredAPIServerCIDR: preferredAPIServerCIDR, + Devices: []NetworkDeviceSpec{}, + }, + }, + }, + }, + }, + } + for _, ip := range ips { + VSphereMachineTemplate.Spec.Template.Spec.Network.Devices = append(VSphereMachineTemplate.Spec.Template.Spec.Network.Devices, NetworkDeviceSpec{ + IPAddrs: []string{ip}, + }) + } + return VSphereMachineTemplate +} diff --git a/api/v1alpha4/vspheremachinetemplatelist_webhook.go b/api/v1alpha4/vspheremachinetemplatelist_webhook.go new file mode 100644 index 0000000000..176a33ccd4 --- /dev/null +++ b/api/v1alpha4/vspheremachinetemplatelist_webhook.go @@ -0,0 +1,27 @@ +/* +Copyright 2021 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 v1alpha4 + +import ( + ctrl "sigs.k8s.io/controller-runtime" +) + +func (r *VSphereMachineTemplateList) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} diff --git a/api/v1alpha4/vspherevm_conversion.go b/api/v1alpha4/vspherevm_conversion.go new file mode 100644 index 0000000000..cbf1041b78 --- /dev/null +++ b/api/v1alpha4/vspherevm_conversion.go @@ -0,0 +1,23 @@ +/* +Copyright 2021 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 v1alpha4 + +// Hub marks VSphereVM as a conversion hub. +func (*VSphereVM) Hub() {} + +// Hub marks VSphereVMList as a conversion hub. +func (*VSphereVMList) Hub() {} diff --git a/api/v1alpha4/vspherevm_types.go b/api/v1alpha4/vspherevm_types.go new file mode 100644 index 0000000000..e743780371 --- /dev/null +++ b/api/v1alpha4/vspherevm_types.go @@ -0,0 +1,156 @@ +/* +Copyright 2021 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 v1alpha4 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + clusterv1 "sigs.k8s.io/cluster-api/api/v1alpha3" + "sigs.k8s.io/cluster-api/errors" +) + +const ( + // VMFinalizer allows the reconciler to clean up resources associated + // with a VSphereVM before removing it from the API Server. + VMFinalizer = "vspherevm.infrastructure.cluster.x-k8s.io" +) + +// VSphereVMSpec defines the desired state of VSphereVM. +type VSphereVMSpec struct { + VirtualMachineCloneSpec `json:",inline"` + + // BootstrapRef is a reference to a bootstrap provider-specific resource + // that holds configuration details. + // This field is optional in case no bootstrap data is required to create + // a VM. + // +optional + BootstrapRef *corev1.ObjectReference `json:"bootstrapRef,omitempty"` + + // BiosUUID is the the VM's BIOS UUID that is assigned at runtime after + // the VM has been created. + // This field is required at runtime for other controllers that read + // this CRD as unstructured data. + // +optional + BiosUUID string `json:"biosUUID,omitempty"` +} + +// VSphereVMStatus defines the observed state of VSphereVM +type VSphereVMStatus struct { + // Ready is true when the provider resource is ready. + // This field is required at runtime for other controllers that read + // this CRD as unstructured data. + // +optional + Ready bool `json:"ready,omitempty"` + + // Addresses is a list of the VM's IP addresses. + // This field is required at runtime for other controllers that read + // this CRD as unstructured data. + // +optional + Addresses []string `json:"addresses,omitempty"` + + // CloneMode is the type of clone operation used to clone this VM. Since + // LinkedMode is the default but fails gracefully if the source of the + // clone has no snapshots, this field may be used to determine the actual + // type of clone operation used to create this VM. + // +optional + CloneMode CloneMode `json:"cloneMode,omitempty"` + + // Snapshot is the name of the snapshot from which the VM was cloned if + // LinkedMode is enabled. + // +optional + Snapshot string `json:"snapshot,omitempty"` + + // TaskRef is a managed object reference to a Task related to the machine. + // This value is set automatically at runtime and should not be set or + // modified by users. + // +optional + TaskRef string `json:"taskRef,omitempty"` + + // Network returns the network status for each of the machine's configured + // network interfaces. + // +optional + Network []NetworkStatus `json:"network,omitempty"` + + // FailureReason will be set in the event that there is a terminal problem + // reconciling the vspherevm and will contain a succinct value suitable + // for vm interpretation. + // + // This field should not be set for transitive errors that a controller + // faces that are expected to be fixed automatically over + // time (like service outages), but instead indicate that something is + // fundamentally wrong with the vm. + // + // Any transient errors that occur during the reconciliation of vspherevms + // can be added as events to the vspherevm object and/or logged in the + // controller's output. + // +optional + FailureReason *errors.MachineStatusError `json:"failureReason,omitempty"` + + // FailureMessage will be set in the event that there is a terminal problem + // reconciling the vspherevm and will contain a more verbose string suitable + // for logging and human consumption. + // + // This field should not be set for transitive errors that a controller + // faces that are expected to be fixed automatically over + // time (like service outages), but instead indicate that something is + // fundamentally wrong with the vm. + // + // Any transient errors that occur during the reconciliation of vspherevms + // can be added as events to the vspherevm object and/or logged in the + // controller's output. + // +optional + FailureMessage *string `json:"failureMessage,omitempty"` + + // Conditions defines current service state of the VSphereVM. + // +optional + Conditions clusterv1.Conditions `json:"conditions,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:resource:path=vspherevms,scope=Namespaced +// +kubebuilder:storageversion +// +kubebuilder:subresource:status + +// VSphereVM is the Schema for the vspherevms API +type VSphereVM struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec VSphereVMSpec `json:"spec,omitempty"` + Status VSphereVMStatus `json:"status,omitempty"` +} + +func (m *VSphereVM) GetConditions() clusterv1.Conditions { + return m.Status.Conditions +} + +func (m *VSphereVM) SetConditions(conditions clusterv1.Conditions) { + m.Status.Conditions = conditions +} + +// +kubebuilder:object:root=true + +// VSphereVMList contains a list of VSphereVM +type VSphereVMList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []VSphereVM `json:"items"` +} + +func init() { + SchemeBuilder.Register(&VSphereVM{}, &VSphereVMList{}) +} diff --git a/api/v1alpha4/vspherevm_webhook.go b/api/v1alpha4/vspherevm_webhook.go new file mode 100644 index 0000000000..cf202ed557 --- /dev/null +++ b/api/v1alpha4/vspherevm_webhook.go @@ -0,0 +1,100 @@ +/* +Copyright 2021 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 v1alpha4 + +import ( + "fmt" + "net" + "reflect" + + "github.com/pkg/errors" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/validation/field" + ctrl "sigs.k8s.io/controller-runtime" +) + +func (r *VSphereVM) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} + +// +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1alpha4-vspherevm,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=vspherevms,versions=v1alpha4,name=validation.vspherevm.infrastructure.x-k8s.io,sideEffects=None + +// ValidateCreate implements webhook.Validator so a webhook will be registered for the type +func (r *VSphereVM) ValidateCreate() error { + var allErrs field.ErrorList + spec := r.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")) + } + + for i, device := range spec.Network.Devices { + for j, ip := range device.IPAddrs { + if _, _, err := net.ParseCIDR(ip); err != nil { + allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "network", fmt.Sprintf("devices[%d]", i), fmt.Sprintf("ipAddrs[%d]", j)), ip, "ip addresses should be in the CIDR format")) + } + } + } + + return aggregateObjErrors(r.GroupVersionKind().GroupKind(), r.Name, allErrs) +} + +// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type +func (r *VSphereVM) ValidateUpdate(old runtime.Object) error { //nolint + newVSphereVM, err := runtime.DefaultUnstructuredConverter.ToUnstructured(r) + if err != nil { + return apierrors.NewInternalError(errors.Wrap(err, "failed to convert new VSphereVM to unstructured object")) + } + oldVSphereVM, err := runtime.DefaultUnstructuredConverter.ToUnstructured(old) + if err != nil { + return apierrors.NewInternalError(errors.Wrap(err, "failed to convert old VSphereVM to unstructured object")) + } + + var allErrs field.ErrorList + + newVSphereVMSpec := newVSphereVM["spec"].(map[string]interface{}) + oldVSphereVMSpec := oldVSphereVM["spec"].(map[string]interface{}) + + // allow changes to biosUUID + delete(oldVSphereVMSpec, "biosUUID") + delete(newVSphereVMSpec, "biosUUID") + + // allow changes to bootstrapRef + delete(oldVSphereVMSpec, "bootstrapRef") + delete(newVSphereVMSpec, "bootstrapRef") + + newVSphereVMNetwork := newVSphereVMSpec["network"].(map[string]interface{}) + oldVSphereVMNetwork := oldVSphereVMSpec["network"].(map[string]interface{}) + + // allow changes to the network devices + delete(oldVSphereVMNetwork, "devices") + delete(newVSphereVMNetwork, "devices") + + if !reflect.DeepEqual(oldVSphereVMSpec, newVSphereVMSpec) { + allErrs = append(allErrs, field.Forbidden(field.NewPath("spec"), "cannot be modified")) + } + + return aggregateObjErrors(r.GroupVersionKind().GroupKind(), r.Name, allErrs) +} + +// ValidateDelete implements webhook.Validator so a webhook will be registered for the type +func (r *VSphereVM) ValidateDelete() error { + return nil +} diff --git a/api/v1alpha4/vspherevm_webhook_test.go b/api/v1alpha4/vspherevm_webhook_test.go new file mode 100644 index 0000000000..8263805f7c --- /dev/null +++ b/api/v1alpha4/vspherevm_webhook_test.go @@ -0,0 +1,135 @@ +/* +Copyright 2021 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 v1alpha4 + +import ( + "testing" + + . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" +) + +var ( + biosUUID = "vsphere://42305f0b-dad7-1d3d-5727-0eafffffbbbfc" +) + +//nolint +func TestVSphereVM_ValidateCreate(t *testing.T) { + + g := NewWithT(t) + tests := []struct { + name string + vSphereVM *VSphereVM + wantErr bool + }{ + { + name: "preferredAPIServerCIDR set on creation ", + vSphereVM: createVSphereVM("foo.com", "", "192.168.0.1/32", []string{}, nil), + wantErr: true, + }, + { + name: "IPs are not in CIDR format", + vSphereVM: createVSphereVM("foo.com", "", "", []string{"192.168.0.1/32", "192.168.0.3"}, nil), + wantErr: true, + }, + { + name: "successful VSphereVM creation", + vSphereVM: createVSphereVM("foo.com", "", "", []string{"192.168.0.1/32", "192.168.0.3/32"}, nil), + wantErr: false, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + err := tc.vSphereVM.ValidateCreate() + if tc.wantErr { + g.Expect(err).To(HaveOccurred()) + } else { + g.Expect(err).NotTo(HaveOccurred()) + } + }) + } +} + +//nolint +func TestVSphereVM_ValidateUpdate(t *testing.T) { + + g := NewWithT(t) + + tests := []struct { + name string + oldVSphereVM *VSphereVM + vSphereVM *VSphereVM + wantErr bool + }{ + { + name: "ProviderID can be updated", + oldVSphereVM: createVSphereVM("foo.com", "", "", []string{"192.168.0.1/32"}, nil), + vSphereVM: createVSphereVM("foo.com", biosUUID, "", []string{"192.168.0.1/32"}, nil), + wantErr: false, + }, + { + name: "updating ips can be done", + oldVSphereVM: createVSphereVM("foo.com", "", "", []string{"192.168.0.1/32"}, nil), + vSphereVM: createVSphereVM("foo.com", biosUUID, "", []string{"192.168.0.1/32", "192.168.0.10/32"}, nil), + wantErr: false, + }, + { + name: "updating bootstrapRef can be done", + oldVSphereVM: createVSphereVM("foo.com", "", "", []string{"192.168.0.1/32"}, nil), + vSphereVM: createVSphereVM("foo.com", biosUUID, "", []string{"192.168.0.1/32", "192.168.0.10/32"}, &corev1.ObjectReference{}), + wantErr: false, + }, + { + name: "updating server cannot be done", + oldVSphereVM: createVSphereVM("foo.com", "", "", []string{"192.168.0.1/32"}, nil), + vSphereVM: createVSphereVM("bar.com", biosUUID, "", []string{"192.168.0.1/32", "192.168.0.10/32"}, nil), + wantErr: true, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + err := tc.vSphereVM.ValidateUpdate(tc.oldVSphereVM) + if tc.wantErr { + g.Expect(err).To(HaveOccurred()) + } else { + g.Expect(err).NotTo(HaveOccurred()) + } + }) + } +} + +func createVSphereVM(server string, biosUUID string, preferredAPIServerCIDR string, ips []string, bootstrapRef *corev1.ObjectReference) *VSphereVM { + VSphereVM := &VSphereVM{ + Spec: VSphereVMSpec{ + BiosUUID: biosUUID, + BootstrapRef: bootstrapRef, + VirtualMachineCloneSpec: VirtualMachineCloneSpec{ + Server: server, + Network: NetworkSpec{ + PreferredAPIServerCIDR: preferredAPIServerCIDR, + Devices: []NetworkDeviceSpec{}, + }, + }, + }, + } + for _, ip := range ips { + VSphereVM.Spec.Network.Devices = append(VSphereVM.Spec.Network.Devices, NetworkDeviceSpec{ + IPAddrs: []string{ip}, + }) + } + return VSphereVM +} diff --git a/api/v1alpha4/vspherevmlist_webhook.go b/api/v1alpha4/vspherevmlist_webhook.go new file mode 100644 index 0000000000..95594243a6 --- /dev/null +++ b/api/v1alpha4/vspherevmlist_webhook.go @@ -0,0 +1,27 @@ +/* +Copyright 2021 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 v1alpha4 + +import ( + ctrl "sigs.k8s.io/controller-runtime" +) + +func (r *VSphereVMList) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} diff --git a/api/v1alpha4/webhooks.go b/api/v1alpha4/webhooks.go new file mode 100644 index 0000000000..ca0a158e6f --- /dev/null +++ b/api/v1alpha4/webhooks.go @@ -0,0 +1,35 @@ +/* +Copyright 2021 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 v1alpha4 + +import ( + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/validation/field" +) + +func aggregateObjErrors(gk schema.GroupKind, name string, allErrs field.ErrorList) error { + if len(allErrs) == 0 { + return nil + } + + return apierrors.NewInvalid( + gk, + name, + allErrs, + ) +} diff --git a/api/v1alpha4/zz_generated.deepcopy.go b/api/v1alpha4/zz_generated.deepcopy.go new file mode 100644 index 0000000000..9edf7a3c8f --- /dev/null +++ b/api/v1alpha4/zz_generated.deepcopy.go @@ -0,0 +1,936 @@ +// +build !ignore_autogenerated + +/* +Copyright 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. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v1alpha4 + +import ( + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/cluster-api/api/v1alpha3" + "sigs.k8s.io/cluster-api/errors" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *APIEndpoint) DeepCopyInto(out *APIEndpoint) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIEndpoint. +func (in *APIEndpoint) DeepCopy() *APIEndpoint { + if in == nil { + return nil + } + out := new(APIEndpoint) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CPICloudConfig) DeepCopyInto(out *CPICloudConfig) { + *out = *in + if in.ExtraArgs != nil { + in, out := &in.ExtraArgs, &out.ExtraArgs + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CPICloudConfig. +func (in *CPICloudConfig) DeepCopy() *CPICloudConfig { + if in == nil { + return nil + } + out := new(CPICloudConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CPIConfig) DeepCopyInto(out *CPIConfig) { + *out = *in + in.Global.DeepCopyInto(&out.Global) + if in.VCenter != nil { + in, out := &in.VCenter, &out.VCenter + *out = make(map[string]CPIVCenterConfig, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + out.Network = in.Network + out.Disk = in.Disk + out.Workspace = in.Workspace + out.Labels = in.Labels + in.ProviderConfig.DeepCopyInto(&out.ProviderConfig) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CPIConfig. +func (in *CPIConfig) DeepCopy() *CPIConfig { + if in == nil { + return nil + } + out := new(CPIConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CPIDiskConfig) DeepCopyInto(out *CPIDiskConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CPIDiskConfig. +func (in *CPIDiskConfig) DeepCopy() *CPIDiskConfig { + if in == nil { + return nil + } + out := new(CPIDiskConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CPIGlobalConfig) DeepCopyInto(out *CPIGlobalConfig) { + *out = *in + if in.APIDisable != nil { + in, out := &in.APIDisable, &out.APIDisable + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CPIGlobalConfig. +func (in *CPIGlobalConfig) DeepCopy() *CPIGlobalConfig { + if in == nil { + return nil + } + out := new(CPIGlobalConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CPILabelConfig) DeepCopyInto(out *CPILabelConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CPILabelConfig. +func (in *CPILabelConfig) DeepCopy() *CPILabelConfig { + if in == nil { + return nil + } + out := new(CPILabelConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CPINetworkConfig) DeepCopyInto(out *CPINetworkConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CPINetworkConfig. +func (in *CPINetworkConfig) DeepCopy() *CPINetworkConfig { + if in == nil { + return nil + } + out := new(CPINetworkConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CPIProviderConfig) DeepCopyInto(out *CPIProviderConfig) { + *out = *in + if in.Cloud != nil { + in, out := &in.Cloud, &out.Cloud + *out = new(CPICloudConfig) + (*in).DeepCopyInto(*out) + } + if in.Storage != nil { + in, out := &in.Storage, &out.Storage + *out = new(CPIStorageConfig) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CPIProviderConfig. +func (in *CPIProviderConfig) DeepCopy() *CPIProviderConfig { + if in == nil { + return nil + } + out := new(CPIProviderConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CPIStorageConfig) DeepCopyInto(out *CPIStorageConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CPIStorageConfig. +func (in *CPIStorageConfig) DeepCopy() *CPIStorageConfig { + if in == nil { + return nil + } + out := new(CPIStorageConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CPIVCenterConfig) DeepCopyInto(out *CPIVCenterConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CPIVCenterConfig. +func (in *CPIVCenterConfig) DeepCopy() *CPIVCenterConfig { + if in == nil { + return nil + } + out := new(CPIVCenterConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CPIWorkspaceConfig) DeepCopyInto(out *CPIWorkspaceConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CPIWorkspaceConfig. +func (in *CPIWorkspaceConfig) DeepCopy() *CPIWorkspaceConfig { + if in == nil { + return nil + } + out := new(CPIWorkspaceConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HAProxyLoadBalancer) DeepCopyInto(out *HAProxyLoadBalancer) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HAProxyLoadBalancer. +func (in *HAProxyLoadBalancer) DeepCopy() *HAProxyLoadBalancer { + if in == nil { + return nil + } + out := new(HAProxyLoadBalancer) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *HAProxyLoadBalancer) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HAProxyLoadBalancerList) DeepCopyInto(out *HAProxyLoadBalancerList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]HAProxyLoadBalancer, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HAProxyLoadBalancerList. +func (in *HAProxyLoadBalancerList) DeepCopy() *HAProxyLoadBalancerList { + if in == nil { + return nil + } + out := new(HAProxyLoadBalancerList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *HAProxyLoadBalancerList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HAProxyLoadBalancerSpec) DeepCopyInto(out *HAProxyLoadBalancerSpec) { + *out = *in + in.VirtualMachineConfiguration.DeepCopyInto(&out.VirtualMachineConfiguration) + if in.User != nil { + in, out := &in.User, &out.User + *out = new(SSHUser) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HAProxyLoadBalancerSpec. +func (in *HAProxyLoadBalancerSpec) DeepCopy() *HAProxyLoadBalancerSpec { + if in == nil { + return nil + } + out := new(HAProxyLoadBalancerSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HAProxyLoadBalancerStatus) DeepCopyInto(out *HAProxyLoadBalancerStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HAProxyLoadBalancerStatus. +func (in *HAProxyLoadBalancerStatus) DeepCopy() *HAProxyLoadBalancerStatus { + if in == nil { + return nil + } + out := new(HAProxyLoadBalancerStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkDeviceSpec) DeepCopyInto(out *NetworkDeviceSpec) { + *out = *in + if in.IPAddrs != nil { + in, out := &in.IPAddrs, &out.IPAddrs + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.MTU != nil { + in, out := &in.MTU, &out.MTU + *out = new(int64) + **out = **in + } + if in.Nameservers != nil { + in, out := &in.Nameservers, &out.Nameservers + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Routes != nil { + in, out := &in.Routes, &out.Routes + *out = make([]NetworkRouteSpec, len(*in)) + copy(*out, *in) + } + if in.SearchDomains != nil { + in, out := &in.SearchDomains, &out.SearchDomains + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkDeviceSpec. +func (in *NetworkDeviceSpec) DeepCopy() *NetworkDeviceSpec { + if in == nil { + return nil + } + out := new(NetworkDeviceSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkRouteSpec) DeepCopyInto(out *NetworkRouteSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkRouteSpec. +func (in *NetworkRouteSpec) DeepCopy() *NetworkRouteSpec { + if in == nil { + return nil + } + out := new(NetworkRouteSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkSpec) DeepCopyInto(out *NetworkSpec) { + *out = *in + if in.Devices != nil { + in, out := &in.Devices, &out.Devices + *out = make([]NetworkDeviceSpec, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Routes != nil { + in, out := &in.Routes, &out.Routes + *out = make([]NetworkRouteSpec, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkSpec. +func (in *NetworkSpec) DeepCopy() *NetworkSpec { + if in == nil { + return nil + } + out := new(NetworkSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkStatus) DeepCopyInto(out *NetworkStatus) { + *out = *in + if in.IPAddrs != nil { + in, out := &in.IPAddrs, &out.IPAddrs + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkStatus. +func (in *NetworkStatus) DeepCopy() *NetworkStatus { + if in == nil { + return nil + } + out := new(NetworkStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SSHUser) DeepCopyInto(out *SSHUser) { + *out = *in + if in.AuthorizedKeys != nil { + in, out := &in.AuthorizedKeys, &out.AuthorizedKeys + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SSHUser. +func (in *SSHUser) DeepCopy() *SSHUser { + if in == nil { + return nil + } + out := new(SSHUser) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VSphereCluster) DeepCopyInto(out *VSphereCluster) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VSphereCluster. +func (in *VSphereCluster) DeepCopy() *VSphereCluster { + if in == nil { + return nil + } + out := new(VSphereCluster) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VSphereCluster) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VSphereClusterList) DeepCopyInto(out *VSphereClusterList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]VSphereCluster, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VSphereClusterList. +func (in *VSphereClusterList) DeepCopy() *VSphereClusterList { + if in == nil { + return nil + } + out := new(VSphereClusterList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VSphereClusterList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VSphereClusterSpec) DeepCopyInto(out *VSphereClusterSpec) { + *out = *in + if in.Insecure != nil { + in, out := &in.Insecure, &out.Insecure + *out = new(bool) + **out = **in + } + in.CloudProviderConfiguration.DeepCopyInto(&out.CloudProviderConfiguration) + out.ControlPlaneEndpoint = in.ControlPlaneEndpoint + if in.LoadBalancerRef != nil { + in, out := &in.LoadBalancerRef, &out.LoadBalancerRef + *out = new(v1.ObjectReference) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VSphereClusterSpec. +func (in *VSphereClusterSpec) DeepCopy() *VSphereClusterSpec { + if in == nil { + return nil + } + out := new(VSphereClusterSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VSphereClusterStatus) DeepCopyInto(out *VSphereClusterStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make(v1alpha3.Conditions, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VSphereClusterStatus. +func (in *VSphereClusterStatus) DeepCopy() *VSphereClusterStatus { + if in == nil { + return nil + } + out := new(VSphereClusterStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VSphereMachine) DeepCopyInto(out *VSphereMachine) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VSphereMachine. +func (in *VSphereMachine) DeepCopy() *VSphereMachine { + if in == nil { + return nil + } + out := new(VSphereMachine) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VSphereMachine) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VSphereMachineList) DeepCopyInto(out *VSphereMachineList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]VSphereMachine, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VSphereMachineList. +func (in *VSphereMachineList) DeepCopy() *VSphereMachineList { + if in == nil { + return nil + } + out := new(VSphereMachineList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VSphereMachineList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VSphereMachineSpec) DeepCopyInto(out *VSphereMachineSpec) { + *out = *in + in.VirtualMachineCloneSpec.DeepCopyInto(&out.VirtualMachineCloneSpec) + if in.ProviderID != nil { + in, out := &in.ProviderID, &out.ProviderID + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VSphereMachineSpec. +func (in *VSphereMachineSpec) DeepCopy() *VSphereMachineSpec { + if in == nil { + return nil + } + out := new(VSphereMachineSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VSphereMachineStatus) DeepCopyInto(out *VSphereMachineStatus) { + *out = *in + if in.Addresses != nil { + in, out := &in.Addresses, &out.Addresses + *out = make([]v1alpha3.MachineAddress, len(*in)) + copy(*out, *in) + } + if in.Network != nil { + in, out := &in.Network, &out.Network + *out = make([]NetworkStatus, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.FailureReason != nil { + in, out := &in.FailureReason, &out.FailureReason + *out = new(errors.MachineStatusError) + **out = **in + } + if in.FailureMessage != nil { + in, out := &in.FailureMessage, &out.FailureMessage + *out = new(string) + **out = **in + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make(v1alpha3.Conditions, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VSphereMachineStatus. +func (in *VSphereMachineStatus) DeepCopy() *VSphereMachineStatus { + if in == nil { + return nil + } + out := new(VSphereMachineStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VSphereMachineTemplate) DeepCopyInto(out *VSphereMachineTemplate) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VSphereMachineTemplate. +func (in *VSphereMachineTemplate) DeepCopy() *VSphereMachineTemplate { + if in == nil { + return nil + } + out := new(VSphereMachineTemplate) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VSphereMachineTemplate) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VSphereMachineTemplateList) DeepCopyInto(out *VSphereMachineTemplateList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]VSphereMachineTemplate, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VSphereMachineTemplateList. +func (in *VSphereMachineTemplateList) DeepCopy() *VSphereMachineTemplateList { + if in == nil { + return nil + } + out := new(VSphereMachineTemplateList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VSphereMachineTemplateList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VSphereMachineTemplateResource) DeepCopyInto(out *VSphereMachineTemplateResource) { + *out = *in + in.Spec.DeepCopyInto(&out.Spec) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VSphereMachineTemplateResource. +func (in *VSphereMachineTemplateResource) DeepCopy() *VSphereMachineTemplateResource { + if in == nil { + return nil + } + out := new(VSphereMachineTemplateResource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VSphereMachineTemplateSpec) DeepCopyInto(out *VSphereMachineTemplateSpec) { + *out = *in + in.Template.DeepCopyInto(&out.Template) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VSphereMachineTemplateSpec. +func (in *VSphereMachineTemplateSpec) DeepCopy() *VSphereMachineTemplateSpec { + if in == nil { + return nil + } + out := new(VSphereMachineTemplateSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VSphereVM) DeepCopyInto(out *VSphereVM) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VSphereVM. +func (in *VSphereVM) DeepCopy() *VSphereVM { + if in == nil { + return nil + } + out := new(VSphereVM) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VSphereVM) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VSphereVMList) DeepCopyInto(out *VSphereVMList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]VSphereVM, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VSphereVMList. +func (in *VSphereVMList) DeepCopy() *VSphereVMList { + if in == nil { + return nil + } + out := new(VSphereVMList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VSphereVMList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VSphereVMSpec) DeepCopyInto(out *VSphereVMSpec) { + *out = *in + in.VirtualMachineCloneSpec.DeepCopyInto(&out.VirtualMachineCloneSpec) + if in.BootstrapRef != nil { + in, out := &in.BootstrapRef, &out.BootstrapRef + *out = new(v1.ObjectReference) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VSphereVMSpec. +func (in *VSphereVMSpec) DeepCopy() *VSphereVMSpec { + if in == nil { + return nil + } + out := new(VSphereVMSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VSphereVMStatus) DeepCopyInto(out *VSphereVMStatus) { + *out = *in + if in.Addresses != nil { + in, out := &in.Addresses, &out.Addresses + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Network != nil { + in, out := &in.Network, &out.Network + *out = make([]NetworkStatus, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.FailureReason != nil { + in, out := &in.FailureReason, &out.FailureReason + *out = new(errors.MachineStatusError) + **out = **in + } + if in.FailureMessage != nil { + in, out := &in.FailureMessage, &out.FailureMessage + *out = new(string) + **out = **in + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make(v1alpha3.Conditions, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VSphereVMStatus. +func (in *VSphereVMStatus) DeepCopy() *VSphereVMStatus { + if in == nil { + return nil + } + out := new(VSphereVMStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachine) DeepCopyInto(out *VirtualMachine) { + *out = *in + if in.Network != nil { + in, out := &in.Network, &out.Network + *out = make([]NetworkStatus, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachine. +func (in *VirtualMachine) DeepCopy() *VirtualMachine { + if in == nil { + return nil + } + out := new(VirtualMachine) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineCloneSpec) DeepCopyInto(out *VirtualMachineCloneSpec) { + *out = *in + in.Network.DeepCopyInto(&out.Network) + if in.CustomVMXKeys != nil { + in, out := &in.CustomVMXKeys, &out.CustomVMXKeys + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineCloneSpec. +func (in *VirtualMachineCloneSpec) DeepCopy() *VirtualMachineCloneSpec { + if in == nil { + return nil + } + out := new(VirtualMachineCloneSpec) + in.DeepCopyInto(out) + return out +} diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_haproxyloadbalancers.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_haproxyloadbalancers.yaml index 3470938268..0aa7c81a21 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_haproxyloadbalancers.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_haproxyloadbalancers.yaml @@ -291,6 +291,284 @@ spec: type: object type: object served: true + storage: false + subresources: + status: {} + - name: v1alpha4 + schema: + openAPIV3Schema: + description: 'HAProxyLoadBalancer is the Schema for the haproxyloadbalancers + API DEPRECATED: will be removed in v1alpha4' + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: HAProxyLoadBalancerSpec defines the desired state of HAProxyLoadBalancer. + properties: + user: + description: SSHUser specifies the name of a user that is granted + remote access to the deployed VM. + properties: + authorizedKeys: + description: AuthorizedKeys is one or more public SSH keys that + grant remote access. + items: + type: string + type: array + name: + description: Name is the name of the SSH user. + type: string + required: + - authorizedKeys + - name + type: object + virtualMachineConfiguration: + description: VirtualMachineConfiguration is information used to deploy + a load balancer VM. + properties: + cloneMode: + description: CloneMode specifies the type of clone operation. + The LinkedClone mode is only support for templates that have + at least one snapshot. If the template has no snapshots, then + CloneMode defaults to FullClone. When LinkedClone mode is enabled + the DiskGiB field is ignored as it is not possible to expand + disks of linked clones. Defaults to LinkedClone, but fails gracefully + to FullClone if the source of the clone operation has no snapshots. + type: string + customVMXKeys: + additionalProperties: + type: string + description: CustomVMXKeys is a dictionary of advanced VMX options + that can be set on VM Defaults to empty map + type: object + datacenter: + description: Datacenter is the name or inventory path of the datacenter + in which the virtual machine is created/located. + type: string + datastore: + description: Datastore is the name or inventory path of the datastore + in which the virtual machine is created/located. + type: string + diskGiB: + description: DiskGiB is the size of a virtual machine's disk, + in GiB. Defaults to the eponymous property value in the template + from which the virtual machine is cloned. + format: int32 + type: integer + folder: + description: Folder is the name or inventory path of the folder + in which the virtual machine is created/located. + type: string + memoryMiB: + description: MemoryMiB is the size of a virtual machine's memory, + in MiB. Defaults to the eponymous property value in the template + from which the virtual machine is cloned. + format: int64 + type: integer + network: + description: Network is the network configuration for this machine's + VM. + properties: + devices: + description: Devices is the list of network devices used by + the virtual machine. TODO(akutz) Make sure at least one + network matches the ClusterSpec.CloudProviderConfiguration.Network.Name + items: + description: NetworkDeviceSpec defines the network configuration + for a virtual machine's network device. + properties: + deviceName: + description: DeviceName may be used to explicitly assign + a name to the network device as it exists in the guest + operating system. + type: string + dhcp4: + description: DHCP4 is a flag that indicates whether + or not to use DHCP for IPv4 on this device. If true + then IPAddrs should not contain any IPv4 addresses. + type: boolean + dhcp6: + description: DHCP6 is a flag that indicates whether + or not to use DHCP for IPv6 on this device. If true + then IPAddrs should not contain any IPv6 addresses. + type: boolean + gateway4: + description: Gateway4 is the IPv4 gateway used by this + device. Required when DHCP4 is false. + type: string + gateway6: + description: Gateway4 is the IPv4 gateway used by this + device. Required when DHCP6 is false. + type: string + ipAddrs: + description: IPAddrs is a list of one or more IPv4 and/or + IPv6 addresses to assign to this device. Required + when DHCP4 and DHCP6 are both false. + items: + type: string + type: array + macAddr: + description: MACAddr is the MAC address used by this + device. It is generally a good idea to omit this field + and allow a MAC address to be generated. Please note + that this value must use the VMware OUI to work with + the in-tree vSphere cloud provider. + type: string + mtu: + description: MTU is the device’s Maximum Transmission + Unit size in bytes. + format: int64 + type: integer + nameservers: + description: Nameservers is a list of IPv4 and/or IPv6 + addresses used as DNS nameservers. Please note that + Linux allows only three nameservers (https://linux.die.net/man/5/resolv.conf). + items: + type: string + type: array + networkName: + description: NetworkName is the name of the vSphere + network to which the device will be connected. + type: string + routes: + description: Routes is a list of optional, static routes + applied to the device. + items: + description: NetworkRouteSpec defines a static network + route. + properties: + metric: + description: Metric is the weight/priority of + the route. + format: int32 + type: integer + to: + description: To is an IPv4 or IPv6 address. + type: string + via: + description: Via is an IPv4 or IPv6 address. + type: string + required: + - metric + - to + - via + type: object + type: array + searchDomains: + description: SearchDomains is a list of search domains + used when resolving IP addresses with DNS. + items: + type: string + type: array + required: + - networkName + type: object + type: array + preferredAPIServerCidr: + description: PreferredAPIServeCIDR is the preferred CIDR for + the Kubernetes API server endpoint on this machine + type: string + routes: + description: Routes is a list of optional, static routes applied + to the virtual machine. + items: + description: NetworkRouteSpec defines a static network route. + properties: + metric: + description: Metric is the weight/priority of the route. + format: int32 + type: integer + to: + description: To is an IPv4 or IPv6 address. + type: string + via: + description: Via is an IPv4 or IPv6 address. + type: string + required: + - metric + - to + - via + type: object + type: array + required: + - devices + type: object + numCPUs: + description: NumCPUs is the number of virtual processors in a + virtual machine. Defaults to the eponymous property value in + the template from which the virtual machine is cloned. + format: int32 + type: integer + numCoresPerSocket: + description: NumCPUs is the number of cores among which to distribute + CPUs in this virtual machine. Defaults to the eponymous property + value in the template from which the virtual machine is cloned. + format: int32 + type: integer + resourcePool: + description: ResourcePool is the name or inventory path of the + resource pool in which the virtual machine is created/located. + type: string + server: + description: Server is the IP address or FQDN of the vSphere server + on which the virtual machine is created/located. + type: string + snapshot: + description: Snapshot is the name of the snapshot from which to + create a linked clone. This field is ignored if LinkedClone + is not enabled. Defaults to the source's current snapshot. + type: string + storagePolicyName: + description: StoragePolicyName of the storage policy to use with + this Virtual Machine + type: string + template: + description: Template is the name or inventory path of the template + used to clone the virtual machine. + minLength: 1 + type: string + thumbprint: + description: Thumbprint is the colon-separated SHA-1 checksum + of the given vCenter server's host certificate When this is + set to empty, this VirtualMachine would be created without TLS + certificate validation of the communication between Cluster + API Provider vSphere and the VMware vCenter server. + type: string + required: + - network + - template + type: object + required: + - virtualMachineConfiguration + type: object + status: + description: HAProxyLoadBalancerStatus defines the observed state of HAProxyLoadBalancer. + properties: + address: + description: "Address is the IP address or DNS name of the load balancer. + \n This field is required as part of the Portable Load Balancer + model and is inspected via an unstructured reader by other controllers + to determine the status of the load balancer." + type: string + ready: + description: "Ready indicates whether or not the load balancer is + ready. \n This field is required as part of the Portable Load Balancer + model and is inspected via an unstructured reader by other controllers + to determine the status of the load balancer." + type: boolean + type: object + type: object + served: true storage: true subresources: status: {} diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_vsphereclusters.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_vsphereclusters.yaml index 21b0fb77d1..5b33deb085 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_vsphereclusters.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_vsphereclusters.yaml @@ -18,7 +18,7 @@ spec: singular: vspherecluster scope: Namespaced versions: - - name: v1alpha2 + - name: v1alpha3 schema: openAPIV3Schema: description: VSphereCluster is the Schema for the vsphereclusters API @@ -39,8 +39,8 @@ spec: description: VSphereClusterSpec defines the desired state of VSphereCluster properties: cloudProviderConfiguration: - description: CloudProviderConfiguration holds the cluster-wide configuration - for the vSphere cloud provider. + description: 'CloudProviderConfiguration holds the cluster-wide configuration + for the DEPRECATED: will be removed in v1alpha4 vSphere cloud provider.' properties: disk: description: Disk is the vSphere cloud provider's disk configuration. @@ -143,6 +143,13 @@ spec: properties: controllerImage: type: string + extraArgs: + additionalProperties: + type: string + description: ExtraArgs passes through extra arguments + to the cloud provider. The arguments here are passed + to the cloud provider daemonset specification + type: object type: object storage: properties: @@ -219,45 +226,131 @@ spec: type: string type: object type: object + controlPlaneEndpoint: + description: ControlPlaneEndpoint represents the endpoint used to + communicate with the control plane. + properties: + host: + description: The hostname on which the API server is serving. + type: string + port: + description: The port on which the API server is serving. + format: int32 + type: integer + required: + - host + - port + type: object insecure: - description: Insecure is a flag that controls whether or not to validate - the vSphere server's certificate. + description: 'Insecure is a flag that controls whether or not to validate + the vSphere server''s certificate. DEPRECATED: will be removed in + v1alpha4' type: boolean + loadBalancerRef: + description: 'LoadBalancerRef may be used to enable a control plane + load balancer for this cluster. When a LoadBalancerRef is provided, + the VSphereCluster.Status.Ready field will not be true until the + referenced resource is Status.Ready and has a non-empty Status.Address + value. DEPRECATED: will be removed in v1alpha4' + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: 'If referring to a piece of an object instead of + an entire object, this string should contain a valid JSON/Go + field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within + a pod, this would take on a value like: "spec.containers{name}" + (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" + (container with index 2 in this pod). This syntax is chosen + only to have some well-defined way of referencing a part of + an object. TODO: this design is not final and this field is + subject to change in the future.' + type: string + kind: + description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + namespace: + description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/' + type: string + resourceVersion: + description: 'Specific resourceVersion to which this reference + is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency' + type: string + uid: + description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids' + type: string + type: object server: description: Server is the address of the vSphere endpoint. type: string + thumbprint: + description: Thumbprint is the colon-separated SHA-1 checksum of the + given vCenter server's host certificate When provided, Insecure + should not be set to true + type: string type: object status: description: VSphereClusterStatus defines the observed state of VSphereClusterSpec properties: - apiEndpoints: - description: APIEndpoints represents the endpoints to communicate - with the control plane. + conditions: + description: Conditions defines current service state of the VSphereCluster. items: - description: APIEndpoint represents a reachable Kubernetes API endpoint. + description: Condition defines an observation of a Cluster API resource + operational state. properties: - host: - description: The hostname on which the API server is serving. + lastTransitionTime: + description: Last time the condition transitioned from one status + to another. This should be when the underlying condition changed. + If that is not known, then using the time when the API field + changed is acceptable. + format: date-time + type: string + message: + description: A human readable message indicating details about + the transition. This field may be empty. + type: string + reason: + description: The reason for the condition's last transition + in CamelCase. The specific API may choose whether or not this + field is considered a guaranteed API. This field may not be + empty. + type: string + severity: + description: Severity provides an explicit classification of + Reason code, so the users or machines can immediately understand + the current situation and act accordingly. The Severity field + MUST be set only when Status=False. + type: string + status: + description: Status of the condition, one of True, False, Unknown. + type: string + type: + description: Type of condition in CamelCase or in foo.example.com/CamelCase. + Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. type: string - port: - description: The port on which the API server is serving. - type: integer required: - - host - - port + - status + - type type: object type: array ready: type: boolean - required: - - ready type: object type: object served: true storage: false subresources: status: {} - - name: v1alpha3 + - name: v1alpha4 schema: openAPIV3Schema: description: VSphereCluster is the Schema for the vsphereclusters API diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_vspheremachines.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_vspheremachines.yaml index dcd7761b74..90622ea4ee 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_vspheremachines.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_vspheremachines.yaml @@ -18,7 +18,7 @@ spec: singular: vspheremachine scope: Namespaced versions: - - name: v1alpha2 + - name: v1alpha3 schema: openAPIV3Schema: description: VSphereMachine is the Schema for the vspheremachines API @@ -38,20 +38,43 @@ spec: spec: description: VSphereMachineSpec defines the desired state of VSphereMachine properties: + cloneMode: + description: CloneMode specifies the type of clone operation. The + LinkedClone mode is only support for templates that have at least + one snapshot. If the template has no snapshots, then CloneMode defaults + to FullClone. When LinkedClone mode is enabled the DiskGiB field + is ignored as it is not possible to expand disks of linked clones. + Defaults to LinkedClone, but fails gracefully to FullClone if the + source of the clone operation has no snapshots. + type: string + customVMXKeys: + additionalProperties: + type: string + description: CustomVMXKeys is a dictionary of advanced VMX options + that can be set on VM Defaults to empty map + type: object datacenter: description: Datacenter is the name or inventory path of the datacenter - where this machine's VM is created/located. + in which the virtual machine is created/located. + type: string + datastore: + description: Datastore is the name or inventory path of the datastore + in which the virtual machine is created/located. type: string diskGiB: description: DiskGiB is the size of a virtual machine's disk, in GiB. - Defaults to the analogue property value in the template from which - this machine is cloned. + Defaults to the eponymous property value in the template from which + the virtual machine is cloned. format: int32 type: integer + folder: + description: Folder is the name or inventory path of the folder in + which the virtual machine is created/located. + type: string memoryMiB: description: MemoryMiB is the size of a virtual machine's memory, - in MiB. Defaults to the analogue property value in the template - from which this machine is cloned. + in MiB. Defaults to the eponymous property value in the template + from which the virtual machine is cloned. format: int64 type: integer network: @@ -184,26 +207,50 @@ spec: type: object numCPUs: description: NumCPUs is the number of virtual processors in a virtual - machine. Defaults to the analogue property value in the template - from which this machine is cloned. + machine. Defaults to the eponymous property value in the template + from which the virtual machine is cloned. format: int32 type: integer numCoresPerSocket: description: NumCPUs is the number of cores among which to distribute - CPUs in this virtual machine. Defaults to the analogue property - value in the template from which this machine is cloned. + CPUs in this virtual machine. Defaults to the eponymous property + value in the template from which the virtual machine is cloned. format: int32 type: integer providerID: description: ProviderID is the virtual machine's BIOS UUID formated as vsphere://12345678-1234-1234-1234-123456789abc type: string + resourcePool: + description: ResourcePool is the name or inventory path of the resource + pool in which the virtual machine is created/located. + type: string + server: + description: Server is the IP address or FQDN of the vSphere server + on which the virtual machine is created/located. + type: string + snapshot: + description: Snapshot is the name of the snapshot from which to create + a linked clone. This field is ignored if LinkedClone is not enabled. + Defaults to the source's current snapshot. + type: string + storagePolicyName: + description: StoragePolicyName of the storage policy to use with this + Virtual Machine + type: string template: - description: Template is the name, inventory path, or instance UUID - of the template used to clone new machines. + description: Template is the name or inventory path of the template + used to clone the virtual machine. + minLength: 1 + type: string + thumbprint: + description: Thumbprint is the colon-separated SHA-1 checksum of the + given vCenter server's host certificate When this is set to empty, + this VirtualMachine would be created without TLS certificate validation + of the communication between Cluster API Provider vSphere and the + VMware vCenter server. type: string required: - - datacenter - network - template type: object @@ -213,13 +260,14 @@ spec: addresses: description: Addresses contains the VSphere instance associated addresses. items: - description: NodeAddress contains information for the node's address. + description: MachineAddress contains information for the node's + address. properties: address: - description: The node address. + description: The machine address. type: string type: - description: Node address type, one of Hostname, ExternalIP + description: Machine address type, one of Hostname, ExternalIP or InternalIP. type: string required: @@ -227,8 +275,52 @@ spec: - type type: object type: array - errorMessage: - description: "ErrorMessage will be set in the event that there is + conditions: + description: Conditions defines current service state of the VSphereMachine. + items: + description: Condition defines an observation of a Cluster API resource + operational state. + properties: + lastTransitionTime: + description: Last time the condition transitioned from one status + to another. This should be when the underlying condition changed. + If that is not known, then using the time when the API field + changed is acceptable. + format: date-time + type: string + message: + description: A human readable message indicating details about + the transition. This field may be empty. + type: string + reason: + description: The reason for the condition's last transition + in CamelCase. The specific API may choose whether or not this + field is considered a guaranteed API. This field may not be + empty. + type: string + severity: + description: Severity provides an explicit classification of + Reason code, so the users or machines can immediately understand + the current situation and act accordingly. The Severity field + MUST be set only when Status=False. + type: string + status: + description: Status of the condition, one of True, False, Unknown. + type: string + type: + description: Type of condition in CamelCase or in foo.example.com/CamelCase. + Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. + type: string + required: + - status + - type + type: object + type: array + failureMessage: + description: "FailureMessage will be set in the event that there is a terminal problem reconciling the Machine and will contain a more verbose string suitable for logging and human consumption. \n This field should not be set for transitive errors that a controller @@ -242,9 +334,9 @@ spec: occur during the reconciliation of Machines can be added as events to the Machine object and/or logged in the controller's output." type: string - errorReason: - description: "ErrorReason will be set in the event that there is a - terminal problem reconciling the Machine and will contain a succinct + failureReason: + description: "FailureReason will be set in the event that there is + a terminal problem reconciling the Machine and will contain a succinct value suitable for machine interpretation. \n This field should not be set for transitive errors that a controller faces that are expected to be fixed automatically over time (like service outages), @@ -257,7 +349,7 @@ spec: during the reconciliation of Machines can be added as events to the Machine object and/or logged in the controller's output." type: string - networkStatus: + network: description: Network returns the network status for each of the machine's configured network interfaces. items: @@ -287,18 +379,13 @@ spec: ready: description: Ready is true when the provider resource is ready. type: boolean - taskRef: - description: TaskRef is a managed object reference to a Task related - to the machine. This value is set automatically at runtime and should - not be set or modified by users. - type: string type: object type: object served: true storage: false subresources: status: {} - - name: v1alpha3 + - name: v1alpha4 schema: openAPIV3Schema: description: VSphereMachine is the Schema for the vspheremachines API diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_vspheremachinetemplates.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_vspheremachinetemplates.yaml index 4d2492d58f..aa0103e48c 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_vspheremachinetemplates.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_vspheremachinetemplates.yaml @@ -18,7 +18,7 @@ spec: singular: vspheremachinetemplate scope: Namespaced versions: - - name: v1alpha2 + - name: v1alpha3 schema: openAPIV3Schema: description: VSphereMachineTemplate is the Schema for the vspheremachinetemplates @@ -43,135 +43,48 @@ spec: description: VSphereMachineTemplateResource describes the data needed to create a VSphereMachine from a template properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this - representation of an object. Servers should convert recognized - schemas to the latest internal value, and may reject unrecognized - values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource - this object represents. Servers may infer this from the endpoint - the client submits requests to. Cannot be updated. In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - description: Standard object's metadata. + spec: + description: Spec is the specification of the desired behavior + of the machine. properties: - annotations: - additionalProperties: - type: string - description: 'Annotations is an unstructured key value map - stored with a resource that may be set by external tools - to store and retrieve arbitrary metadata. They are not queryable - and should be preserved when modifying objects. More info: - http://kubernetes.io/docs/user-guide/annotations' - type: object - generateName: - description: "GenerateName is an optional prefix, used by - the server, to generate a unique name ONLY IF the Name field - has not been provided. If this field is used, the name returned - to the client will be different than the name passed. This - value will also be combined with a unique suffix. The provided - value has the same validation rules as the Name field, and - may be truncated by the length of the suffix required to - make the value unique on the server. \n If this field is - specified and the generated name exists, the server will - NOT return a 409 - instead, it will either return 201 Created - or 500 with Reason ServerTimeout indicating a unique name - could not be found in the time allotted, and the client - should retry (optionally after the time indicated in the - Retry-After header). \n Applied only if Name is not specified. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#idempotency" + cloneMode: + description: CloneMode specifies the type of clone operation. + The LinkedClone mode is only support for templates that + have at least one snapshot. If the template has no snapshots, + then CloneMode defaults to FullClone. When LinkedClone mode + is enabled the DiskGiB field is ignored as it is not possible + to expand disks of linked clones. Defaults to LinkedClone, + but fails gracefully to FullClone if the source of the clone + operation has no snapshots. type: string - labels: + customVMXKeys: additionalProperties: type: string - description: 'Map of string keys and values that can be used - to organize and categorize (scope and select) objects. May - match selectors of replication controllers and services. - More info: http://kubernetes.io/docs/user-guide/labels' + description: CustomVMXKeys is a dictionary of advanced VMX + options that can be set on VM Defaults to empty map type: object - name: - description: 'Name must be unique within a namespace. Is required - when creating resources, although some resources may allow - a client to request the generation of an appropriate name - automatically. Name is primarily intended for creation idempotence - and configuration definition. Cannot be updated. More info: - http://kubernetes.io/docs/user-guide/identifiers#names' - type: string - namespace: - description: "Namespace defines the space within each name - must be unique. An empty namespace is equivalent to the - \"default\" namespace, but \"default\" is the canonical - representation. Not all objects are required to be scoped - to a namespace - the value of this field for those objects - will be empty. \n Must be a DNS_LABEL. Cannot be updated. - More info: http://kubernetes.io/docs/user-guide/namespaces" - type: string - ownerReferences: - description: List of objects depended by this object. If ALL - objects in the list have been deleted, this object will - be garbage collected. If this object is managed by a controller, - then an entry in this list will point to this controller, - with the controller field set to true. There cannot be more - than one managing controller. - items: - description: OwnerReference contains enough information - to let you identify an owning object. An owning object - must be in the same namespace as the dependent, or be - cluster-scoped, so there is no namespace field. - properties: - apiVersion: - description: API version of the referent. - type: string - blockOwnerDeletion: - description: If true, AND if the owner has the "foregroundDeletion" - finalizer, then the owner cannot be deleted from the - key-value store until this reference is removed. Defaults - to false. To set this field, a user needs "delete" - permission of the owner, otherwise 422 (Unprocessable - Entity) will be returned. - type: boolean - controller: - description: If true, this reference points to the managing - controller. - type: boolean - kind: - description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - name: - description: 'Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names' - type: string - uid: - description: 'UID of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#uids' - type: string - required: - - apiVersion - - kind - - name - - uid - type: object - type: array - type: object - spec: - description: Spec is the specification of the desired behavior - of the machine. - properties: datacenter: description: Datacenter is the name or inventory path of the - datacenter where this machine's VM is created/located. + datacenter in which the virtual machine is created/located. + type: string + datastore: + description: Datastore is the name or inventory path of the + datastore in which the virtual machine is created/located. type: string diskGiB: description: DiskGiB is the size of a virtual machine's disk, - in GiB. Defaults to the analogue property value in the template - from which this machine is cloned. + in GiB. Defaults to the eponymous property value in the + template from which the virtual machine is cloned. format: int32 type: integer + folder: + description: Folder is the name or inventory path of the folder + in which the virtual machine is created/located. + type: string memoryMiB: description: MemoryMiB is the size of a virtual machine's - memory, in MiB. Defaults to the analogue property value - in the template from which this machine is cloned. + memory, in MiB. Defaults to the eponymous property value + in the template from which the virtual machine is cloned. format: int64 type: integer network: @@ -309,27 +222,51 @@ spec: type: object numCPUs: description: NumCPUs is the number of virtual processors in - a virtual machine. Defaults to the analogue property value - in the template from which this machine is cloned. + a virtual machine. Defaults to the eponymous property value + in the template from which the virtual machine is cloned. format: int32 type: integer numCoresPerSocket: description: NumCPUs is the number of cores among which to distribute CPUs in this virtual machine. Defaults to the - analogue property value in the template from which this - machine is cloned. + eponymous property value in the template from which the + virtual machine is cloned. format: int32 type: integer providerID: description: ProviderID is the virtual machine's BIOS UUID formated as vsphere://12345678-1234-1234-1234-123456789abc type: string + resourcePool: + description: ResourcePool is the name or inventory path of + the resource pool in which the virtual machine is created/located. + type: string + server: + description: Server is the IP address or FQDN of the vSphere + server on which the virtual machine is created/located. + type: string + snapshot: + description: Snapshot is the name of the snapshot from which + to create a linked clone. This field is ignored if LinkedClone + is not enabled. Defaults to the source's current snapshot. + type: string + storagePolicyName: + description: StoragePolicyName of the storage policy to use + with this Virtual Machine + type: string template: - description: Template is the name, inventory path, or instance - UUID of the template used to clone new machines. + description: Template is the name or inventory path of the + template used to clone the virtual machine. + minLength: 1 + type: string + thumbprint: + description: Thumbprint is the colon-separated SHA-1 checksum + of the given vCenter server's host certificate When this + is set to empty, this VirtualMachine would be created without + TLS certificate validation of the communication between + Cluster API Provider vSphere and the VMware vCenter server. type: string required: - - datacenter - network - template type: object @@ -342,7 +279,7 @@ spec: type: object served: true storage: false - - name: v1alpha3 + - name: v1alpha4 schema: openAPIV3Schema: description: VSphereMachineTemplate is the Schema for the vspheremachinetemplates diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_vspherevms.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_vspherevms.yaml index 3e640b945d..17d516d256 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_vspherevms.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_vspherevms.yaml @@ -419,6 +419,412 @@ spec: type: object type: object served: true + storage: false + subresources: + status: {} + - name: v1alpha4 + schema: + openAPIV3Schema: + description: VSphereVM is the Schema for the vspherevms API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: VSphereVMSpec defines the desired state of VSphereVM. + properties: + biosUUID: + description: BiosUUID is the the VM's BIOS UUID that is assigned at + runtime after the VM has been created. This field is required at + runtime for other controllers that read this CRD as unstructured + data. + type: string + bootstrapRef: + description: BootstrapRef is a reference to a bootstrap provider-specific + resource that holds configuration details. This field is optional + in case no bootstrap data is required to create a VM. + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: 'If referring to a piece of an object instead of + an entire object, this string should contain a valid JSON/Go + field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within + a pod, this would take on a value like: "spec.containers{name}" + (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" + (container with index 2 in this pod). This syntax is chosen + only to have some well-defined way of referencing a part of + an object. TODO: this design is not final and this field is + subject to change in the future.' + type: string + kind: + description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + namespace: + description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/' + type: string + resourceVersion: + description: 'Specific resourceVersion to which this reference + is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency' + type: string + uid: + description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids' + type: string + type: object + cloneMode: + description: CloneMode specifies the type of clone operation. The + LinkedClone mode is only support for templates that have at least + one snapshot. If the template has no snapshots, then CloneMode defaults + to FullClone. When LinkedClone mode is enabled the DiskGiB field + is ignored as it is not possible to expand disks of linked clones. + Defaults to LinkedClone, but fails gracefully to FullClone if the + source of the clone operation has no snapshots. + type: string + customVMXKeys: + additionalProperties: + type: string + description: CustomVMXKeys is a dictionary of advanced VMX options + that can be set on VM Defaults to empty map + type: object + datacenter: + description: Datacenter is the name or inventory path of the datacenter + in which the virtual machine is created/located. + type: string + datastore: + description: Datastore is the name or inventory path of the datastore + in which the virtual machine is created/located. + type: string + diskGiB: + description: DiskGiB is the size of a virtual machine's disk, in GiB. + Defaults to the eponymous property value in the template from which + the virtual machine is cloned. + format: int32 + type: integer + folder: + description: Folder is the name or inventory path of the folder in + which the virtual machine is created/located. + type: string + memoryMiB: + description: MemoryMiB is the size of a virtual machine's memory, + in MiB. Defaults to the eponymous property value in the template + from which the virtual machine is cloned. + format: int64 + type: integer + network: + description: Network is the network configuration for this machine's + VM. + properties: + devices: + description: Devices is the list of network devices used by the + virtual machine. TODO(akutz) Make sure at least one network + matches the ClusterSpec.CloudProviderConfiguration.Network.Name + items: + description: NetworkDeviceSpec defines the network configuration + for a virtual machine's network device. + properties: + deviceName: + description: DeviceName may be used to explicitly assign + a name to the network device as it exists in the guest + operating system. + type: string + dhcp4: + description: DHCP4 is a flag that indicates whether or not + to use DHCP for IPv4 on this device. If true then IPAddrs + should not contain any IPv4 addresses. + type: boolean + dhcp6: + description: DHCP6 is a flag that indicates whether or not + to use DHCP for IPv6 on this device. If true then IPAddrs + should not contain any IPv6 addresses. + type: boolean + gateway4: + description: Gateway4 is the IPv4 gateway used by this device. + Required when DHCP4 is false. + type: string + gateway6: + description: Gateway4 is the IPv4 gateway used by this device. + Required when DHCP6 is false. + type: string + ipAddrs: + description: IPAddrs is a list of one or more IPv4 and/or + IPv6 addresses to assign to this device. Required when + DHCP4 and DHCP6 are both false. + items: + type: string + type: array + macAddr: + description: MACAddr is the MAC address used by this device. + It is generally a good idea to omit this field and allow + a MAC address to be generated. Please note that this value + must use the VMware OUI to work with the in-tree vSphere + cloud provider. + type: string + mtu: + description: MTU is the device’s Maximum Transmission Unit + size in bytes. + format: int64 + type: integer + nameservers: + description: Nameservers is a list of IPv4 and/or IPv6 addresses + used as DNS nameservers. Please note that Linux allows + only three nameservers (https://linux.die.net/man/5/resolv.conf). + items: + type: string + type: array + networkName: + description: NetworkName is the name of the vSphere network + to which the device will be connected. + type: string + routes: + description: Routes is a list of optional, static routes + applied to the device. + items: + description: NetworkRouteSpec defines a static network + route. + properties: + metric: + description: Metric is the weight/priority of the + route. + format: int32 + type: integer + to: + description: To is an IPv4 or IPv6 address. + type: string + via: + description: Via is an IPv4 or IPv6 address. + type: string + required: + - metric + - to + - via + type: object + type: array + searchDomains: + description: SearchDomains is a list of search domains used + when resolving IP addresses with DNS. + items: + type: string + type: array + required: + - networkName + type: object + type: array + preferredAPIServerCidr: + description: PreferredAPIServeCIDR is the preferred CIDR for the + Kubernetes API server endpoint on this machine + type: string + routes: + description: Routes is a list of optional, static routes applied + to the virtual machine. + items: + description: NetworkRouteSpec defines a static network route. + properties: + metric: + description: Metric is the weight/priority of the route. + format: int32 + type: integer + to: + description: To is an IPv4 or IPv6 address. + type: string + via: + description: Via is an IPv4 or IPv6 address. + type: string + required: + - metric + - to + - via + type: object + type: array + required: + - devices + type: object + numCPUs: + description: NumCPUs is the number of virtual processors in a virtual + machine. Defaults to the eponymous property value in the template + from which the virtual machine is cloned. + format: int32 + type: integer + numCoresPerSocket: + description: NumCPUs is the number of cores among which to distribute + CPUs in this virtual machine. Defaults to the eponymous property + value in the template from which the virtual machine is cloned. + format: int32 + type: integer + resourcePool: + description: ResourcePool is the name or inventory path of the resource + pool in which the virtual machine is created/located. + type: string + server: + description: Server is the IP address or FQDN of the vSphere server + on which the virtual machine is created/located. + type: string + snapshot: + description: Snapshot is the name of the snapshot from which to create + a linked clone. This field is ignored if LinkedClone is not enabled. + Defaults to the source's current snapshot. + type: string + storagePolicyName: + description: StoragePolicyName of the storage policy to use with this + Virtual Machine + type: string + template: + description: Template is the name or inventory path of the template + used to clone the virtual machine. + minLength: 1 + type: string + thumbprint: + description: Thumbprint is the colon-separated SHA-1 checksum of the + given vCenter server's host certificate When this is set to empty, + this VirtualMachine would be created without TLS certificate validation + of the communication between Cluster API Provider vSphere and the + VMware vCenter server. + type: string + required: + - network + - template + type: object + status: + description: VSphereVMStatus defines the observed state of VSphereVM + properties: + addresses: + description: Addresses is a list of the VM's IP addresses. This field + is required at runtime for other controllers that read this CRD + as unstructured data. + items: + type: string + type: array + cloneMode: + description: CloneMode is the type of clone operation used to clone + this VM. Since LinkedMode is the default but fails gracefully if + the source of the clone has no snapshots, this field may be used + to determine the actual type of clone operation used to create this + VM. + type: string + conditions: + description: Conditions defines current service state of the VSphereVM. + items: + description: Condition defines an observation of a Cluster API resource + operational state. + properties: + lastTransitionTime: + description: Last time the condition transitioned from one status + to another. This should be when the underlying condition changed. + If that is not known, then using the time when the API field + changed is acceptable. + format: date-time + type: string + message: + description: A human readable message indicating details about + the transition. This field may be empty. + type: string + reason: + description: The reason for the condition's last transition + in CamelCase. The specific API may choose whether or not this + field is considered a guaranteed API. This field may not be + empty. + type: string + severity: + description: Severity provides an explicit classification of + Reason code, so the users or machines can immediately understand + the current situation and act accordingly. The Severity field + MUST be set only when Status=False. + type: string + status: + description: Status of the condition, one of True, False, Unknown. + type: string + type: + description: Type of condition in CamelCase or in foo.example.com/CamelCase. + Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. + type: string + required: + - status + - type + type: object + type: array + failureMessage: + description: "FailureMessage will be set in the event that there is + a terminal problem reconciling the vspherevm and will contain a + more verbose string suitable for logging and human consumption. + \n This field should not be set for transitive errors that a controller + faces that are expected to be fixed automatically over time (like + service outages), but instead indicate that something is fundamentally + wrong with the vm. \n Any transient errors that occur during the + reconciliation of vspherevms can be added as events to the vspherevm + object and/or logged in the controller's output." + type: string + failureReason: + description: "FailureReason will be set in the event that there is + a terminal problem reconciling the vspherevm and will contain a + succinct value suitable for vm interpretation. \n This field should + not be set for transitive errors that a controller faces that are + expected to be fixed automatically over time (like service outages), + but instead indicate that something is fundamentally wrong with + the vm. \n Any transient errors that occur during the reconciliation + of vspherevms can be added as events to the vspherevm object and/or + logged in the controller's output." + type: string + network: + description: Network returns the network status for each of the machine's + configured network interfaces. + items: + description: NetworkStatus provides information about one of a VM's + networks. + properties: + connected: + description: Connected is a flag that indicates whether this + network is currently connected to the VM. + type: boolean + ipAddrs: + description: IPAddrs is one or more IP addresses reported by + vm-tools. + items: + type: string + type: array + macAddr: + description: MACAddr is the MAC address of the network device. + type: string + networkName: + description: NetworkName is the name of the network. + type: string + required: + - macAddr + type: object + type: array + ready: + description: Ready is true when the provider resource is ready. This + field is required at runtime for other controllers that read this + CRD as unstructured data. + type: boolean + snapshot: + description: Snapshot is the name of the snapshot from which the VM + was cloned if LinkedMode is enabled. + type: string + taskRef: + description: TaskRef is a managed object reference to a Task related + to the machine. This value is set automatically at runtime and should + not be set or modified by users. + type: string + type: object + type: object + served: true storage: true subresources: status: {} diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml index c8f90dce3d..dc5e5e868a 100644 --- a/config/webhook/manifests.yaml +++ b/config/webhook/manifests.yaml @@ -6,6 +6,86 @@ metadata: creationTimestamp: null name: validating-webhook-configuration webhooks: +- clientConfig: + caBundle: Cg== + service: + name: webhook-service + namespace: system + path: /validate-infrastructure-cluster-x-k8s-io-v1alpha4-vspherecluster + failurePolicy: Fail + matchPolicy: Equivalent + name: validation.vspherecluster.infrastructure.x-k8s.io + rules: + - apiGroups: + - infrastructure.cluster.x-k8s.io + apiVersions: + - v1alpha4 + operations: + - CREATE + - UPDATE + resources: + - vsphereclusters + sideEffects: None +- clientConfig: + caBundle: Cg== + service: + name: webhook-service + namespace: system + path: /validate-infrastructure-cluster-x-k8s-io-v1alpha4-vspheremachine + failurePolicy: Fail + matchPolicy: Equivalent + name: validation.vspheremachine.infrastructure.x-k8s.io + rules: + - apiGroups: + - infrastructure.cluster.x-k8s.io + apiVersions: + - v1alpha4 + operations: + - CREATE + - UPDATE + resources: + - vspheremachines + sideEffects: None +- clientConfig: + caBundle: Cg== + service: + name: webhook-service + namespace: system + path: /validate-infrastructure-cluster-x-k8s-io-v1alpha4-vspheremachinetemplate + failurePolicy: Fail + matchPolicy: Equivalent + name: validation.vspheremachinetemplate.infrastructure.x-k8s.io + rules: + - apiGroups: + - infrastructure.cluster.x-k8s.io + apiVersions: + - v1alpha4 + operations: + - CREATE + - UPDATE + resources: + - vspheremachinetemplates + sideEffects: None +- clientConfig: + caBundle: Cg== + service: + name: webhook-service + namespace: system + path: /validate-infrastructure-cluster-x-k8s-io-v1alpha4-vspherevm + failurePolicy: Fail + matchPolicy: Equivalent + name: validation.vspherevm.infrastructure.x-k8s.io + rules: + - apiGroups: + - infrastructure.cluster.x-k8s.io + apiVersions: + - v1alpha4 + operations: + - CREATE + - UPDATE + resources: + - vspherevms + sideEffects: None - clientConfig: caBundle: Cg== service: diff --git a/main.go b/main.go index 18e0cab09c..33bd5c79d1 100644 --- a/main.go +++ b/main.go @@ -24,8 +24,8 @@ import ( "os" "time" - "sigs.k8s.io/cluster-api-provider-vsphere/api/v1alpha2" "sigs.k8s.io/cluster-api-provider-vsphere/api/v1alpha3" + "sigs.k8s.io/cluster-api-provider-vsphere/api/v1alpha4" "k8s.io/klog" "k8s.io/klog/klogr" @@ -143,6 +143,12 @@ func main() { if err := (&v1alpha3.VSphereClusterList{}).SetupWebhookWithManager(mgr); err != nil { return err } + if err := (&v1alpha4.VSphereCluster{}).SetupWebhookWithManager(mgr); err != nil { + return err + } + if err := (&v1alpha4.VSphereClusterList{}).SetupWebhookWithManager(mgr); err != nil { + return err + } if err := (&v1alpha3.VSphereMachine{}).SetupWebhookWithManager(mgr); err != nil { return err @@ -150,6 +156,12 @@ func main() { if err := (&v1alpha3.VSphereMachineList{}).SetupWebhookWithManager(mgr); err != nil { return err } + if err := (&v1alpha4.VSphereMachine{}).SetupWebhookWithManager(mgr); err != nil { + return err + } + if err := (&v1alpha4.VSphereMachineList{}).SetupWebhookWithManager(mgr); err != nil { + return err + } if err := (&v1alpha3.VSphereMachineTemplate{}).SetupWebhookWithManager(mgr); err != nil { return err @@ -157,27 +169,30 @@ func main() { if err := (&v1alpha3.VSphereMachineTemplateList{}).SetupWebhookWithManager(mgr); err != nil { return err } - - if err := (&v1alpha3.VSphereVM{}).SetupWebhookWithManager(mgr); err != nil { + if err := (&v1alpha4.VSphereMachineTemplate{}).SetupWebhookWithManager(mgr); err != nil { return err } - if err := (&v1alpha3.VSphereVMList{}).SetupWebhookWithManager(mgr); err != nil { + if err := (&v1alpha4.VSphereMachineTemplateList{}).SetupWebhookWithManager(mgr); err != nil { return err } - if err := (&v1alpha3.HAProxyLoadBalancer{}).SetupWebhookWithManager(mgr); err != nil { + if err := (&v1alpha3.VSphereVM{}).SetupWebhookWithManager(mgr); err != nil { return err } - if err := (&v1alpha3.HAProxyLoadBalancerList{}).SetupWebhookWithManager(mgr); err != nil { + if err := (&v1alpha3.VSphereVMList{}).SetupWebhookWithManager(mgr); err != nil { return err } - if err := (&v1alpha2.VSphereCluster{}).SetupWebhookWithManager(mgr); err != nil { + if err := (&v1alpha4.VSphereVM{}).SetupWebhookWithManager(mgr); err != nil { return err } - if err := (&v1alpha2.VSphereMachine{}).SetupWebhookWithManager(mgr); err != nil { + if err := (&v1alpha4.VSphereVMList{}).SetupWebhookWithManager(mgr); err != nil { return err } - if err := (&v1alpha2.VSphereMachineTemplate{}).SetupWebhookWithManager(mgr); err != nil { + + if err := (&v1alpha3.HAProxyLoadBalancer{}).SetupWebhookWithManager(mgr); err != nil { + return err + } + if err := (&v1alpha3.HAProxyLoadBalancerList{}).SetupWebhookWithManager(mgr); err != nil { return err } } else {