feat: restructure HW information in Server resources (v1alpha2)

This is basically subset of PR #735 with only CRD changes without actual
code changes to use new CRDs. As storage version is v1alpha2, every
access goes twice via conversion webhooks (for better test coverage).

Other parts of #735 will be incorporated in a follow-up PR, I decided to
split things up for easier review.

Example:

```bash
$ kubectl get servers.v1alpha1.metal.sidero.dev 49fd7c2d-1ba4-4157-8cc0-3f7212f119f0 -o yaml
...
  cpu:
    manufacturer: QEMU
    version: pc-q35-6.0
  hostname: pxe-3
  managementApi:
    endpoint: 172.25.0.1:39565
  system:
    family: Unknown
    manufacturer: QEMU
    productName: Standard PC (Q35 + ICH9, 2009)
    serialNumber: Unknown
    skuNumber: Unknown
    version: pc-q35-6.0
$ kubectl get servers.v1alpha2.metal.sidero.dev 49fd7c2d-1ba4-4157-8cc0-3f7212f119f0 -o yaml
...
  hardware:
    compute:
      processors:
      - manufacturer: QEMU
        productName: pc-q35-6.0
    system:
      family: Unknown
      manufacturer: QEMU
      productName: Standard PC (Q35 + ICH9, 2009)
      serialNumber: Unknown
      skuNumber: Unknown
      version: pc-q35-6.0
```

We can make more changes to v1alpha2 resources in follow-up PRs.

Co-authored-by: Gerard de Leeuw <gdeleeuw@leeuwit.nl>
Signed-off-by: Gerard de Leeuw <gdeleeuw@leeuwit.nl>
Signed-off-by: Andrey Smirnov <andrey.smirnov@talos-systems.com>
This commit is contained in:
Andrey Smirnov 2022-04-14 17:39:47 +03:00
parent 6c81518b17
commit e4bb4165e9
No known key found for this signature in database
GPG Key ID: 7B26396447AB6DFD
38 changed files with 4421 additions and 30 deletions

View File

@ -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} .

View File

@ -15,5 +15,5 @@ spec:
caBundle: Cg==
service:
namespace: system
name: webhook-service
name: caps-webhook-service
path: /convert

View File

@ -15,5 +15,5 @@ spec:
caBundle: Cg==
service:
namespace: system
name: webhook-service
name: caps-webhook-service
path: /convert

View File

@ -15,5 +15,5 @@ spec:
caBundle: Cg==
service:
namespace: system
name: webhook-service
name: caps-webhook-service
path: /convert

View File

@ -15,5 +15,5 @@ spec:
caBundle: Cg==
service:
namespace: system
name: webhook-service
name: caps-webhook-service
path: /convert

View File

@ -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"

View File

@ -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

View File

@ -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)
}

View File

@ -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
)

View File

@ -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)
}

View File

@ -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,
)
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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

View File

@ -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() {}

View File

@ -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{})
}

View File

@ -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()
}

View File

@ -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
)

View File

@ -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() {}

View File

@ -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{})
}

View File

@ -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)
}
})
}
}

View File

@ -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)
}

View File

@ -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() {}

View File

@ -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
}

View File

@ -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)
})
}
}

View File

@ -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{})
}

View File

@ -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()
}

View File

@ -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"`
}

View File

@ -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
}

View File

@ -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: {}

View File

@ -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: {}

View File

@ -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: {}

View File

@ -15,5 +15,5 @@ spec:
caBundle: Cg==
service:
namespace: system
name: webhook-service
name: sidero-webhook-service
path: /convert

View File

@ -15,5 +15,5 @@ spec:
caBundle: Cg==
service:
namespace: system
name: webhook-service
name: sidero-webhook-service
path: /convert

View File

@ -15,5 +15,5 @@ spec:
caBundle: Cg==
service:
namespace: system
name: webhook-service
name: sidero-webhook-service
path: /convert

View File

@ -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:

View File

@ -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,22 +259,6 @@ 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"`)
os.Exit(1)
}
if err = controllers.ReconcileEnvironmentDefault(ctx, k8sClient, TalosRelease, apiEndpoint, uint16(apiPort)); err != nil {
setupLog.Error(err, `failed to reconcile Environment "default"`)
os.Exit(1)
}
if err = mgr.Add(manager.RunnableFunc(func(ctx context.Context) error {
return siderolink.Cfg.LoadOrCreate(ctx, mgr.GetClient())
})); err != nil {
@ -281,6 +266,18 @@ func main() {
os.Exit(1)
}
if err = mgr.Add(RunnableClientFunc(controllers.ReconcileServerClassAny)); err != nil {
setupLog.Error(err, `failed to add initial reconcile`)
os.Exit(1)
}
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 initial reconcile`)
os.Exit(1)
}
setupLog.Info("starting manager and HTTP server")
go func() {
@ -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)
}

View File

@ -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))