diff --git a/Dockerfile b/Dockerfile index 1acad1232..94c30c173 100644 --- a/Dockerfile +++ b/Dockerfile @@ -79,6 +79,7 @@ RUN protoc -I/src/app/sidero-controller-manager/internal/api \ api.proto RUN --mount=type=cache,target=/.cache controller-gen object:headerFile="./hack/boilerplate.go.txt" paths="./..." RUN --mount=type=cache,target=/.cache conversion-gen --input-dirs="./app/caps-controller-manager/api/v1alpha2" --output-base ./ --output-file-base="zz_generated.conversion" --go-header-file="./hack/boilerplate.go.txt" +RUN --mount=type=cache,target=/.cache conversion-gen --input-dirs="./app/sidero-controller-manager/api/v1alpha1" --output-base ./ --output-file-base="zz_generated.conversion" --go-header-file="./hack/boilerplate.go.txt" ARG MODULE RUN --mount=type=cache,target=/.cache gofumports -w -local ${MODULE} . diff --git a/app/caps-controller-manager/config/crd/patches/webhook_in_metalclusters.yaml b/app/caps-controller-manager/config/crd/patches/webhook_in_metalclusters.yaml index 2324040ba..e85ab4769 100644 --- a/app/caps-controller-manager/config/crd/patches/webhook_in_metalclusters.yaml +++ b/app/caps-controller-manager/config/crd/patches/webhook_in_metalclusters.yaml @@ -15,5 +15,5 @@ spec: caBundle: Cg== service: namespace: system - name: webhook-service + name: caps-webhook-service path: /convert diff --git a/app/caps-controller-manager/config/crd/patches/webhook_in_metalmachines.yaml b/app/caps-controller-manager/config/crd/patches/webhook_in_metalmachines.yaml index 71510e9dd..2862905f8 100644 --- a/app/caps-controller-manager/config/crd/patches/webhook_in_metalmachines.yaml +++ b/app/caps-controller-manager/config/crd/patches/webhook_in_metalmachines.yaml @@ -15,5 +15,5 @@ spec: caBundle: Cg== service: namespace: system - name: webhook-service + name: caps-webhook-service path: /convert diff --git a/app/caps-controller-manager/config/crd/patches/webhook_in_metalmachinetemplates.yaml b/app/caps-controller-manager/config/crd/patches/webhook_in_metalmachinetemplates.yaml index 600a8964b..6ddb39c7b 100644 --- a/app/caps-controller-manager/config/crd/patches/webhook_in_metalmachinetemplates.yaml +++ b/app/caps-controller-manager/config/crd/patches/webhook_in_metalmachinetemplates.yaml @@ -15,5 +15,5 @@ spec: caBundle: Cg== service: namespace: system - name: webhook-service + name: caps-webhook-service path: /convert diff --git a/app/caps-controller-manager/config/crd/patches/webhook_in_serverbindings.yaml b/app/caps-controller-manager/config/crd/patches/webhook_in_serverbindings.yaml index 4ffa25713..b4269944d 100644 --- a/app/caps-controller-manager/config/crd/patches/webhook_in_serverbindings.yaml +++ b/app/caps-controller-manager/config/crd/patches/webhook_in_serverbindings.yaml @@ -15,5 +15,5 @@ spec: caBundle: Cg== service: namespace: system - name: webhook-service + name: caps-webhook-service path: /convert diff --git a/app/sidero-controller-manager/PROJECT b/app/sidero-controller-manager/PROJECT index 6bf695d0a..1472e279c 100644 --- a/app/sidero-controller-manager/PROJECT +++ b/app/sidero-controller-manager/PROJECT @@ -10,4 +10,13 @@ resources: - group: metal kind: ServerClass version: v1alpha1 +- group: metal + kind: Environment + version: v1alpha2 +- group: metal + kind: Server + version: v1alpha2 +- group: metal + kind: ServerClass + version: v1alpha2 version: "2" diff --git a/app/sidero-controller-manager/api/v1alpha1/doc.go b/app/sidero-controller-manager/api/v1alpha1/doc.go new file mode 100644 index 000000000..5aac563b1 --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha1/doc.go @@ -0,0 +1,7 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package v1alpha1 + +// +k8s:conversion-gen=github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2 diff --git a/app/sidero-controller-manager/api/v1alpha1/environment_conversion.go b/app/sidero-controller-manager/api/v1alpha1/environment_conversion.go new file mode 100644 index 000000000..924bc0b2f --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha1/environment_conversion.go @@ -0,0 +1,56 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +//nolint:golint,stylecheck +package v1alpha1 + +import ( + utilconversion "sigs.k8s.io/cluster-api/util/conversion" + "sigs.k8s.io/controller-runtime/pkg/conversion" + + metalv1alpha2 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" +) + +// ConvertTo converts this Environment to the Hub version (v1alpha2). +func (src *Environment) ConvertTo(dstRaw conversion.Hub) error { + dst := dstRaw.(*metalv1alpha2.Environment) + if err := Convert_v1alpha1_Environment_To_v1alpha2_Environment(src, dst, nil); err != nil { + return err + } + + // Manually restore data from annotations + restored := &metalv1alpha2.Environment{} + if ok, err := utilconversion.UnmarshalData(src, restored); err != nil || !ok { + return err + } + + return nil +} + +// ConvertFrom converts from the Hub version (v1alpha3) to this version. +func (dst *Environment) ConvertFrom(srcRaw conversion.Hub) error { + src := srcRaw.(*metalv1alpha2.Environment) + if err := Convert_v1alpha2_Environment_To_v1alpha1_Environment(src, dst, nil); err != nil { + return err + } + + // Preserve Hub data on down-conversion. + if err := utilconversion.MarshalData(src, dst); err != nil { + return err + } + + return nil +} + +// ConvertTo converts this MetalMachineTemplateList to the Hub version (v1alpha3). +func (src *EnvironmentList) ConvertTo(dstRaw conversion.Hub) error { + dst := dstRaw.(*metalv1alpha2.EnvironmentList) + return Convert_v1alpha1_EnvironmentList_To_v1alpha2_EnvironmentList(src, dst, nil) +} + +// ConvertFrom converts from the Hub version (v1alpha3) to this version. +func (dst *EnvironmentList) ConvertFrom(srcRaw conversion.Hub) error { + src := srcRaw.(*metalv1alpha2.EnvironmentList) + return Convert_v1alpha2_EnvironmentList_To_v1alpha1_EnvironmentList(src, dst, nil) +} diff --git a/app/sidero-controller-manager/api/v1alpha1/groupversion_info.go b/app/sidero-controller-manager/api/v1alpha1/groupversion_info.go index 201054aa4..44d835731 100644 --- a/app/sidero-controller-manager/api/v1alpha1/groupversion_info.go +++ b/app/sidero-controller-manager/api/v1alpha1/groupversion_info.go @@ -21,4 +21,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/app/sidero-controller-manager/api/v1alpha1/server_conversion.go b/app/sidero-controller-manager/api/v1alpha1/server_conversion.go new file mode 100644 index 000000000..5b6d5d52b --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha1/server_conversion.go @@ -0,0 +1,133 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +//nolint:golint,stylecheck +package v1alpha1 + +import ( + apiconversion "k8s.io/apimachinery/pkg/conversion" + utilconversion "sigs.k8s.io/cluster-api/util/conversion" + "sigs.k8s.io/controller-runtime/pkg/conversion" + + metalv1alpha2 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" +) + +// ConvertTo converts this Server to the Hub version (v1alpha2). +func (src *Server) ConvertTo(dstRaw conversion.Hub) error { + dst := dstRaw.(*metalv1alpha2.Server) + if err := Convert_v1alpha1_Server_To_v1alpha2_Server(src, dst, nil); err != nil { + return err + } + + // Manually restore data from annotations + restored := &metalv1alpha2.Server{} + if ok, err := utilconversion.UnmarshalData(src, restored); err != nil || !ok { + return err + } + + return nil +} + +// ConvertFrom converts from the Hub version (v1alpha3) to this version. +func (dst *Server) ConvertFrom(srcRaw conversion.Hub) error { + src := srcRaw.(*metalv1alpha2.Server) + if err := Convert_v1alpha2_Server_To_v1alpha1_Server(src, dst, nil); err != nil { + return err + } + + // Preserve Hub data on down-conversion. + if err := utilconversion.MarshalData(src, dst); err != nil { + return err + } + + return nil +} + +// ConvertTo converts this MetalMachineTemplateList to the Hub version (v1alpha3). +func (src *ServerList) ConvertTo(dstRaw conversion.Hub) error { + dst := dstRaw.(*metalv1alpha2.ServerList) + return Convert_v1alpha1_ServerList_To_v1alpha2_ServerList(src, dst, nil) +} + +// ConvertFrom converts from the Hub version (v1alpha3) to this version. +func (dst *ServerList) ConvertFrom(srcRaw conversion.Hub) error { + src := srcRaw.(*metalv1alpha2.ServerList) + return Convert_v1alpha2_ServerList_To_v1alpha1_ServerList(src, dst, nil) +} + +// Convert_v1alpha1_ServerSpec_To_v1alpha2_ServerSpec converts to the Hub version (v1alpha2). +func Convert_v1alpha1_ServerSpec_To_v1alpha2_ServerSpec(in *ServerSpec, out *metalv1alpha2.ServerSpec, s apiconversion.Scope) error { + if err := autoConvert_v1alpha1_ServerSpec_To_v1alpha2_ServerSpec(in, out, s); err != nil { + return err + } + + // Manually convert SystemInformation to Hardware. + if in.SystemInformation != nil { + if out.Hardware == nil { + out.Hardware = &metalv1alpha2.HardwareInformation{} + } + + out.Hardware.System = &metalv1alpha2.SystemInformation{ + Manufacturer: in.SystemInformation.Manufacturer, + ProductName: in.SystemInformation.ProductName, + Version: in.SystemInformation.Version, + SerialNumber: in.SystemInformation.SerialNumber, + SKUNumber: in.SystemInformation.SKUNumber, + Family: in.SystemInformation.Family, + } + } + + // Manually convert CPU to Hardware. + if in.CPU != nil { + if out.Hardware == nil { + out.Hardware = &metalv1alpha2.HardwareInformation{} + } + + out.Hardware.Compute = &metalv1alpha2.ComputeInformation{ + Processors: []*metalv1alpha2.Processor{ + { + Manufacturer: in.CPU.Manufacturer, + ProductName: in.CPU.Version, + }, + }, + } + } + + return nil +} + +// Convert_v1alpha2_ServerSpec_To_v1alpha1_ServerSpec converts from the Hub version (v1alpha2). +func Convert_v1alpha2_ServerSpec_To_v1alpha1_ServerSpec(in *metalv1alpha2.ServerSpec, out *ServerSpec, s apiconversion.Scope) error { + if err := autoConvert_v1alpha2_ServerSpec_To_v1alpha1_ServerSpec(in, out, s); err != nil { + return err + } + + // Manually convert Hardware to SystemInformation. + if in.Hardware != nil && in.Hardware.System != nil { + out.SystemInformation = &SystemInformation{ + Manufacturer: in.Hardware.System.Manufacturer, + ProductName: in.Hardware.System.ProductName, + Version: in.Hardware.System.Version, + SerialNumber: in.Hardware.System.SerialNumber, + SKUNumber: in.Hardware.System.SKUNumber, + Family: in.Hardware.System.Family, + } + } + + // Manually convert Hardware to CPU. + if in.Hardware != nil && in.Hardware.Compute != nil && len(in.Hardware.Compute.Processors) > 0 { + cpu := in.Hardware.Compute.Processors[0] + + out.CPU = &CPUInformation{ + Manufacturer: cpu.Manufacturer, + Version: cpu.ProductName, + } + } + + return nil +} + +func Convert_v1alpha2_SystemInformation_To_v1alpha1_SystemInformation(in *metalv1alpha2.SystemInformation, out *SystemInformation, s apiconversion.Scope) error { + return autoConvert_v1alpha2_SystemInformation_To_v1alpha1_SystemInformation(in, out, s) +} diff --git a/app/sidero-controller-manager/api/v1alpha1/server_conversion_test.go b/app/sidero-controller-manager/api/v1alpha1/server_conversion_test.go new file mode 100644 index 000000000..93d8697f1 --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha1/server_conversion_test.go @@ -0,0 +1,99 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package v1alpha1_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + metalv1alpha1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha1" + metalv1alpha2 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" +) + +func TestServerConvertV1alpha1V1Alpha2(t *testing.T) { + src := &metalv1alpha1.Server{ + Spec: metalv1alpha1.ServerSpec{ + Hostname: "example.com", + SystemInformation: &metalv1alpha1.SystemInformation{ + Manufacturer: "Sidero", + ProductName: "Server", + Version: "v1.0", + }, + CPU: &metalv1alpha1.CPUInformation{ + Manufacturer: "Sidero CPU", + Version: "v1", + }, + }, + } + dst := &metalv1alpha2.Server{} + + require.NoError(t, src.ConvertTo(dst)) + + assert.Equal(t, "example.com", dst.Spec.Hostname) + assert.Equal(t, + &metalv1alpha2.SystemInformation{ + Manufacturer: "Sidero", + ProductName: "Server", + Version: "v1.0", + }, + dst.Spec.Hardware.System, + ) + assert.Equal(t, + &metalv1alpha2.ComputeInformation{ + Processors: []*metalv1alpha2.Processor{ + { + Manufacturer: "Sidero CPU", + ProductName: "v1", + }, + }, + }, + dst.Spec.Hardware.Compute, + ) +} + +func TestServerConvertV1alpha2V1Alpha1(t *testing.T) { + src := &metalv1alpha2.Server{ + Spec: metalv1alpha2.ServerSpec{ + Hostname: "example.com", + Hardware: &metalv1alpha2.HardwareInformation{ + System: &metalv1alpha2.SystemInformation{ + Manufacturer: "Sidero", + ProductName: "Server", + Version: "v1.0", + }, + Compute: &metalv1alpha2.ComputeInformation{ + Processors: []*metalv1alpha2.Processor{ + { + Manufacturer: "Sidero CPU", + ProductName: "v1", + }, + }, + }, + }, + }, + } + dst := &metalv1alpha1.Server{} + + require.NoError(t, dst.ConvertFrom(src)) + + assert.Equal(t, "example.com", dst.Spec.Hostname) + assert.Equal(t, + &metalv1alpha1.SystemInformation{ + Manufacturer: "Sidero", + ProductName: "Server", + Version: "v1.0", + }, + dst.Spec.SystemInformation, + ) + assert.Equal(t, + &metalv1alpha1.CPUInformation{ + Manufacturer: "Sidero CPU", + Version: "v1", + }, + dst.Spec.CPU, + ) +} diff --git a/app/sidero-controller-manager/api/v1alpha1/serverclass_conversion.go b/app/sidero-controller-manager/api/v1alpha1/serverclass_conversion.go new file mode 100644 index 000000000..43d4e4017 --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha1/serverclass_conversion.go @@ -0,0 +1,126 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +//nolint:golint,stylecheck +package v1alpha1 + +import ( + apiconversion "k8s.io/apimachinery/pkg/conversion" + utilconversion "sigs.k8s.io/cluster-api/util/conversion" + "sigs.k8s.io/controller-runtime/pkg/conversion" + + metalv1alpha2 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" +) + +// ConvertTo converts this ServerClass to the Hub version (v1alpha2). +func (src *ServerClass) ConvertTo(dstRaw conversion.Hub) error { + dst := dstRaw.(*metalv1alpha2.ServerClass) + if err := Convert_v1alpha1_ServerClass_To_v1alpha2_ServerClass(src, dst, nil); err != nil { + return err + } + + // Manually restore data from annotations + restored := &metalv1alpha2.ServerClass{} + if ok, err := utilconversion.UnmarshalData(src, restored); err != nil || !ok { + return err + } + + return nil +} + +// ConvertFrom converts from the Hub version (v1alpha3) to this version. +func (dst *ServerClass) ConvertFrom(srcRaw conversion.Hub) error { + src := srcRaw.(*metalv1alpha2.ServerClass) + if err := Convert_v1alpha2_ServerClass_To_v1alpha1_ServerClass(src, dst, nil); err != nil { + return err + } + + // Preserve Hub data on down-conversion. + if err := utilconversion.MarshalData(src, dst); err != nil { + return err + } + + return nil +} + +// ConvertTo converts this MetalMachineTemplateList to the Hub version (v1alpha3). +func (src *ServerClassList) ConvertTo(dstRaw conversion.Hub) error { + dst := dstRaw.(*metalv1alpha2.ServerClassList) + return Convert_v1alpha1_ServerClassList_To_v1alpha2_ServerClassList(src, dst, nil) +} + +// ConvertFrom converts from the Hub version (v1alpha3) to this version. +func (dst *ServerClassList) ConvertFrom(srcRaw conversion.Hub) error { + src := srcRaw.(*metalv1alpha2.ServerClassList) + return Convert_v1alpha2_ServerClassList_To_v1alpha1_ServerClassList(src, dst, nil) +} + +// Convert_v1alpha1_Qualifiers_To_v1alpha2_Qualifiers converts to the Hub version (v1alpha2). +func Convert_v1alpha1_Qualifiers_To_v1alpha2_Qualifiers(in *Qualifiers, out *metalv1alpha2.Qualifiers, s apiconversion.Scope) error { + if err := autoConvert_v1alpha1_Qualifiers_To_v1alpha2_Qualifiers(in, out, s); err != nil { + return err + } + + // Manually convert SystemInformation to Hardware. + for _, v := range in.SystemInformation { + out.Hardware = append(out.Hardware, metalv1alpha2.HardwareInformation{ + System: &metalv1alpha2.SystemInformation{ + Manufacturer: v.Manufacturer, + ProductName: v.ProductName, + Version: v.Version, + SerialNumber: v.SerialNumber, + SKUNumber: v.SKUNumber, + Family: v.Family, + }, + }) + } + + // Manually convert CPU to Hardware. + for _, v := range in.CPU { + out.Hardware = append(out.Hardware, metalv1alpha2.HardwareInformation{ + Compute: &metalv1alpha2.ComputeInformation{ + Processors: []*metalv1alpha2.Processor{ + { + Manufacturer: v.Manufacturer, + ProductName: v.Version, + }, + }, + }, + }) + } + + return nil +} + +// Convert_v1alpha2_Qualifiers_To_v1alpha1_Qualifiers converts from the Hub version (v1alpha2). +func Convert_v1alpha2_Qualifiers_To_v1alpha1_Qualifiers(in *metalv1alpha2.Qualifiers, out *Qualifiers, s apiconversion.Scope) error { + if err := autoConvert_v1alpha2_Qualifiers_To_v1alpha1_Qualifiers(in, out, s); err != nil { + return err + } + + // Manually convert Hardware to SystemInformation or CPU. + for _, v := range in.Hardware { + if v.System != nil { + out.SystemInformation = append(out.SystemInformation, SystemInformation{ + Manufacturer: v.System.Manufacturer, + ProductName: v.System.ProductName, + Version: v.System.Version, + SerialNumber: v.System.SerialNumber, + SKUNumber: v.System.SKUNumber, + Family: v.System.Family, + }) + } + + if v.Compute != nil && len(v.Compute.Processors) > 0 { + cpu := v.Compute.Processors[0] + + out.CPU = append(out.CPU, CPUInformation{ + Manufacturer: cpu.Manufacturer, + Version: cpu.ProductName, + }) + } + } + + return nil +} diff --git a/app/sidero-controller-manager/api/v1alpha1/zz_generated.conversion.go b/app/sidero-controller-manager/api/v1alpha1/zz_generated.conversion.go new file mode 100644 index 000000000..ac273f357 --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha1/zz_generated.conversion.go @@ -0,0 +1,886 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +// Code generated by conversion-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + unsafe "unsafe" + + v1 "k8s.io/api/core/v1" + conversion "k8s.io/apimachinery/pkg/conversion" + runtime "k8s.io/apimachinery/pkg/runtime" + v1beta1 "sigs.k8s.io/cluster-api/api/v1beta1" + + v1alpha2 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" + types "github.com/talos-systems/sidero/app/sidero-controller-manager/pkg/types" +) + +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((*Asset)(nil), (*v1alpha2.Asset)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_Asset_To_v1alpha2_Asset(a.(*Asset), b.(*v1alpha2.Asset), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.Asset)(nil), (*Asset)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_Asset_To_v1alpha1_Asset(a.(*v1alpha2.Asset), b.(*Asset), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*AssetCondition)(nil), (*v1alpha2.AssetCondition)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_AssetCondition_To_v1alpha2_AssetCondition(a.(*AssetCondition), b.(*v1alpha2.AssetCondition), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.AssetCondition)(nil), (*AssetCondition)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_AssetCondition_To_v1alpha1_AssetCondition(a.(*v1alpha2.AssetCondition), b.(*AssetCondition), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*BMC)(nil), (*v1alpha2.BMC)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_BMC_To_v1alpha2_BMC(a.(*BMC), b.(*v1alpha2.BMC), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.BMC)(nil), (*BMC)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_BMC_To_v1alpha1_BMC(a.(*v1alpha2.BMC), b.(*BMC), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ConfigPatches)(nil), (*v1alpha2.ConfigPatches)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ConfigPatches_To_v1alpha2_ConfigPatches(a.(*ConfigPatches), b.(*v1alpha2.ConfigPatches), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.ConfigPatches)(nil), (*ConfigPatches)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_ConfigPatches_To_v1alpha1_ConfigPatches(a.(*v1alpha2.ConfigPatches), b.(*ConfigPatches), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*CredentialSource)(nil), (*v1alpha2.CredentialSource)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_CredentialSource_To_v1alpha2_CredentialSource(a.(*CredentialSource), b.(*v1alpha2.CredentialSource), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.CredentialSource)(nil), (*CredentialSource)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_CredentialSource_To_v1alpha1_CredentialSource(a.(*v1alpha2.CredentialSource), b.(*CredentialSource), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*Environment)(nil), (*v1alpha2.Environment)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_Environment_To_v1alpha2_Environment(a.(*Environment), b.(*v1alpha2.Environment), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.Environment)(nil), (*Environment)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_Environment_To_v1alpha1_Environment(a.(*v1alpha2.Environment), b.(*Environment), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*EnvironmentList)(nil), (*v1alpha2.EnvironmentList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_EnvironmentList_To_v1alpha2_EnvironmentList(a.(*EnvironmentList), b.(*v1alpha2.EnvironmentList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.EnvironmentList)(nil), (*EnvironmentList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_EnvironmentList_To_v1alpha1_EnvironmentList(a.(*v1alpha2.EnvironmentList), b.(*EnvironmentList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*EnvironmentSpec)(nil), (*v1alpha2.EnvironmentSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_EnvironmentSpec_To_v1alpha2_EnvironmentSpec(a.(*EnvironmentSpec), b.(*v1alpha2.EnvironmentSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.EnvironmentSpec)(nil), (*EnvironmentSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_EnvironmentSpec_To_v1alpha1_EnvironmentSpec(a.(*v1alpha2.EnvironmentSpec), b.(*EnvironmentSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*EnvironmentStatus)(nil), (*v1alpha2.EnvironmentStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_EnvironmentStatus_To_v1alpha2_EnvironmentStatus(a.(*EnvironmentStatus), b.(*v1alpha2.EnvironmentStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.EnvironmentStatus)(nil), (*EnvironmentStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_EnvironmentStatus_To_v1alpha1_EnvironmentStatus(a.(*v1alpha2.EnvironmentStatus), b.(*EnvironmentStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*Initrd)(nil), (*v1alpha2.Initrd)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_Initrd_To_v1alpha2_Initrd(a.(*Initrd), b.(*v1alpha2.Initrd), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.Initrd)(nil), (*Initrd)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_Initrd_To_v1alpha1_Initrd(a.(*v1alpha2.Initrd), b.(*Initrd), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*Kernel)(nil), (*v1alpha2.Kernel)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_Kernel_To_v1alpha2_Kernel(a.(*Kernel), b.(*v1alpha2.Kernel), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.Kernel)(nil), (*Kernel)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_Kernel_To_v1alpha1_Kernel(a.(*v1alpha2.Kernel), b.(*Kernel), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ManagementAPI)(nil), (*v1alpha2.ManagementAPI)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ManagementAPI_To_v1alpha2_ManagementAPI(a.(*ManagementAPI), b.(*v1alpha2.ManagementAPI), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.ManagementAPI)(nil), (*ManagementAPI)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_ManagementAPI_To_v1alpha1_ManagementAPI(a.(*v1alpha2.ManagementAPI), b.(*ManagementAPI), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*SecretKeyRef)(nil), (*v1alpha2.SecretKeyRef)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_SecretKeyRef_To_v1alpha2_SecretKeyRef(a.(*SecretKeyRef), b.(*v1alpha2.SecretKeyRef), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.SecretKeyRef)(nil), (*SecretKeyRef)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_SecretKeyRef_To_v1alpha1_SecretKeyRef(a.(*v1alpha2.SecretKeyRef), b.(*SecretKeyRef), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*Server)(nil), (*v1alpha2.Server)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_Server_To_v1alpha2_Server(a.(*Server), b.(*v1alpha2.Server), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.Server)(nil), (*Server)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_Server_To_v1alpha1_Server(a.(*v1alpha2.Server), b.(*Server), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ServerClass)(nil), (*v1alpha2.ServerClass)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ServerClass_To_v1alpha2_ServerClass(a.(*ServerClass), b.(*v1alpha2.ServerClass), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.ServerClass)(nil), (*ServerClass)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_ServerClass_To_v1alpha1_ServerClass(a.(*v1alpha2.ServerClass), b.(*ServerClass), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ServerClassList)(nil), (*v1alpha2.ServerClassList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ServerClassList_To_v1alpha2_ServerClassList(a.(*ServerClassList), b.(*v1alpha2.ServerClassList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.ServerClassList)(nil), (*ServerClassList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_ServerClassList_To_v1alpha1_ServerClassList(a.(*v1alpha2.ServerClassList), b.(*ServerClassList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ServerClassSpec)(nil), (*v1alpha2.ServerClassSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ServerClassSpec_To_v1alpha2_ServerClassSpec(a.(*ServerClassSpec), b.(*v1alpha2.ServerClassSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.ServerClassSpec)(nil), (*ServerClassSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_ServerClassSpec_To_v1alpha1_ServerClassSpec(a.(*v1alpha2.ServerClassSpec), b.(*ServerClassSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ServerClassStatus)(nil), (*v1alpha2.ServerClassStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ServerClassStatus_To_v1alpha2_ServerClassStatus(a.(*ServerClassStatus), b.(*v1alpha2.ServerClassStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.ServerClassStatus)(nil), (*ServerClassStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_ServerClassStatus_To_v1alpha1_ServerClassStatus(a.(*v1alpha2.ServerClassStatus), b.(*ServerClassStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ServerList)(nil), (*v1alpha2.ServerList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ServerList_To_v1alpha2_ServerList(a.(*ServerList), b.(*v1alpha2.ServerList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.ServerList)(nil), (*ServerList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_ServerList_To_v1alpha1_ServerList(a.(*v1alpha2.ServerList), b.(*ServerList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ServerStatus)(nil), (*v1alpha2.ServerStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ServerStatus_To_v1alpha2_ServerStatus(a.(*ServerStatus), b.(*v1alpha2.ServerStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.ServerStatus)(nil), (*ServerStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_ServerStatus_To_v1alpha1_ServerStatus(a.(*v1alpha2.ServerStatus), b.(*ServerStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*SystemInformation)(nil), (*v1alpha2.SystemInformation)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_SystemInformation_To_v1alpha2_SystemInformation(a.(*SystemInformation), b.(*v1alpha2.SystemInformation), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*Qualifiers)(nil), (*v1alpha2.Qualifiers)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_Qualifiers_To_v1alpha2_Qualifiers(a.(*Qualifiers), b.(*v1alpha2.Qualifiers), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*ServerSpec)(nil), (*v1alpha2.ServerSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ServerSpec_To_v1alpha2_ServerSpec(a.(*ServerSpec), b.(*v1alpha2.ServerSpec), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1alpha2.Qualifiers)(nil), (*Qualifiers)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_Qualifiers_To_v1alpha1_Qualifiers(a.(*v1alpha2.Qualifiers), b.(*Qualifiers), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1alpha2.ServerSpec)(nil), (*ServerSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_ServerSpec_To_v1alpha1_ServerSpec(a.(*v1alpha2.ServerSpec), b.(*ServerSpec), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1alpha2.SystemInformation)(nil), (*SystemInformation)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_SystemInformation_To_v1alpha1_SystemInformation(a.(*v1alpha2.SystemInformation), b.(*SystemInformation), scope) + }); err != nil { + return err + } + return nil +} + +func autoConvert_v1alpha1_Asset_To_v1alpha2_Asset(in *Asset, out *v1alpha2.Asset, s conversion.Scope) error { + out.URL = in.URL + out.SHA512 = in.SHA512 + return nil +} + +// Convert_v1alpha1_Asset_To_v1alpha2_Asset is an autogenerated conversion function. +func Convert_v1alpha1_Asset_To_v1alpha2_Asset(in *Asset, out *v1alpha2.Asset, s conversion.Scope) error { + return autoConvert_v1alpha1_Asset_To_v1alpha2_Asset(in, out, s) +} + +func autoConvert_v1alpha2_Asset_To_v1alpha1_Asset(in *v1alpha2.Asset, out *Asset, s conversion.Scope) error { + out.URL = in.URL + out.SHA512 = in.SHA512 + return nil +} + +// Convert_v1alpha2_Asset_To_v1alpha1_Asset is an autogenerated conversion function. +func Convert_v1alpha2_Asset_To_v1alpha1_Asset(in *v1alpha2.Asset, out *Asset, s conversion.Scope) error { + return autoConvert_v1alpha2_Asset_To_v1alpha1_Asset(in, out, s) +} + +func autoConvert_v1alpha1_AssetCondition_To_v1alpha2_AssetCondition(in *AssetCondition, out *v1alpha2.AssetCondition, s conversion.Scope) error { + if err := Convert_v1alpha1_Asset_To_v1alpha2_Asset(&in.Asset, &out.Asset, s); err != nil { + return err + } + out.Status = in.Status + out.Type = in.Type + return nil +} + +// Convert_v1alpha1_AssetCondition_To_v1alpha2_AssetCondition is an autogenerated conversion function. +func Convert_v1alpha1_AssetCondition_To_v1alpha2_AssetCondition(in *AssetCondition, out *v1alpha2.AssetCondition, s conversion.Scope) error { + return autoConvert_v1alpha1_AssetCondition_To_v1alpha2_AssetCondition(in, out, s) +} + +func autoConvert_v1alpha2_AssetCondition_To_v1alpha1_AssetCondition(in *v1alpha2.AssetCondition, out *AssetCondition, s conversion.Scope) error { + if err := Convert_v1alpha2_Asset_To_v1alpha1_Asset(&in.Asset, &out.Asset, s); err != nil { + return err + } + out.Status = in.Status + out.Type = in.Type + return nil +} + +// Convert_v1alpha2_AssetCondition_To_v1alpha1_AssetCondition is an autogenerated conversion function. +func Convert_v1alpha2_AssetCondition_To_v1alpha1_AssetCondition(in *v1alpha2.AssetCondition, out *AssetCondition, s conversion.Scope) error { + return autoConvert_v1alpha2_AssetCondition_To_v1alpha1_AssetCondition(in, out, s) +} + +func autoConvert_v1alpha1_BMC_To_v1alpha2_BMC(in *BMC, out *v1alpha2.BMC, s conversion.Scope) error { + out.Endpoint = in.Endpoint + out.Port = in.Port + out.User = in.User + out.UserFrom = (*v1alpha2.CredentialSource)(unsafe.Pointer(in.UserFrom)) + out.Pass = in.Pass + out.PassFrom = (*v1alpha2.CredentialSource)(unsafe.Pointer(in.PassFrom)) + out.Interface = in.Interface + return nil +} + +// Convert_v1alpha1_BMC_To_v1alpha2_BMC is an autogenerated conversion function. +func Convert_v1alpha1_BMC_To_v1alpha2_BMC(in *BMC, out *v1alpha2.BMC, s conversion.Scope) error { + return autoConvert_v1alpha1_BMC_To_v1alpha2_BMC(in, out, s) +} + +func autoConvert_v1alpha2_BMC_To_v1alpha1_BMC(in *v1alpha2.BMC, out *BMC, s conversion.Scope) error { + out.Endpoint = in.Endpoint + out.Port = in.Port + out.User = in.User + out.UserFrom = (*CredentialSource)(unsafe.Pointer(in.UserFrom)) + out.Pass = in.Pass + out.PassFrom = (*CredentialSource)(unsafe.Pointer(in.PassFrom)) + out.Interface = in.Interface + return nil +} + +// Convert_v1alpha2_BMC_To_v1alpha1_BMC is an autogenerated conversion function. +func Convert_v1alpha2_BMC_To_v1alpha1_BMC(in *v1alpha2.BMC, out *BMC, s conversion.Scope) error { + return autoConvert_v1alpha2_BMC_To_v1alpha1_BMC(in, out, s) +} + +func autoConvert_v1alpha1_ConfigPatches_To_v1alpha2_ConfigPatches(in *ConfigPatches, out *v1alpha2.ConfigPatches, s conversion.Scope) error { + out.Op = in.Op + out.Path = in.Path + out.Value = in.Value + return nil +} + +// Convert_v1alpha1_ConfigPatches_To_v1alpha2_ConfigPatches is an autogenerated conversion function. +func Convert_v1alpha1_ConfigPatches_To_v1alpha2_ConfigPatches(in *ConfigPatches, out *v1alpha2.ConfigPatches, s conversion.Scope) error { + return autoConvert_v1alpha1_ConfigPatches_To_v1alpha2_ConfigPatches(in, out, s) +} + +func autoConvert_v1alpha2_ConfigPatches_To_v1alpha1_ConfigPatches(in *v1alpha2.ConfigPatches, out *ConfigPatches, s conversion.Scope) error { + out.Op = in.Op + out.Path = in.Path + out.Value = in.Value + return nil +} + +// Convert_v1alpha2_ConfigPatches_To_v1alpha1_ConfigPatches is an autogenerated conversion function. +func Convert_v1alpha2_ConfigPatches_To_v1alpha1_ConfigPatches(in *v1alpha2.ConfigPatches, out *ConfigPatches, s conversion.Scope) error { + return autoConvert_v1alpha2_ConfigPatches_To_v1alpha1_ConfigPatches(in, out, s) +} + +func autoConvert_v1alpha1_CredentialSource_To_v1alpha2_CredentialSource(in *CredentialSource, out *v1alpha2.CredentialSource, s conversion.Scope) error { + out.SecretKeyRef = (*v1alpha2.SecretKeyRef)(unsafe.Pointer(in.SecretKeyRef)) + return nil +} + +// Convert_v1alpha1_CredentialSource_To_v1alpha2_CredentialSource is an autogenerated conversion function. +func Convert_v1alpha1_CredentialSource_To_v1alpha2_CredentialSource(in *CredentialSource, out *v1alpha2.CredentialSource, s conversion.Scope) error { + return autoConvert_v1alpha1_CredentialSource_To_v1alpha2_CredentialSource(in, out, s) +} + +func autoConvert_v1alpha2_CredentialSource_To_v1alpha1_CredentialSource(in *v1alpha2.CredentialSource, out *CredentialSource, s conversion.Scope) error { + out.SecretKeyRef = (*SecretKeyRef)(unsafe.Pointer(in.SecretKeyRef)) + return nil +} + +// Convert_v1alpha2_CredentialSource_To_v1alpha1_CredentialSource is an autogenerated conversion function. +func Convert_v1alpha2_CredentialSource_To_v1alpha1_CredentialSource(in *v1alpha2.CredentialSource, out *CredentialSource, s conversion.Scope) error { + return autoConvert_v1alpha2_CredentialSource_To_v1alpha1_CredentialSource(in, out, s) +} + +func autoConvert_v1alpha1_Environment_To_v1alpha2_Environment(in *Environment, out *v1alpha2.Environment, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha1_EnvironmentSpec_To_v1alpha2_EnvironmentSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1alpha1_EnvironmentStatus_To_v1alpha2_EnvironmentStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha1_Environment_To_v1alpha2_Environment is an autogenerated conversion function. +func Convert_v1alpha1_Environment_To_v1alpha2_Environment(in *Environment, out *v1alpha2.Environment, s conversion.Scope) error { + return autoConvert_v1alpha1_Environment_To_v1alpha2_Environment(in, out, s) +} + +func autoConvert_v1alpha2_Environment_To_v1alpha1_Environment(in *v1alpha2.Environment, out *Environment, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha2_EnvironmentSpec_To_v1alpha1_EnvironmentSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1alpha2_EnvironmentStatus_To_v1alpha1_EnvironmentStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha2_Environment_To_v1alpha1_Environment is an autogenerated conversion function. +func Convert_v1alpha2_Environment_To_v1alpha1_Environment(in *v1alpha2.Environment, out *Environment, s conversion.Scope) error { + return autoConvert_v1alpha2_Environment_To_v1alpha1_Environment(in, out, s) +} + +func autoConvert_v1alpha1_EnvironmentList_To_v1alpha2_EnvironmentList(in *EnvironmentList, out *v1alpha2.EnvironmentList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]v1alpha2.Environment)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_v1alpha1_EnvironmentList_To_v1alpha2_EnvironmentList is an autogenerated conversion function. +func Convert_v1alpha1_EnvironmentList_To_v1alpha2_EnvironmentList(in *EnvironmentList, out *v1alpha2.EnvironmentList, s conversion.Scope) error { + return autoConvert_v1alpha1_EnvironmentList_To_v1alpha2_EnvironmentList(in, out, s) +} + +func autoConvert_v1alpha2_EnvironmentList_To_v1alpha1_EnvironmentList(in *v1alpha2.EnvironmentList, out *EnvironmentList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]Environment)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_v1alpha2_EnvironmentList_To_v1alpha1_EnvironmentList is an autogenerated conversion function. +func Convert_v1alpha2_EnvironmentList_To_v1alpha1_EnvironmentList(in *v1alpha2.EnvironmentList, out *EnvironmentList, s conversion.Scope) error { + return autoConvert_v1alpha2_EnvironmentList_To_v1alpha1_EnvironmentList(in, out, s) +} + +func autoConvert_v1alpha1_EnvironmentSpec_To_v1alpha2_EnvironmentSpec(in *EnvironmentSpec, out *v1alpha2.EnvironmentSpec, s conversion.Scope) error { + if err := Convert_v1alpha1_Kernel_To_v1alpha2_Kernel(&in.Kernel, &out.Kernel, s); err != nil { + return err + } + if err := Convert_v1alpha1_Initrd_To_v1alpha2_Initrd(&in.Initrd, &out.Initrd, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha1_EnvironmentSpec_To_v1alpha2_EnvironmentSpec is an autogenerated conversion function. +func Convert_v1alpha1_EnvironmentSpec_To_v1alpha2_EnvironmentSpec(in *EnvironmentSpec, out *v1alpha2.EnvironmentSpec, s conversion.Scope) error { + return autoConvert_v1alpha1_EnvironmentSpec_To_v1alpha2_EnvironmentSpec(in, out, s) +} + +func autoConvert_v1alpha2_EnvironmentSpec_To_v1alpha1_EnvironmentSpec(in *v1alpha2.EnvironmentSpec, out *EnvironmentSpec, s conversion.Scope) error { + if err := Convert_v1alpha2_Kernel_To_v1alpha1_Kernel(&in.Kernel, &out.Kernel, s); err != nil { + return err + } + if err := Convert_v1alpha2_Initrd_To_v1alpha1_Initrd(&in.Initrd, &out.Initrd, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha2_EnvironmentSpec_To_v1alpha1_EnvironmentSpec is an autogenerated conversion function. +func Convert_v1alpha2_EnvironmentSpec_To_v1alpha1_EnvironmentSpec(in *v1alpha2.EnvironmentSpec, out *EnvironmentSpec, s conversion.Scope) error { + return autoConvert_v1alpha2_EnvironmentSpec_To_v1alpha1_EnvironmentSpec(in, out, s) +} + +func autoConvert_v1alpha1_EnvironmentStatus_To_v1alpha2_EnvironmentStatus(in *EnvironmentStatus, out *v1alpha2.EnvironmentStatus, s conversion.Scope) error { + out.Conditions = *(*[]v1alpha2.AssetCondition)(unsafe.Pointer(&in.Conditions)) + return nil +} + +// Convert_v1alpha1_EnvironmentStatus_To_v1alpha2_EnvironmentStatus is an autogenerated conversion function. +func Convert_v1alpha1_EnvironmentStatus_To_v1alpha2_EnvironmentStatus(in *EnvironmentStatus, out *v1alpha2.EnvironmentStatus, s conversion.Scope) error { + return autoConvert_v1alpha1_EnvironmentStatus_To_v1alpha2_EnvironmentStatus(in, out, s) +} + +func autoConvert_v1alpha2_EnvironmentStatus_To_v1alpha1_EnvironmentStatus(in *v1alpha2.EnvironmentStatus, out *EnvironmentStatus, s conversion.Scope) error { + out.Conditions = *(*[]AssetCondition)(unsafe.Pointer(&in.Conditions)) + return nil +} + +// Convert_v1alpha2_EnvironmentStatus_To_v1alpha1_EnvironmentStatus is an autogenerated conversion function. +func Convert_v1alpha2_EnvironmentStatus_To_v1alpha1_EnvironmentStatus(in *v1alpha2.EnvironmentStatus, out *EnvironmentStatus, s conversion.Scope) error { + return autoConvert_v1alpha2_EnvironmentStatus_To_v1alpha1_EnvironmentStatus(in, out, s) +} + +func autoConvert_v1alpha1_Initrd_To_v1alpha2_Initrd(in *Initrd, out *v1alpha2.Initrd, s conversion.Scope) error { + if err := Convert_v1alpha1_Asset_To_v1alpha2_Asset(&in.Asset, &out.Asset, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha1_Initrd_To_v1alpha2_Initrd is an autogenerated conversion function. +func Convert_v1alpha1_Initrd_To_v1alpha2_Initrd(in *Initrd, out *v1alpha2.Initrd, s conversion.Scope) error { + return autoConvert_v1alpha1_Initrd_To_v1alpha2_Initrd(in, out, s) +} + +func autoConvert_v1alpha2_Initrd_To_v1alpha1_Initrd(in *v1alpha2.Initrd, out *Initrd, s conversion.Scope) error { + if err := Convert_v1alpha2_Asset_To_v1alpha1_Asset(&in.Asset, &out.Asset, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha2_Initrd_To_v1alpha1_Initrd is an autogenerated conversion function. +func Convert_v1alpha2_Initrd_To_v1alpha1_Initrd(in *v1alpha2.Initrd, out *Initrd, s conversion.Scope) error { + return autoConvert_v1alpha2_Initrd_To_v1alpha1_Initrd(in, out, s) +} + +func autoConvert_v1alpha1_Kernel_To_v1alpha2_Kernel(in *Kernel, out *v1alpha2.Kernel, s conversion.Scope) error { + if err := Convert_v1alpha1_Asset_To_v1alpha2_Asset(&in.Asset, &out.Asset, s); err != nil { + return err + } + out.Args = *(*[]string)(unsafe.Pointer(&in.Args)) + return nil +} + +// Convert_v1alpha1_Kernel_To_v1alpha2_Kernel is an autogenerated conversion function. +func Convert_v1alpha1_Kernel_To_v1alpha2_Kernel(in *Kernel, out *v1alpha2.Kernel, s conversion.Scope) error { + return autoConvert_v1alpha1_Kernel_To_v1alpha2_Kernel(in, out, s) +} + +func autoConvert_v1alpha2_Kernel_To_v1alpha1_Kernel(in *v1alpha2.Kernel, out *Kernel, s conversion.Scope) error { + if err := Convert_v1alpha2_Asset_To_v1alpha1_Asset(&in.Asset, &out.Asset, s); err != nil { + return err + } + out.Args = *(*[]string)(unsafe.Pointer(&in.Args)) + return nil +} + +// Convert_v1alpha2_Kernel_To_v1alpha1_Kernel is an autogenerated conversion function. +func Convert_v1alpha2_Kernel_To_v1alpha1_Kernel(in *v1alpha2.Kernel, out *Kernel, s conversion.Scope) error { + return autoConvert_v1alpha2_Kernel_To_v1alpha1_Kernel(in, out, s) +} + +func autoConvert_v1alpha1_ManagementAPI_To_v1alpha2_ManagementAPI(in *ManagementAPI, out *v1alpha2.ManagementAPI, s conversion.Scope) error { + out.Endpoint = in.Endpoint + return nil +} + +// Convert_v1alpha1_ManagementAPI_To_v1alpha2_ManagementAPI is an autogenerated conversion function. +func Convert_v1alpha1_ManagementAPI_To_v1alpha2_ManagementAPI(in *ManagementAPI, out *v1alpha2.ManagementAPI, s conversion.Scope) error { + return autoConvert_v1alpha1_ManagementAPI_To_v1alpha2_ManagementAPI(in, out, s) +} + +func autoConvert_v1alpha2_ManagementAPI_To_v1alpha1_ManagementAPI(in *v1alpha2.ManagementAPI, out *ManagementAPI, s conversion.Scope) error { + out.Endpoint = in.Endpoint + return nil +} + +// Convert_v1alpha2_ManagementAPI_To_v1alpha1_ManagementAPI is an autogenerated conversion function. +func Convert_v1alpha2_ManagementAPI_To_v1alpha1_ManagementAPI(in *v1alpha2.ManagementAPI, out *ManagementAPI, s conversion.Scope) error { + return autoConvert_v1alpha2_ManagementAPI_To_v1alpha1_ManagementAPI(in, out, s) +} + +func autoConvert_v1alpha1_Qualifiers_To_v1alpha2_Qualifiers(in *Qualifiers, out *v1alpha2.Qualifiers, s conversion.Scope) error { + // WARNING: in.CPU requires manual conversion: does not exist in peer-type + // WARNING: in.SystemInformation requires manual conversion: does not exist in peer-type + out.LabelSelectors = *(*[]map[string]string)(unsafe.Pointer(&in.LabelSelectors)) + return nil +} + +func autoConvert_v1alpha2_Qualifiers_To_v1alpha1_Qualifiers(in *v1alpha2.Qualifiers, out *Qualifiers, s conversion.Scope) error { + // WARNING: in.Hardware requires manual conversion: does not exist in peer-type + out.LabelSelectors = *(*[]map[string]string)(unsafe.Pointer(&in.LabelSelectors)) + return nil +} + +func autoConvert_v1alpha1_SecretKeyRef_To_v1alpha2_SecretKeyRef(in *SecretKeyRef, out *v1alpha2.SecretKeyRef, s conversion.Scope) error { + out.Namespace = in.Namespace + out.Name = in.Name + out.Key = in.Key + return nil +} + +// Convert_v1alpha1_SecretKeyRef_To_v1alpha2_SecretKeyRef is an autogenerated conversion function. +func Convert_v1alpha1_SecretKeyRef_To_v1alpha2_SecretKeyRef(in *SecretKeyRef, out *v1alpha2.SecretKeyRef, s conversion.Scope) error { + return autoConvert_v1alpha1_SecretKeyRef_To_v1alpha2_SecretKeyRef(in, out, s) +} + +func autoConvert_v1alpha2_SecretKeyRef_To_v1alpha1_SecretKeyRef(in *v1alpha2.SecretKeyRef, out *SecretKeyRef, s conversion.Scope) error { + out.Namespace = in.Namespace + out.Name = in.Name + out.Key = in.Key + return nil +} + +// Convert_v1alpha2_SecretKeyRef_To_v1alpha1_SecretKeyRef is an autogenerated conversion function. +func Convert_v1alpha2_SecretKeyRef_To_v1alpha1_SecretKeyRef(in *v1alpha2.SecretKeyRef, out *SecretKeyRef, s conversion.Scope) error { + return autoConvert_v1alpha2_SecretKeyRef_To_v1alpha1_SecretKeyRef(in, out, s) +} + +func autoConvert_v1alpha1_Server_To_v1alpha2_Server(in *Server, out *v1alpha2.Server, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha1_ServerSpec_To_v1alpha2_ServerSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1alpha1_ServerStatus_To_v1alpha2_ServerStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha1_Server_To_v1alpha2_Server is an autogenerated conversion function. +func Convert_v1alpha1_Server_To_v1alpha2_Server(in *Server, out *v1alpha2.Server, s conversion.Scope) error { + return autoConvert_v1alpha1_Server_To_v1alpha2_Server(in, out, s) +} + +func autoConvert_v1alpha2_Server_To_v1alpha1_Server(in *v1alpha2.Server, out *Server, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha2_ServerSpec_To_v1alpha1_ServerSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1alpha2_ServerStatus_To_v1alpha1_ServerStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha2_Server_To_v1alpha1_Server is an autogenerated conversion function. +func Convert_v1alpha2_Server_To_v1alpha1_Server(in *v1alpha2.Server, out *Server, s conversion.Scope) error { + return autoConvert_v1alpha2_Server_To_v1alpha1_Server(in, out, s) +} + +func autoConvert_v1alpha1_ServerClass_To_v1alpha2_ServerClass(in *ServerClass, out *v1alpha2.ServerClass, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha1_ServerClassSpec_To_v1alpha2_ServerClassSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1alpha1_ServerClassStatus_To_v1alpha2_ServerClassStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha1_ServerClass_To_v1alpha2_ServerClass is an autogenerated conversion function. +func Convert_v1alpha1_ServerClass_To_v1alpha2_ServerClass(in *ServerClass, out *v1alpha2.ServerClass, s conversion.Scope) error { + return autoConvert_v1alpha1_ServerClass_To_v1alpha2_ServerClass(in, out, s) +} + +func autoConvert_v1alpha2_ServerClass_To_v1alpha1_ServerClass(in *v1alpha2.ServerClass, out *ServerClass, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha2_ServerClassSpec_To_v1alpha1_ServerClassSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1alpha2_ServerClassStatus_To_v1alpha1_ServerClassStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha2_ServerClass_To_v1alpha1_ServerClass is an autogenerated conversion function. +func Convert_v1alpha2_ServerClass_To_v1alpha1_ServerClass(in *v1alpha2.ServerClass, out *ServerClass, s conversion.Scope) error { + return autoConvert_v1alpha2_ServerClass_To_v1alpha1_ServerClass(in, out, s) +} + +func autoConvert_v1alpha1_ServerClassList_To_v1alpha2_ServerClassList(in *ServerClassList, out *v1alpha2.ServerClassList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]v1alpha2.ServerClass, len(*in)) + for i := range *in { + if err := Convert_v1alpha1_ServerClass_To_v1alpha2_ServerClass(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } + return nil +} + +// Convert_v1alpha1_ServerClassList_To_v1alpha2_ServerClassList is an autogenerated conversion function. +func Convert_v1alpha1_ServerClassList_To_v1alpha2_ServerClassList(in *ServerClassList, out *v1alpha2.ServerClassList, s conversion.Scope) error { + return autoConvert_v1alpha1_ServerClassList_To_v1alpha2_ServerClassList(in, out, s) +} + +func autoConvert_v1alpha2_ServerClassList_To_v1alpha1_ServerClassList(in *v1alpha2.ServerClassList, out *ServerClassList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ServerClass, len(*in)) + for i := range *in { + if err := Convert_v1alpha2_ServerClass_To_v1alpha1_ServerClass(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } + return nil +} + +// Convert_v1alpha2_ServerClassList_To_v1alpha1_ServerClassList is an autogenerated conversion function. +func Convert_v1alpha2_ServerClassList_To_v1alpha1_ServerClassList(in *v1alpha2.ServerClassList, out *ServerClassList, s conversion.Scope) error { + return autoConvert_v1alpha2_ServerClassList_To_v1alpha1_ServerClassList(in, out, s) +} + +func autoConvert_v1alpha1_ServerClassSpec_To_v1alpha2_ServerClassSpec(in *ServerClassSpec, out *v1alpha2.ServerClassSpec, s conversion.Scope) error { + out.EnvironmentRef = (*v1.ObjectReference)(unsafe.Pointer(in.EnvironmentRef)) + if err := Convert_v1alpha1_Qualifiers_To_v1alpha2_Qualifiers(&in.Qualifiers, &out.Qualifiers, s); err != nil { + return err + } + out.Selector = in.Selector + out.ConfigPatches = *(*[]v1alpha2.ConfigPatches)(unsafe.Pointer(&in.ConfigPatches)) + out.BootFromDiskMethod = types.BootFromDisk(in.BootFromDiskMethod) + return nil +} + +// Convert_v1alpha1_ServerClassSpec_To_v1alpha2_ServerClassSpec is an autogenerated conversion function. +func Convert_v1alpha1_ServerClassSpec_To_v1alpha2_ServerClassSpec(in *ServerClassSpec, out *v1alpha2.ServerClassSpec, s conversion.Scope) error { + return autoConvert_v1alpha1_ServerClassSpec_To_v1alpha2_ServerClassSpec(in, out, s) +} + +func autoConvert_v1alpha2_ServerClassSpec_To_v1alpha1_ServerClassSpec(in *v1alpha2.ServerClassSpec, out *ServerClassSpec, s conversion.Scope) error { + out.EnvironmentRef = (*v1.ObjectReference)(unsafe.Pointer(in.EnvironmentRef)) + if err := Convert_v1alpha2_Qualifiers_To_v1alpha1_Qualifiers(&in.Qualifiers, &out.Qualifiers, s); err != nil { + return err + } + out.Selector = in.Selector + out.ConfigPatches = *(*[]ConfigPatches)(unsafe.Pointer(&in.ConfigPatches)) + out.BootFromDiskMethod = types.BootFromDisk(in.BootFromDiskMethod) + return nil +} + +// Convert_v1alpha2_ServerClassSpec_To_v1alpha1_ServerClassSpec is an autogenerated conversion function. +func Convert_v1alpha2_ServerClassSpec_To_v1alpha1_ServerClassSpec(in *v1alpha2.ServerClassSpec, out *ServerClassSpec, s conversion.Scope) error { + return autoConvert_v1alpha2_ServerClassSpec_To_v1alpha1_ServerClassSpec(in, out, s) +} + +func autoConvert_v1alpha1_ServerClassStatus_To_v1alpha2_ServerClassStatus(in *ServerClassStatus, out *v1alpha2.ServerClassStatus, s conversion.Scope) error { + out.ServersAvailable = *(*[]string)(unsafe.Pointer(&in.ServersAvailable)) + out.ServersInUse = *(*[]string)(unsafe.Pointer(&in.ServersInUse)) + return nil +} + +// Convert_v1alpha1_ServerClassStatus_To_v1alpha2_ServerClassStatus is an autogenerated conversion function. +func Convert_v1alpha1_ServerClassStatus_To_v1alpha2_ServerClassStatus(in *ServerClassStatus, out *v1alpha2.ServerClassStatus, s conversion.Scope) error { + return autoConvert_v1alpha1_ServerClassStatus_To_v1alpha2_ServerClassStatus(in, out, s) +} + +func autoConvert_v1alpha2_ServerClassStatus_To_v1alpha1_ServerClassStatus(in *v1alpha2.ServerClassStatus, out *ServerClassStatus, s conversion.Scope) error { + out.ServersAvailable = *(*[]string)(unsafe.Pointer(&in.ServersAvailable)) + out.ServersInUse = *(*[]string)(unsafe.Pointer(&in.ServersInUse)) + return nil +} + +// Convert_v1alpha2_ServerClassStatus_To_v1alpha1_ServerClassStatus is an autogenerated conversion function. +func Convert_v1alpha2_ServerClassStatus_To_v1alpha1_ServerClassStatus(in *v1alpha2.ServerClassStatus, out *ServerClassStatus, s conversion.Scope) error { + return autoConvert_v1alpha2_ServerClassStatus_To_v1alpha1_ServerClassStatus(in, out, s) +} + +func autoConvert_v1alpha1_ServerList_To_v1alpha2_ServerList(in *ServerList, out *v1alpha2.ServerList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]v1alpha2.Server, len(*in)) + for i := range *in { + if err := Convert_v1alpha1_Server_To_v1alpha2_Server(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } + return nil +} + +// Convert_v1alpha1_ServerList_To_v1alpha2_ServerList is an autogenerated conversion function. +func Convert_v1alpha1_ServerList_To_v1alpha2_ServerList(in *ServerList, out *v1alpha2.ServerList, s conversion.Scope) error { + return autoConvert_v1alpha1_ServerList_To_v1alpha2_ServerList(in, out, s) +} + +func autoConvert_v1alpha2_ServerList_To_v1alpha1_ServerList(in *v1alpha2.ServerList, out *ServerList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Server, len(*in)) + for i := range *in { + if err := Convert_v1alpha2_Server_To_v1alpha1_Server(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } + return nil +} + +// Convert_v1alpha2_ServerList_To_v1alpha1_ServerList is an autogenerated conversion function. +func Convert_v1alpha2_ServerList_To_v1alpha1_ServerList(in *v1alpha2.ServerList, out *ServerList, s conversion.Scope) error { + return autoConvert_v1alpha2_ServerList_To_v1alpha1_ServerList(in, out, s) +} + +func autoConvert_v1alpha1_ServerSpec_To_v1alpha2_ServerSpec(in *ServerSpec, out *v1alpha2.ServerSpec, s conversion.Scope) error { + out.EnvironmentRef = (*v1.ObjectReference)(unsafe.Pointer(in.EnvironmentRef)) + out.Hostname = in.Hostname + // WARNING: in.SystemInformation requires manual conversion: does not exist in peer-type + // WARNING: in.CPU requires manual conversion: does not exist in peer-type + out.BMC = (*v1alpha2.BMC)(unsafe.Pointer(in.BMC)) + out.ManagementAPI = (*v1alpha2.ManagementAPI)(unsafe.Pointer(in.ManagementAPI)) + out.ConfigPatches = *(*[]v1alpha2.ConfigPatches)(unsafe.Pointer(&in.ConfigPatches)) + out.Accepted = in.Accepted + out.Cordoned = in.Cordoned + out.PXEBootAlways = in.PXEBootAlways + out.BootFromDiskMethod = types.BootFromDisk(in.BootFromDiskMethod) + return nil +} + +func autoConvert_v1alpha2_ServerSpec_To_v1alpha1_ServerSpec(in *v1alpha2.ServerSpec, out *ServerSpec, s conversion.Scope) error { + out.EnvironmentRef = (*v1.ObjectReference)(unsafe.Pointer(in.EnvironmentRef)) + // WARNING: in.Hardware requires manual conversion: does not exist in peer-type + out.Hostname = in.Hostname + out.BMC = (*BMC)(unsafe.Pointer(in.BMC)) + out.ManagementAPI = (*ManagementAPI)(unsafe.Pointer(in.ManagementAPI)) + out.ConfigPatches = *(*[]ConfigPatches)(unsafe.Pointer(&in.ConfigPatches)) + out.Accepted = in.Accepted + out.Cordoned = in.Cordoned + out.PXEBootAlways = in.PXEBootAlways + out.BootFromDiskMethod = types.BootFromDisk(in.BootFromDiskMethod) + return nil +} + +func autoConvert_v1alpha1_ServerStatus_To_v1alpha2_ServerStatus(in *ServerStatus, out *v1alpha2.ServerStatus, s conversion.Scope) error { + out.Ready = in.Ready + out.InUse = in.InUse + out.IsClean = in.IsClean + out.Conditions = *(*[]v1beta1.Condition)(unsafe.Pointer(&in.Conditions)) + out.Addresses = *(*[]v1.NodeAddress)(unsafe.Pointer(&in.Addresses)) + out.Power = in.Power + return nil +} + +// Convert_v1alpha1_ServerStatus_To_v1alpha2_ServerStatus is an autogenerated conversion function. +func Convert_v1alpha1_ServerStatus_To_v1alpha2_ServerStatus(in *ServerStatus, out *v1alpha2.ServerStatus, s conversion.Scope) error { + return autoConvert_v1alpha1_ServerStatus_To_v1alpha2_ServerStatus(in, out, s) +} + +func autoConvert_v1alpha2_ServerStatus_To_v1alpha1_ServerStatus(in *v1alpha2.ServerStatus, out *ServerStatus, s conversion.Scope) error { + out.Ready = in.Ready + out.InUse = in.InUse + out.IsClean = in.IsClean + out.Conditions = *(*[]v1beta1.Condition)(unsafe.Pointer(&in.Conditions)) + out.Addresses = *(*[]v1.NodeAddress)(unsafe.Pointer(&in.Addresses)) + out.Power = in.Power + return nil +} + +// Convert_v1alpha2_ServerStatus_To_v1alpha1_ServerStatus is an autogenerated conversion function. +func Convert_v1alpha2_ServerStatus_To_v1alpha1_ServerStatus(in *v1alpha2.ServerStatus, out *ServerStatus, s conversion.Scope) error { + return autoConvert_v1alpha2_ServerStatus_To_v1alpha1_ServerStatus(in, out, s) +} + +func autoConvert_v1alpha1_SystemInformation_To_v1alpha2_SystemInformation(in *SystemInformation, out *v1alpha2.SystemInformation, s conversion.Scope) error { + out.Manufacturer = in.Manufacturer + out.ProductName = in.ProductName + out.Version = in.Version + out.SerialNumber = in.SerialNumber + out.SKUNumber = in.SKUNumber + out.Family = in.Family + return nil +} + +// Convert_v1alpha1_SystemInformation_To_v1alpha2_SystemInformation is an autogenerated conversion function. +func Convert_v1alpha1_SystemInformation_To_v1alpha2_SystemInformation(in *SystemInformation, out *v1alpha2.SystemInformation, s conversion.Scope) error { + return autoConvert_v1alpha1_SystemInformation_To_v1alpha2_SystemInformation(in, out, s) +} + +func autoConvert_v1alpha2_SystemInformation_To_v1alpha1_SystemInformation(in *v1alpha2.SystemInformation, out *SystemInformation, s conversion.Scope) error { + // WARNING: in.Uuid requires manual conversion: does not exist in peer-type + out.Manufacturer = in.Manufacturer + out.ProductName = in.ProductName + out.Version = in.Version + out.SerialNumber = in.SerialNumber + out.SKUNumber = in.SKUNumber + out.Family = in.Family + return nil +} diff --git a/app/sidero-controller-manager/api/v1alpha2/doc.go b/app/sidero-controller-manager/api/v1alpha2/doc.go new file mode 100644 index 000000000..fd95a0726 --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha2/doc.go @@ -0,0 +1,5 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package v1alpha2 diff --git a/app/sidero-controller-manager/api/v1alpha2/environment_conversion.go b/app/sidero-controller-manager/api/v1alpha2/environment_conversion.go new file mode 100644 index 000000000..cd8e4ebf9 --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha2/environment_conversion.go @@ -0,0 +1,8 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package v1alpha2 + +func (*Environment) Hub() {} +func (*EnvironmentList) Hub() {} diff --git a/app/sidero-controller-manager/api/v1alpha2/environment_types.go b/app/sidero-controller-manager/api/v1alpha2/environment_types.go new file mode 100644 index 000000000..a9a01b056 --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha2/environment_types.go @@ -0,0 +1,123 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package v1alpha2 + +import ( + "fmt" + "sort" + + "github.com/talos-systems/talos/pkg/machinery/kernel" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// EnvironmentDefault is an automatically created Environment. +const EnvironmentDefault = "default" + +type Asset struct { + URL string `json:"url,omitempty"` + SHA512 string `json:"sha512,omitempty"` +} + +type Kernel struct { + Asset `json:",inline"` + + Args []string `json:"args,omitempty"` +} + +type Initrd struct { + Asset `json:",inline"` +} + +// EnvironmentSpec defines the desired state of Environment. +type EnvironmentSpec struct { + Kernel Kernel `json:"kernel,omitempty"` + Initrd Initrd `json:"initrd,omitempty"` +} + +type AssetCondition struct { + Asset `json:",inline"` + Status string `json:"status"` + Type string `json:"type"` +} + +// EnvironmentStatus defines the observed state of Environment. +type EnvironmentStatus struct { + Conditions []AssetCondition `json:"conditions,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:resource:scope=Cluster +// +kubebuilder:printcolumn:name="Kernel",type="string",JSONPath=".spec.kernel.url",description="the kernel for the environment" +// +kubebuilder:printcolumn:name="Initrd",type="string",JSONPath=".spec.initrd.url",description="the initrd for the environment" +// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status",description="indicates the readiness of the environment" +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="The age of this resource" +// +kubebuilder:storageversion + +// Environment is the Schema for the environments API. +type Environment struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec EnvironmentSpec `json:"spec,omitempty"` + Status EnvironmentStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// EnvironmentList contains a list of Environment. +type EnvironmentList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Environment `json:"items"` +} + +// EnvironmentDefaultSpec returns EnvironmentDefault's spec. +func EnvironmentDefaultSpec(talosRelease, apiEndpoint string, apiPort uint16) *EnvironmentSpec { + args := make([]string, 0, len(kernel.DefaultArgs)+6) + args = append(args, kernel.DefaultArgs...) + args = append(args, "console=tty0", "console=ttyS0", "earlyprintk=ttyS0") + args = append(args, "initrd=initramfs.xz", "talos.platform=metal") + sort.Strings(args) + + return &EnvironmentSpec{ + Kernel: Kernel{ + Asset: Asset{ + URL: fmt.Sprintf("https://github.com/siderolabs/talos/releases/download/%s/vmlinuz-amd64", talosRelease), + }, + Args: args, + }, + Initrd: Initrd{ + Asset: Asset{ + URL: fmt.Sprintf("https://github.com/siderolabs/talos/releases/download/%s/initramfs-amd64.xz", talosRelease), + }, + }, + } +} + +// IsReady returns aggregated Environment readiness. +func (env *Environment) IsReady() bool { + assetURLs := map[string]struct{}{} + + if env.Spec.Kernel.URL != "" { + assetURLs[env.Spec.Kernel.URL] = struct{}{} + } + + if env.Spec.Initrd.URL != "" { + assetURLs[env.Spec.Initrd.URL] = struct{}{} + } + + for _, cond := range env.Status.Conditions { + if cond.Status == "True" && cond.Type == "Ready" { + delete(assetURLs, cond.URL) + } + } + + return len(assetURLs) == 0 +} + +func init() { + SchemeBuilder.Register(&Environment{}, &EnvironmentList{}) +} diff --git a/app/sidero-controller-manager/api/v1alpha2/environment_webhook.go b/app/sidero-controller-manager/api/v1alpha2/environment_webhook.go new file mode 100644 index 000000000..1b0ccf6f2 --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha2/environment_webhook.go @@ -0,0 +1,21 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package v1alpha2 + +import ( + ctrl "sigs.k8s.io/controller-runtime" +) + +func (r *Environment) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} + +func (r *EnvironmentList) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} diff --git a/app/sidero-controller-manager/api/v1alpha2/groupversion_info.go b/app/sidero-controller-manager/api/v1alpha2/groupversion_info.go new file mode 100644 index 000000000..35a2bc3bc --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha2/groupversion_info.go @@ -0,0 +1,24 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +// package v1alpha2 contains API Schema definitions for the metal v1alpha2 API group +// +kubebuilder:object:generate=true +// +groupName=metal.sidero.dev +package v1alpha2 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects. + GroupVersion = schema.GroupVersion{Group: "metal.sidero.dev", Version: "v1alpha2"} + + // 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/app/sidero-controller-manager/api/v1alpha2/server_conversion.go b/app/sidero-controller-manager/api/v1alpha2/server_conversion.go new file mode 100644 index 000000000..f32f528a2 --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha2/server_conversion.go @@ -0,0 +1,8 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package v1alpha2 + +func (*Server) Hub() {} +func (*ServerList) Hub() {} diff --git a/app/sidero-controller-manager/api/v1alpha2/server_types.go b/app/sidero-controller-manager/api/v1alpha2/server_types.go new file mode 100644 index 000000000..c7ae5215a --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha2/server_types.go @@ -0,0 +1,329 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package v1alpha2 + +import ( + "context" + "fmt" + "reflect" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" + "sigs.k8s.io/controller-runtime/pkg/client" + + siderotypes "github.com/talos-systems/sidero/app/sidero-controller-manager/pkg/types" +) + +// BMC defines data about how to talk to the node via ipmitool. +type BMC struct { + // BMC endpoint. + Endpoint string `json:"endpoint"` + // BMC port. Defaults to 623. + // +optional + Port uint32 `json:"port,omitempty"` + // BMC user value. + // +optional + User string `json:"user,omitempty"` + // Source for the user value. Cannot be used if User is not empty. + // +optional + UserFrom *CredentialSource `json:"userFrom,omitempty"` + // BMC password value. + // +optional + Pass string `json:"pass,omitempty"` + // Source for the password value. Cannot be used if Pass is not empty. + // +optional + PassFrom *CredentialSource `json:"passFrom,omitempty"` + // BMC Interface Type. Defaults to lanplus. + // +optional + Interface string `json:"interface,omitempty"` +} + +// CredentialSource defines a reference to the credential value. +type CredentialSource struct { + SecretKeyRef *SecretKeyRef `json:"secretKeyRef,omitempty"` +} + +// SecretKeyRef defines a ref to a given key within a secret. +type SecretKeyRef struct { + // Namespace and name of credential secret + // nb: can't use namespacedname here b/c it doesn't have json tags in the struct :( + Namespace string `json:"namespace"` + Name string `json:"name"` + // Key to select + Key string `json:"key"` +} + +// Resolve the value using the references. +func (source *CredentialSource) Resolve(ctx context.Context, reader client.Client) (string, error) { + if source == nil { + return "", nil + } + + if source.SecretKeyRef == nil { + return "", fmt.Errorf("missing secretKeyRef") + } + + var secrets corev1.Secret + + if err := reader.Get( + ctx, + types.NamespacedName{ + Namespace: source.SecretKeyRef.Namespace, + Name: source.SecretKeyRef.Name, + }, + &secrets, + ); err != nil { + return "", fmt.Errorf("error getting secret %q: %w", source.SecretKeyRef.Name, err) + } + + rawValue, ok := secrets.Data[source.SecretKeyRef.Key] + if !ok { + return "", fmt.Errorf("secret key %q is missing in secret %q", source.SecretKeyRef.Key, source.SecretKeyRef.Name) + } + + return string(rawValue), nil +} + +// ManagementAPI defines data about how to talk to the node via simple HTTP API. +type ManagementAPI struct { + Endpoint string `json:"endpoint"` +} + +type SystemInformation struct { + Uuid string `json:"uuid,omitempty"` + Manufacturer string `json:"manufacturer,omitempty"` + ProductName string `json:"productName,omitempty"` + Version string `json:"version,omitempty"` + SerialNumber string `json:"serialNumber,omitempty"` + SKUNumber string `json:"skuNumber,omitempty"` + Family string `json:"family,omitempty"` +} + +type Processor struct { + Manufacturer string `json:"manufacturer,omitempty"` + ProductName string `json:"productName,omitempty"` + SerialNumber string `json:"serialNumber,omitempty"` + // Speed is in megahertz (Mhz) + Speed uint32 `json:"speed,omitempty"` + CoreCount uint32 `json:"coreCount,omitempty"` + ThreadCount uint32 `json:"threadCount,omitempty"` +} + +type ComputeInformation struct { + TotalCoreCount uint32 `json:"totalCoreCount,omitempty"` + TotalThreadCount uint32 `json:"totalThreadCount,omitempty"` + ProcessorCount uint32 `json:"processorCount,omitempty"` + Processors []*Processor `json:"processors,omitempty"` +} + +type MemoryModule struct { + Manufacturer string `json:"manufacturer,omitempty"` + ProductName string `json:"productName,omitempty"` + SerialNumber string `json:"serialNumber,omitempty"` + Type string `json:"type,omitempty"` + // Size is in megabytes (MB) + Size uint32 `json:"size,omitempty"` + // Speed is in megatransfers per second (MT/S) + Speed uint32 `json:"speed,omitempty"` +} + +type MemoryInformation struct { + TotalSize string `json:"totalSize,omitempty"` + ModuleCount uint32 `json:"moduleCount,omitempty"` + Modules []*MemoryModule `json:"modules,omitempty"` +} + +type StorageDevice struct { + Type string `json:"type,omitempty"` + // Size is in bytes + Size uint64 `json:"size,omitempty"` + Model string `json:"productName,omitempty"` + Serial string `json:"serialNumber,omitempty"` + Name string `json:"name,omitempty"` + DeviceName string `json:"deviceName,omitempty"` + UUID string `json:"uuid,omitempty"` + WWID string `json:"wwid,omitempty"` +} + +type StorageInformation struct { + TotalSize string `json:"totalSize,omitempty"` + DeviceCount uint32 `json:"deviceCount,omitempty"` + Devices []*StorageDevice `json:"devices,omitempty"` +} + +type NetworkInterface struct { + Index uint32 `json:"index,omitempty"` + Name string `json:"name,omitempty"` + Flags string `json:"flags,omitempty"` + MTU uint32 `json:"mtu,omitempty"` + MAC string `json:"mac,omitempty"` + Addresses []string `json:"addresses,omitempty"` +} + +type NetworkInformation struct { + InterfaceCount uint32 `json:"interfaceCount,omitempty"` + Interfaces []*NetworkInterface `json:"interfaces,omitempty"` +} + +type HardwareInformation struct { + System *SystemInformation `json:"system,omitempty"` + Compute *ComputeInformation `json:"compute,omitempty"` + Memory *MemoryInformation `json:"memory,omitempty"` + Storage *StorageInformation `json:"storage,omitempty"` + Network *NetworkInformation `json:"network,omitempty"` +} + +func (a *HardwareInformation) PartialEqual(b *HardwareInformation) bool { + return PartialEqual(a, b) +} + +func PartialEqual(a, b interface{}) bool { + old := reflect.ValueOf(a) + new := reflect.ValueOf(b) + + if old.Kind() == reflect.Ptr { + old = old.Elem() + } + + if new.Kind() == reflect.Ptr { + new = new.Elem() + } + + // Skip invalid or zero values, since that indicates that the user + // did not supply the field, and does not want to compare it. + if !old.IsValid() || old.IsZero() { + return true + } + + switch { + case old.Kind() == reflect.Struct && new.Kind() == reflect.Struct: + // Recursively compare structs + for i := 0; i < old.NumField(); i++ { + f1 := old.Field(i).Interface() + f2 := new.Field(i).Interface() + + if !PartialEqual(f1, f2) { + return false + } + } + case old.Kind() == reflect.Slice && new.Kind() == reflect.Slice: + // Skip slices where the requested slice is larger than the actual slice, + // as that indicates that the user wants to filter for more + // processors/memory modules/storage devices than are present. + if old.Len() > new.Len() { + return false + } + // Recursively compare slices + for i := 0; i < old.Len(); i++ { + f1 := old.Index(i).Interface() + f2 := new.Index(i).Interface() + + if !PartialEqual(f1, f2) { + return false + } + } + default: + // Directly compare values, but only if the actual value is valid. + return new.IsValid() && old.Interface() == new.Interface() + } + + return true +} + +// ServerSpec defines the desired state of Server. +type ServerSpec struct { + EnvironmentRef *corev1.ObjectReference `json:"environmentRef,omitempty"` + Hardware *HardwareInformation `json:"hardware,omitempty"` + Hostname string `json:"hostname,omitempty"` + BMC *BMC `json:"bmc,omitempty"` + ManagementAPI *ManagementAPI `json:"managementApi,omitempty"` + ConfigPatches []ConfigPatches `json:"configPatches,omitempty"` + Accepted bool `json:"accepted"` + Cordoned bool `json:"cordoned,omitempty"` + PXEBootAlways bool `json:"pxeBootAlways,omitempty"` + // BootFromDiskMethod specifies the method to exit iPXE to force boot from disk. + // + // If not set, controller default is used. + // Valid values: ipxe-exit, http-404, ipxe-sanboot. + // + // +optional + BootFromDiskMethod siderotypes.BootFromDisk `json:"bootFromDiskMethod,omitempty"` +} + +const ( + // ConditionPowerCycle is used to control the powercycle flow. + ConditionPowerCycle clusterv1.ConditionType = "PowerCycle" + // ConditionPXEBooted is used to record the fact that server got PXE booted. + ConditionPXEBooted clusterv1.ConditionType = "PXEBooted" +) + +// ServerStatus defines the observed state of Server. +type ServerStatus struct { + // Ready is true when server is accepted and in use. + // +optional + Ready bool `json:"ready"` + + // InUse is true when server is assigned to some MetalMachine. + // +optional + InUse bool `json:"inUse"` + + // IsClean is true when server disks are wiped. + // +optional + IsClean bool `json:"isClean"` + + // Conditions defines current service state of the Server. + Conditions []clusterv1.Condition `json:"conditions,omitempty"` + + // Addresses lists discovered node IPs. + Addresses []corev1.NodeAddress `json:"addresses,omitempty"` + + // Power is the current power state of the server: "on", "off" or "unknown". + Power string `json:"power,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:resource:scope=Cluster +// +kubebuilder:printcolumn:name="Hostname",type="string",JSONPath=".spec.hostname",description="server hostname" +// +kubebuilder:printcolumn:name="BMC IP",type="string",priority=1,JSONPath=".spec.bmc.endpoint",description="BMC IP" +// +kubebuilder:printcolumn:name="Accepted",type="boolean",JSONPath=".spec.accepted",description="indicates if the server is accepted" +// +kubebuilder:printcolumn:name="Cordoned",type="boolean",JSONPath=".spec.cordoned",description="indicates if the server is cordoned" +// +kubebuilder:printcolumn:name="Allocated",type="boolean",JSONPath=".status.inUse",description="indicates that the server has been allocated" +// +kubebuilder:printcolumn:name="Clean",type="boolean",JSONPath=".status.isClean",description="indicates if the server is clean or not" +// +kubebuilder:printcolumn:name="Power",type="string",JSONPath=".status.power",description="display the current power status" +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="The age of this resource" +// +kubebuilder:storageversion + +// Server is the Schema for the servers API. +type Server struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec ServerSpec `json:"spec,omitempty"` + Status ServerStatus `json:"status,omitempty"` +} + +func (s *Server) GetConditions() clusterv1.Conditions { + return s.Status.Conditions +} + +func (s *Server) SetConditions(conditions clusterv1.Conditions) { + s.Status.Conditions = conditions +} + +// +kubebuilder:object:root=true + +// ServerList contains a list of Server. +type ServerList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Server `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Server{}, &ServerList{}) +} diff --git a/app/sidero-controller-manager/api/v1alpha2/server_types_test.go b/app/sidero-controller-manager/api/v1alpha2/server_types_test.go new file mode 100644 index 000000000..92d0fe9c8 --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha2/server_types_test.go @@ -0,0 +1,147 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +//nolint:scopelint +package v1alpha2_test + +import ( + "testing" + + metal "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" +) + +func Test_PartialEqual(t *testing.T) { + info := &metal.HardwareInformation{ + System: &metal.SystemInformation{ + Uuid: "4c4c4544-0039-3010-8048-b7c04f384432", + Manufacturer: "Dell Inc.", + ProductName: "PowerEdge R630", + SerialNumber: "790H8D2", + SKUNumber: "", + Family: "", + }, + Compute: &metal.ComputeInformation{ + TotalCoreCount: 8, + TotalThreadCount: 16, + ProcessorCount: 1, + Processors: []*metal.Processor{ + { + Manufacturer: "Intel", + ProductName: "Intel(R) Xeon(R) CPU E5-2630 v3 @ 2.40GHz", + SerialNumber: "", + Speed: 2400, + CoreCount: 8, + ThreadCount: 16, + }, + }, + }, + Memory: &metal.MemoryInformation{ + TotalSize: "32 GB", + ModuleCount: 2, + Modules: []*metal.MemoryModule{ + { + Manufacturer: "002C00B3002C", + ProductName: "18ASF2G72PDZ-2G3B1", + SerialNumber: "12BDC045", + Type: "LPDDR3", + Size: 16384, + Speed: 2400, + }, + { + Manufacturer: "002C00B3002C", + ProductName: "18ASF2G72PDZ-2G3B1", + SerialNumber: "12BDBF5D", + Type: "LPDDR3", + Size: 16384, + Speed: 2400, + }, + }, + }, + Storage: &metal.StorageInformation{ + TotalSize: "1116 GB", + DeviceCount: 1, + Devices: []*metal.StorageDevice{ + { + Type: "HDD", + Size: 1199101181952, + Model: "PERC H730 Mini", + Serial: "", + Name: "sda", + DeviceName: "/dev/sda", + UUID: "", + WWID: "naa.61866da055de070028d8e83307cc6df2", + }, + }, + }, + Network: &metal.NetworkInformation{ + InterfaceCount: 2, + Interfaces: []*metal.NetworkInterface{ + { + Index: 1, + Name: "lo", + Flags: "up|loopback", + MTU: 65536, + MAC: "", + Addresses: []string{"127.0.0.1/8", "::1/128"}, + }, + { + Index: 2, + Name: "enp3s0", + Flags: "up|broadcast|multicast", + MTU: 1500, + MAC: "40:8d:5c:86:5a:14", + Addresses: []string{"192.168.2.8/24", "fe80::dcb3:295c:755b:91bb/64"}, + }, + }, + }, + } + + tests := []struct { + name string + args *metal.HardwareInformation + want bool + }{ + { + name: "defaults are partially equal", + args: &metal.HardwareInformation{}, + want: true, + }, + { + name: "cpu is partially equal", + args: &metal.HardwareInformation{ + Compute: &metal.ComputeInformation{ + Processors: []*metal.Processor{ + { + Manufacturer: "Intel", + }, + }, + }, + // Skip all other fields to indicate that we don't want to compare it. + }, + want: true, + }, + { + name: "cpu is not partially equal", + args: &metal.HardwareInformation{ + Compute: &metal.ComputeInformation{ + Processors: []*metal.Processor{ + { + Manufacturer: "AMD", + }, + }, + }, + // Skip all other fields to indicate that we don't want to compare it. + }, + want: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.args.PartialEqual(info); got != tt.want { + t.Errorf("PartialEqual() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/app/sidero-controller-manager/api/v1alpha2/server_webhook.go b/app/sidero-controller-manager/api/v1alpha2/server_webhook.go new file mode 100644 index 000000000..83125f5ab --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha2/server_webhook.go @@ -0,0 +1,118 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package v1alpha2 + +import ( + "fmt" + "sort" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + runtime "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/validation/field" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/webhook" + + siderotypes "github.com/talos-systems/sidero/app/sidero-controller-manager/pkg/types" +) + +var operations = map[string]struct{}{ + "add": {}, + "remove": {}, + "replace": {}, + "copy": {}, + "move": {}, + "test": {}, +} + +var operationKinds = []string{} + +func (r *ServerList) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} + +func (r *Server) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} + +//+kubebuilder:webhook:verbs=create;update;delete,path=/validate-metal-sidero-dev-v1alpha2-server,mutating=false,failurePolicy=fail,groups=metal.sidero.dev,resources=servers,versions=v1alpha2,name=vservers.metal.sidero.dev,sideEffects=None,admissionReviewVersions=v1 + +var _ webhook.Validator = &Server{} + +// ValidateCreate implements webhook.Validator so a webhook will be registered for the type. +func (r *Server) ValidateCreate() error { + return r.validate() +} + +// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type. +func (r *Server) ValidateUpdate(old runtime.Object) error { + return r.validate() +} + +// ValidateDelete implements webhook.Validator so a webhook will be registered for the type. +func (r *Server) ValidateDelete() error { + return nil +} + +func (r *Server) validate() error { + var allErrs field.ErrorList + + validValues := []siderotypes.BootFromDisk{ + "", + siderotypes.BootIPXEExit, + siderotypes.Boot404, + siderotypes.BootSANDisk, + } + + var valid bool + + for _, v := range validValues { + if r.Spec.BootFromDiskMethod == v { + valid = true + + break + } + } + + if !valid { + allErrs = append(allErrs, + field.Invalid(field.NewPath("spec").Child("bootFromDiskMethod"), r.Spec.BootFromDiskMethod, + fmt.Sprintf("valid values are: %q", validValues), + ), + ) + } + + for index, patch := range r.Spec.ConfigPatches { + if _, ok := operations[patch.Op]; !ok { + allErrs = append(allErrs, + field.Invalid(field.NewPath("spec").Child("configPatches").Child(fmt.Sprintf("%d", index)).Child("op"), patch.Op, + fmt.Sprintf("valid values are: %q", operationKinds), + ), + ) + } + } + + if len(allErrs) == 0 { + return nil + } + + return apierrors.NewInvalid( + schema.GroupKind{Group: GroupVersion.Group, Kind: "Server"}, + r.Name, allErrs) +} + +func init() { + operationKinds = make([]string, 0, len(operations)) + + for key := range operations { + operationKinds = append(operationKinds, key) + } + + sort.Strings(operationKinds) +} diff --git a/app/sidero-controller-manager/api/v1alpha2/serverclass_conversion.go b/app/sidero-controller-manager/api/v1alpha2/serverclass_conversion.go new file mode 100644 index 000000000..dbeb291af --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha2/serverclass_conversion.go @@ -0,0 +1,8 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package v1alpha2 + +func (*ServerClass) Hub() {} +func (*ServerClassList) Hub() {} diff --git a/app/sidero-controller-manager/api/v1alpha2/serverclass_filter.go b/app/sidero-controller-manager/api/v1alpha2/serverclass_filter.go new file mode 100644 index 000000000..f5ce08250 --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha2/serverclass_filter.go @@ -0,0 +1,110 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package v1alpha2 + +import ( + "fmt" + "sort" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" +) + +// AcceptedServerFilter matches Servers that have Spec.Accepted set to true. +func AcceptedServerFilter(s Server) (bool, error) { + return s.Spec.Accepted, nil +} + +// NotCordonedServerFilter matches Servers that have Spec.Paused set to false. +func NotCordonedServerFilter(s Server) (bool, error) { + return !s.Spec.Cordoned, nil +} + +// SelectorFilter returns a ServerFilter that matches servers against the +// serverclass's selector field. +func (sc *ServerClass) SelectorFilter() func(Server) (bool, error) { + return func(server Server) (bool, error) { + s, err := metav1.LabelSelectorAsSelector(&sc.Spec.Selector) + if err != nil { + return false, fmt.Errorf("failed to get selector from labelselector: %v", err) + } + + return s.Matches(labels.Set(server.GetLabels())), nil + } +} + +// QualifiersFilter returns a ServerFilter that matches servers against the +// serverclass's qualifiers field. +func (sc *ServerClass) QualifiersFilter() func(Server) (bool, error) { + return func(server Server) (bool, error) { + q := sc.Spec.Qualifiers + + // check hardware qualifiers if they are present + if filters := q.Hardware; len(filters) > 0 { + var match bool + + for _, filter := range filters { + if info := server.Spec.Hardware; info != nil && filter.PartialEqual(info) { + match = true + break + } + } + + if !match { + return false, nil + } + } + + if filters := q.LabelSelectors; len(filters) > 0 { + var match bool + + for _, filter := range filters { + for labelKey, labelVal := range filter { + if val, ok := server.ObjectMeta.Labels[labelKey]; ok && labelVal == val { + match = true + break + } + } + } + + if !match { + return false, nil + } + } + + return true, nil + } +} + +// FilterServers returns the subset of servers that pass all provided filters. +// In case of error the returned slice will be nil. +func FilterServers(servers []Server, filters ...func(Server) (bool, error)) ([]Server, error) { + matches := make([]Server, 0, len(servers)) + + for _, server := range servers { + match := true + + for _, filter := range filters { + var err error + + match, err = filter(server) + if err != nil { + return nil, fmt.Errorf("failed to filter server: %v", err) + } + + if !match { + break + } + } + + if match { + matches = append(matches, server) + } + } + + sort.Slice(matches, func(i, j int) bool { return matches[i].Name < matches[j].Name }) + + return matches, nil +} diff --git a/app/sidero-controller-manager/api/v1alpha2/serverclass_filter_test.go b/app/sidero-controller-manager/api/v1alpha2/serverclass_filter_test.go new file mode 100644 index 000000000..125bec1dc --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha2/serverclass_filter_test.go @@ -0,0 +1,378 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package v1alpha2_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + metal "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" +) + +func TestFilterAcceptedServers(t *testing.T) { + t.Parallel() + + atom := metal.Server{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + "common-label": "true", + "zone": "central", + }, + }, + Spec: metal.ServerSpec{ + Accepted: true, + Hardware: &metal.HardwareInformation{ + Compute: &metal.ComputeInformation{ + TotalCoreCount: 4, + TotalThreadCount: 4, + ProcessorCount: 1, + Processors: []*metal.Processor{ + { + Manufacturer: "Intel(R) Corporation", + ProductName: "Intel(R) Atom(TM) CPU C3558 @ 2.20GHz", + SerialNumber: "", + Speed: 2200, + CoreCount: 4, + ThreadCount: 4, + }, + }, + }, + }, + }, + } + dualXeon := metal.Server{ + Spec: metal.ServerSpec{ + Accepted: true, + Hardware: &metal.HardwareInformation{ + Compute: &metal.ComputeInformation{ + TotalCoreCount: 16, + TotalThreadCount: 32, + ProcessorCount: 2, + Processors: []*metal.Processor{ + { + Manufacturer: "Intel(R) Corporation", + ProductName: "Intel(R) Xeon(R) CPU E5-2630 v3 @ 2.40GHz", + SerialNumber: "", + Speed: 2400, + CoreCount: 8, + ThreadCount: 16, + }, + { + Manufacturer: "Intel(R) Corporation", + ProductName: "Intel(R) Xeon(R) CPU E5-2630 v3 @ 2.40GHz", + SerialNumber: "", + Speed: 2400, + CoreCount: 8, + ThreadCount: 16, + }, + }, + }, + }, + }, + } + ryzen := metal.Server{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + "common-label": "true", + "zone": "east", + }, + }, + Spec: metal.ServerSpec{ + Accepted: true, + Hardware: &metal.HardwareInformation{ + System: &metal.SystemInformation{ + Manufacturer: "QEMU", + }, + Compute: &metal.ComputeInformation{ + TotalCoreCount: 8, + TotalThreadCount: 16, + ProcessorCount: 1, + Processors: []*metal.Processor{ + { + Manufacturer: "Advanced Micro Devices, Inc.", + ProductName: "AMD Ryzen 7 2700X Eight-Core Processor", + SerialNumber: "", + Speed: 3700, + CoreCount: 8, + ThreadCount: 16, + }, + }, + }, + }, + }, + } + notAccepted := metal.Server{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + "common-label": "true", + "zone": "west", + }, + }, + Spec: metal.ServerSpec{ + Accepted: false, + Hardware: &metal.HardwareInformation{ + System: &metal.SystemInformation{ + Manufacturer: "QEMU", + }, + Compute: &metal.ComputeInformation{ + TotalCoreCount: 8, + TotalThreadCount: 16, + ProcessorCount: 1, + Processors: []*metal.Processor{ + { + Manufacturer: "Advanced Micro Devices, Inc.", + ProductName: "AMD Ryzen 7 2700X Eight-Core Processor", + SerialNumber: "", + Speed: 3700, + CoreCount: 8, + ThreadCount: 16, + }, + }, + }, + }, + }, + } + + servers := []metal.Server{atom, dualXeon, ryzen, notAccepted} + + testdata := map[string]struct { + s metav1.LabelSelector + q metal.Qualifiers + expected []metal.Server + }{ + "empty selector - empty qualifier": { + // Matches all servers + expected: []metal.Server{atom, dualXeon, ryzen}, + }, + "Intel only": { + q: metal.Qualifiers{ + Hardware: []metal.HardwareInformation{ + { + Compute: &metal.ComputeInformation{ + Processors: []*metal.Processor{ + { + Manufacturer: "Intel(R) Corporation", + }, + }, + }, + }, + }, + }, + expected: []metal.Server{atom, dualXeon}, + }, + "Intel and AMD": { + q: metal.Qualifiers{ + Hardware: []metal.HardwareInformation{ + { + Compute: &metal.ComputeInformation{ + Processors: []*metal.Processor{ + { + Manufacturer: "Intel(R) Corporation", + }, + }, + }, + }, + { + Compute: &metal.ComputeInformation{ + Processors: []*metal.Processor{ + { + Manufacturer: "Advanced Micro Devices, Inc.", + }, + }, + }, + }, + }, + }, + expected: []metal.Server{atom, dualXeon, ryzen}, + }, + "QEMU only": { + q: metal.Qualifiers{ + Hardware: []metal.HardwareInformation{ + { + System: &metal.SystemInformation{ + Manufacturer: "QEMU", + }, + }, + }, + }, + expected: []metal.Server{ryzen}, + }, + "with label": { + q: metal.Qualifiers{ + LabelSelectors: []map[string]string{ + { + "common-label": "true", + }, + }, + }, + expected: []metal.Server{atom, ryzen}, + }, + // This should probably only return atom. Leaving it as-is to + // avoid breaking changes before we remove LabelSelectors in + // favor of Selector. + "with multiple labels - single selector": { + q: metal.Qualifiers{ + LabelSelectors: []map[string]string{ + { + "common-label": "true", + "zone": "central", + }, + }, + }, + expected: []metal.Server{atom, ryzen}, + }, + "with multiple labels - multiple selectors": { + q: metal.Qualifiers{ + LabelSelectors: []map[string]string{ + { + "common-label": "true", + }, + { + "zone": "central", + }, + }, + }, + expected: []metal.Server{atom, ryzen}, + }, + "with same label key different label value": { + q: metal.Qualifiers{ + LabelSelectors: []map[string]string{ + { + "zone": "central", + }, + }, + }, + expected: []metal.Server{atom}, + }, + "selector - single MatchLabels single result": { + s: metav1.LabelSelector{ + MatchLabels: map[string]string{ + "zone": "central", + }, + }, + expected: []metal.Server{atom}, + }, + "selector - single MatchLabels multiple results": { + s: metav1.LabelSelector{ + MatchLabels: map[string]string{ + "common-label": "true", + }, + }, + expected: []metal.Server{atom, ryzen}, + }, + "selector - multiple MatchLabels": { + s: metav1.LabelSelector{ + MatchLabels: map[string]string{ + "zone": "central", + "common-label": "true", + }, + }, + expected: []metal.Server{atom}, + }, + "selector - MatchExpressions common label key": { + s: metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: "common-label", + Operator: "Exists", + }, + }, + }, + expected: []metal.Server{atom, ryzen}, + }, + "selector - MatchExpressions multiple values": { + s: metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: "zone", + Operator: "In", + Values: []string{ + "east", + "west", + }, + }, + }, + }, + expected: []metal.Server{ryzen}, + }, + "selector and qualifiers both match": { + s: metav1.LabelSelector{ + MatchLabels: map[string]string{ + "common-label": "true", + }, + }, + q: metal.Qualifiers{ + Hardware: []metal.HardwareInformation{ + { + System: &metal.SystemInformation{ + Manufacturer: "QEMU", + }, + }, + }, + }, + expected: []metal.Server{ryzen}, + }, + "selector and qualifiers with disqualifying selector": { + s: metav1.LabelSelector{ + MatchLabels: map[string]string{ + "common-label": "no-match", + }, + }, + q: metal.Qualifiers{ + Hardware: []metal.HardwareInformation{ + { + System: &metal.SystemInformation{ + Manufacturer: "QEMU", + }, + }, + }, + }, + expected: []metal.Server{}, + }, + "selector and qualifiers with disqualifying qualifier": { + s: metav1.LabelSelector{ + MatchLabels: map[string]string{ + "common-label": "true", + }, + }, + q: metal.Qualifiers{ + Hardware: []metal.HardwareInformation{ + { + System: &metal.SystemInformation{ + Manufacturer: "Gateway", + }, + }, + }, + }, + expected: []metal.Server{}, + }, + metal.ServerClassAny: { + expected: []metal.Server{atom, dualXeon, ryzen}, + }, + } + + for name, td := range testdata { + name, td := name, td + t.Run(name, func(t *testing.T) { + t.Parallel() + + sc := &metal.ServerClass{ + Spec: metal.ServerClassSpec{ + Selector: td.s, + Qualifiers: td.q, + }, + } + actual, err := metal.FilterServers(servers, + metal.AcceptedServerFilter, + sc.SelectorFilter(), + sc.QualifiersFilter(), + ) + assert.NoError(t, err) + assert.Equal(t, td.expected, actual) + }) + } +} diff --git a/app/sidero-controller-manager/api/v1alpha2/serverclass_types.go b/app/sidero-controller-manager/api/v1alpha2/serverclass_types.go new file mode 100644 index 000000000..45ea2ba92 --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha2/serverclass_types.go @@ -0,0 +1,84 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package v1alpha2 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + siderotypes "github.com/talos-systems/sidero/app/sidero-controller-manager/pkg/types" +) + +// ServerClassAny is an automatically created ServerClass that includes all Servers. +const ServerClassAny = "any" + +type Qualifiers struct { + Hardware []HardwareInformation `json:"hardware,omitempty"` + LabelSelectors []map[string]string `json:"labelSelectors,omitempty"` +} + +// ServerClassSpec defines the desired state of ServerClass. +type ServerClassSpec struct { + // Reference to the environment which should be used to provision the servers via this server class. + // +optional + EnvironmentRef *corev1.ObjectReference `json:"environmentRef,omitempty"` + // Qualifiers to match on the server spec. + // + // If qualifiers are empty, they match all servers. + // Server should match both qualifiers and selector conditions to be included into the server class. + // +optional + Qualifiers Qualifiers `json:"qualifiers"` + // Label selector to filter the matching servers based on labels. + // A label selector is a label query over a set of resources. The result of matchLabels and + // matchExpressions are ANDed. An empty label selector matches all objects. A null label selector matches no objects. + // +optional + Selector metav1.LabelSelector `json:"selector"` + // Set of config patches to apply to the machine configuration to the servers provisioned via this server class. + // +optional + ConfigPatches []ConfigPatches `json:"configPatches,omitempty"` + // BootFromDiskMethod specifies the method to exit iPXE to force boot from disk. + // + // If not set, controller default is used. + // Valid values: ipxe-exit, http-404, ipxe-sanboot. + // + // +optional + BootFromDiskMethod siderotypes.BootFromDisk `json:"bootFromDiskMethod,omitempty"` +} + +// ServerClassStatus defines the observed state of ServerClass. +type ServerClassStatus struct { + ServersAvailable []string `json:"serversAvailable"` + ServersInUse []string `json:"serversInUse"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:resource:scope=Cluster +// +kubebuilder:printcolumn:name="Available",type="string",JSONPath=".status.serversAvailable",description="the number of available servers" +// +kubebuilder:printcolumn:name="In Use",type="string",JSONPath=".status.serversInUse",description="the number of servers in use" +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="The age of this resource" +// +kubebuilder:storageversion + +// ServerClass is the Schema for the serverclasses API. +type ServerClass struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec ServerClassSpec `json:"spec,omitempty"` + Status ServerClassStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// ServerClassList contains a list of ServerClass. +type ServerClassList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ServerClass `json:"items"` +} + +func init() { + SchemeBuilder.Register(&ServerClass{}, &ServerClassList{}) +} diff --git a/app/sidero-controller-manager/api/v1alpha2/serverclass_webhook.go b/app/sidero-controller-manager/api/v1alpha2/serverclass_webhook.go new file mode 100644 index 000000000..45aa1eff5 --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha2/serverclass_webhook.go @@ -0,0 +1,21 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package v1alpha2 + +import ( + ctrl "sigs.k8s.io/controller-runtime" +) + +func (r *ServerClass) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} + +func (r *ServerClassList) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} diff --git a/app/sidero-controller-manager/api/v1alpha2/types.go b/app/sidero-controller-manager/api/v1alpha2/types.go new file mode 100644 index 000000000..80525d27d --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha2/types.go @@ -0,0 +1,16 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package v1alpha2 + +import apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + +// nb: we use apiextensions.JSON for the value below b/c we can't use interface{} with controller-gen. +// found this workaround here: https://github.com/kubernetes-sigs/controller-tools/pull/126#issuecomment-630769075 + +type ConfigPatches struct { + Op string `json:"op"` + Path string `json:"path"` + Value apiextensions.JSON `json:"value,omitempty"` +} diff --git a/app/sidero-controller-manager/api/v1alpha2/zz_generated.deepcopy.go b/app/sidero-controller-manager/api/v1alpha2/zz_generated.deepcopy.go new file mode 100644 index 000000000..b27db6381 --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha2/zz_generated.deepcopy.go @@ -0,0 +1,771 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +// Code generated by controller-gen. DO NOT EDIT. + +package v1alpha2 + +import ( + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/cluster-api/api/v1beta1" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Asset) DeepCopyInto(out *Asset) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Asset. +func (in *Asset) DeepCopy() *Asset { + if in == nil { + return nil + } + out := new(Asset) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AssetCondition) DeepCopyInto(out *AssetCondition) { + *out = *in + out.Asset = in.Asset +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AssetCondition. +func (in *AssetCondition) DeepCopy() *AssetCondition { + if in == nil { + return nil + } + out := new(AssetCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BMC) DeepCopyInto(out *BMC) { + *out = *in + if in.UserFrom != nil { + in, out := &in.UserFrom, &out.UserFrom + *out = new(CredentialSource) + (*in).DeepCopyInto(*out) + } + if in.PassFrom != nil { + in, out := &in.PassFrom, &out.PassFrom + *out = new(CredentialSource) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BMC. +func (in *BMC) DeepCopy() *BMC { + if in == nil { + return nil + } + out := new(BMC) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ComputeInformation) DeepCopyInto(out *ComputeInformation) { + *out = *in + if in.Processors != nil { + in, out := &in.Processors, &out.Processors + *out = make([]*Processor, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(Processor) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComputeInformation. +func (in *ComputeInformation) DeepCopy() *ComputeInformation { + if in == nil { + return nil + } + out := new(ComputeInformation) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConfigPatches) DeepCopyInto(out *ConfigPatches) { + *out = *in + in.Value.DeepCopyInto(&out.Value) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigPatches. +func (in *ConfigPatches) DeepCopy() *ConfigPatches { + if in == nil { + return nil + } + out := new(ConfigPatches) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CredentialSource) DeepCopyInto(out *CredentialSource) { + *out = *in + if in.SecretKeyRef != nil { + in, out := &in.SecretKeyRef, &out.SecretKeyRef + *out = new(SecretKeyRef) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialSource. +func (in *CredentialSource) DeepCopy() *CredentialSource { + if in == nil { + return nil + } + out := new(CredentialSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Environment) DeepCopyInto(out *Environment) { + *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 Environment. +func (in *Environment) DeepCopy() *Environment { + if in == nil { + return nil + } + out := new(Environment) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Environment) 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 *EnvironmentList) DeepCopyInto(out *EnvironmentList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Environment, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvironmentList. +func (in *EnvironmentList) DeepCopy() *EnvironmentList { + if in == nil { + return nil + } + out := new(EnvironmentList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *EnvironmentList) 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 *EnvironmentSpec) DeepCopyInto(out *EnvironmentSpec) { + *out = *in + in.Kernel.DeepCopyInto(&out.Kernel) + out.Initrd = in.Initrd +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvironmentSpec. +func (in *EnvironmentSpec) DeepCopy() *EnvironmentSpec { + if in == nil { + return nil + } + out := new(EnvironmentSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EnvironmentStatus) DeepCopyInto(out *EnvironmentStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]AssetCondition, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvironmentStatus. +func (in *EnvironmentStatus) DeepCopy() *EnvironmentStatus { + if in == nil { + return nil + } + out := new(EnvironmentStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HardwareInformation) DeepCopyInto(out *HardwareInformation) { + *out = *in + if in.System != nil { + in, out := &in.System, &out.System + *out = new(SystemInformation) + **out = **in + } + if in.Compute != nil { + in, out := &in.Compute, &out.Compute + *out = new(ComputeInformation) + (*in).DeepCopyInto(*out) + } + if in.Memory != nil { + in, out := &in.Memory, &out.Memory + *out = new(MemoryInformation) + (*in).DeepCopyInto(*out) + } + if in.Storage != nil { + in, out := &in.Storage, &out.Storage + *out = new(StorageInformation) + (*in).DeepCopyInto(*out) + } + if in.Network != nil { + in, out := &in.Network, &out.Network + *out = new(NetworkInformation) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HardwareInformation. +func (in *HardwareInformation) DeepCopy() *HardwareInformation { + if in == nil { + return nil + } + out := new(HardwareInformation) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Initrd) DeepCopyInto(out *Initrd) { + *out = *in + out.Asset = in.Asset +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Initrd. +func (in *Initrd) DeepCopy() *Initrd { + if in == nil { + return nil + } + out := new(Initrd) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Kernel) DeepCopyInto(out *Kernel) { + *out = *in + out.Asset = in.Asset + if in.Args != nil { + in, out := &in.Args, &out.Args + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Kernel. +func (in *Kernel) DeepCopy() *Kernel { + if in == nil { + return nil + } + out := new(Kernel) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ManagementAPI) DeepCopyInto(out *ManagementAPI) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagementAPI. +func (in *ManagementAPI) DeepCopy() *ManagementAPI { + if in == nil { + return nil + } + out := new(ManagementAPI) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MemoryInformation) DeepCopyInto(out *MemoryInformation) { + *out = *in + if in.Modules != nil { + in, out := &in.Modules, &out.Modules + *out = make([]*MemoryModule, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(MemoryModule) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MemoryInformation. +func (in *MemoryInformation) DeepCopy() *MemoryInformation { + if in == nil { + return nil + } + out := new(MemoryInformation) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MemoryModule) DeepCopyInto(out *MemoryModule) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MemoryModule. +func (in *MemoryModule) DeepCopy() *MemoryModule { + if in == nil { + return nil + } + out := new(MemoryModule) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkInformation) DeepCopyInto(out *NetworkInformation) { + *out = *in + if in.Interfaces != nil { + in, out := &in.Interfaces, &out.Interfaces + *out = make([]*NetworkInterface, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(NetworkInterface) + (*in).DeepCopyInto(*out) + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkInformation. +func (in *NetworkInformation) DeepCopy() *NetworkInformation { + if in == nil { + return nil + } + out := new(NetworkInformation) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkInterface) DeepCopyInto(out *NetworkInterface) { + *out = *in + if in.Addresses != nil { + in, out := &in.Addresses, &out.Addresses + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkInterface. +func (in *NetworkInterface) DeepCopy() *NetworkInterface { + if in == nil { + return nil + } + out := new(NetworkInterface) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Processor) DeepCopyInto(out *Processor) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Processor. +func (in *Processor) DeepCopy() *Processor { + if in == nil { + return nil + } + out := new(Processor) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Qualifiers) DeepCopyInto(out *Qualifiers) { + *out = *in + if in.Hardware != nil { + in, out := &in.Hardware, &out.Hardware + *out = make([]HardwareInformation, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.LabelSelectors != nil { + in, out := &in.LabelSelectors, &out.LabelSelectors + *out = make([]map[string]string, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *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 Qualifiers. +func (in *Qualifiers) DeepCopy() *Qualifiers { + if in == nil { + return nil + } + out := new(Qualifiers) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SecretKeyRef) DeepCopyInto(out *SecretKeyRef) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretKeyRef. +func (in *SecretKeyRef) DeepCopy() *SecretKeyRef { + if in == nil { + return nil + } + out := new(SecretKeyRef) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Server) DeepCopyInto(out *Server) { + *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 Server. +func (in *Server) DeepCopy() *Server { + if in == nil { + return nil + } + out := new(Server) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Server) 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 *ServerClass) DeepCopyInto(out *ServerClass) { + *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 ServerClass. +func (in *ServerClass) DeepCopy() *ServerClass { + if in == nil { + return nil + } + out := new(ServerClass) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ServerClass) 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 *ServerClassList) DeepCopyInto(out *ServerClassList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ServerClass, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServerClassList. +func (in *ServerClassList) DeepCopy() *ServerClassList { + if in == nil { + return nil + } + out := new(ServerClassList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ServerClassList) 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 *ServerClassSpec) DeepCopyInto(out *ServerClassSpec) { + *out = *in + if in.EnvironmentRef != nil { + in, out := &in.EnvironmentRef, &out.EnvironmentRef + *out = new(v1.ObjectReference) + **out = **in + } + in.Qualifiers.DeepCopyInto(&out.Qualifiers) + in.Selector.DeepCopyInto(&out.Selector) + if in.ConfigPatches != nil { + in, out := &in.ConfigPatches, &out.ConfigPatches + *out = make([]ConfigPatches, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServerClassSpec. +func (in *ServerClassSpec) DeepCopy() *ServerClassSpec { + if in == nil { + return nil + } + out := new(ServerClassSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServerClassStatus) DeepCopyInto(out *ServerClassStatus) { + *out = *in + if in.ServersAvailable != nil { + in, out := &in.ServersAvailable, &out.ServersAvailable + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ServersInUse != nil { + in, out := &in.ServersInUse, &out.ServersInUse + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServerClassStatus. +func (in *ServerClassStatus) DeepCopy() *ServerClassStatus { + if in == nil { + return nil + } + out := new(ServerClassStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServerList) DeepCopyInto(out *ServerList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Server, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServerList. +func (in *ServerList) DeepCopy() *ServerList { + if in == nil { + return nil + } + out := new(ServerList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ServerList) 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 *ServerSpec) DeepCopyInto(out *ServerSpec) { + *out = *in + if in.EnvironmentRef != nil { + in, out := &in.EnvironmentRef, &out.EnvironmentRef + *out = new(v1.ObjectReference) + **out = **in + } + if in.Hardware != nil { + in, out := &in.Hardware, &out.Hardware + *out = new(HardwareInformation) + (*in).DeepCopyInto(*out) + } + if in.BMC != nil { + in, out := &in.BMC, &out.BMC + *out = new(BMC) + (*in).DeepCopyInto(*out) + } + if in.ManagementAPI != nil { + in, out := &in.ManagementAPI, &out.ManagementAPI + *out = new(ManagementAPI) + **out = **in + } + if in.ConfigPatches != nil { + in, out := &in.ConfigPatches, &out.ConfigPatches + *out = make([]ConfigPatches, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServerSpec. +func (in *ServerSpec) DeepCopy() *ServerSpec { + if in == nil { + return nil + } + out := new(ServerSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServerStatus) DeepCopyInto(out *ServerStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]v1beta1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Addresses != nil { + in, out := &in.Addresses, &out.Addresses + *out = make([]v1.NodeAddress, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServerStatus. +func (in *ServerStatus) DeepCopy() *ServerStatus { + if in == nil { + return nil + } + out := new(ServerStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageDevice) DeepCopyInto(out *StorageDevice) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageDevice. +func (in *StorageDevice) DeepCopy() *StorageDevice { + if in == nil { + return nil + } + out := new(StorageDevice) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageInformation) DeepCopyInto(out *StorageInformation) { + *out = *in + if in.Devices != nil { + in, out := &in.Devices, &out.Devices + *out = make([]*StorageDevice, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(StorageDevice) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageInformation. +func (in *StorageInformation) DeepCopy() *StorageInformation { + if in == nil { + return nil + } + out := new(StorageInformation) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SystemInformation) DeepCopyInto(out *SystemInformation) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SystemInformation. +func (in *SystemInformation) DeepCopy() *SystemInformation { + if in == nil { + return nil + } + out := new(SystemInformation) + in.DeepCopyInto(out) + return out +} diff --git a/app/sidero-controller-manager/config/crd/bases/metal.sidero.dev_environments.yaml b/app/sidero-controller-manager/config/crd/bases/metal.sidero.dev_environments.yaml index 1be7df478..f4885592a 100644 --- a/app/sidero-controller-manager/config/crd/bases/metal.sidero.dev_environments.yaml +++ b/app/sidero-controller-manager/config/crd/bases/metal.sidero.dev_environments.yaml @@ -93,6 +93,87 @@ spec: type: object type: object served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - description: the kernel for the environment + jsonPath: .spec.kernel.url + name: Kernel + type: string + - description: the initrd for the environment + jsonPath: .spec.initrd.url + name: Initrd + type: string + - description: indicates the readiness of the environment + jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - description: The age of this resource + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 + schema: + openAPIV3Schema: + description: Environment is the Schema for the environments 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: EnvironmentSpec defines the desired state of Environment. + properties: + initrd: + properties: + sha512: + type: string + url: + type: string + type: object + kernel: + properties: + args: + items: + type: string + type: array + sha512: + type: string + url: + type: string + type: object + type: object + status: + description: EnvironmentStatus defines the observed state of Environment. + properties: + conditions: + items: + properties: + sha512: + type: string + status: + type: string + type: + type: string + url: + type: string + required: + - status + - type + type: object + type: array + type: object + type: object + served: true storage: true subresources: status: {} diff --git a/app/sidero-controller-manager/config/crd/bases/metal.sidero.dev_serverclasses.yaml b/app/sidero-controller-manager/config/crd/bases/metal.sidero.dev_serverclasses.yaml index 3577cc945..168690bec 100644 --- a/app/sidero-controller-manager/config/crd/bases/metal.sidero.dev_serverclasses.yaml +++ b/app/sidero-controller-manager/config/crd/bases/metal.sidero.dev_serverclasses.yaml @@ -210,6 +210,321 @@ spec: type: object type: object served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - description: the number of available servers + jsonPath: .status.serversAvailable + name: Available + type: string + - description: the number of servers in use + jsonPath: .status.serversInUse + name: In Use + type: string + - description: The age of this resource + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 + schema: + openAPIV3Schema: + description: ServerClass is the Schema for the serverclasses 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: ServerClassSpec defines the desired state of ServerClass. + properties: + bootFromDiskMethod: + description: "BootFromDiskMethod specifies the method to exit iPXE + to force boot from disk. \n If not set, controller default is used. + Valid values: ipxe-exit, http-404, ipxe-sanboot." + type: string + configPatches: + description: Set of config patches to apply to the machine configuration + to the servers provisioned via this server class. + items: + properties: + op: + type: string + path: + type: string + value: + x-kubernetes-preserve-unknown-fields: true + required: + - op + - path + type: object + type: array + environmentRef: + description: Reference to the environment which should be used to + provision the servers via this server class. + 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 + qualifiers: + description: "Qualifiers to match on the server spec. \n If qualifiers + are empty, they match all servers. Server should match both qualifiers + and selector conditions to be included into the server class." + properties: + hardware: + items: + properties: + compute: + properties: + processorCount: + format: int32 + type: integer + processors: + items: + properties: + coreCount: + format: int32 + type: integer + manufacturer: + type: string + productName: + type: string + serialNumber: + type: string + speed: + description: Speed is in megahertz (Mhz) + format: int32 + type: integer + threadCount: + format: int32 + type: integer + type: object + type: array + totalCoreCount: + format: int32 + type: integer + totalThreadCount: + format: int32 + type: integer + type: object + memory: + properties: + moduleCount: + format: int32 + type: integer + modules: + items: + properties: + manufacturer: + type: string + productName: + type: string + serialNumber: + type: string + size: + description: Size is in megabytes (MB) + format: int32 + type: integer + speed: + description: Speed is in megatransfers per second + (MT/S) + format: int32 + type: integer + type: + type: string + type: object + type: array + totalSize: + type: string + type: object + network: + properties: + interfaceCount: + format: int32 + type: integer + interfaces: + items: + properties: + addresses: + items: + type: string + type: array + flags: + type: string + index: + format: int32 + type: integer + mac: + type: string + mtu: + format: int32 + type: integer + name: + type: string + type: object + type: array + type: object + storage: + properties: + deviceCount: + format: int32 + type: integer + devices: + items: + properties: + deviceName: + type: string + name: + type: string + productName: + type: string + serialNumber: + type: string + size: + description: Size is in bytes + format: int64 + type: integer + type: + type: string + uuid: + type: string + wwid: + type: string + type: object + type: array + totalSize: + type: string + type: object + system: + properties: + family: + type: string + manufacturer: + type: string + productName: + type: string + serialNumber: + type: string + skuNumber: + type: string + uuid: + type: string + version: + type: string + type: object + type: object + type: array + labelSelectors: + items: + additionalProperties: + type: string + type: object + type: array + type: object + selector: + description: Label selector to filter the matching servers based on + labels. A label selector is a label query over a set of resources. + The result of matchLabels and matchExpressions are ANDed. An empty + label selector matches all objects. A null label selector matches + no objects. + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector requirement is a selector that + contains values, a key, and an operator that relates the key + and values. + properties: + key: + description: key is the label key that the selector applies + to. + type: string + operator: + description: operator represents a key's relationship to + a set of values. Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of string values. If the + operator is In or NotIn, the values array must be non-empty. + If the operator is Exists or DoesNotExist, the values + array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. A single + {key,value} in the matchLabels map is equivalent to an element + of matchExpressions, whose key field is "key", the operator + is "In", and the values array contains only "value". The requirements + are ANDed. + type: object + type: object + type: object + status: + description: ServerClassStatus defines the observed state of ServerClass. + properties: + serversAvailable: + items: + type: string + type: array + serversInUse: + items: + type: string + type: array + required: + - serversAvailable + - serversInUse + type: object + type: object + served: true storage: true subresources: status: {} diff --git a/app/sidero-controller-manager/config/crd/bases/metal.sidero.dev_servers.yaml b/app/sidero-controller-manager/config/crd/bases/metal.sidero.dev_servers.yaml index df6777103..a30534044 100644 --- a/app/sidero-controller-manager/config/crd/bases/metal.sidero.dev_servers.yaml +++ b/app/sidero-controller-manager/config/crd/bases/metal.sidero.dev_servers.yaml @@ -339,6 +339,451 @@ spec: type: object type: object served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - description: server hostname + jsonPath: .spec.hostname + name: Hostname + type: string + - description: BMC IP + jsonPath: .spec.bmc.endpoint + name: BMC IP + priority: 1 + type: string + - description: indicates if the server is accepted + jsonPath: .spec.accepted + name: Accepted + type: boolean + - description: indicates if the server is cordoned + jsonPath: .spec.cordoned + name: Cordoned + type: boolean + - description: indicates that the server has been allocated + jsonPath: .status.inUse + name: Allocated + type: boolean + - description: indicates if the server is clean or not + jsonPath: .status.isClean + name: Clean + type: boolean + - description: display the current power status + jsonPath: .status.power + name: Power + type: string + - description: The age of this resource + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 + schema: + openAPIV3Schema: + description: Server is the Schema for the servers 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: ServerSpec defines the desired state of Server. + properties: + accepted: + type: boolean + bmc: + description: BMC defines data about how to talk to the node via ipmitool. + properties: + endpoint: + description: BMC endpoint. + type: string + interface: + description: BMC Interface Type. Defaults to lanplus. + type: string + pass: + description: BMC password value. + type: string + passFrom: + description: Source for the password value. Cannot be used if + Pass is not empty. + properties: + secretKeyRef: + description: SecretKeyRef defines a ref to a given key within + a secret. + properties: + key: + description: Key to select + type: string + name: + type: string + namespace: + description: 'Namespace and name of credential secret + nb: can''t use namespacedname here b/c it doesn''t have + json tags in the struct :(' + type: string + required: + - key + - name + - namespace + type: object + type: object + port: + description: BMC port. Defaults to 623. + format: int32 + type: integer + user: + description: BMC user value. + type: string + userFrom: + description: Source for the user value. Cannot be used if User + is not empty. + properties: + secretKeyRef: + description: SecretKeyRef defines a ref to a given key within + a secret. + properties: + key: + description: Key to select + type: string + name: + type: string + namespace: + description: 'Namespace and name of credential secret + nb: can''t use namespacedname here b/c it doesn''t have + json tags in the struct :(' + type: string + required: + - key + - name + - namespace + type: object + type: object + required: + - endpoint + type: object + bootFromDiskMethod: + description: "BootFromDiskMethod specifies the method to exit iPXE + to force boot from disk. \n If not set, controller default is used. + Valid values: ipxe-exit, http-404, ipxe-sanboot." + type: string + configPatches: + items: + properties: + op: + type: string + path: + type: string + value: + x-kubernetes-preserve-unknown-fields: true + required: + - op + - path + type: object + type: array + cordoned: + type: boolean + environmentRef: + description: 'ObjectReference contains enough information to let you + inspect or modify the referred object. --- New uses of this type + are discouraged because of difficulty describing its usage when + embedded in APIs. 1. Ignored fields. It includes many fields which + are not generally honored. For instance, ResourceVersion and FieldPath + are both very rarely valid in actual usage. 2. Invalid usage help. It + is impossible to add specific help for individual usage. In most + embedded usages, there are particular restrictions like, "must refer + only to types A and B" or "UID not honored" or "name must be restricted". + Those cannot be well described when embedded. 3. Inconsistent validation. Because + the usages are different, the validation rules are different by + usage, which makes it hard for users to predict what will happen. + 4. The fields are both imprecise and overly precise. Kind is not + a precise mapping to a URL. This can produce ambiguity during interpretation + and require a REST mapping. In most cases, the dependency is on + the group,resource tuple and the version of the actual struct is + irrelevant. 5. We cannot easily change it. Because this type is + embedded in many locations, updates to this type will affect numerous + schemas. Don''t make new APIs embed an underspecified API type + they do not control. Instead of using this type, create a locally + provided and used type that is well-focused on your reference. For + example, ServiceReferences for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533 + .' + 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 + hardware: + properties: + compute: + properties: + processorCount: + format: int32 + type: integer + processors: + items: + properties: + coreCount: + format: int32 + type: integer + manufacturer: + type: string + productName: + type: string + serialNumber: + type: string + speed: + description: Speed is in megahertz (Mhz) + format: int32 + type: integer + threadCount: + format: int32 + type: integer + type: object + type: array + totalCoreCount: + format: int32 + type: integer + totalThreadCount: + format: int32 + type: integer + type: object + memory: + properties: + moduleCount: + format: int32 + type: integer + modules: + items: + properties: + manufacturer: + type: string + productName: + type: string + serialNumber: + type: string + size: + description: Size is in megabytes (MB) + format: int32 + type: integer + speed: + description: Speed is in megatransfers per second (MT/S) + format: int32 + type: integer + type: + type: string + type: object + type: array + totalSize: + type: string + type: object + network: + properties: + interfaceCount: + format: int32 + type: integer + interfaces: + items: + properties: + addresses: + items: + type: string + type: array + flags: + type: string + index: + format: int32 + type: integer + mac: + type: string + mtu: + format: int32 + type: integer + name: + type: string + type: object + type: array + type: object + storage: + properties: + deviceCount: + format: int32 + type: integer + devices: + items: + properties: + deviceName: + type: string + name: + type: string + productName: + type: string + serialNumber: + type: string + size: + description: Size is in bytes + format: int64 + type: integer + type: + type: string + uuid: + type: string + wwid: + type: string + type: object + type: array + totalSize: + type: string + type: object + system: + properties: + family: + type: string + manufacturer: + type: string + productName: + type: string + serialNumber: + type: string + skuNumber: + type: string + uuid: + type: string + version: + type: string + type: object + type: object + hostname: + type: string + managementApi: + description: ManagementAPI defines data about how to talk to the node + via simple HTTP API. + properties: + endpoint: + type: string + required: + - endpoint + type: object + pxeBootAlways: + type: boolean + required: + - accepted + type: object + status: + description: ServerStatus defines the observed state of Server. + properties: + addresses: + description: Addresses lists discovered node IPs. + items: + description: NodeAddress contains information for the node's address. + properties: + address: + description: The node address. + type: string + type: + description: Node address type, one of Hostname, ExternalIP + or InternalIP. + type: string + required: + - address + - type + type: object + type: array + conditions: + description: Conditions defines current service state of the Server. + 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: + - lastTransitionTime + - status + - type + type: object + type: array + inUse: + description: InUse is true when server is assigned to some MetalMachine. + type: boolean + isClean: + description: IsClean is true when server disks are wiped. + type: boolean + power: + description: 'Power is the current power state of the server: "on", + "off" or "unknown".' + type: string + ready: + description: Ready is true when server is accepted and in use. + type: boolean + type: object + type: object + served: true storage: true subresources: status: {} diff --git a/app/sidero-controller-manager/config/crd/patches/webhook_in_environments.yaml b/app/sidero-controller-manager/config/crd/patches/webhook_in_environments.yaml index b66be96c2..c544e3afa 100644 --- a/app/sidero-controller-manager/config/crd/patches/webhook_in_environments.yaml +++ b/app/sidero-controller-manager/config/crd/patches/webhook_in_environments.yaml @@ -15,5 +15,5 @@ spec: caBundle: Cg== service: namespace: system - name: webhook-service + name: sidero-webhook-service path: /convert diff --git a/app/sidero-controller-manager/config/crd/patches/webhook_in_serverclasses.yaml b/app/sidero-controller-manager/config/crd/patches/webhook_in_serverclasses.yaml index 73196078f..b6d7513a4 100644 --- a/app/sidero-controller-manager/config/crd/patches/webhook_in_serverclasses.yaml +++ b/app/sidero-controller-manager/config/crd/patches/webhook_in_serverclasses.yaml @@ -15,5 +15,5 @@ spec: caBundle: Cg== service: namespace: system - name: webhook-service + name: sidero-webhook-service path: /convert diff --git a/app/sidero-controller-manager/config/crd/patches/webhook_in_servers.yaml b/app/sidero-controller-manager/config/crd/patches/webhook_in_servers.yaml index 99a9aa48e..76cc70a71 100644 --- a/app/sidero-controller-manager/config/crd/patches/webhook_in_servers.yaml +++ b/app/sidero-controller-manager/config/crd/patches/webhook_in_servers.yaml @@ -15,5 +15,5 @@ spec: caBundle: Cg== service: namespace: system - name: webhook-service + name: sidero-webhook-service path: /convert diff --git a/app/sidero-controller-manager/config/webhook/manifests.yaml b/app/sidero-controller-manager/config/webhook/manifests.yaml index 763cf66d6..a87b8ae64 100644 --- a/app/sidero-controller-manager/config/webhook/manifests.yaml +++ b/app/sidero-controller-manager/config/webhook/manifests.yaml @@ -5,6 +5,27 @@ metadata: creationTimestamp: null name: validating-webhook-configuration webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /validate-metal-sidero-dev-v1alpha2-server + failurePolicy: Fail + name: vservers.metal.sidero.dev + rules: + - apiGroups: + - metal.sidero.dev + apiVersions: + - v1alpha2 + operations: + - CREATE + - UPDATE + - DELETE + resources: + - servers + sideEffects: None - admissionReviewVersions: - v1 clientConfig: diff --git a/app/sidero-controller-manager/main.go b/app/sidero-controller-manager/main.go index 99258fd57..010851c94 100644 --- a/app/sidero-controller-manager/main.go +++ b/app/sidero-controller-manager/main.go @@ -25,13 +25,14 @@ import ( "k8s.io/client-go/tools/record" capi "sigs.k8s.io/cluster-api/api/v1beta1" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/log/zap" "sigs.k8s.io/controller-runtime/pkg/manager" infrav1alpha3 "github.com/talos-systems/sidero/app/caps-controller-manager/api/v1alpha3" - "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha1" metalv1alpha1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha1" + metalv1alpha2 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" "github.com/talos-systems/sidero/app/sidero-controller-manager/controllers" "github.com/talos-systems/sidero/app/sidero-controller-manager/internal/ipxe" "github.com/talos-systems/sidero/app/sidero-controller-manager/internal/metadata" @@ -42,7 +43,6 @@ import ( "github.com/talos-systems/sidero/app/sidero-controller-manager/internal/tftp" "github.com/talos-systems/sidero/app/sidero-controller-manager/pkg/constants" siderotypes "github.com/talos-systems/sidero/app/sidero-controller-manager/pkg/types" - "github.com/talos-systems/sidero/internal/client" // +kubebuilder:scaffold:imports ) @@ -65,6 +65,7 @@ func init() { _ = capi.AddToScheme(scheme) _ = metalv1alpha1.AddToScheme(scheme) + _ = metalv1alpha2.AddToScheme(scheme) _ = infrav1alpha3.AddToScheme(scheme) // +kubebuilder:scaffold:scheme } @@ -258,26 +259,22 @@ func main() { grpcServer := server.CreateServer(mgr.GetClient(), apiRecorder, mgr.GetScheme(), autoAcceptServers, insecureWipe, autoBMCSetup, serverRebootTimeout) - k8sClient, err := client.NewClient(nil) - if err != nil { - setupLog.Error(err, `failed to create k8s client`) - os.Exit(1) - } - - if err = controllers.ReconcileServerClassAny(ctx, k8sClient); err != nil { - setupLog.Error(err, `failed to reconcile ServerClass "any"`) + if err = mgr.Add(manager.RunnableFunc(func(ctx context.Context) error { + return siderolink.Cfg.LoadOrCreate(ctx, mgr.GetClient()) + })); err != nil { + setupLog.Error(err, `failed to add SideroLink configuration initialization`) os.Exit(1) } - if err = controllers.ReconcileEnvironmentDefault(ctx, k8sClient, TalosRelease, apiEndpoint, uint16(apiPort)); err != nil { - setupLog.Error(err, `failed to reconcile Environment "default"`) + if err = mgr.Add(RunnableClientFunc(controllers.ReconcileServerClassAny)); err != nil { + setupLog.Error(err, `failed to add initial reconcile`) os.Exit(1) } - if err = mgr.Add(manager.RunnableFunc(func(ctx context.Context) error { - return siderolink.Cfg.LoadOrCreate(ctx, mgr.GetClient()) + if err = mgr.Add(RunnableClientFunc(func(ctx context.Context, k8sClient client.Client) error { + return controllers.ReconcileEnvironmentDefault(ctx, k8sClient, TalosRelease, apiEndpoint, uint16(apiPort)) })); err != nil { - setupLog.Error(err, `failed to add SideroLink configuration initialization`) + setupLog.Error(err, `failed to add initial reconcile`) os.Exit(1) } @@ -329,17 +326,32 @@ func main() { } func setupWebhooks(mgr ctrl.Manager) { - if err := (&v1alpha1.ServerClass{}).SetupWebhookWithManager(mgr); err != nil { + if err := (&metalv1alpha1.ServerClass{}).SetupWebhookWithManager(mgr); err != nil { setupLog.Error(err, "unable to create webhook", "webhook", "ServerClass") os.Exit(1) } - if err := (&v1alpha1.Environment{}).SetupWebhookWithManager(mgr); err != nil { + if err := (&metalv1alpha1.Environment{}).SetupWebhookWithManager(mgr); err != nil { setupLog.Error(err, "unable to create webhook", "webhook", "Environment") os.Exit(1) } - if err := (&v1alpha1.Server{}).SetupWebhookWithManager(mgr); err != nil { + if err := (&metalv1alpha1.Server{}).SetupWebhookWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create webhook", "webhook", "Server") + os.Exit(1) + } + + if err := (&metalv1alpha2.ServerClass{}).SetupWebhookWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create webhook", "webhook", "ServerClass") + os.Exit(1) + } + + if err := (&metalv1alpha2.Environment{}).SetupWebhookWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create webhook", "webhook", "Environment") + os.Exit(1) + } + + if err := (&metalv1alpha2.Server{}).SetupWebhookWithManager(mgr); err != nil { setupLog.Error(err, "unable to create webhook", "webhook", "Server") os.Exit(1) } @@ -358,3 +370,29 @@ func setupChecks(mgr ctrl.Manager, httpPort int) { os.Exit(1) } } + +// RunnableClientFunc implements Runnable and inject.Client using a function. +func RunnableClientFunc(f func(context.Context, client.Client) error) *runnableClientFunc { + return &runnableClientFunc{ + Func: f, + } +} + +type runnableClientFunc struct { + Client client.Client + Func func(context.Context, client.Client) error +} + +// InjectClient implements inject.Client. +// +//nolint:unparam +func (r *runnableClientFunc) InjectClient(c client.Client) error { + r.Client = c + + return nil +} + +// Start implements Runnable. +func (r *runnableClientFunc) Start(ctx context.Context) error { + return r.Func(ctx, r.Client) +} diff --git a/sfyra/pkg/tests/compatibility.go b/sfyra/pkg/tests/compatibility.go index 532cb7807..bc7fb8764 100644 --- a/sfyra/pkg/tests/compatibility.go +++ b/sfyra/pkg/tests/compatibility.go @@ -59,10 +59,10 @@ func TestCompatibilityCluster(ctx context.Context, metalClient client.Client, cl environment.APIVersion = constants.SideroAPIVersion environment.Name = envName - environment.Spec.Kernel.URL = fmt.Sprintf("https://github.com/talos-systems/talos/releases/download/%s/vmlinuz-amd64", talosRelease) + environment.Spec.Kernel.URL = fmt.Sprintf("https://github.com/siderolabs/talos/releases/download/%s/vmlinuz-amd64", talosRelease) environment.Spec.Kernel.SHA512 = "" environment.Spec.Kernel.Args = cmdline.Strings() - environment.Spec.Initrd.URL = fmt.Sprintf("https://github.com/talos-systems/talos/releases/download/%s/initramfs-amd64.xz", talosRelease) + environment.Spec.Initrd.URL = fmt.Sprintf("https://github.com/siderolabs/talos/releases/download/%s/initramfs-amd64.xz", talosRelease) environment.Spec.Initrd.SHA512 = "" require.NoError(t, metalClient.Create(ctx, &environment))