diff --git a/Dockerfile b/Dockerfile index 1044c1361..a351adec7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -70,6 +70,7 @@ RUN --mount=type=cache,target=/.cache controller-gen \ FROM scratch AS manifests COPY --from=manifests-build /src/app/caps-controller-manager/config ./app/caps-controller-manager/config COPY --from=manifests-build /src/app/sidero-controller-manager/config ./app/sidero-controller-manager/config +COPY --from=manifests-build /src/app/webhook-server/config ./app/webhook-server/config FROM base AS generate-build COPY ./app/sidero-controller-manager/internal/api/api.proto \ @@ -79,6 +80,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} . @@ -94,12 +96,15 @@ COPY ./config ./config COPY ./templates ./templates COPY ./app/caps-controller-manager/config ./app/caps-controller-manager/config COPY ./app/sidero-controller-manager/config ./app/sidero-controller-manager/config +COPY ./app/webhook-server/config ./app/webhook-server/config ARG REGISTRY_AND_USERNAME ARG TAG RUN cd ./app/caps-controller-manager/config/manager \ && kustomize edit set image controller=${REGISTRY_AND_USERNAME}/caps-controller-manager:${TAG} RUN cd ./app/sidero-controller-manager/config/manager \ && kustomize edit set image controller=${REGISTRY_AND_USERNAME}/sidero-controller-manager:${TAG} +RUN cd ./app/webhook-server/config/webhook-server \ + && kustomize edit set image controller=${REGISTRY_AND_USERNAME}/webhook-server:${TAG} RUN kustomize build config > /infrastructure-components.yaml \ && cp ./config/metadata/metadata.yaml /metadata.yaml \ && cp ./templates/cluster-template.yaml /cluster-template.yaml @@ -217,6 +222,23 @@ FROM sidero-controller-manager-image AS sidero-controller-manager LABEL org.opencontainers.image.source https://github.com/siderolabs/sidero ENTRYPOINT [ "/manager" ] +FROM base AS build-webhook-server +ARG TALOS_RELEASE +ARG TARGETARCH +ARG GO_BUILDFLAGS +ARG GO_LDFLAGS +RUN --mount=type=cache,target=/.cache GOOS=linux GOARCH=${TARGETARCH} go build ${GO_BUILDFLAGS} -ldflags "${GO_LDFLAGS} -X main.TalosRelease=${TALOS_RELEASE}" -o /webhook-server ./app/webhook-server +RUN chmod +x /webhook-server + +FROM scratch AS webhook-server +COPY --from=pkg-ca-certificates / / +COPY --from=pkg-fhs / / +COPY --from=pkg-musl / / +COPY --from=pkg-libressl / / +COPY --from=build-webhook-server /webhook-server /webhook-server +LABEL org.opencontainers.image.source https://github.com/talos-systems/sidero +ENTRYPOINT [ "/webhook-server" ] + FROM base AS unit-tests-runner ARG TEST_PKGS RUN --mount=type=cache,target=/.cache --mount=type=cache,id=testspace,target=/tmp --mount=type=cache,target=/root/.cache/go-build go test -v -covermode=atomic -coverprofile=coverage.txt -count 1 ${TEST_PKGS} diff --git a/Makefile b/Makefile index bfece0720..94d0f40ef 100644 --- a/Makefile +++ b/Makefile @@ -56,7 +56,7 @@ COMMON_ARGS += --build-arg=CGO_ENABLED=$(CGO_ENABLED) COMMON_ARGS += --build-arg=GO_BUILDFLAGS="$(GO_BUILDFLAGS)" COMMON_ARGS += --build-arg=GO_LDFLAGS="$(GO_LDFLAGS)" -all: manifests generate caps-controller-manager sidero-controller-manager sfyra +all: manifests generate caps-controller-manager sidero-controller-manager webhook-server sfyra # Help Menu @@ -139,6 +139,10 @@ caps-controller-manager: ## Build the CAPI provider container image. sidero-controller-manager: ## Build the CAPI provider container image. @$(MAKE) docker-$@ TARGET_ARGS="--push=$(PUSH)" NAME="$@" +.PHONY: webhook-server +webhook-server: ## Build the webhook server container image. + @$(MAKE) docker-$@ TARGET_ARGS="--push=$(PUSH)" NAME="$@" + .PHONY: release-notes release-notes: @mkdir -p $(ARTIFACTS) diff --git a/app/caps-controller-manager/config/crd/kustomizeconfig.yaml b/app/caps-controller-manager/config/crd/kustomizeconfig.yaml index 8e2d8d6b1..8080584b9 100644 --- a/app/caps-controller-manager/config/crd/kustomizeconfig.yaml +++ b/app/caps-controller-manager/config/crd/kustomizeconfig.yaml @@ -1,17 +1,11 @@ # This file is for teaching kustomize how to substitute name and namespace reference in CRD nameReference: -- kind: Service - version: v1 - fieldSpecs: - - kind: CustomResourceDefinition - group: apiextensions.k8s.io - path: spec/conversion/webhook/clientConfig/service/name - -namespace: -- kind: CustomResourceDefinition - group: apiextensions.k8s.io - path: spec/conversion/webhook/clientConfig/service/namespace - create: false + - kind: Service + version: v1 + fieldSpecs: + - kind: CustomResourceDefinition + group: apiextensions.k8s.io + path: spec/conversion/webhook/clientConfig/service/name varReference: -- path: metadata/annotations + - path: metadata/annotations \ No newline at end of file diff --git a/app/caps-controller-manager/config/default/kustomization.yaml b/app/caps-controller-manager/config/default/kustomization.yaml index 806f302ef..34992e219 100644 --- a/app/caps-controller-manager/config/default/kustomization.yaml +++ b/app/caps-controller-manager/config/default/kustomization.yaml @@ -6,44 +6,7 @@ namePrefix: caps- commonLabels: cluster.x-k8s.io/provider: "control-plane-talos" -bases: +resources: - ../crd - - ../certmanager - - ../webhook - ../rbac - ../manager - -patchesStrategicMerge: - - manager_webhook_patch.yaml -# - webhookcainjection_patch.yaml - -vars: - - name: CERTIFICATE_NAMESPACE # namespace of the certificate CR - objref: - kind: Certificate - group: cert-manager.io - version: v1 - name: serving-cert # this name should match the one in certificate.yaml - fieldref: - fieldpath: metadata.namespace - - name: CERTIFICATE_NAME - objref: - kind: Certificate - group: cert-manager.io - version: v1 - name: serving-cert # this name should match the one in certificate.yaml - - name: SERVICE_NAMESPACE # namespace of the service - objref: - kind: Service - version: v1 - name: webhook-service - fieldref: - fieldpath: metadata.namespace - - name: SERVICE_NAME - objref: - kind: Service - version: v1 - name: webhook-service - -configurations: - - kustomizeconfig.yaml diff --git a/app/caps-controller-manager/config/default/kustomizeconfig.yaml b/app/caps-controller-manager/config/default/kustomizeconfig.yaml deleted file mode 100644 index 524d39cc2..000000000 --- a/app/caps-controller-manager/config/default/kustomizeconfig.yaml +++ /dev/null @@ -1,4 +0,0 @@ -# This configuration is for teaching kustomize how to update name ref and var substitution -varReference: - - kind: Deployment - path: spec/template/spec/volumes/secret/secretName diff --git a/app/caps-controller-manager/config/default/manager_webhook_patch.yaml b/app/caps-controller-manager/config/default/manager_webhook_patch.yaml deleted file mode 100644 index 35e2de074..000000000 --- a/app/caps-controller-manager/config/default/manager_webhook_patch.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: controller-manager - namespace: system -spec: - template: - spec: - containers: - - name: manager - ports: - - containerPort: 9443 - name: webhook-server - protocol: TCP - volumeMounts: - - mountPath: /tmp/k8s-webhook-server/serving-certs - name: cert - readOnly: true - volumes: - - name: cert - secret: - defaultMode: 420 - secretName: $(SERVICE_NAME)-cert diff --git a/app/caps-controller-manager/config/webhook/kustomization.yaml b/app/caps-controller-manager/config/webhook/kustomization.yaml deleted file mode 100644 index 40947312a..000000000 --- a/app/caps-controller-manager/config/webhook/kustomization.yaml +++ /dev/null @@ -1,5 +0,0 @@ -resources: - - service.yaml - -configurations: - - kustomizeconfig.yaml \ No newline at end of file diff --git a/app/caps-controller-manager/config/webhook/service.yaml b/app/caps-controller-manager/config/webhook/service.yaml deleted file mode 100644 index d4e830243..000000000 --- a/app/caps-controller-manager/config/webhook/service.yaml +++ /dev/null @@ -1,12 +0,0 @@ - -apiVersion: v1 -kind: Service -metadata: - name: webhook-service - namespace: system -spec: - ports: - - port: 443 - targetPort: 9443 - selector: - control-plane: caps-controller-manager diff --git a/app/caps-controller-manager/controllers/metalmachine_controller.go b/app/caps-controller-manager/controllers/metalmachine_controller.go index a6b4ce47c..9c61ccc95 100644 --- a/app/caps-controller-manager/controllers/metalmachine_controller.go +++ b/app/caps-controller-manager/controllers/metalmachine_controller.go @@ -35,7 +35,7 @@ import ( infrav1 "github.com/talos-systems/sidero/app/caps-controller-manager/api/v1alpha3" "github.com/talos-systems/sidero/app/caps-controller-manager/pkg/constants" - metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha1" + metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" ) var ErrNoServersInServerClass = errors.New("no servers available in serverclass") diff --git a/app/caps-controller-manager/controllers/serverbinding_controller.go b/app/caps-controller-manager/controllers/serverbinding_controller.go index 12031b0ff..27cfab8a6 100644 --- a/app/caps-controller-manager/controllers/serverbinding_controller.go +++ b/app/caps-controller-manager/controllers/serverbinding_controller.go @@ -23,7 +23,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/source" infrav1 "github.com/talos-systems/sidero/app/caps-controller-manager/api/v1alpha3" - metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha1" + metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" ) // ServerBindingReconciler reconciles a ServerBinding object. diff --git a/app/caps-controller-manager/main.go b/app/caps-controller-manager/main.go index 4a53b13e8..26a5eadce 100644 --- a/app/caps-controller-manager/main.go +++ b/app/caps-controller-manager/main.go @@ -8,6 +8,7 @@ import ( "context" "flag" "os" + "sigs.k8s.io/controller-runtime/pkg/healthz" debug "github.com/talos-systems/go-debug" corev1 "k8s.io/api/core/v1" @@ -16,7 +17,7 @@ import ( clientgoscheme "k8s.io/client-go/kubernetes/scheme" typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1" cgrecord "k8s.io/client-go/tools/record" - capiv1 "sigs.k8s.io/cluster-api/api/v1beta1" + capiv1beta1 "sigs.k8s.io/cluster-api/api/v1beta1" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/log/zap" @@ -25,6 +26,7 @@ import ( infrav1alpha3 "github.com/talos-systems/sidero/app/caps-controller-manager/api/v1alpha3" "github.com/talos-systems/sidero/app/caps-controller-manager/controllers" metalv1alpha1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha1" + metalv1alpha2 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" // +kubebuilder:scaffold:imports ) @@ -41,10 +43,11 @@ var ( //nolint:wsl func init() { _ = clientgoscheme.AddToScheme(scheme) - _ = capiv1.AddToScheme(scheme) + _ = capiv1beta1.AddToScheme(scheme) _ = infrav1alpha2.AddToScheme(scheme) _ = infrav1alpha3.AddToScheme(scheme) _ = metalv1alpha1.AddToScheme(scheme) + _ = metalv1alpha2.AddToScheme(scheme) // +kubebuilder:scaffold:scheme } @@ -53,14 +56,12 @@ func main() { metricsAddr string healthAddr string enableLeaderElection bool - webhookPort int ) flag.StringVar(&metricsAddr, "metrics-bind-addr", ":8080", "The address the metric endpoint binds to.") flag.StringVar(&healthAddr, "health-addr", ":9440", "The address the health endpoint binds to.") flag.BoolVar(&enableLeaderElection, "enable-leader-election", true, "Enable leader election for controller manager. Enabling this will ensure there is only one active controller manager.") - flag.IntVar(&webhookPort, "webhook-port", 9443, "Webhook Server port, disabled by default. When enabled, the manager will only work as webhook server, no reconcilers are installed.") flag.Parse() ctrl.SetLogger(zap.New(func(o *zap.Options) { @@ -88,7 +89,7 @@ func main() { MetricsBindAddress: metricsAddr, LeaderElection: enableLeaderElection, LeaderElectionID: "controller-leader-election-capm", - Port: webhookPort, + Port: 9443, EventBroadcaster: broadcaster, HealthProbeBindAddress: healthAddr, }) @@ -143,26 +144,6 @@ func main() { setupLog.Error(err, "unable to create controller", "controller", "ServerBinding") os.Exit(1) } - - if err = (&infrav1alpha3.MetalCluster{}).SetupWebhookWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create webhook", "webhook", "MetalCluster") - os.Exit(1) - } - - if err = (&infrav1alpha3.MetalMachine{}).SetupWebhookWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create webhook", "webhook", "MetalMachine") - os.Exit(1) - } - - if err = (&infrav1alpha3.MetalMachineTemplate{}).SetupWebhookWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create webhook", "webhook", "MetalMachineTemplate") - os.Exit(1) - } - - if err = (&infrav1alpha3.ServerBinding{}).SetupWebhookWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create webhook", "webhook", "ServerBinding") - os.Exit(1) - } // +kubebuilder:scaffold:builder setupChecks(mgr) @@ -176,12 +157,12 @@ func main() { } func setupChecks(mgr ctrl.Manager) { - if err := mgr.AddReadyzCheck("webhook", mgr.GetWebhookServer().StartedChecker()); err != nil { + if err := mgr.AddReadyzCheck("ping", healthz.Ping); err != nil { setupLog.Error(err, "unable to create ready check") os.Exit(1) } - if err := mgr.AddHealthzCheck("webhook", mgr.GetWebhookServer().StartedChecker()); err != nil { + if err := mgr.AddHealthzCheck("ping", healthz.Ping); err != nil { setupLog.Error(err, "unable to create health check") os.Exit(1) } diff --git a/app/sidero-controller-manager/PROJECT b/app/sidero-controller-manager/PROJECT index 6bf695d0a..1472e279c 100644 --- a/app/sidero-controller-manager/PROJECT +++ b/app/sidero-controller-manager/PROJECT @@ -10,4 +10,13 @@ resources: - group: metal kind: ServerClass version: v1alpha1 +- group: metal + kind: Environment + version: v1alpha2 +- group: metal + kind: Server + version: v1alpha2 +- group: metal + kind: ServerClass + version: v1alpha2 version: "2" diff --git a/app/sidero-controller-manager/api/v1alpha1/doc.go b/app/sidero-controller-manager/api/v1alpha1/doc.go new file mode 100644 index 000000000..5aac563b1 --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha1/doc.go @@ -0,0 +1,7 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package v1alpha1 + +// +k8s:conversion-gen=github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2 diff --git a/app/sidero-controller-manager/api/v1alpha1/environment_conversion.go b/app/sidero-controller-manager/api/v1alpha1/environment_conversion.go new file mode 100644 index 000000000..924bc0b2f --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha1/environment_conversion.go @@ -0,0 +1,56 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +//nolint:golint,stylecheck +package v1alpha1 + +import ( + utilconversion "sigs.k8s.io/cluster-api/util/conversion" + "sigs.k8s.io/controller-runtime/pkg/conversion" + + metalv1alpha2 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" +) + +// ConvertTo converts this Environment to the Hub version (v1alpha2). +func (src *Environment) ConvertTo(dstRaw conversion.Hub) error { + dst := dstRaw.(*metalv1alpha2.Environment) + if err := Convert_v1alpha1_Environment_To_v1alpha2_Environment(src, dst, nil); err != nil { + return err + } + + // Manually restore data from annotations + restored := &metalv1alpha2.Environment{} + if ok, err := utilconversion.UnmarshalData(src, restored); err != nil || !ok { + return err + } + + return nil +} + +// ConvertFrom converts from the Hub version (v1alpha3) to this version. +func (dst *Environment) ConvertFrom(srcRaw conversion.Hub) error { + src := srcRaw.(*metalv1alpha2.Environment) + if err := Convert_v1alpha2_Environment_To_v1alpha1_Environment(src, dst, nil); err != nil { + return err + } + + // Preserve Hub data on down-conversion. + if err := utilconversion.MarshalData(src, dst); err != nil { + return err + } + + return nil +} + +// ConvertTo converts this MetalMachineTemplateList to the Hub version (v1alpha3). +func (src *EnvironmentList) ConvertTo(dstRaw conversion.Hub) error { + dst := dstRaw.(*metalv1alpha2.EnvironmentList) + return Convert_v1alpha1_EnvironmentList_To_v1alpha2_EnvironmentList(src, dst, nil) +} + +// ConvertFrom converts from the Hub version (v1alpha3) to this version. +func (dst *EnvironmentList) ConvertFrom(srcRaw conversion.Hub) error { + src := srcRaw.(*metalv1alpha2.EnvironmentList) + return Convert_v1alpha2_EnvironmentList_To_v1alpha1_EnvironmentList(src, dst, nil) +} diff --git a/app/sidero-controller-manager/api/v1alpha1/groupversion_info.go b/app/sidero-controller-manager/api/v1alpha1/groupversion_info.go index 201054aa4..44d835731 100644 --- a/app/sidero-controller-manager/api/v1alpha1/groupversion_info.go +++ b/app/sidero-controller-manager/api/v1alpha1/groupversion_info.go @@ -21,4 +21,7 @@ var ( // AddToScheme adds the types in this group-version to the given scheme. AddToScheme = SchemeBuilder.AddToScheme + + // localSchemeBuilder is used for type conversions. + localSchemeBuilder = SchemeBuilder.SchemeBuilder ) diff --git a/app/sidero-controller-manager/api/v1alpha1/server_conversion.go b/app/sidero-controller-manager/api/v1alpha1/server_conversion.go new file mode 100644 index 000000000..4d909569a --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha1/server_conversion.go @@ -0,0 +1,130 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +//nolint:golint,stylecheck +package v1alpha1 + +import ( + apiconversion "k8s.io/apimachinery/pkg/conversion" + utilconversion "sigs.k8s.io/cluster-api/util/conversion" + "sigs.k8s.io/controller-runtime/pkg/conversion" + + metalv1alpha2 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" +) + +// ConvertTo converts this Server to the Hub version (v1alpha2). +func (src *Server) ConvertTo(dstRaw conversion.Hub) error { + dst := dstRaw.(*metalv1alpha2.Server) + if err := Convert_v1alpha1_Server_To_v1alpha2_Server(src, dst, nil); err != nil { + return err + } + + // Manually restore data from annotations + restored := &metalv1alpha2.Server{} + if ok, err := utilconversion.UnmarshalData(src, restored); err != nil || !ok { + return err + } + + return nil +} + +// ConvertFrom converts from the Hub version (v1alpha3) to this version. +func (dst *Server) ConvertFrom(srcRaw conversion.Hub) error { + src := srcRaw.(*metalv1alpha2.Server) + if err := Convert_v1alpha2_Server_To_v1alpha1_Server(src, dst, nil); err != nil { + return err + } + + // Preserve Hub data on down-conversion. + if err := utilconversion.MarshalData(src, dst); err != nil { + return err + } + + return nil +} + +// ConvertTo converts this MetalMachineTemplateList to the Hub version (v1alpha3). +func (src *ServerList) ConvertTo(dstRaw conversion.Hub) error { + dst := dstRaw.(*metalv1alpha2.ServerList) + return Convert_v1alpha1_ServerList_To_v1alpha2_ServerList(src, dst, nil) +} + +// ConvertFrom converts from the Hub version (v1alpha3) to this version. +func (dst *ServerList) ConvertFrom(srcRaw conversion.Hub) error { + src := srcRaw.(*metalv1alpha2.ServerList) + return Convert_v1alpha2_ServerList_To_v1alpha1_ServerList(src, dst, nil) +} + +// Convert_v1alpha1_ServerSpec_To_v1alpha2_ServerSpec converts to the Hub version (v1alpha2). +func Convert_v1alpha1_ServerSpec_To_v1alpha2_ServerSpec(in *ServerSpec, out *metalv1alpha2.ServerSpec, s apiconversion.Scope) error { + if err := autoConvert_v1alpha1_ServerSpec_To_v1alpha2_ServerSpec(in, out, s); err != nil { + return err + } + + // Manually convert SystemInformation to Hardware. + if in.SystemInformation != nil { + if out.Hardware == nil { + out.Hardware = &metalv1alpha2.HardwareInformation{} + } + out.Hardware.System = &metalv1alpha2.SystemInformation{ + Manufacturer: in.SystemInformation.Manufacturer, + ProductName: in.SystemInformation.ProductName, + Version: in.SystemInformation.Version, + SerialNumber: in.SystemInformation.SerialNumber, + SKUNumber: in.SystemInformation.SKUNumber, + Family: in.SystemInformation.Family, + } + } + + // Manually convert CPU to Hardware. + if in.CPU != nil { + if out.Hardware == nil { + out.Hardware = &metalv1alpha2.HardwareInformation{} + } + out.Hardware.Compute = &metalv1alpha2.ComputeInformation{ + Processors: []*metalv1alpha2.Processor{ + { + Manufacturer: in.CPU.Manufacturer, + ProductName: in.CPU.Version, + }, + }, + } + } + + return nil +} + +// Convert_v1alpha2_ServerSpec_To_v1alpha1_ServerSpec converts from the Hub version (v1alpha2). +func Convert_v1alpha2_ServerSpec_To_v1alpha1_ServerSpec(in *metalv1alpha2.ServerSpec, out *ServerSpec, s apiconversion.Scope) error { + if err := autoConvert_v1alpha2_ServerSpec_To_v1alpha1_ServerSpec(in, out, s); err != nil { + return err + } + + // Manually convert Hardware to SystemInformation. + if in.Hardware != nil && in.Hardware.System != nil { + out.SystemInformation = &SystemInformation{ + Manufacturer: in.Hardware.System.Manufacturer, + ProductName: in.Hardware.System.ProductName, + Version: in.Hardware.System.Version, + SerialNumber: in.Hardware.System.SerialNumber, + SKUNumber: in.Hardware.System.SKUNumber, + Family: in.Hardware.System.Family, + } + } + + // Manually convert Hardware to CPU. + if in.Hardware != nil && in.Hardware.Compute != nil && len(in.Hardware.Compute.Processors) > 0 { + cpu := in.Hardware.Compute.Processors[0] + out.CPU = &CPUInformation{ + Manufacturer: cpu.Manufacturer, + Version: cpu.ProductName, + } + } + + return nil +} + +func Convert_v1alpha2_SystemInformation_To_v1alpha1_SystemInformation(in *metalv1alpha2.SystemInformation, out *SystemInformation, s apiconversion.Scope) error { + return autoConvert_v1alpha2_SystemInformation_To_v1alpha1_SystemInformation(in, out, s) +} diff --git a/app/sidero-controller-manager/api/v1alpha1/serverclass_conversion.go b/app/sidero-controller-manager/api/v1alpha1/serverclass_conversion.go new file mode 100644 index 000000000..ea54850be --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha1/serverclass_conversion.go @@ -0,0 +1,124 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +//nolint:golint,stylecheck +package v1alpha1 + +import ( + apiconversion "k8s.io/apimachinery/pkg/conversion" + utilconversion "sigs.k8s.io/cluster-api/util/conversion" + "sigs.k8s.io/controller-runtime/pkg/conversion" + + metalv1alpha2 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" +) + +// ConvertTo converts this ServerClass to the Hub version (v1alpha2). +func (src *ServerClass) ConvertTo(dstRaw conversion.Hub) error { + dst := dstRaw.(*metalv1alpha2.ServerClass) + if err := Convert_v1alpha1_ServerClass_To_v1alpha2_ServerClass(src, dst, nil); err != nil { + return err + } + + // Manually restore data from annotations + restored := &metalv1alpha2.ServerClass{} + if ok, err := utilconversion.UnmarshalData(src, restored); err != nil || !ok { + return err + } + + return nil +} + +// ConvertFrom converts from the Hub version (v1alpha3) to this version. +func (dst *ServerClass) ConvertFrom(srcRaw conversion.Hub) error { + src := srcRaw.(*metalv1alpha2.ServerClass) + if err := Convert_v1alpha2_ServerClass_To_v1alpha1_ServerClass(src, dst, nil); err != nil { + return err + } + + // Preserve Hub data on down-conversion. + if err := utilconversion.MarshalData(src, dst); err != nil { + return err + } + + return nil +} + +// ConvertTo converts this MetalMachineTemplateList to the Hub version (v1alpha3). +func (src *ServerClassList) ConvertTo(dstRaw conversion.Hub) error { + dst := dstRaw.(*metalv1alpha2.ServerClassList) + return Convert_v1alpha1_ServerClassList_To_v1alpha2_ServerClassList(src, dst, nil) +} + +// ConvertFrom converts from the Hub version (v1alpha3) to this version. +func (dst *ServerClassList) ConvertFrom(srcRaw conversion.Hub) error { + src := srcRaw.(*metalv1alpha2.ServerClassList) + return Convert_v1alpha2_ServerClassList_To_v1alpha1_ServerClassList(src, dst, nil) +} + +// Convert_v1alpha1_Qualifiers_To_v1alpha2_Qualifiers converts to the Hub version (v1alpha2). +func Convert_v1alpha1_Qualifiers_To_v1alpha2_Qualifiers(in *Qualifiers, out *metalv1alpha2.Qualifiers, s apiconversion.Scope) error { + if err := autoConvert_v1alpha1_Qualifiers_To_v1alpha2_Qualifiers(in, out, s); err != nil { + return err + } + + // Manually convert SystemInformation to Hardware. + for _, v := range in.SystemInformation { + out.Hardware = append(out.Hardware, metalv1alpha2.HardwareInformation{ + System: &metalv1alpha2.SystemInformation{ + Manufacturer: v.Manufacturer, + ProductName: v.ProductName, + Version: v.Version, + SerialNumber: v.SerialNumber, + SKUNumber: v.SKUNumber, + Family: v.Family, + }, + }) + } + + // Manually convert CPU to Hardware. + for _, v := range in.CPU { + out.Hardware = append(out.Hardware, metalv1alpha2.HardwareInformation{ + Compute: &metalv1alpha2.ComputeInformation{ + Processors: []*metalv1alpha2.Processor{ + { + Manufacturer: v.Manufacturer, + ProductName: v.Version, + }, + }, + }, + }) + } + + return nil +} + +// Convert_v1alpha2_Qualifiers_To_v1alpha1_Qualifiers converts from the Hub version (v1alpha2). +func Convert_v1alpha2_Qualifiers_To_v1alpha1_Qualifiers(in *metalv1alpha2.Qualifiers, out *Qualifiers, s apiconversion.Scope) error { + if err := autoConvert_v1alpha2_Qualifiers_To_v1alpha1_Qualifiers(in, out, s); err != nil { + return err + } + + // Manually convert Hardware to SystemInformation or CPU. + for _, v := range in.Hardware { + if v.System != nil { + out.SystemInformation = append(out.SystemInformation, SystemInformation{ + Manufacturer: v.System.Manufacturer, + ProductName: v.System.ProductName, + Version: v.System.Version, + SerialNumber: v.System.SerialNumber, + SKUNumber: v.System.SKUNumber, + Family: v.System.Family, + }) + } + if v.Compute != nil && len(v.Compute.Processors) > 0 { + cpu := v.Compute.Processors[0] + out.CPU = append(out.CPU, CPUInformation{ + Manufacturer: cpu.Manufacturer, + Version: cpu.ProductName, + }) + } + } + + return nil +} diff --git a/app/sidero-controller-manager/api/v1alpha1/zz_generated.conversion.go b/app/sidero-controller-manager/api/v1alpha1/zz_generated.conversion.go new file mode 100644 index 000000000..ac273f357 --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha1/zz_generated.conversion.go @@ -0,0 +1,886 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +// Code generated by conversion-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + unsafe "unsafe" + + v1 "k8s.io/api/core/v1" + conversion "k8s.io/apimachinery/pkg/conversion" + runtime "k8s.io/apimachinery/pkg/runtime" + v1beta1 "sigs.k8s.io/cluster-api/api/v1beta1" + + v1alpha2 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" + types "github.com/talos-systems/sidero/app/sidero-controller-manager/pkg/types" +) + +func init() { + localSchemeBuilder.Register(RegisterConversions) +} + +// RegisterConversions adds conversion functions to the given scheme. +// Public to allow building arbitrary schemes. +func RegisterConversions(s *runtime.Scheme) error { + if err := s.AddGeneratedConversionFunc((*Asset)(nil), (*v1alpha2.Asset)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_Asset_To_v1alpha2_Asset(a.(*Asset), b.(*v1alpha2.Asset), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.Asset)(nil), (*Asset)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_Asset_To_v1alpha1_Asset(a.(*v1alpha2.Asset), b.(*Asset), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*AssetCondition)(nil), (*v1alpha2.AssetCondition)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_AssetCondition_To_v1alpha2_AssetCondition(a.(*AssetCondition), b.(*v1alpha2.AssetCondition), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.AssetCondition)(nil), (*AssetCondition)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_AssetCondition_To_v1alpha1_AssetCondition(a.(*v1alpha2.AssetCondition), b.(*AssetCondition), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*BMC)(nil), (*v1alpha2.BMC)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_BMC_To_v1alpha2_BMC(a.(*BMC), b.(*v1alpha2.BMC), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.BMC)(nil), (*BMC)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_BMC_To_v1alpha1_BMC(a.(*v1alpha2.BMC), b.(*BMC), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ConfigPatches)(nil), (*v1alpha2.ConfigPatches)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ConfigPatches_To_v1alpha2_ConfigPatches(a.(*ConfigPatches), b.(*v1alpha2.ConfigPatches), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.ConfigPatches)(nil), (*ConfigPatches)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_ConfigPatches_To_v1alpha1_ConfigPatches(a.(*v1alpha2.ConfigPatches), b.(*ConfigPatches), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*CredentialSource)(nil), (*v1alpha2.CredentialSource)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_CredentialSource_To_v1alpha2_CredentialSource(a.(*CredentialSource), b.(*v1alpha2.CredentialSource), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.CredentialSource)(nil), (*CredentialSource)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_CredentialSource_To_v1alpha1_CredentialSource(a.(*v1alpha2.CredentialSource), b.(*CredentialSource), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*Environment)(nil), (*v1alpha2.Environment)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_Environment_To_v1alpha2_Environment(a.(*Environment), b.(*v1alpha2.Environment), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.Environment)(nil), (*Environment)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_Environment_To_v1alpha1_Environment(a.(*v1alpha2.Environment), b.(*Environment), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*EnvironmentList)(nil), (*v1alpha2.EnvironmentList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_EnvironmentList_To_v1alpha2_EnvironmentList(a.(*EnvironmentList), b.(*v1alpha2.EnvironmentList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.EnvironmentList)(nil), (*EnvironmentList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_EnvironmentList_To_v1alpha1_EnvironmentList(a.(*v1alpha2.EnvironmentList), b.(*EnvironmentList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*EnvironmentSpec)(nil), (*v1alpha2.EnvironmentSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_EnvironmentSpec_To_v1alpha2_EnvironmentSpec(a.(*EnvironmentSpec), b.(*v1alpha2.EnvironmentSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.EnvironmentSpec)(nil), (*EnvironmentSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_EnvironmentSpec_To_v1alpha1_EnvironmentSpec(a.(*v1alpha2.EnvironmentSpec), b.(*EnvironmentSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*EnvironmentStatus)(nil), (*v1alpha2.EnvironmentStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_EnvironmentStatus_To_v1alpha2_EnvironmentStatus(a.(*EnvironmentStatus), b.(*v1alpha2.EnvironmentStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.EnvironmentStatus)(nil), (*EnvironmentStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_EnvironmentStatus_To_v1alpha1_EnvironmentStatus(a.(*v1alpha2.EnvironmentStatus), b.(*EnvironmentStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*Initrd)(nil), (*v1alpha2.Initrd)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_Initrd_To_v1alpha2_Initrd(a.(*Initrd), b.(*v1alpha2.Initrd), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.Initrd)(nil), (*Initrd)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_Initrd_To_v1alpha1_Initrd(a.(*v1alpha2.Initrd), b.(*Initrd), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*Kernel)(nil), (*v1alpha2.Kernel)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_Kernel_To_v1alpha2_Kernel(a.(*Kernel), b.(*v1alpha2.Kernel), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.Kernel)(nil), (*Kernel)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_Kernel_To_v1alpha1_Kernel(a.(*v1alpha2.Kernel), b.(*Kernel), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ManagementAPI)(nil), (*v1alpha2.ManagementAPI)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ManagementAPI_To_v1alpha2_ManagementAPI(a.(*ManagementAPI), b.(*v1alpha2.ManagementAPI), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.ManagementAPI)(nil), (*ManagementAPI)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_ManagementAPI_To_v1alpha1_ManagementAPI(a.(*v1alpha2.ManagementAPI), b.(*ManagementAPI), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*SecretKeyRef)(nil), (*v1alpha2.SecretKeyRef)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_SecretKeyRef_To_v1alpha2_SecretKeyRef(a.(*SecretKeyRef), b.(*v1alpha2.SecretKeyRef), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.SecretKeyRef)(nil), (*SecretKeyRef)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_SecretKeyRef_To_v1alpha1_SecretKeyRef(a.(*v1alpha2.SecretKeyRef), b.(*SecretKeyRef), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*Server)(nil), (*v1alpha2.Server)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_Server_To_v1alpha2_Server(a.(*Server), b.(*v1alpha2.Server), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.Server)(nil), (*Server)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_Server_To_v1alpha1_Server(a.(*v1alpha2.Server), b.(*Server), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ServerClass)(nil), (*v1alpha2.ServerClass)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ServerClass_To_v1alpha2_ServerClass(a.(*ServerClass), b.(*v1alpha2.ServerClass), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.ServerClass)(nil), (*ServerClass)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_ServerClass_To_v1alpha1_ServerClass(a.(*v1alpha2.ServerClass), b.(*ServerClass), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ServerClassList)(nil), (*v1alpha2.ServerClassList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ServerClassList_To_v1alpha2_ServerClassList(a.(*ServerClassList), b.(*v1alpha2.ServerClassList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.ServerClassList)(nil), (*ServerClassList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_ServerClassList_To_v1alpha1_ServerClassList(a.(*v1alpha2.ServerClassList), b.(*ServerClassList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ServerClassSpec)(nil), (*v1alpha2.ServerClassSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ServerClassSpec_To_v1alpha2_ServerClassSpec(a.(*ServerClassSpec), b.(*v1alpha2.ServerClassSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.ServerClassSpec)(nil), (*ServerClassSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_ServerClassSpec_To_v1alpha1_ServerClassSpec(a.(*v1alpha2.ServerClassSpec), b.(*ServerClassSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ServerClassStatus)(nil), (*v1alpha2.ServerClassStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ServerClassStatus_To_v1alpha2_ServerClassStatus(a.(*ServerClassStatus), b.(*v1alpha2.ServerClassStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.ServerClassStatus)(nil), (*ServerClassStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_ServerClassStatus_To_v1alpha1_ServerClassStatus(a.(*v1alpha2.ServerClassStatus), b.(*ServerClassStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ServerList)(nil), (*v1alpha2.ServerList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ServerList_To_v1alpha2_ServerList(a.(*ServerList), b.(*v1alpha2.ServerList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.ServerList)(nil), (*ServerList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_ServerList_To_v1alpha1_ServerList(a.(*v1alpha2.ServerList), b.(*ServerList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ServerStatus)(nil), (*v1alpha2.ServerStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ServerStatus_To_v1alpha2_ServerStatus(a.(*ServerStatus), b.(*v1alpha2.ServerStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha2.ServerStatus)(nil), (*ServerStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_ServerStatus_To_v1alpha1_ServerStatus(a.(*v1alpha2.ServerStatus), b.(*ServerStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*SystemInformation)(nil), (*v1alpha2.SystemInformation)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_SystemInformation_To_v1alpha2_SystemInformation(a.(*SystemInformation), b.(*v1alpha2.SystemInformation), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*Qualifiers)(nil), (*v1alpha2.Qualifiers)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_Qualifiers_To_v1alpha2_Qualifiers(a.(*Qualifiers), b.(*v1alpha2.Qualifiers), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*ServerSpec)(nil), (*v1alpha2.ServerSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ServerSpec_To_v1alpha2_ServerSpec(a.(*ServerSpec), b.(*v1alpha2.ServerSpec), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1alpha2.Qualifiers)(nil), (*Qualifiers)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_Qualifiers_To_v1alpha1_Qualifiers(a.(*v1alpha2.Qualifiers), b.(*Qualifiers), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1alpha2.ServerSpec)(nil), (*ServerSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_ServerSpec_To_v1alpha1_ServerSpec(a.(*v1alpha2.ServerSpec), b.(*ServerSpec), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1alpha2.SystemInformation)(nil), (*SystemInformation)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_SystemInformation_To_v1alpha1_SystemInformation(a.(*v1alpha2.SystemInformation), b.(*SystemInformation), scope) + }); err != nil { + return err + } + return nil +} + +func autoConvert_v1alpha1_Asset_To_v1alpha2_Asset(in *Asset, out *v1alpha2.Asset, s conversion.Scope) error { + out.URL = in.URL + out.SHA512 = in.SHA512 + return nil +} + +// Convert_v1alpha1_Asset_To_v1alpha2_Asset is an autogenerated conversion function. +func Convert_v1alpha1_Asset_To_v1alpha2_Asset(in *Asset, out *v1alpha2.Asset, s conversion.Scope) error { + return autoConvert_v1alpha1_Asset_To_v1alpha2_Asset(in, out, s) +} + +func autoConvert_v1alpha2_Asset_To_v1alpha1_Asset(in *v1alpha2.Asset, out *Asset, s conversion.Scope) error { + out.URL = in.URL + out.SHA512 = in.SHA512 + return nil +} + +// Convert_v1alpha2_Asset_To_v1alpha1_Asset is an autogenerated conversion function. +func Convert_v1alpha2_Asset_To_v1alpha1_Asset(in *v1alpha2.Asset, out *Asset, s conversion.Scope) error { + return autoConvert_v1alpha2_Asset_To_v1alpha1_Asset(in, out, s) +} + +func autoConvert_v1alpha1_AssetCondition_To_v1alpha2_AssetCondition(in *AssetCondition, out *v1alpha2.AssetCondition, s conversion.Scope) error { + if err := Convert_v1alpha1_Asset_To_v1alpha2_Asset(&in.Asset, &out.Asset, s); err != nil { + return err + } + out.Status = in.Status + out.Type = in.Type + return nil +} + +// Convert_v1alpha1_AssetCondition_To_v1alpha2_AssetCondition is an autogenerated conversion function. +func Convert_v1alpha1_AssetCondition_To_v1alpha2_AssetCondition(in *AssetCondition, out *v1alpha2.AssetCondition, s conversion.Scope) error { + return autoConvert_v1alpha1_AssetCondition_To_v1alpha2_AssetCondition(in, out, s) +} + +func autoConvert_v1alpha2_AssetCondition_To_v1alpha1_AssetCondition(in *v1alpha2.AssetCondition, out *AssetCondition, s conversion.Scope) error { + if err := Convert_v1alpha2_Asset_To_v1alpha1_Asset(&in.Asset, &out.Asset, s); err != nil { + return err + } + out.Status = in.Status + out.Type = in.Type + return nil +} + +// Convert_v1alpha2_AssetCondition_To_v1alpha1_AssetCondition is an autogenerated conversion function. +func Convert_v1alpha2_AssetCondition_To_v1alpha1_AssetCondition(in *v1alpha2.AssetCondition, out *AssetCondition, s conversion.Scope) error { + return autoConvert_v1alpha2_AssetCondition_To_v1alpha1_AssetCondition(in, out, s) +} + +func autoConvert_v1alpha1_BMC_To_v1alpha2_BMC(in *BMC, out *v1alpha2.BMC, s conversion.Scope) error { + out.Endpoint = in.Endpoint + out.Port = in.Port + out.User = in.User + out.UserFrom = (*v1alpha2.CredentialSource)(unsafe.Pointer(in.UserFrom)) + out.Pass = in.Pass + out.PassFrom = (*v1alpha2.CredentialSource)(unsafe.Pointer(in.PassFrom)) + out.Interface = in.Interface + return nil +} + +// Convert_v1alpha1_BMC_To_v1alpha2_BMC is an autogenerated conversion function. +func Convert_v1alpha1_BMC_To_v1alpha2_BMC(in *BMC, out *v1alpha2.BMC, s conversion.Scope) error { + return autoConvert_v1alpha1_BMC_To_v1alpha2_BMC(in, out, s) +} + +func autoConvert_v1alpha2_BMC_To_v1alpha1_BMC(in *v1alpha2.BMC, out *BMC, s conversion.Scope) error { + out.Endpoint = in.Endpoint + out.Port = in.Port + out.User = in.User + out.UserFrom = (*CredentialSource)(unsafe.Pointer(in.UserFrom)) + out.Pass = in.Pass + out.PassFrom = (*CredentialSource)(unsafe.Pointer(in.PassFrom)) + out.Interface = in.Interface + return nil +} + +// Convert_v1alpha2_BMC_To_v1alpha1_BMC is an autogenerated conversion function. +func Convert_v1alpha2_BMC_To_v1alpha1_BMC(in *v1alpha2.BMC, out *BMC, s conversion.Scope) error { + return autoConvert_v1alpha2_BMC_To_v1alpha1_BMC(in, out, s) +} + +func autoConvert_v1alpha1_ConfigPatches_To_v1alpha2_ConfigPatches(in *ConfigPatches, out *v1alpha2.ConfigPatches, s conversion.Scope) error { + out.Op = in.Op + out.Path = in.Path + out.Value = in.Value + return nil +} + +// Convert_v1alpha1_ConfigPatches_To_v1alpha2_ConfigPatches is an autogenerated conversion function. +func Convert_v1alpha1_ConfigPatches_To_v1alpha2_ConfigPatches(in *ConfigPatches, out *v1alpha2.ConfigPatches, s conversion.Scope) error { + return autoConvert_v1alpha1_ConfigPatches_To_v1alpha2_ConfigPatches(in, out, s) +} + +func autoConvert_v1alpha2_ConfigPatches_To_v1alpha1_ConfigPatches(in *v1alpha2.ConfigPatches, out *ConfigPatches, s conversion.Scope) error { + out.Op = in.Op + out.Path = in.Path + out.Value = in.Value + return nil +} + +// Convert_v1alpha2_ConfigPatches_To_v1alpha1_ConfigPatches is an autogenerated conversion function. +func Convert_v1alpha2_ConfigPatches_To_v1alpha1_ConfigPatches(in *v1alpha2.ConfigPatches, out *ConfigPatches, s conversion.Scope) error { + return autoConvert_v1alpha2_ConfigPatches_To_v1alpha1_ConfigPatches(in, out, s) +} + +func autoConvert_v1alpha1_CredentialSource_To_v1alpha2_CredentialSource(in *CredentialSource, out *v1alpha2.CredentialSource, s conversion.Scope) error { + out.SecretKeyRef = (*v1alpha2.SecretKeyRef)(unsafe.Pointer(in.SecretKeyRef)) + return nil +} + +// Convert_v1alpha1_CredentialSource_To_v1alpha2_CredentialSource is an autogenerated conversion function. +func Convert_v1alpha1_CredentialSource_To_v1alpha2_CredentialSource(in *CredentialSource, out *v1alpha2.CredentialSource, s conversion.Scope) error { + return autoConvert_v1alpha1_CredentialSource_To_v1alpha2_CredentialSource(in, out, s) +} + +func autoConvert_v1alpha2_CredentialSource_To_v1alpha1_CredentialSource(in *v1alpha2.CredentialSource, out *CredentialSource, s conversion.Scope) error { + out.SecretKeyRef = (*SecretKeyRef)(unsafe.Pointer(in.SecretKeyRef)) + return nil +} + +// Convert_v1alpha2_CredentialSource_To_v1alpha1_CredentialSource is an autogenerated conversion function. +func Convert_v1alpha2_CredentialSource_To_v1alpha1_CredentialSource(in *v1alpha2.CredentialSource, out *CredentialSource, s conversion.Scope) error { + return autoConvert_v1alpha2_CredentialSource_To_v1alpha1_CredentialSource(in, out, s) +} + +func autoConvert_v1alpha1_Environment_To_v1alpha2_Environment(in *Environment, out *v1alpha2.Environment, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha1_EnvironmentSpec_To_v1alpha2_EnvironmentSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1alpha1_EnvironmentStatus_To_v1alpha2_EnvironmentStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha1_Environment_To_v1alpha2_Environment is an autogenerated conversion function. +func Convert_v1alpha1_Environment_To_v1alpha2_Environment(in *Environment, out *v1alpha2.Environment, s conversion.Scope) error { + return autoConvert_v1alpha1_Environment_To_v1alpha2_Environment(in, out, s) +} + +func autoConvert_v1alpha2_Environment_To_v1alpha1_Environment(in *v1alpha2.Environment, out *Environment, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha2_EnvironmentSpec_To_v1alpha1_EnvironmentSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1alpha2_EnvironmentStatus_To_v1alpha1_EnvironmentStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha2_Environment_To_v1alpha1_Environment is an autogenerated conversion function. +func Convert_v1alpha2_Environment_To_v1alpha1_Environment(in *v1alpha2.Environment, out *Environment, s conversion.Scope) error { + return autoConvert_v1alpha2_Environment_To_v1alpha1_Environment(in, out, s) +} + +func autoConvert_v1alpha1_EnvironmentList_To_v1alpha2_EnvironmentList(in *EnvironmentList, out *v1alpha2.EnvironmentList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]v1alpha2.Environment)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_v1alpha1_EnvironmentList_To_v1alpha2_EnvironmentList is an autogenerated conversion function. +func Convert_v1alpha1_EnvironmentList_To_v1alpha2_EnvironmentList(in *EnvironmentList, out *v1alpha2.EnvironmentList, s conversion.Scope) error { + return autoConvert_v1alpha1_EnvironmentList_To_v1alpha2_EnvironmentList(in, out, s) +} + +func autoConvert_v1alpha2_EnvironmentList_To_v1alpha1_EnvironmentList(in *v1alpha2.EnvironmentList, out *EnvironmentList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]Environment)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_v1alpha2_EnvironmentList_To_v1alpha1_EnvironmentList is an autogenerated conversion function. +func Convert_v1alpha2_EnvironmentList_To_v1alpha1_EnvironmentList(in *v1alpha2.EnvironmentList, out *EnvironmentList, s conversion.Scope) error { + return autoConvert_v1alpha2_EnvironmentList_To_v1alpha1_EnvironmentList(in, out, s) +} + +func autoConvert_v1alpha1_EnvironmentSpec_To_v1alpha2_EnvironmentSpec(in *EnvironmentSpec, out *v1alpha2.EnvironmentSpec, s conversion.Scope) error { + if err := Convert_v1alpha1_Kernel_To_v1alpha2_Kernel(&in.Kernel, &out.Kernel, s); err != nil { + return err + } + if err := Convert_v1alpha1_Initrd_To_v1alpha2_Initrd(&in.Initrd, &out.Initrd, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha1_EnvironmentSpec_To_v1alpha2_EnvironmentSpec is an autogenerated conversion function. +func Convert_v1alpha1_EnvironmentSpec_To_v1alpha2_EnvironmentSpec(in *EnvironmentSpec, out *v1alpha2.EnvironmentSpec, s conversion.Scope) error { + return autoConvert_v1alpha1_EnvironmentSpec_To_v1alpha2_EnvironmentSpec(in, out, s) +} + +func autoConvert_v1alpha2_EnvironmentSpec_To_v1alpha1_EnvironmentSpec(in *v1alpha2.EnvironmentSpec, out *EnvironmentSpec, s conversion.Scope) error { + if err := Convert_v1alpha2_Kernel_To_v1alpha1_Kernel(&in.Kernel, &out.Kernel, s); err != nil { + return err + } + if err := Convert_v1alpha2_Initrd_To_v1alpha1_Initrd(&in.Initrd, &out.Initrd, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha2_EnvironmentSpec_To_v1alpha1_EnvironmentSpec is an autogenerated conversion function. +func Convert_v1alpha2_EnvironmentSpec_To_v1alpha1_EnvironmentSpec(in *v1alpha2.EnvironmentSpec, out *EnvironmentSpec, s conversion.Scope) error { + return autoConvert_v1alpha2_EnvironmentSpec_To_v1alpha1_EnvironmentSpec(in, out, s) +} + +func autoConvert_v1alpha1_EnvironmentStatus_To_v1alpha2_EnvironmentStatus(in *EnvironmentStatus, out *v1alpha2.EnvironmentStatus, s conversion.Scope) error { + out.Conditions = *(*[]v1alpha2.AssetCondition)(unsafe.Pointer(&in.Conditions)) + return nil +} + +// Convert_v1alpha1_EnvironmentStatus_To_v1alpha2_EnvironmentStatus is an autogenerated conversion function. +func Convert_v1alpha1_EnvironmentStatus_To_v1alpha2_EnvironmentStatus(in *EnvironmentStatus, out *v1alpha2.EnvironmentStatus, s conversion.Scope) error { + return autoConvert_v1alpha1_EnvironmentStatus_To_v1alpha2_EnvironmentStatus(in, out, s) +} + +func autoConvert_v1alpha2_EnvironmentStatus_To_v1alpha1_EnvironmentStatus(in *v1alpha2.EnvironmentStatus, out *EnvironmentStatus, s conversion.Scope) error { + out.Conditions = *(*[]AssetCondition)(unsafe.Pointer(&in.Conditions)) + return nil +} + +// Convert_v1alpha2_EnvironmentStatus_To_v1alpha1_EnvironmentStatus is an autogenerated conversion function. +func Convert_v1alpha2_EnvironmentStatus_To_v1alpha1_EnvironmentStatus(in *v1alpha2.EnvironmentStatus, out *EnvironmentStatus, s conversion.Scope) error { + return autoConvert_v1alpha2_EnvironmentStatus_To_v1alpha1_EnvironmentStatus(in, out, s) +} + +func autoConvert_v1alpha1_Initrd_To_v1alpha2_Initrd(in *Initrd, out *v1alpha2.Initrd, s conversion.Scope) error { + if err := Convert_v1alpha1_Asset_To_v1alpha2_Asset(&in.Asset, &out.Asset, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha1_Initrd_To_v1alpha2_Initrd is an autogenerated conversion function. +func Convert_v1alpha1_Initrd_To_v1alpha2_Initrd(in *Initrd, out *v1alpha2.Initrd, s conversion.Scope) error { + return autoConvert_v1alpha1_Initrd_To_v1alpha2_Initrd(in, out, s) +} + +func autoConvert_v1alpha2_Initrd_To_v1alpha1_Initrd(in *v1alpha2.Initrd, out *Initrd, s conversion.Scope) error { + if err := Convert_v1alpha2_Asset_To_v1alpha1_Asset(&in.Asset, &out.Asset, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha2_Initrd_To_v1alpha1_Initrd is an autogenerated conversion function. +func Convert_v1alpha2_Initrd_To_v1alpha1_Initrd(in *v1alpha2.Initrd, out *Initrd, s conversion.Scope) error { + return autoConvert_v1alpha2_Initrd_To_v1alpha1_Initrd(in, out, s) +} + +func autoConvert_v1alpha1_Kernel_To_v1alpha2_Kernel(in *Kernel, out *v1alpha2.Kernel, s conversion.Scope) error { + if err := Convert_v1alpha1_Asset_To_v1alpha2_Asset(&in.Asset, &out.Asset, s); err != nil { + return err + } + out.Args = *(*[]string)(unsafe.Pointer(&in.Args)) + return nil +} + +// Convert_v1alpha1_Kernel_To_v1alpha2_Kernel is an autogenerated conversion function. +func Convert_v1alpha1_Kernel_To_v1alpha2_Kernel(in *Kernel, out *v1alpha2.Kernel, s conversion.Scope) error { + return autoConvert_v1alpha1_Kernel_To_v1alpha2_Kernel(in, out, s) +} + +func autoConvert_v1alpha2_Kernel_To_v1alpha1_Kernel(in *v1alpha2.Kernel, out *Kernel, s conversion.Scope) error { + if err := Convert_v1alpha2_Asset_To_v1alpha1_Asset(&in.Asset, &out.Asset, s); err != nil { + return err + } + out.Args = *(*[]string)(unsafe.Pointer(&in.Args)) + return nil +} + +// Convert_v1alpha2_Kernel_To_v1alpha1_Kernel is an autogenerated conversion function. +func Convert_v1alpha2_Kernel_To_v1alpha1_Kernel(in *v1alpha2.Kernel, out *Kernel, s conversion.Scope) error { + return autoConvert_v1alpha2_Kernel_To_v1alpha1_Kernel(in, out, s) +} + +func autoConvert_v1alpha1_ManagementAPI_To_v1alpha2_ManagementAPI(in *ManagementAPI, out *v1alpha2.ManagementAPI, s conversion.Scope) error { + out.Endpoint = in.Endpoint + return nil +} + +// Convert_v1alpha1_ManagementAPI_To_v1alpha2_ManagementAPI is an autogenerated conversion function. +func Convert_v1alpha1_ManagementAPI_To_v1alpha2_ManagementAPI(in *ManagementAPI, out *v1alpha2.ManagementAPI, s conversion.Scope) error { + return autoConvert_v1alpha1_ManagementAPI_To_v1alpha2_ManagementAPI(in, out, s) +} + +func autoConvert_v1alpha2_ManagementAPI_To_v1alpha1_ManagementAPI(in *v1alpha2.ManagementAPI, out *ManagementAPI, s conversion.Scope) error { + out.Endpoint = in.Endpoint + return nil +} + +// Convert_v1alpha2_ManagementAPI_To_v1alpha1_ManagementAPI is an autogenerated conversion function. +func Convert_v1alpha2_ManagementAPI_To_v1alpha1_ManagementAPI(in *v1alpha2.ManagementAPI, out *ManagementAPI, s conversion.Scope) error { + return autoConvert_v1alpha2_ManagementAPI_To_v1alpha1_ManagementAPI(in, out, s) +} + +func autoConvert_v1alpha1_Qualifiers_To_v1alpha2_Qualifiers(in *Qualifiers, out *v1alpha2.Qualifiers, s conversion.Scope) error { + // WARNING: in.CPU requires manual conversion: does not exist in peer-type + // WARNING: in.SystemInformation requires manual conversion: does not exist in peer-type + out.LabelSelectors = *(*[]map[string]string)(unsafe.Pointer(&in.LabelSelectors)) + return nil +} + +func autoConvert_v1alpha2_Qualifiers_To_v1alpha1_Qualifiers(in *v1alpha2.Qualifiers, out *Qualifiers, s conversion.Scope) error { + // WARNING: in.Hardware requires manual conversion: does not exist in peer-type + out.LabelSelectors = *(*[]map[string]string)(unsafe.Pointer(&in.LabelSelectors)) + return nil +} + +func autoConvert_v1alpha1_SecretKeyRef_To_v1alpha2_SecretKeyRef(in *SecretKeyRef, out *v1alpha2.SecretKeyRef, s conversion.Scope) error { + out.Namespace = in.Namespace + out.Name = in.Name + out.Key = in.Key + return nil +} + +// Convert_v1alpha1_SecretKeyRef_To_v1alpha2_SecretKeyRef is an autogenerated conversion function. +func Convert_v1alpha1_SecretKeyRef_To_v1alpha2_SecretKeyRef(in *SecretKeyRef, out *v1alpha2.SecretKeyRef, s conversion.Scope) error { + return autoConvert_v1alpha1_SecretKeyRef_To_v1alpha2_SecretKeyRef(in, out, s) +} + +func autoConvert_v1alpha2_SecretKeyRef_To_v1alpha1_SecretKeyRef(in *v1alpha2.SecretKeyRef, out *SecretKeyRef, s conversion.Scope) error { + out.Namespace = in.Namespace + out.Name = in.Name + out.Key = in.Key + return nil +} + +// Convert_v1alpha2_SecretKeyRef_To_v1alpha1_SecretKeyRef is an autogenerated conversion function. +func Convert_v1alpha2_SecretKeyRef_To_v1alpha1_SecretKeyRef(in *v1alpha2.SecretKeyRef, out *SecretKeyRef, s conversion.Scope) error { + return autoConvert_v1alpha2_SecretKeyRef_To_v1alpha1_SecretKeyRef(in, out, s) +} + +func autoConvert_v1alpha1_Server_To_v1alpha2_Server(in *Server, out *v1alpha2.Server, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha1_ServerSpec_To_v1alpha2_ServerSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1alpha1_ServerStatus_To_v1alpha2_ServerStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha1_Server_To_v1alpha2_Server is an autogenerated conversion function. +func Convert_v1alpha1_Server_To_v1alpha2_Server(in *Server, out *v1alpha2.Server, s conversion.Scope) error { + return autoConvert_v1alpha1_Server_To_v1alpha2_Server(in, out, s) +} + +func autoConvert_v1alpha2_Server_To_v1alpha1_Server(in *v1alpha2.Server, out *Server, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha2_ServerSpec_To_v1alpha1_ServerSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1alpha2_ServerStatus_To_v1alpha1_ServerStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha2_Server_To_v1alpha1_Server is an autogenerated conversion function. +func Convert_v1alpha2_Server_To_v1alpha1_Server(in *v1alpha2.Server, out *Server, s conversion.Scope) error { + return autoConvert_v1alpha2_Server_To_v1alpha1_Server(in, out, s) +} + +func autoConvert_v1alpha1_ServerClass_To_v1alpha2_ServerClass(in *ServerClass, out *v1alpha2.ServerClass, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha1_ServerClassSpec_To_v1alpha2_ServerClassSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1alpha1_ServerClassStatus_To_v1alpha2_ServerClassStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha1_ServerClass_To_v1alpha2_ServerClass is an autogenerated conversion function. +func Convert_v1alpha1_ServerClass_To_v1alpha2_ServerClass(in *ServerClass, out *v1alpha2.ServerClass, s conversion.Scope) error { + return autoConvert_v1alpha1_ServerClass_To_v1alpha2_ServerClass(in, out, s) +} + +func autoConvert_v1alpha2_ServerClass_To_v1alpha1_ServerClass(in *v1alpha2.ServerClass, out *ServerClass, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha2_ServerClassSpec_To_v1alpha1_ServerClassSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1alpha2_ServerClassStatus_To_v1alpha1_ServerClassStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha2_ServerClass_To_v1alpha1_ServerClass is an autogenerated conversion function. +func Convert_v1alpha2_ServerClass_To_v1alpha1_ServerClass(in *v1alpha2.ServerClass, out *ServerClass, s conversion.Scope) error { + return autoConvert_v1alpha2_ServerClass_To_v1alpha1_ServerClass(in, out, s) +} + +func autoConvert_v1alpha1_ServerClassList_To_v1alpha2_ServerClassList(in *ServerClassList, out *v1alpha2.ServerClassList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]v1alpha2.ServerClass, len(*in)) + for i := range *in { + if err := Convert_v1alpha1_ServerClass_To_v1alpha2_ServerClass(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } + return nil +} + +// Convert_v1alpha1_ServerClassList_To_v1alpha2_ServerClassList is an autogenerated conversion function. +func Convert_v1alpha1_ServerClassList_To_v1alpha2_ServerClassList(in *ServerClassList, out *v1alpha2.ServerClassList, s conversion.Scope) error { + return autoConvert_v1alpha1_ServerClassList_To_v1alpha2_ServerClassList(in, out, s) +} + +func autoConvert_v1alpha2_ServerClassList_To_v1alpha1_ServerClassList(in *v1alpha2.ServerClassList, out *ServerClassList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ServerClass, len(*in)) + for i := range *in { + if err := Convert_v1alpha2_ServerClass_To_v1alpha1_ServerClass(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } + return nil +} + +// Convert_v1alpha2_ServerClassList_To_v1alpha1_ServerClassList is an autogenerated conversion function. +func Convert_v1alpha2_ServerClassList_To_v1alpha1_ServerClassList(in *v1alpha2.ServerClassList, out *ServerClassList, s conversion.Scope) error { + return autoConvert_v1alpha2_ServerClassList_To_v1alpha1_ServerClassList(in, out, s) +} + +func autoConvert_v1alpha1_ServerClassSpec_To_v1alpha2_ServerClassSpec(in *ServerClassSpec, out *v1alpha2.ServerClassSpec, s conversion.Scope) error { + out.EnvironmentRef = (*v1.ObjectReference)(unsafe.Pointer(in.EnvironmentRef)) + if err := Convert_v1alpha1_Qualifiers_To_v1alpha2_Qualifiers(&in.Qualifiers, &out.Qualifiers, s); err != nil { + return err + } + out.Selector = in.Selector + out.ConfigPatches = *(*[]v1alpha2.ConfigPatches)(unsafe.Pointer(&in.ConfigPatches)) + out.BootFromDiskMethod = types.BootFromDisk(in.BootFromDiskMethod) + return nil +} + +// Convert_v1alpha1_ServerClassSpec_To_v1alpha2_ServerClassSpec is an autogenerated conversion function. +func Convert_v1alpha1_ServerClassSpec_To_v1alpha2_ServerClassSpec(in *ServerClassSpec, out *v1alpha2.ServerClassSpec, s conversion.Scope) error { + return autoConvert_v1alpha1_ServerClassSpec_To_v1alpha2_ServerClassSpec(in, out, s) +} + +func autoConvert_v1alpha2_ServerClassSpec_To_v1alpha1_ServerClassSpec(in *v1alpha2.ServerClassSpec, out *ServerClassSpec, s conversion.Scope) error { + out.EnvironmentRef = (*v1.ObjectReference)(unsafe.Pointer(in.EnvironmentRef)) + if err := Convert_v1alpha2_Qualifiers_To_v1alpha1_Qualifiers(&in.Qualifiers, &out.Qualifiers, s); err != nil { + return err + } + out.Selector = in.Selector + out.ConfigPatches = *(*[]ConfigPatches)(unsafe.Pointer(&in.ConfigPatches)) + out.BootFromDiskMethod = types.BootFromDisk(in.BootFromDiskMethod) + return nil +} + +// Convert_v1alpha2_ServerClassSpec_To_v1alpha1_ServerClassSpec is an autogenerated conversion function. +func Convert_v1alpha2_ServerClassSpec_To_v1alpha1_ServerClassSpec(in *v1alpha2.ServerClassSpec, out *ServerClassSpec, s conversion.Scope) error { + return autoConvert_v1alpha2_ServerClassSpec_To_v1alpha1_ServerClassSpec(in, out, s) +} + +func autoConvert_v1alpha1_ServerClassStatus_To_v1alpha2_ServerClassStatus(in *ServerClassStatus, out *v1alpha2.ServerClassStatus, s conversion.Scope) error { + out.ServersAvailable = *(*[]string)(unsafe.Pointer(&in.ServersAvailable)) + out.ServersInUse = *(*[]string)(unsafe.Pointer(&in.ServersInUse)) + return nil +} + +// Convert_v1alpha1_ServerClassStatus_To_v1alpha2_ServerClassStatus is an autogenerated conversion function. +func Convert_v1alpha1_ServerClassStatus_To_v1alpha2_ServerClassStatus(in *ServerClassStatus, out *v1alpha2.ServerClassStatus, s conversion.Scope) error { + return autoConvert_v1alpha1_ServerClassStatus_To_v1alpha2_ServerClassStatus(in, out, s) +} + +func autoConvert_v1alpha2_ServerClassStatus_To_v1alpha1_ServerClassStatus(in *v1alpha2.ServerClassStatus, out *ServerClassStatus, s conversion.Scope) error { + out.ServersAvailable = *(*[]string)(unsafe.Pointer(&in.ServersAvailable)) + out.ServersInUse = *(*[]string)(unsafe.Pointer(&in.ServersInUse)) + return nil +} + +// Convert_v1alpha2_ServerClassStatus_To_v1alpha1_ServerClassStatus is an autogenerated conversion function. +func Convert_v1alpha2_ServerClassStatus_To_v1alpha1_ServerClassStatus(in *v1alpha2.ServerClassStatus, out *ServerClassStatus, s conversion.Scope) error { + return autoConvert_v1alpha2_ServerClassStatus_To_v1alpha1_ServerClassStatus(in, out, s) +} + +func autoConvert_v1alpha1_ServerList_To_v1alpha2_ServerList(in *ServerList, out *v1alpha2.ServerList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]v1alpha2.Server, len(*in)) + for i := range *in { + if err := Convert_v1alpha1_Server_To_v1alpha2_Server(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } + return nil +} + +// Convert_v1alpha1_ServerList_To_v1alpha2_ServerList is an autogenerated conversion function. +func Convert_v1alpha1_ServerList_To_v1alpha2_ServerList(in *ServerList, out *v1alpha2.ServerList, s conversion.Scope) error { + return autoConvert_v1alpha1_ServerList_To_v1alpha2_ServerList(in, out, s) +} + +func autoConvert_v1alpha2_ServerList_To_v1alpha1_ServerList(in *v1alpha2.ServerList, out *ServerList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Server, len(*in)) + for i := range *in { + if err := Convert_v1alpha2_Server_To_v1alpha1_Server(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } + return nil +} + +// Convert_v1alpha2_ServerList_To_v1alpha1_ServerList is an autogenerated conversion function. +func Convert_v1alpha2_ServerList_To_v1alpha1_ServerList(in *v1alpha2.ServerList, out *ServerList, s conversion.Scope) error { + return autoConvert_v1alpha2_ServerList_To_v1alpha1_ServerList(in, out, s) +} + +func autoConvert_v1alpha1_ServerSpec_To_v1alpha2_ServerSpec(in *ServerSpec, out *v1alpha2.ServerSpec, s conversion.Scope) error { + out.EnvironmentRef = (*v1.ObjectReference)(unsafe.Pointer(in.EnvironmentRef)) + out.Hostname = in.Hostname + // WARNING: in.SystemInformation requires manual conversion: does not exist in peer-type + // WARNING: in.CPU requires manual conversion: does not exist in peer-type + out.BMC = (*v1alpha2.BMC)(unsafe.Pointer(in.BMC)) + out.ManagementAPI = (*v1alpha2.ManagementAPI)(unsafe.Pointer(in.ManagementAPI)) + out.ConfigPatches = *(*[]v1alpha2.ConfigPatches)(unsafe.Pointer(&in.ConfigPatches)) + out.Accepted = in.Accepted + out.Cordoned = in.Cordoned + out.PXEBootAlways = in.PXEBootAlways + out.BootFromDiskMethod = types.BootFromDisk(in.BootFromDiskMethod) + return nil +} + +func autoConvert_v1alpha2_ServerSpec_To_v1alpha1_ServerSpec(in *v1alpha2.ServerSpec, out *ServerSpec, s conversion.Scope) error { + out.EnvironmentRef = (*v1.ObjectReference)(unsafe.Pointer(in.EnvironmentRef)) + // WARNING: in.Hardware requires manual conversion: does not exist in peer-type + out.Hostname = in.Hostname + out.BMC = (*BMC)(unsafe.Pointer(in.BMC)) + out.ManagementAPI = (*ManagementAPI)(unsafe.Pointer(in.ManagementAPI)) + out.ConfigPatches = *(*[]ConfigPatches)(unsafe.Pointer(&in.ConfigPatches)) + out.Accepted = in.Accepted + out.Cordoned = in.Cordoned + out.PXEBootAlways = in.PXEBootAlways + out.BootFromDiskMethod = types.BootFromDisk(in.BootFromDiskMethod) + return nil +} + +func autoConvert_v1alpha1_ServerStatus_To_v1alpha2_ServerStatus(in *ServerStatus, out *v1alpha2.ServerStatus, s conversion.Scope) error { + out.Ready = in.Ready + out.InUse = in.InUse + out.IsClean = in.IsClean + out.Conditions = *(*[]v1beta1.Condition)(unsafe.Pointer(&in.Conditions)) + out.Addresses = *(*[]v1.NodeAddress)(unsafe.Pointer(&in.Addresses)) + out.Power = in.Power + return nil +} + +// Convert_v1alpha1_ServerStatus_To_v1alpha2_ServerStatus is an autogenerated conversion function. +func Convert_v1alpha1_ServerStatus_To_v1alpha2_ServerStatus(in *ServerStatus, out *v1alpha2.ServerStatus, s conversion.Scope) error { + return autoConvert_v1alpha1_ServerStatus_To_v1alpha2_ServerStatus(in, out, s) +} + +func autoConvert_v1alpha2_ServerStatus_To_v1alpha1_ServerStatus(in *v1alpha2.ServerStatus, out *ServerStatus, s conversion.Scope) error { + out.Ready = in.Ready + out.InUse = in.InUse + out.IsClean = in.IsClean + out.Conditions = *(*[]v1beta1.Condition)(unsafe.Pointer(&in.Conditions)) + out.Addresses = *(*[]v1.NodeAddress)(unsafe.Pointer(&in.Addresses)) + out.Power = in.Power + return nil +} + +// Convert_v1alpha2_ServerStatus_To_v1alpha1_ServerStatus is an autogenerated conversion function. +func Convert_v1alpha2_ServerStatus_To_v1alpha1_ServerStatus(in *v1alpha2.ServerStatus, out *ServerStatus, s conversion.Scope) error { + return autoConvert_v1alpha2_ServerStatus_To_v1alpha1_ServerStatus(in, out, s) +} + +func autoConvert_v1alpha1_SystemInformation_To_v1alpha2_SystemInformation(in *SystemInformation, out *v1alpha2.SystemInformation, s conversion.Scope) error { + out.Manufacturer = in.Manufacturer + out.ProductName = in.ProductName + out.Version = in.Version + out.SerialNumber = in.SerialNumber + out.SKUNumber = in.SKUNumber + out.Family = in.Family + return nil +} + +// Convert_v1alpha1_SystemInformation_To_v1alpha2_SystemInformation is an autogenerated conversion function. +func Convert_v1alpha1_SystemInformation_To_v1alpha2_SystemInformation(in *SystemInformation, out *v1alpha2.SystemInformation, s conversion.Scope) error { + return autoConvert_v1alpha1_SystemInformation_To_v1alpha2_SystemInformation(in, out, s) +} + +func autoConvert_v1alpha2_SystemInformation_To_v1alpha1_SystemInformation(in *v1alpha2.SystemInformation, out *SystemInformation, s conversion.Scope) error { + // WARNING: in.Uuid requires manual conversion: does not exist in peer-type + out.Manufacturer = in.Manufacturer + out.ProductName = in.ProductName + out.Version = in.Version + out.SerialNumber = in.SerialNumber + out.SKUNumber = in.SKUNumber + out.Family = in.Family + return nil +} diff --git a/app/sidero-controller-manager/api/v1alpha2/doc.go b/app/sidero-controller-manager/api/v1alpha2/doc.go new file mode 100644 index 000000000..fd95a0726 --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha2/doc.go @@ -0,0 +1,5 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package v1alpha2 diff --git a/app/sidero-controller-manager/api/v1alpha2/environment_conversion.go b/app/sidero-controller-manager/api/v1alpha2/environment_conversion.go new file mode 100644 index 000000000..cd8e4ebf9 --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha2/environment_conversion.go @@ -0,0 +1,8 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package v1alpha2 + +func (*Environment) Hub() {} +func (*EnvironmentList) Hub() {} diff --git a/app/sidero-controller-manager/api/v1alpha2/environment_types.go b/app/sidero-controller-manager/api/v1alpha2/environment_types.go new file mode 100644 index 000000000..0e92621df --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha2/environment_types.go @@ -0,0 +1,123 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package v1alpha2 + +import ( + "fmt" + "sort" + + "github.com/talos-systems/talos/pkg/machinery/kernel" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// EnvironmentDefault is an automatically created Environment. +const EnvironmentDefault = "default" + +type Asset struct { + URL string `json:"url,omitempty"` + SHA512 string `json:"sha512,omitempty"` +} + +type Kernel struct { + Asset `json:",inline"` + + Args []string `json:"args,omitempty"` +} + +type Initrd struct { + Asset `json:",inline"` +} + +// EnvironmentSpec defines the desired state of Environment. +type EnvironmentSpec struct { + Kernel Kernel `json:"kernel,omitempty"` + Initrd Initrd `json:"initrd,omitempty"` +} + +type AssetCondition struct { + Asset `json:",inline"` + Status string `json:"status"` + Type string `json:"type"` +} + +// EnvironmentStatus defines the observed state of Environment. +type EnvironmentStatus struct { + Conditions []AssetCondition `json:"conditions,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:resource:scope=Cluster +// +kubebuilder:printcolumn:name="Kernel",type="string",JSONPath=".spec.kernel.url",description="the kernel for the environment" +// +kubebuilder:printcolumn:name="Initrd",type="string",JSONPath=".spec.initrd.url",description="the initrd for the environment" +// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status",description="indicates the readiness of the environment" +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="The age of this resource" +// +kubebuilder:storageversion + +// Environment is the Schema for the environments API. +type Environment struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec EnvironmentSpec `json:"spec,omitempty"` + Status EnvironmentStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// EnvironmentList contains a list of Environment. +type EnvironmentList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Environment `json:"items"` +} + +// EnvironmentDefaultSpec returns EnvironmentDefault's spec. +func EnvironmentDefaultSpec(talosRelease, apiEndpoint string, apiPort uint16) *EnvironmentSpec { + args := make([]string, 0, len(kernel.DefaultArgs)+6) + args = append(args, kernel.DefaultArgs...) + args = append(args, "console=tty0", "console=ttyS0", "earlyprintk=ttyS0") + args = append(args, "initrd=initramfs.xz", "talos.platform=metal") + sort.Strings(args) + + return &EnvironmentSpec{ + Kernel: Kernel{ + Asset: Asset{ + URL: fmt.Sprintf("https://github.com/talos-systems/talos/releases/download/%s/vmlinuz-amd64", talosRelease), + }, + Args: args, + }, + Initrd: Initrd{ + Asset: Asset{ + URL: fmt.Sprintf("https://github.com/talos-systems/talos/releases/download/%s/initramfs-amd64.xz", talosRelease), + }, + }, + } +} + +// IsReady returns aggregated Environment readiness. +func (env *Environment) IsReady() bool { + assetURLs := map[string]struct{}{} + + if env.Spec.Kernel.URL != "" { + assetURLs[env.Spec.Kernel.URL] = struct{}{} + } + + if env.Spec.Initrd.URL != "" { + assetURLs[env.Spec.Initrd.URL] = struct{}{} + } + + for _, cond := range env.Status.Conditions { + if cond.Status == "True" && cond.Type == "Ready" { + delete(assetURLs, cond.URL) + } + } + + return len(assetURLs) == 0 +} + +func init() { + SchemeBuilder.Register(&Environment{}, &EnvironmentList{}) +} diff --git a/app/sidero-controller-manager/api/v1alpha2/environment_webhook.go b/app/sidero-controller-manager/api/v1alpha2/environment_webhook.go new file mode 100644 index 000000000..1b0ccf6f2 --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha2/environment_webhook.go @@ -0,0 +1,21 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package v1alpha2 + +import ( + ctrl "sigs.k8s.io/controller-runtime" +) + +func (r *Environment) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} + +func (r *EnvironmentList) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} diff --git a/app/sidero-controller-manager/api/v1alpha2/groupversion_info.go b/app/sidero-controller-manager/api/v1alpha2/groupversion_info.go new file mode 100644 index 000000000..35a2bc3bc --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha2/groupversion_info.go @@ -0,0 +1,24 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +// package v1alpha2 contains API Schema definitions for the metal v1alpha2 API group +// +kubebuilder:object:generate=true +// +groupName=metal.sidero.dev +package v1alpha2 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects. + GroupVersion = schema.GroupVersion{Group: "metal.sidero.dev", Version: "v1alpha2"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme. + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) diff --git a/app/sidero-controller-manager/api/v1alpha2/server_conversion.go b/app/sidero-controller-manager/api/v1alpha2/server_conversion.go new file mode 100644 index 000000000..f32f528a2 --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha2/server_conversion.go @@ -0,0 +1,8 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package v1alpha2 + +func (*Server) Hub() {} +func (*ServerList) Hub() {} diff --git a/app/sidero-controller-manager/api/v1alpha2/server_types.go b/app/sidero-controller-manager/api/v1alpha2/server_types.go new file mode 100644 index 000000000..e3d1e5e55 --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha2/server_types.go @@ -0,0 +1,328 @@ +// 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 + } + + if 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 + } + } + } else if 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 + } + } + } else { + // Directly compare values, but only if the actual value is valid. + return new.IsValid() && old.Interface() == new.Interface() + } + + return true +} + +// ServerSpec defines the desired state of Server. +type ServerSpec struct { + EnvironmentRef *corev1.ObjectReference `json:"environmentRef,omitempty"` + Hardware *HardwareInformation `json:"hardware,omitempty"` + Hostname string `json:"hostname,omitempty"` + BMC *BMC `json:"bmc,omitempty"` + ManagementAPI *ManagementAPI `json:"managementApi,omitempty"` + ConfigPatches []ConfigPatches `json:"configPatches,omitempty"` + Accepted bool `json:"accepted"` + Cordoned bool `json:"cordoned,omitempty"` + PXEBootAlways bool `json:"pxeBootAlways,omitempty"` + // BootFromDiskMethod specifies the method to exit iPXE to force boot from disk. + // + // If not set, controller default is used. + // Valid values: ipxe-exit, http-404, ipxe-sanboot. + // + // +optional + BootFromDiskMethod siderotypes.BootFromDisk `json:"bootFromDiskMethod,omitempty"` +} + +const ( + // ConditionPowerCycle is used to control the powercycle flow. + ConditionPowerCycle clusterv1.ConditionType = "PowerCycle" + // ConditionPXEBooted is used to record the fact that server got PXE booted. + ConditionPXEBooted clusterv1.ConditionType = "PXEBooted" +) + +// ServerStatus defines the observed state of Server. +type ServerStatus struct { + // Ready is true when server is accepted and in use. + // +optional + Ready bool `json:"ready"` + + // InUse is true when server is assigned to some MetalMachine. + // +optional + InUse bool `json:"inUse"` + + // IsClean is true when server disks are wiped. + // +optional + IsClean bool `json:"isClean"` + + // Conditions defines current service state of the Server. + Conditions []clusterv1.Condition `json:"conditions,omitempty"` + + // Addresses lists discovered node IPs. + Addresses []corev1.NodeAddress `json:"addresses,omitempty"` + + // Power is the current power state of the server: "on", "off" or "unknown". + Power string `json:"power,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:resource:scope=Cluster +// +kubebuilder:printcolumn:name="Hostname",type="string",JSONPath=".spec.hostname",description="server hostname" +// +kubebuilder:printcolumn:name="BMC IP",type="string",priority=1,JSONPath=".spec.bmc.endpoint",description="BMC IP" +// +kubebuilder:printcolumn:name="Accepted",type="boolean",JSONPath=".spec.accepted",description="indicates if the server is accepted" +// +kubebuilder:printcolumn:name="Cordoned",type="boolean",JSONPath=".spec.cordoned",description="indicates if the server is cordoned" +// +kubebuilder:printcolumn:name="Allocated",type="boolean",JSONPath=".status.inUse",description="indicates that the server has been allocated" +// +kubebuilder:printcolumn:name="Clean",type="boolean",JSONPath=".status.isClean",description="indicates if the server is clean or not" +// +kubebuilder:printcolumn:name="Power",type="string",JSONPath=".status.power",description="display the current power status" +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="The age of this resource" +// +kubebuilder:storageversion + +// Server is the Schema for the servers API. +type Server struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec ServerSpec `json:"spec,omitempty"` + Status ServerStatus `json:"status,omitempty"` +} + +func (s *Server) GetConditions() clusterv1.Conditions { + return s.Status.Conditions +} + +func (s *Server) SetConditions(conditions clusterv1.Conditions) { + s.Status.Conditions = conditions +} + +// +kubebuilder:object:root=true + +// ServerList contains a list of Server. +type ServerList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Server `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Server{}, &ServerList{}) +} diff --git a/app/sidero-controller-manager/api/v1alpha2/server_types_test.go b/app/sidero-controller-manager/api/v1alpha2/server_types_test.go new file mode 100644 index 000000000..92d0fe9c8 --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha2/server_types_test.go @@ -0,0 +1,147 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +//nolint:scopelint +package v1alpha2_test + +import ( + "testing" + + metal "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" +) + +func Test_PartialEqual(t *testing.T) { + info := &metal.HardwareInformation{ + System: &metal.SystemInformation{ + Uuid: "4c4c4544-0039-3010-8048-b7c04f384432", + Manufacturer: "Dell Inc.", + ProductName: "PowerEdge R630", + SerialNumber: "790H8D2", + SKUNumber: "", + Family: "", + }, + Compute: &metal.ComputeInformation{ + TotalCoreCount: 8, + TotalThreadCount: 16, + ProcessorCount: 1, + Processors: []*metal.Processor{ + { + Manufacturer: "Intel", + ProductName: "Intel(R) Xeon(R) CPU E5-2630 v3 @ 2.40GHz", + SerialNumber: "", + Speed: 2400, + CoreCount: 8, + ThreadCount: 16, + }, + }, + }, + Memory: &metal.MemoryInformation{ + TotalSize: "32 GB", + ModuleCount: 2, + Modules: []*metal.MemoryModule{ + { + Manufacturer: "002C00B3002C", + ProductName: "18ASF2G72PDZ-2G3B1", + SerialNumber: "12BDC045", + Type: "LPDDR3", + Size: 16384, + Speed: 2400, + }, + { + Manufacturer: "002C00B3002C", + ProductName: "18ASF2G72PDZ-2G3B1", + SerialNumber: "12BDBF5D", + Type: "LPDDR3", + Size: 16384, + Speed: 2400, + }, + }, + }, + Storage: &metal.StorageInformation{ + TotalSize: "1116 GB", + DeviceCount: 1, + Devices: []*metal.StorageDevice{ + { + Type: "HDD", + Size: 1199101181952, + Model: "PERC H730 Mini", + Serial: "", + Name: "sda", + DeviceName: "/dev/sda", + UUID: "", + WWID: "naa.61866da055de070028d8e83307cc6df2", + }, + }, + }, + Network: &metal.NetworkInformation{ + InterfaceCount: 2, + Interfaces: []*metal.NetworkInterface{ + { + Index: 1, + Name: "lo", + Flags: "up|loopback", + MTU: 65536, + MAC: "", + Addresses: []string{"127.0.0.1/8", "::1/128"}, + }, + { + Index: 2, + Name: "enp3s0", + Flags: "up|broadcast|multicast", + MTU: 1500, + MAC: "40:8d:5c:86:5a:14", + Addresses: []string{"192.168.2.8/24", "fe80::dcb3:295c:755b:91bb/64"}, + }, + }, + }, + } + + tests := []struct { + name string + args *metal.HardwareInformation + want bool + }{ + { + name: "defaults are partially equal", + args: &metal.HardwareInformation{}, + want: true, + }, + { + name: "cpu is partially equal", + args: &metal.HardwareInformation{ + Compute: &metal.ComputeInformation{ + Processors: []*metal.Processor{ + { + Manufacturer: "Intel", + }, + }, + }, + // Skip all other fields to indicate that we don't want to compare it. + }, + want: true, + }, + { + name: "cpu is not partially equal", + args: &metal.HardwareInformation{ + Compute: &metal.ComputeInformation{ + Processors: []*metal.Processor{ + { + Manufacturer: "AMD", + }, + }, + }, + // Skip all other fields to indicate that we don't want to compare it. + }, + want: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.args.PartialEqual(info); got != tt.want { + t.Errorf("PartialEqual() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/app/sidero-controller-manager/api/v1alpha2/server_webhook.go b/app/sidero-controller-manager/api/v1alpha2/server_webhook.go new file mode 100644 index 000000000..ef13778e0 --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha2/server_webhook.go @@ -0,0 +1,21 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package v1alpha2 + +import ( + ctrl "sigs.k8s.io/controller-runtime" +) + +func (r *Server) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} + +func (r *ServerList) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} diff --git a/app/sidero-controller-manager/api/v1alpha2/serverclass_conversion.go b/app/sidero-controller-manager/api/v1alpha2/serverclass_conversion.go new file mode 100644 index 000000000..dbeb291af --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha2/serverclass_conversion.go @@ -0,0 +1,8 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package v1alpha2 + +func (*ServerClass) Hub() {} +func (*ServerClassList) Hub() {} diff --git a/app/sidero-controller-manager/api/v1alpha2/serverclass_filter.go b/app/sidero-controller-manager/api/v1alpha2/serverclass_filter.go new file mode 100644 index 000000000..f5ce08250 --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha2/serverclass_filter.go @@ -0,0 +1,110 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package v1alpha2 + +import ( + "fmt" + "sort" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" +) + +// AcceptedServerFilter matches Servers that have Spec.Accepted set to true. +func AcceptedServerFilter(s Server) (bool, error) { + return s.Spec.Accepted, nil +} + +// NotCordonedServerFilter matches Servers that have Spec.Paused set to false. +func NotCordonedServerFilter(s Server) (bool, error) { + return !s.Spec.Cordoned, nil +} + +// SelectorFilter returns a ServerFilter that matches servers against the +// serverclass's selector field. +func (sc *ServerClass) SelectorFilter() func(Server) (bool, error) { + return func(server Server) (bool, error) { + s, err := metav1.LabelSelectorAsSelector(&sc.Spec.Selector) + if err != nil { + return false, fmt.Errorf("failed to get selector from labelselector: %v", err) + } + + return s.Matches(labels.Set(server.GetLabels())), nil + } +} + +// QualifiersFilter returns a ServerFilter that matches servers against the +// serverclass's qualifiers field. +func (sc *ServerClass) QualifiersFilter() func(Server) (bool, error) { + return func(server Server) (bool, error) { + q := sc.Spec.Qualifiers + + // check hardware qualifiers if they are present + if filters := q.Hardware; len(filters) > 0 { + var match bool + + for _, filter := range filters { + if info := server.Spec.Hardware; info != nil && filter.PartialEqual(info) { + match = true + break + } + } + + if !match { + return false, nil + } + } + + if filters := q.LabelSelectors; len(filters) > 0 { + var match bool + + for _, filter := range filters { + for labelKey, labelVal := range filter { + if val, ok := server.ObjectMeta.Labels[labelKey]; ok && labelVal == val { + match = true + break + } + } + } + + if !match { + return false, nil + } + } + + return true, nil + } +} + +// FilterServers returns the subset of servers that pass all provided filters. +// In case of error the returned slice will be nil. +func FilterServers(servers []Server, filters ...func(Server) (bool, error)) ([]Server, error) { + matches := make([]Server, 0, len(servers)) + + for _, server := range servers { + match := true + + for _, filter := range filters { + var err error + + match, err = filter(server) + if err != nil { + return nil, fmt.Errorf("failed to filter server: %v", err) + } + + if !match { + break + } + } + + if match { + matches = append(matches, server) + } + } + + sort.Slice(matches, func(i, j int) bool { return matches[i].Name < matches[j].Name }) + + return matches, nil +} diff --git a/app/sidero-controller-manager/api/v1alpha2/serverclass_filter_test.go b/app/sidero-controller-manager/api/v1alpha2/serverclass_filter_test.go new file mode 100644 index 000000000..125bec1dc --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha2/serverclass_filter_test.go @@ -0,0 +1,378 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package v1alpha2_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + metal "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" +) + +func TestFilterAcceptedServers(t *testing.T) { + t.Parallel() + + atom := metal.Server{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + "common-label": "true", + "zone": "central", + }, + }, + Spec: metal.ServerSpec{ + Accepted: true, + Hardware: &metal.HardwareInformation{ + Compute: &metal.ComputeInformation{ + TotalCoreCount: 4, + TotalThreadCount: 4, + ProcessorCount: 1, + Processors: []*metal.Processor{ + { + Manufacturer: "Intel(R) Corporation", + ProductName: "Intel(R) Atom(TM) CPU C3558 @ 2.20GHz", + SerialNumber: "", + Speed: 2200, + CoreCount: 4, + ThreadCount: 4, + }, + }, + }, + }, + }, + } + dualXeon := metal.Server{ + Spec: metal.ServerSpec{ + Accepted: true, + Hardware: &metal.HardwareInformation{ + Compute: &metal.ComputeInformation{ + TotalCoreCount: 16, + TotalThreadCount: 32, + ProcessorCount: 2, + Processors: []*metal.Processor{ + { + Manufacturer: "Intel(R) Corporation", + ProductName: "Intel(R) Xeon(R) CPU E5-2630 v3 @ 2.40GHz", + SerialNumber: "", + Speed: 2400, + CoreCount: 8, + ThreadCount: 16, + }, + { + Manufacturer: "Intel(R) Corporation", + ProductName: "Intel(R) Xeon(R) CPU E5-2630 v3 @ 2.40GHz", + SerialNumber: "", + Speed: 2400, + CoreCount: 8, + ThreadCount: 16, + }, + }, + }, + }, + }, + } + ryzen := metal.Server{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + "common-label": "true", + "zone": "east", + }, + }, + Spec: metal.ServerSpec{ + Accepted: true, + Hardware: &metal.HardwareInformation{ + System: &metal.SystemInformation{ + Manufacturer: "QEMU", + }, + Compute: &metal.ComputeInformation{ + TotalCoreCount: 8, + TotalThreadCount: 16, + ProcessorCount: 1, + Processors: []*metal.Processor{ + { + Manufacturer: "Advanced Micro Devices, Inc.", + ProductName: "AMD Ryzen 7 2700X Eight-Core Processor", + SerialNumber: "", + Speed: 3700, + CoreCount: 8, + ThreadCount: 16, + }, + }, + }, + }, + }, + } + notAccepted := metal.Server{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + "common-label": "true", + "zone": "west", + }, + }, + Spec: metal.ServerSpec{ + Accepted: false, + Hardware: &metal.HardwareInformation{ + System: &metal.SystemInformation{ + Manufacturer: "QEMU", + }, + Compute: &metal.ComputeInformation{ + TotalCoreCount: 8, + TotalThreadCount: 16, + ProcessorCount: 1, + Processors: []*metal.Processor{ + { + Manufacturer: "Advanced Micro Devices, Inc.", + ProductName: "AMD Ryzen 7 2700X Eight-Core Processor", + SerialNumber: "", + Speed: 3700, + CoreCount: 8, + ThreadCount: 16, + }, + }, + }, + }, + }, + } + + servers := []metal.Server{atom, dualXeon, ryzen, notAccepted} + + testdata := map[string]struct { + s metav1.LabelSelector + q metal.Qualifiers + expected []metal.Server + }{ + "empty selector - empty qualifier": { + // Matches all servers + expected: []metal.Server{atom, dualXeon, ryzen}, + }, + "Intel only": { + q: metal.Qualifiers{ + Hardware: []metal.HardwareInformation{ + { + Compute: &metal.ComputeInformation{ + Processors: []*metal.Processor{ + { + Manufacturer: "Intel(R) Corporation", + }, + }, + }, + }, + }, + }, + expected: []metal.Server{atom, dualXeon}, + }, + "Intel and AMD": { + q: metal.Qualifiers{ + Hardware: []metal.HardwareInformation{ + { + Compute: &metal.ComputeInformation{ + Processors: []*metal.Processor{ + { + Manufacturer: "Intel(R) Corporation", + }, + }, + }, + }, + { + Compute: &metal.ComputeInformation{ + Processors: []*metal.Processor{ + { + Manufacturer: "Advanced Micro Devices, Inc.", + }, + }, + }, + }, + }, + }, + expected: []metal.Server{atom, dualXeon, ryzen}, + }, + "QEMU only": { + q: metal.Qualifiers{ + Hardware: []metal.HardwareInformation{ + { + System: &metal.SystemInformation{ + Manufacturer: "QEMU", + }, + }, + }, + }, + expected: []metal.Server{ryzen}, + }, + "with label": { + q: metal.Qualifiers{ + LabelSelectors: []map[string]string{ + { + "common-label": "true", + }, + }, + }, + expected: []metal.Server{atom, ryzen}, + }, + // This should probably only return atom. Leaving it as-is to + // avoid breaking changes before we remove LabelSelectors in + // favor of Selector. + "with multiple labels - single selector": { + q: metal.Qualifiers{ + LabelSelectors: []map[string]string{ + { + "common-label": "true", + "zone": "central", + }, + }, + }, + expected: []metal.Server{atom, ryzen}, + }, + "with multiple labels - multiple selectors": { + q: metal.Qualifiers{ + LabelSelectors: []map[string]string{ + { + "common-label": "true", + }, + { + "zone": "central", + }, + }, + }, + expected: []metal.Server{atom, ryzen}, + }, + "with same label key different label value": { + q: metal.Qualifiers{ + LabelSelectors: []map[string]string{ + { + "zone": "central", + }, + }, + }, + expected: []metal.Server{atom}, + }, + "selector - single MatchLabels single result": { + s: metav1.LabelSelector{ + MatchLabels: map[string]string{ + "zone": "central", + }, + }, + expected: []metal.Server{atom}, + }, + "selector - single MatchLabels multiple results": { + s: metav1.LabelSelector{ + MatchLabels: map[string]string{ + "common-label": "true", + }, + }, + expected: []metal.Server{atom, ryzen}, + }, + "selector - multiple MatchLabels": { + s: metav1.LabelSelector{ + MatchLabels: map[string]string{ + "zone": "central", + "common-label": "true", + }, + }, + expected: []metal.Server{atom}, + }, + "selector - MatchExpressions common label key": { + s: metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: "common-label", + Operator: "Exists", + }, + }, + }, + expected: []metal.Server{atom, ryzen}, + }, + "selector - MatchExpressions multiple values": { + s: metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: "zone", + Operator: "In", + Values: []string{ + "east", + "west", + }, + }, + }, + }, + expected: []metal.Server{ryzen}, + }, + "selector and qualifiers both match": { + s: metav1.LabelSelector{ + MatchLabels: map[string]string{ + "common-label": "true", + }, + }, + q: metal.Qualifiers{ + Hardware: []metal.HardwareInformation{ + { + System: &metal.SystemInformation{ + Manufacturer: "QEMU", + }, + }, + }, + }, + expected: []metal.Server{ryzen}, + }, + "selector and qualifiers with disqualifying selector": { + s: metav1.LabelSelector{ + MatchLabels: map[string]string{ + "common-label": "no-match", + }, + }, + q: metal.Qualifiers{ + Hardware: []metal.HardwareInformation{ + { + System: &metal.SystemInformation{ + Manufacturer: "QEMU", + }, + }, + }, + }, + expected: []metal.Server{}, + }, + "selector and qualifiers with disqualifying qualifier": { + s: metav1.LabelSelector{ + MatchLabels: map[string]string{ + "common-label": "true", + }, + }, + q: metal.Qualifiers{ + Hardware: []metal.HardwareInformation{ + { + System: &metal.SystemInformation{ + Manufacturer: "Gateway", + }, + }, + }, + }, + expected: []metal.Server{}, + }, + metal.ServerClassAny: { + expected: []metal.Server{atom, dualXeon, ryzen}, + }, + } + + for name, td := range testdata { + name, td := name, td + t.Run(name, func(t *testing.T) { + t.Parallel() + + sc := &metal.ServerClass{ + Spec: metal.ServerClassSpec{ + Selector: td.s, + Qualifiers: td.q, + }, + } + actual, err := metal.FilterServers(servers, + metal.AcceptedServerFilter, + sc.SelectorFilter(), + sc.QualifiersFilter(), + ) + assert.NoError(t, err) + assert.Equal(t, td.expected, actual) + }) + } +} diff --git a/app/sidero-controller-manager/api/v1alpha2/serverclass_types.go b/app/sidero-controller-manager/api/v1alpha2/serverclass_types.go new file mode 100644 index 000000000..45ea2ba92 --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha2/serverclass_types.go @@ -0,0 +1,84 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package v1alpha2 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + siderotypes "github.com/talos-systems/sidero/app/sidero-controller-manager/pkg/types" +) + +// ServerClassAny is an automatically created ServerClass that includes all Servers. +const ServerClassAny = "any" + +type Qualifiers struct { + Hardware []HardwareInformation `json:"hardware,omitempty"` + LabelSelectors []map[string]string `json:"labelSelectors,omitempty"` +} + +// ServerClassSpec defines the desired state of ServerClass. +type ServerClassSpec struct { + // Reference to the environment which should be used to provision the servers via this server class. + // +optional + EnvironmentRef *corev1.ObjectReference `json:"environmentRef,omitempty"` + // Qualifiers to match on the server spec. + // + // If qualifiers are empty, they match all servers. + // Server should match both qualifiers and selector conditions to be included into the server class. + // +optional + Qualifiers Qualifiers `json:"qualifiers"` + // Label selector to filter the matching servers based on labels. + // A label selector is a label query over a set of resources. The result of matchLabels and + // matchExpressions are ANDed. An empty label selector matches all objects. A null label selector matches no objects. + // +optional + Selector metav1.LabelSelector `json:"selector"` + // Set of config patches to apply to the machine configuration to the servers provisioned via this server class. + // +optional + ConfigPatches []ConfigPatches `json:"configPatches,omitempty"` + // BootFromDiskMethod specifies the method to exit iPXE to force boot from disk. + // + // If not set, controller default is used. + // Valid values: ipxe-exit, http-404, ipxe-sanboot. + // + // +optional + BootFromDiskMethod siderotypes.BootFromDisk `json:"bootFromDiskMethod,omitempty"` +} + +// ServerClassStatus defines the observed state of ServerClass. +type ServerClassStatus struct { + ServersAvailable []string `json:"serversAvailable"` + ServersInUse []string `json:"serversInUse"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:resource:scope=Cluster +// +kubebuilder:printcolumn:name="Available",type="string",JSONPath=".status.serversAvailable",description="the number of available servers" +// +kubebuilder:printcolumn:name="In Use",type="string",JSONPath=".status.serversInUse",description="the number of servers in use" +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="The age of this resource" +// +kubebuilder:storageversion + +// ServerClass is the Schema for the serverclasses API. +type ServerClass struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec ServerClassSpec `json:"spec,omitempty"` + Status ServerClassStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// ServerClassList contains a list of ServerClass. +type ServerClassList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ServerClass `json:"items"` +} + +func init() { + SchemeBuilder.Register(&ServerClass{}, &ServerClassList{}) +} diff --git a/app/sidero-controller-manager/api/v1alpha2/serverclass_webhook.go b/app/sidero-controller-manager/api/v1alpha2/serverclass_webhook.go new file mode 100644 index 000000000..45aa1eff5 --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha2/serverclass_webhook.go @@ -0,0 +1,21 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package v1alpha2 + +import ( + ctrl "sigs.k8s.io/controller-runtime" +) + +func (r *ServerClass) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} + +func (r *ServerClassList) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} diff --git a/app/sidero-controller-manager/api/v1alpha2/types.go b/app/sidero-controller-manager/api/v1alpha2/types.go new file mode 100644 index 000000000..80525d27d --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha2/types.go @@ -0,0 +1,16 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package v1alpha2 + +import apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + +// nb: we use apiextensions.JSON for the value below b/c we can't use interface{} with controller-gen. +// found this workaround here: https://github.com/kubernetes-sigs/controller-tools/pull/126#issuecomment-630769075 + +type ConfigPatches struct { + Op string `json:"op"` + Path string `json:"path"` + Value apiextensions.JSON `json:"value,omitempty"` +} diff --git a/app/sidero-controller-manager/api/v1alpha2/zz_generated.deepcopy.go b/app/sidero-controller-manager/api/v1alpha2/zz_generated.deepcopy.go new file mode 100644 index 000000000..198731e69 --- /dev/null +++ b/app/sidero-controller-manager/api/v1alpha2/zz_generated.deepcopy.go @@ -0,0 +1,771 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +// Code generated by controller-gen. DO NOT EDIT. + +package v1alpha2 + +import ( + v1 "k8s.io/api/core/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/cluster-api/api/v1beta1" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Asset) DeepCopyInto(out *Asset) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Asset. +func (in *Asset) DeepCopy() *Asset { + if in == nil { + return nil + } + out := new(Asset) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AssetCondition) DeepCopyInto(out *AssetCondition) { + *out = *in + out.Asset = in.Asset +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AssetCondition. +func (in *AssetCondition) DeepCopy() *AssetCondition { + if in == nil { + return nil + } + out := new(AssetCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BMC) DeepCopyInto(out *BMC) { + *out = *in + if in.UserFrom != nil { + in, out := &in.UserFrom, &out.UserFrom + *out = new(CredentialSource) + (*in).DeepCopyInto(*out) + } + if in.PassFrom != nil { + in, out := &in.PassFrom, &out.PassFrom + *out = new(CredentialSource) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BMC. +func (in *BMC) DeepCopy() *BMC { + if in == nil { + return nil + } + out := new(BMC) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ComputeInformation) DeepCopyInto(out *ComputeInformation) { + *out = *in + if in.Processors != nil { + in, out := &in.Processors, &out.Processors + *out = make([]*Processor, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(Processor) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComputeInformation. +func (in *ComputeInformation) DeepCopy() *ComputeInformation { + if in == nil { + return nil + } + out := new(ComputeInformation) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConfigPatches) DeepCopyInto(out *ConfigPatches) { + *out = *in + in.Value.DeepCopyInto(&out.Value) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigPatches. +func (in *ConfigPatches) DeepCopy() *ConfigPatches { + if in == nil { + return nil + } + out := new(ConfigPatches) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CredentialSource) DeepCopyInto(out *CredentialSource) { + *out = *in + if in.SecretKeyRef != nil { + in, out := &in.SecretKeyRef, &out.SecretKeyRef + *out = new(SecretKeyRef) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialSource. +func (in *CredentialSource) DeepCopy() *CredentialSource { + if in == nil { + return nil + } + out := new(CredentialSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Environment) DeepCopyInto(out *Environment) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Environment. +func (in *Environment) DeepCopy() *Environment { + if in == nil { + return nil + } + out := new(Environment) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Environment) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EnvironmentList) DeepCopyInto(out *EnvironmentList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Environment, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvironmentList. +func (in *EnvironmentList) DeepCopy() *EnvironmentList { + if in == nil { + return nil + } + out := new(EnvironmentList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *EnvironmentList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EnvironmentSpec) DeepCopyInto(out *EnvironmentSpec) { + *out = *in + in.Kernel.DeepCopyInto(&out.Kernel) + out.Initrd = in.Initrd +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvironmentSpec. +func (in *EnvironmentSpec) DeepCopy() *EnvironmentSpec { + if in == nil { + return nil + } + out := new(EnvironmentSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EnvironmentStatus) DeepCopyInto(out *EnvironmentStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]AssetCondition, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvironmentStatus. +func (in *EnvironmentStatus) DeepCopy() *EnvironmentStatus { + if in == nil { + return nil + } + out := new(EnvironmentStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HardwareInformation) DeepCopyInto(out *HardwareInformation) { + *out = *in + if in.System != nil { + in, out := &in.System, &out.System + *out = new(SystemInformation) + **out = **in + } + if in.Compute != nil { + in, out := &in.Compute, &out.Compute + *out = new(ComputeInformation) + (*in).DeepCopyInto(*out) + } + if in.Memory != nil { + in, out := &in.Memory, &out.Memory + *out = new(MemoryInformation) + (*in).DeepCopyInto(*out) + } + if in.Storage != nil { + in, out := &in.Storage, &out.Storage + *out = new(StorageInformation) + (*in).DeepCopyInto(*out) + } + if in.Network != nil { + in, out := &in.Network, &out.Network + *out = new(NetworkInformation) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HardwareInformation. +func (in *HardwareInformation) DeepCopy() *HardwareInformation { + if in == nil { + return nil + } + out := new(HardwareInformation) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Initrd) DeepCopyInto(out *Initrd) { + *out = *in + out.Asset = in.Asset +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Initrd. +func (in *Initrd) DeepCopy() *Initrd { + if in == nil { + return nil + } + out := new(Initrd) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Kernel) DeepCopyInto(out *Kernel) { + *out = *in + out.Asset = in.Asset + if in.Args != nil { + in, out := &in.Args, &out.Args + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Kernel. +func (in *Kernel) DeepCopy() *Kernel { + if in == nil { + return nil + } + out := new(Kernel) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ManagementAPI) DeepCopyInto(out *ManagementAPI) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagementAPI. +func (in *ManagementAPI) DeepCopy() *ManagementAPI { + if in == nil { + return nil + } + out := new(ManagementAPI) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MemoryInformation) DeepCopyInto(out *MemoryInformation) { + *out = *in + if in.Modules != nil { + in, out := &in.Modules, &out.Modules + *out = make([]*MemoryModule, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(MemoryModule) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MemoryInformation. +func (in *MemoryInformation) DeepCopy() *MemoryInformation { + if in == nil { + return nil + } + out := new(MemoryInformation) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MemoryModule) DeepCopyInto(out *MemoryModule) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MemoryModule. +func (in *MemoryModule) DeepCopy() *MemoryModule { + if in == nil { + return nil + } + out := new(MemoryModule) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkInformation) DeepCopyInto(out *NetworkInformation) { + *out = *in + if in.Interfaces != nil { + in, out := &in.Interfaces, &out.Interfaces + *out = make([]*NetworkInterface, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(NetworkInterface) + (*in).DeepCopyInto(*out) + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkInformation. +func (in *NetworkInformation) DeepCopy() *NetworkInformation { + if in == nil { + return nil + } + out := new(NetworkInformation) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkInterface) DeepCopyInto(out *NetworkInterface) { + *out = *in + if in.Addresses != nil { + in, out := &in.Addresses, &out.Addresses + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkInterface. +func (in *NetworkInterface) DeepCopy() *NetworkInterface { + if in == nil { + return nil + } + out := new(NetworkInterface) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Processor) DeepCopyInto(out *Processor) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Processor. +func (in *Processor) DeepCopy() *Processor { + if in == nil { + return nil + } + out := new(Processor) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Qualifiers) DeepCopyInto(out *Qualifiers) { + *out = *in + if in.Hardware != nil { + in, out := &in.Hardware, &out.Hardware + *out = make([]HardwareInformation, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.LabelSelectors != nil { + in, out := &in.LabelSelectors, &out.LabelSelectors + *out = make([]map[string]string, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Qualifiers. +func (in *Qualifiers) DeepCopy() *Qualifiers { + if in == nil { + return nil + } + out := new(Qualifiers) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SecretKeyRef) DeepCopyInto(out *SecretKeyRef) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretKeyRef. +func (in *SecretKeyRef) DeepCopy() *SecretKeyRef { + if in == nil { + return nil + } + out := new(SecretKeyRef) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Server) DeepCopyInto(out *Server) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Server. +func (in *Server) DeepCopy() *Server { + if in == nil { + return nil + } + out := new(Server) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Server) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServerClass) DeepCopyInto(out *ServerClass) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServerClass. +func (in *ServerClass) DeepCopy() *ServerClass { + if in == nil { + return nil + } + out := new(ServerClass) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ServerClass) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServerClassList) DeepCopyInto(out *ServerClassList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ServerClass, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServerClassList. +func (in *ServerClassList) DeepCopy() *ServerClassList { + if in == nil { + return nil + } + out := new(ServerClassList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ServerClassList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServerClassSpec) DeepCopyInto(out *ServerClassSpec) { + *out = *in + if in.EnvironmentRef != nil { + in, out := &in.EnvironmentRef, &out.EnvironmentRef + *out = new(v1.ObjectReference) + **out = **in + } + in.Qualifiers.DeepCopyInto(&out.Qualifiers) + in.Selector.DeepCopyInto(&out.Selector) + if in.ConfigPatches != nil { + in, out := &in.ConfigPatches, &out.ConfigPatches + *out = make([]ConfigPatches, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServerClassSpec. +func (in *ServerClassSpec) DeepCopy() *ServerClassSpec { + if in == nil { + return nil + } + out := new(ServerClassSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServerClassStatus) DeepCopyInto(out *ServerClassStatus) { + *out = *in + if in.ServersAvailable != nil { + in, out := &in.ServersAvailable, &out.ServersAvailable + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ServersInUse != nil { + in, out := &in.ServersInUse, &out.ServersInUse + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServerClassStatus. +func (in *ServerClassStatus) DeepCopy() *ServerClassStatus { + if in == nil { + return nil + } + out := new(ServerClassStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServerList) DeepCopyInto(out *ServerList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Server, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServerList. +func (in *ServerList) DeepCopy() *ServerList { + if in == nil { + return nil + } + out := new(ServerList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ServerList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServerSpec) DeepCopyInto(out *ServerSpec) { + *out = *in + if in.EnvironmentRef != nil { + in, out := &in.EnvironmentRef, &out.EnvironmentRef + *out = new(v1.ObjectReference) + **out = **in + } + if in.Hardware != nil { + in, out := &in.Hardware, &out.Hardware + *out = new(HardwareInformation) + (*in).DeepCopyInto(*out) + } + if in.BMC != nil { + in, out := &in.BMC, &out.BMC + *out = new(BMC) + (*in).DeepCopyInto(*out) + } + if in.ManagementAPI != nil { + in, out := &in.ManagementAPI, &out.ManagementAPI + *out = new(ManagementAPI) + **out = **in + } + if in.ConfigPatches != nil { + in, out := &in.ConfigPatches, &out.ConfigPatches + *out = make([]ConfigPatches, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServerSpec. +func (in *ServerSpec) DeepCopy() *ServerSpec { + if in == nil { + return nil + } + out := new(ServerSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServerStatus) DeepCopyInto(out *ServerStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]v1beta1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Addresses != nil { + in, out := &in.Addresses, &out.Addresses + *out = make([]v1.NodeAddress, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServerStatus. +func (in *ServerStatus) DeepCopy() *ServerStatus { + if in == nil { + return nil + } + out := new(ServerStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageDevice) DeepCopyInto(out *StorageDevice) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageDevice. +func (in *StorageDevice) DeepCopy() *StorageDevice { + if in == nil { + return nil + } + out := new(StorageDevice) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageInformation) DeepCopyInto(out *StorageInformation) { + *out = *in + if in.Devices != nil { + in, out := &in.Devices, &out.Devices + *out = make([]*StorageDevice, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(StorageDevice) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageInformation. +func (in *StorageInformation) DeepCopy() *StorageInformation { + if in == nil { + return nil + } + out := new(StorageInformation) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SystemInformation) DeepCopyInto(out *SystemInformation) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SystemInformation. +func (in *SystemInformation) DeepCopy() *SystemInformation { + if in == nil { + return nil + } + out := new(SystemInformation) + in.DeepCopyInto(out) + return out +} diff --git a/app/sidero-controller-manager/cmd/agent/main.go b/app/sidero-controller-manager/cmd/agent/main.go index 5513afe6c..bfa5c6231 100644 --- a/app/sidero-controller-manager/cmd/agent/main.go +++ b/app/sidero-controller-manager/cmd/agent/main.go @@ -30,7 +30,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" - metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha1" + metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" "github.com/talos-systems/sidero/app/sidero-controller-manager/internal/api" "github.com/talos-systems/sidero/app/sidero-controller-manager/internal/power/ipmi" "github.com/talos-systems/sidero/app/sidero-controller-manager/pkg/constants" @@ -94,25 +94,21 @@ func setup() error { } func create(ctx context.Context, client api.AgentClient, s *smbios.SMBIOS) (*api.CreateServerResponse, error) { - uuid, err := s.SystemInformation().UUID() + disks, err := disk.List() if err != nil { - return nil, err + log.Printf("encountered error fetching disks: %q", err) + disks = make([]*disk.Disk, 0) + } + + interfaces, err := net.Interfaces() + if err != nil { + log.Printf("encountered error fetching network interfaces: %q", err) + interfaces = make([]net.Interface, 0) } req := &api.CreateServerRequest{ - SystemInformation: &api.SystemInformation{ - Uuid: uuid.String(), - Manufacturer: s.SystemInformation().Manufacturer(), - ProductName: s.SystemInformation().ProductName(), - Version: s.SystemInformation().Version(), - SerialNumber: s.SystemInformation().SerialNumber(), - SkuNumber: s.SystemInformation().SKUNumber(), - Family: s.SystemInformation().Family(), - }, - Cpu: &api.CPU{ - Manufacturer: s.ProcessorInformation().ProcessorManufacturer(), - Version: s.ProcessorInformation().ProcessorVersion(), - }, + Hardware: MapHardwareInformation(s, disks, interfaces), + Hostname: "", } hostname, err := os.Hostname() @@ -140,16 +136,11 @@ func create(ctx context.Context, client api.AgentClient, s *smbios.SMBIOS) (*api } func wipe(ctx context.Context, client api.AgentClient, s *smbios.SMBIOS) error { - uuid, err := s.SystemInformation().UUID() - if err != nil { - return err - } - return retry.Constant(5*time.Minute, retry.WithUnits(30*time.Second), retry.WithErrorLogging(true)).Retry(func() error { ctx, cancel := context.WithTimeout(ctx, 30*time.Second) defer cancel() - _, err = client.MarkServerAsWiped(ctx, &api.MarkServerAsWipedRequest{Uuid: uuid.String()}) + _, err := client.MarkServerAsWiped(ctx, &api.MarkServerAsWipedRequest{Uuid: s.SystemInformation.UUID}) if err != nil { return retry.ExpectedError(err) } @@ -159,11 +150,6 @@ func wipe(ctx context.Context, client api.AgentClient, s *smbios.SMBIOS) error { } func reconcileIPs(ctx context.Context, client api.AgentClient, s *smbios.SMBIOS, ips []net.IP) error { - uuid, err := s.SystemInformation().UUID() - if err != nil { - return err - } - addresses := make([]*api.Address, len(ips)) for i := range addresses { addresses[i] = &api.Address{ @@ -176,8 +162,8 @@ func reconcileIPs(ctx context.Context, client api.AgentClient, s *smbios.SMBIOS, ctx, cancel := context.WithTimeout(ctx, 30*time.Second) defer cancel() - _, err = client.ReconcileServerAddresses(ctx, &api.ReconcileServerAddressesRequest{ - Uuid: uuid.String(), + _, err := client.ReconcileServerAddresses(ctx, &api.ReconcileServerAddressesRequest{ + Uuid: s.SystemInformation.UUID, Address: addresses, }) if err != nil { @@ -281,11 +267,6 @@ func mainFunc() error { shutdown(err) } - uuid, err := s.SystemInformation().UUID() - if err != nil { - shutdown(err) - } - var ( eg errgroup.Group wg sync.WaitGroup @@ -305,7 +286,7 @@ func mainFunc() error { for { callCtx, cancel := context.WithTimeout(ctx, heartbeatInterval) - if _, err := client.Heartbeat(callCtx, &api.HeartbeatRequest{Uuid: uuid.String()}); err != nil { + if _, err := client.Heartbeat(callCtx, &api.HeartbeatRequest{Uuid: s.SystemInformation.UUID}); err != nil { log.Printf("Failed to send wipe heartbeat %s", err) } @@ -396,11 +377,6 @@ func main() { } func attemptBMCIP(ctx context.Context, client api.AgentClient, s *smbios.SMBIOS) error { - uuid, err := s.SystemInformation().UUID() - if err != nil { - return err - } - bmcInfo := &api.BMCInfo{} // Create "open" client @@ -442,7 +418,7 @@ func attemptBMCIP(ctx context.Context, client api.AgentClient, s *smbios.SMBIOS) _, err = client.UpdateBMCInfo( ctx, &api.UpdateBMCInfoRequest{ - Uuid: uuid.String(), + Uuid: s.SystemInformation.UUID, BmcInfo: bmcInfo, }, ) @@ -458,11 +434,6 @@ func attemptBMCIP(ctx context.Context, client api.AgentClient, s *smbios.SMBIOS) } func attemptBMCUserSetup(ctx context.Context, client api.AgentClient, s *smbios.SMBIOS) error { - uuid, err := s.SystemInformation().UUID() - if err != nil { - return err - } - bmcInfo := &api.BMCInfo{} // Create "open" client @@ -575,7 +546,7 @@ func attemptBMCUserSetup(ctx context.Context, client api.AgentClient, s *smbios. _, err = client.UpdateBMCInfo( ctx, &api.UpdateBMCInfoRequest{ - Uuid: uuid.String(), + Uuid: s.SystemInformation.UUID, BmcInfo: bmcInfo, }, ) @@ -609,3 +580,156 @@ func genPass16() (string, error) { return string(b), nil } + +func MapHardwareInformation(s *smbios.SMBIOS, disks []*disk.Disk, interfaces []net.Interface) *api.HardwareInformation { + if s != nil { + return &api.HardwareInformation{ + System: MapSystemInformation(s), + Compute: MapComputeInformation(s), + Memory: MapMemoryInformation(s), + Storage: MapStorageInformation(disks), + Network: MapNetworkInformation(interfaces), + } + } + + return &api.HardwareInformation{ + Storage: MapStorageInformation(disks), + } +} + +func MapSystemInformation(s *smbios.SMBIOS) *api.SystemInformation { + return &api.SystemInformation{ + Manufacturer: s.SystemInformation.Manufacturer, + ProductName: s.SystemInformation.ProductName, + SerialNumber: s.SystemInformation.SerialNumber, + Uuid: s.SystemInformation.UUID, + SkuNumber: s.SystemInformation.SKUNumber, + Family: s.SystemInformation.Family, + } +} + +func MapComputeInformation(s *smbios.SMBIOS) *api.ComputeInformation { + var totalCoreCount = 0 + var totalThreadCount = 0 + var processors []*api.Processor + for _, v := range s.ProcessorInformation { + if v.Status.SocketPopulated() { + totalCoreCount += int(v.CoreCount) + totalThreadCount += int(v.ThreadCount) + var processor = &api.Processor{ + Manufacturer: v.ProcessorManufacturer, + ProductName: v.ProcessorVersion, + SerialNumber: v.SerialNumber, + Speed: uint32(v.CurrentSpeed), + CoreCount: uint32(v.CoreCount), + ThreadCount: uint32(v.ThreadCount), + } + processors = append(processors, processor) + } + } + return &api.ComputeInformation{ + TotalCoreCount: uint32(totalCoreCount), + TotalThreadCount: uint32(totalThreadCount), + ProcessorCount: uint32(len(processors)), + Processors: processors, + } +} + +func MapMemoryInformation(s *smbios.SMBIOS) *api.MemoryInformation { + var totalSize = 0 + var modules []*api.MemoryModule + for _, v := range s.MemoryDevices { + if v.Size != 0 && v.Size != 0xFFFF { + var size uint32 + if v.Size == 0x7FFF { + totalSize += int(v.ExtendedSize) + size = uint32(v.ExtendedSize) + } else { + totalSize += v.Size.Megabytes() + size = uint32(v.Size) + } + var memoryModule = &api.MemoryModule{ + Manufacturer: v.Manufacturer, + ProductName: v.PartNumber, + SerialNumber: v.SerialNumber, + Type: v.MemoryType.String(), + Size: size, + Speed: uint32(v.Speed), + } + modules = append(modules, memoryModule) + } + } + return &api.MemoryInformation{ + TotalSize: uint32(totalSize), + ModuleCount: uint32(len(modules)), + Modules: modules, + } +} + +func MapStorageInformation(s []*disk.Disk) *api.StorageInformation { + var totalSize = uint64(0) + var devices []*api.StorageDevice + for _, v := range s { + totalSize += v.Size + var storageType api.StorageType + switch v.Type.String() { + case "ssd": + storageType = api.StorageType_SSD + case "hdd": + storageType = api.StorageType_HDD + case "nvme": + storageType = api.StorageType_NVMe + case "sd": + storageType = api.StorageType_SD + default: + storageType = api.StorageType_Unknown + } + var storageDevice = &api.StorageDevice{ + Model: v.Model, + Serial: v.Serial, + Type: storageType, + Size: v.Size, + Name: v.Name, + DeviceName: v.DeviceName, + Uuid: v.UUID, + Wwid: v.WWID, + } + devices = append(devices, storageDevice) + } + return &api.StorageInformation{ + TotalSize: totalSize, + DeviceCount: uint32(len(devices)), + Devices: devices, + } +} + +func MapNetworkInformation(s []net.Interface) *api.NetworkInformation { + var interfaces []*api.NetworkInterface + for _, v := range s { + if len(v.HardwareAddr) == 0 { + continue // skip interfaces without a hardware address + } + var addrs, err = v.Addrs() + if err != nil { + log.Printf("encountered error fetching addresses of network interface %q: %q", v.Name, err) + addrs = make([]net.Addr, 0) + } + var addresses []string + for _, a := range addrs { + addresses = append(addresses, a.String()) + } + var networkInterface = &api.NetworkInterface{ + Index: uint32(v.Index), + Name: v.Name, + Flags: v.Flags.String(), + Mtu: uint32(v.MTU), + Mac: v.HardwareAddr.String(), + Addresses: addresses, + } + interfaces = append(interfaces, networkInterface) + } + return &api.NetworkInformation{ + InterfaceCount: uint32(len(interfaces)), + Interfaces: interfaces, + } +} diff --git a/app/sidero-controller-manager/cmd/agent/main_test.go b/app/sidero-controller-manager/cmd/agent/main_test.go new file mode 100644 index 000000000..293ec2cdd --- /dev/null +++ b/app/sidero-controller-manager/cmd/agent/main_test.go @@ -0,0 +1,14 @@ +// 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 main + +import ( + "testing" +) + +func Test_MapHardwareInformation_DoesNotPanic(t *testing.T) { + MapHardwareInformation(nil, nil, nil) +} diff --git a/app/sidero-controller-manager/config/certmanager/certificate.yaml b/app/sidero-controller-manager/config/certmanager/certificate.yaml deleted file mode 100644 index fac5aa1bb..000000000 --- a/app/sidero-controller-manager/config/certmanager/certificate.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# The following manifests contain a self-signed issuer CR and a certificate CR. -# More document can be found at https://docs.cert-manager.io -# WARNING: Targets CertManager 0.11 check https://docs.cert-manager.io/en/latest/tasks/upgrading/index.html for breaking changes -apiVersion: cert-manager.io/v1 -kind: Issuer -metadata: - name: selfsigned-issuer - namespace: system -spec: - selfSigned: {} ---- -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: serving-cert # this name should match the one appeared in kustomizeconfig.yaml - namespace: system -spec: - # $(SERVICE_NAME) and $(SERVICE_NAMESPACE) will be substituted by kustomize - dnsNames: - - $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc - - $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc.cluster.local - issuerRef: - kind: Issuer - name: selfsigned-issuer - secretName: webhook-server-cert # this secret will not be prefixed, since it's not managed by kustomize diff --git a/app/sidero-controller-manager/config/certmanager/kustomization.yaml b/app/sidero-controller-manager/config/certmanager/kustomization.yaml deleted file mode 100644 index bebea5a59..000000000 --- a/app/sidero-controller-manager/config/certmanager/kustomization.yaml +++ /dev/null @@ -1,5 +0,0 @@ -resources: -- certificate.yaml - -configurations: -- kustomizeconfig.yaml diff --git a/app/sidero-controller-manager/config/certmanager/kustomizeconfig.yaml b/app/sidero-controller-manager/config/certmanager/kustomizeconfig.yaml deleted file mode 100644 index 90d7c313c..000000000 --- a/app/sidero-controller-manager/config/certmanager/kustomizeconfig.yaml +++ /dev/null @@ -1,16 +0,0 @@ -# This configuration is for teaching kustomize how to update name ref and var substitution -nameReference: -- kind: Issuer - group: cert-manager.io - fieldSpecs: - - kind: Certificate - group: cert-manager.io - path: spec/issuerRef/name - -varReference: -- kind: Certificate - group: cert-manager.io - path: spec/commonName -- kind: Certificate - group: cert-manager.io - path: spec/dnsNames diff --git a/app/sidero-controller-manager/config/crd/bases/metal.sidero.dev_environments.yaml b/app/sidero-controller-manager/config/crd/bases/metal.sidero.dev_environments.yaml index 1be7df478..f4885592a 100644 --- a/app/sidero-controller-manager/config/crd/bases/metal.sidero.dev_environments.yaml +++ b/app/sidero-controller-manager/config/crd/bases/metal.sidero.dev_environments.yaml @@ -93,6 +93,87 @@ spec: type: object type: object served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - description: the kernel for the environment + jsonPath: .spec.kernel.url + name: Kernel + type: string + - description: the initrd for the environment + jsonPath: .spec.initrd.url + name: Initrd + type: string + - description: indicates the readiness of the environment + jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - description: The age of this resource + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 + schema: + openAPIV3Schema: + description: Environment is the Schema for the environments API. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: EnvironmentSpec defines the desired state of Environment. + properties: + initrd: + properties: + sha512: + type: string + url: + type: string + type: object + kernel: + properties: + args: + items: + type: string + type: array + sha512: + type: string + url: + type: string + type: object + type: object + status: + description: EnvironmentStatus defines the observed state of Environment. + properties: + conditions: + items: + properties: + sha512: + type: string + status: + type: string + type: + type: string + url: + type: string + required: + - status + - type + type: object + type: array + type: object + type: object + served: true storage: true subresources: status: {} diff --git a/app/sidero-controller-manager/config/crd/bases/metal.sidero.dev_serverclasses.yaml b/app/sidero-controller-manager/config/crd/bases/metal.sidero.dev_serverclasses.yaml index 3577cc945..168690bec 100644 --- a/app/sidero-controller-manager/config/crd/bases/metal.sidero.dev_serverclasses.yaml +++ b/app/sidero-controller-manager/config/crd/bases/metal.sidero.dev_serverclasses.yaml @@ -210,6 +210,321 @@ spec: type: object type: object served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - description: the number of available servers + jsonPath: .status.serversAvailable + name: Available + type: string + - description: the number of servers in use + jsonPath: .status.serversInUse + name: In Use + type: string + - description: The age of this resource + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 + schema: + openAPIV3Schema: + description: ServerClass is the Schema for the serverclasses API. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ServerClassSpec defines the desired state of ServerClass. + properties: + bootFromDiskMethod: + description: "BootFromDiskMethod specifies the method to exit iPXE + to force boot from disk. \n If not set, controller default is used. + Valid values: ipxe-exit, http-404, ipxe-sanboot." + type: string + configPatches: + description: Set of config patches to apply to the machine configuration + to the servers provisioned via this server class. + items: + properties: + op: + type: string + path: + type: string + value: + x-kubernetes-preserve-unknown-fields: true + required: + - op + - path + type: object + type: array + environmentRef: + description: Reference to the environment which should be used to + provision the servers via this server class. + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: 'If referring to a piece of an object instead of + an entire object, this string should contain a valid JSON/Go + field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within + a pod, this would take on a value like: "spec.containers{name}" + (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" + (container with index 2 in this pod). This syntax is chosen + only to have some well-defined way of referencing a part of + an object. TODO: this design is not final and this field is + subject to change in the future.' + type: string + kind: + description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + namespace: + description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/' + type: string + resourceVersion: + description: 'Specific resourceVersion to which this reference + is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency' + type: string + uid: + description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids' + type: string + type: object + qualifiers: + description: "Qualifiers to match on the server spec. \n If qualifiers + are empty, they match all servers. Server should match both qualifiers + and selector conditions to be included into the server class." + properties: + hardware: + items: + properties: + compute: + properties: + processorCount: + format: int32 + type: integer + processors: + items: + properties: + coreCount: + format: int32 + type: integer + manufacturer: + type: string + productName: + type: string + serialNumber: + type: string + speed: + description: Speed is in megahertz (Mhz) + format: int32 + type: integer + threadCount: + format: int32 + type: integer + type: object + type: array + totalCoreCount: + format: int32 + type: integer + totalThreadCount: + format: int32 + type: integer + type: object + memory: + properties: + moduleCount: + format: int32 + type: integer + modules: + items: + properties: + manufacturer: + type: string + productName: + type: string + serialNumber: + type: string + size: + description: Size is in megabytes (MB) + format: int32 + type: integer + speed: + description: Speed is in megatransfers per second + (MT/S) + format: int32 + type: integer + type: + type: string + type: object + type: array + totalSize: + type: string + type: object + network: + properties: + interfaceCount: + format: int32 + type: integer + interfaces: + items: + properties: + addresses: + items: + type: string + type: array + flags: + type: string + index: + format: int32 + type: integer + mac: + type: string + mtu: + format: int32 + type: integer + name: + type: string + type: object + type: array + type: object + storage: + properties: + deviceCount: + format: int32 + type: integer + devices: + items: + properties: + deviceName: + type: string + name: + type: string + productName: + type: string + serialNumber: + type: string + size: + description: Size is in bytes + format: int64 + type: integer + type: + type: string + uuid: + type: string + wwid: + type: string + type: object + type: array + totalSize: + type: string + type: object + system: + properties: + family: + type: string + manufacturer: + type: string + productName: + type: string + serialNumber: + type: string + skuNumber: + type: string + uuid: + type: string + version: + type: string + type: object + type: object + type: array + labelSelectors: + items: + additionalProperties: + type: string + type: object + type: array + type: object + selector: + description: Label selector to filter the matching servers based on + labels. A label selector is a label query over a set of resources. + The result of matchLabels and matchExpressions are ANDed. An empty + label selector matches all objects. A null label selector matches + no objects. + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector requirement is a selector that + contains values, a key, and an operator that relates the key + and values. + properties: + key: + description: key is the label key that the selector applies + to. + type: string + operator: + description: operator represents a key's relationship to + a set of values. Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of string values. If the + operator is In or NotIn, the values array must be non-empty. + If the operator is Exists or DoesNotExist, the values + array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. A single + {key,value} in the matchLabels map is equivalent to an element + of matchExpressions, whose key field is "key", the operator + is "In", and the values array contains only "value". The requirements + are ANDed. + type: object + type: object + type: object + status: + description: ServerClassStatus defines the observed state of ServerClass. + properties: + serversAvailable: + items: + type: string + type: array + serversInUse: + items: + type: string + type: array + required: + - serversAvailable + - serversInUse + type: object + type: object + served: true storage: true subresources: status: {} diff --git a/app/sidero-controller-manager/config/crd/bases/metal.sidero.dev_servers.yaml b/app/sidero-controller-manager/config/crd/bases/metal.sidero.dev_servers.yaml index df6777103..3468139ee 100644 --- a/app/sidero-controller-manager/config/crd/bases/metal.sidero.dev_servers.yaml +++ b/app/sidero-controller-manager/config/crd/bases/metal.sidero.dev_servers.yaml @@ -339,6 +339,452 @@ spec: type: object type: object served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - description: server hostname + jsonPath: .spec.hostname + name: Hostname + type: string + - description: BMC IP + jsonPath: .spec.bmc.endpoint + name: BMC IP + priority: 1 + type: string + - description: indicates if the server is accepted + jsonPath: .spec.accepted + name: Accepted + type: boolean + - description: indicates if the server is cordoned + jsonPath: .spec.cordoned + name: Cordoned + type: boolean + - description: indicates that the server has been allocated + jsonPath: .status.inUse + name: Allocated + type: boolean + - description: indicates if the server is clean or not + jsonPath: .status.isClean + name: Clean + type: boolean + - description: display the current power status + jsonPath: .status.power + name: Power + type: string + - description: The age of this resource + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 + schema: + openAPIV3Schema: + description: Server is the Schema for the servers API. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ServerSpec defines the desired state of Server. + properties: + accepted: + type: boolean + bmc: + description: BMC defines data about how to talk to the node via ipmitool. + properties: + endpoint: + description: BMC endpoint. + type: string + interface: + description: BMC Interface Type. Defaults to lanplus. + type: string + pass: + description: BMC password value. + type: string + passFrom: + description: Source for the password value. Cannot be used if + Pass is not empty. + properties: + secretKeyRef: + description: SecretKeyRef defines a ref to a given key within + a secret. + properties: + key: + description: Key to select + type: string + name: + type: string + namespace: + description: 'Namespace and name of credential secret + nb: can''t use namespacedname here b/c it doesn''t have + json tags in the struct :(' + type: string + required: + - key + - name + - namespace + type: object + type: object + port: + description: BMC port. Defaults to 623. + format: int32 + type: integer + user: + description: BMC user value. + type: string + userFrom: + description: Source for the user value. Cannot be used if User + is not empty. + properties: + secretKeyRef: + description: SecretKeyRef defines a ref to a given key within + a secret. + properties: + key: + description: Key to select + type: string + name: + type: string + namespace: + description: 'Namespace and name of credential secret + nb: can''t use namespacedname here b/c it doesn''t have + json tags in the struct :(' + type: string + required: + - key + - name + - namespace + type: object + type: object + required: + - endpoint + type: object + bootFromDiskMethod: + description: "BootFromDiskMethod specifies the method to exit iPXE + to force boot from disk. \n If not set, controller default is used. + Valid values: ipxe-exit, http-404, ipxe-sanboot." + type: string + configPatches: + items: + properties: + op: + type: string + path: + type: string + value: + x-kubernetes-preserve-unknown-fields: true + required: + - op + - path + type: object + type: array + cordoned: + type: boolean + environmentRef: + description: 'ObjectReference contains enough information to let you + inspect or modify the referred object. --- New uses of this type + are discouraged because of difficulty describing its usage when + embedded in APIs. 1. Ignored fields. It includes many fields which + are not generally honored. For instance, ResourceVersion and FieldPath + are both very rarely valid in actual usage. 2. Invalid usage help. It + is impossible to add specific help for individual usage. In most + embedded usages, there are particular restrictions like, "must + refer only to types A and B" or "UID not honored" or "name must + be restricted". Those cannot be well described when embedded. 3. + Inconsistent validation. Because the usages are different, the + validation rules are different by usage, which makes it hard for + users to predict what will happen. 4. The fields are both imprecise + and overly precise. Kind is not a precise mapping to a URL. This + can produce ambiguity during interpretation and require a REST + mapping. In most cases, the dependency is on the group,resource + tuple and the version of the actual struct is irrelevant. 5. + We cannot easily change it. Because this type is embedded in many + locations, updates to this type will affect numerous schemas. Don''t + make new APIs embed an underspecified API type they do not control. + Instead of using this type, create a locally provided and used type + that is well-focused on your reference. For example, ServiceReferences + for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533 + .' + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: 'If referring to a piece of an object instead of + an entire object, this string should contain a valid JSON/Go + field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within + a pod, this would take on a value like: "spec.containers{name}" + (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" + (container with index 2 in this pod). This syntax is chosen + only to have some well-defined way of referencing a part of + an object. TODO: this design is not final and this field is + subject to change in the future.' + type: string + kind: + description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + namespace: + description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/' + type: string + resourceVersion: + description: 'Specific resourceVersion to which this reference + is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency' + type: string + uid: + description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids' + type: string + type: object + hardware: + properties: + compute: + properties: + processorCount: + format: int32 + type: integer + processors: + items: + properties: + coreCount: + format: int32 + type: integer + manufacturer: + type: string + productName: + type: string + serialNumber: + type: string + speed: + description: Speed is in megahertz (Mhz) + format: int32 + type: integer + threadCount: + format: int32 + type: integer + type: object + type: array + totalCoreCount: + format: int32 + type: integer + totalThreadCount: + format: int32 + type: integer + type: object + memory: + properties: + moduleCount: + format: int32 + type: integer + modules: + items: + properties: + manufacturer: + type: string + productName: + type: string + serialNumber: + type: string + size: + description: Size is in megabytes (MB) + format: int32 + type: integer + speed: + description: Speed is in megatransfers per second (MT/S) + format: int32 + type: integer + type: + type: string + type: object + type: array + totalSize: + type: string + type: object + network: + properties: + interfaceCount: + format: int32 + type: integer + interfaces: + items: + properties: + addresses: + items: + type: string + type: array + flags: + type: string + index: + format: int32 + type: integer + mac: + type: string + mtu: + format: int32 + type: integer + name: + type: string + type: object + type: array + type: object + storage: + properties: + deviceCount: + format: int32 + type: integer + devices: + items: + properties: + deviceName: + type: string + name: + type: string + productName: + type: string + serialNumber: + type: string + size: + description: Size is in bytes + format: int64 + type: integer + type: + type: string + uuid: + type: string + wwid: + type: string + type: object + type: array + totalSize: + type: string + type: object + system: + properties: + family: + type: string + manufacturer: + type: string + productName: + type: string + serialNumber: + type: string + skuNumber: + type: string + uuid: + type: string + version: + type: string + type: object + type: object + hostname: + type: string + managementApi: + description: ManagementAPI defines data about how to talk to the node + via simple HTTP API. + properties: + endpoint: + type: string + required: + - endpoint + type: object + pxeBootAlways: + type: boolean + required: + - accepted + type: object + status: + description: ServerStatus defines the observed state of Server. + properties: + addresses: + description: Addresses lists discovered node IPs. + items: + description: NodeAddress contains information for the node's address. + properties: + address: + description: The node address. + type: string + type: + description: Node address type, one of Hostname, ExternalIP + or InternalIP. + type: string + required: + - address + - type + type: object + type: array + conditions: + description: Conditions defines current service state of the Server. + items: + description: Condition defines an observation of a Cluster API resource + operational state. + properties: + lastTransitionTime: + description: Last time the condition transitioned from one status + to another. This should be when the underlying condition changed. + If that is not known, then using the time when the API field + changed is acceptable. + format: date-time + type: string + message: + description: A human readable message indicating details about + the transition. This field may be empty. + type: string + reason: + description: The reason for the condition's last transition + in CamelCase. The specific API may choose whether or not this + field is considered a guaranteed API. This field may not be + empty. + type: string + severity: + description: Severity provides an explicit classification of + Reason code, so the users or machines can immediately understand + the current situation and act accordingly. The Severity field + MUST be set only when Status=False. + type: string + status: + description: Status of the condition, one of True, False, Unknown. + type: string + type: + description: Type of condition in CamelCase or in foo.example.com/CamelCase. + Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. + type: string + required: + - lastTransitionTime + - status + - type + type: object + type: array + inUse: + description: InUse is true when server is assigned to some MetalMachine. + type: boolean + isClean: + description: IsClean is true when server disks are wiped. + type: boolean + power: + description: 'Power is the current power state of the server: "on", + "off" or "unknown".' + type: string + ready: + description: Ready is true when server is accepted and in use. + type: boolean + type: object + type: object + served: true storage: true subresources: status: {} diff --git a/app/sidero-controller-manager/config/crd/kustomization.yaml b/app/sidero-controller-manager/config/crd/kustomization.yaml index eb4523e0f..02160e519 100644 --- a/app/sidero-controller-manager/config/crd/kustomization.yaml +++ b/app/sidero-controller-manager/config/crd/kustomization.yaml @@ -2,29 +2,29 @@ # since it depends on service name and namespace that are out of this kustomize package. # It should be run by config/default resources: -- bases/metal.sidero.dev_environments.yaml -- bases/metal.sidero.dev_servers.yaml -- bases/metal.sidero.dev_serverclasses.yaml + - bases/metal.sidero.dev_environments.yaml + - bases/metal.sidero.dev_servers.yaml + - bases/metal.sidero.dev_serverclasses.yaml # +kubebuilder:scaffold:crdkustomizeresource commonLabels: clusterctl.cluster.x-k8s.io/move: "" patchesStrategicMerge: -# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix. -# patches here are for enabling the conversion webhook for each CRD -#- patches/webhook_in_environments.yaml -#- patches/webhook_in_servers.yaml -#- patches/webhook_in_serverclasses.yaml -# +kubebuilder:scaffold:crdkustomizewebhookpatch + # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix. + # patches here are for enabling the conversion webhook for each CRD + - patches/webhook_in_environments.yaml + - patches/webhook_in_servers.yaml + - patches/webhook_in_serverclasses.yaml + # +kubebuilder:scaffold:crdkustomizewebhookpatch -# [CERTMANAGER] To enable webhook, uncomment all the sections with [CERTMANAGER] prefix. -# patches here are for enabling the CA injection for each CRD -#- patches/cainjection_in_environments.yaml -#- patches/cainjection_in_servers.yaml -#- patches/cainjection_in_serverclasses.yaml + # [CERTMANAGER] To enable webhook, uncomment all the sections with [CERTMANAGER] prefix. + # patches here are for enabling the CA injection for each CRD + - patches/cainjection_in_environments.yaml + - patches/cainjection_in_servers.yaml + - patches/cainjection_in_serverclasses.yaml # +kubebuilder:scaffold:crdkustomizecainjectionpatch # the following config is for teaching kustomize how to do kustomization for CRDs. configurations: -- kustomizeconfig.yaml + - kustomizeconfig.yaml diff --git a/app/sidero-controller-manager/config/crd/kustomizeconfig.yaml b/app/sidero-controller-manager/config/crd/kustomizeconfig.yaml index 6f83d9a94..c86040980 100644 --- a/app/sidero-controller-manager/config/crd/kustomizeconfig.yaml +++ b/app/sidero-controller-manager/config/crd/kustomizeconfig.yaml @@ -1,17 +1,11 @@ # This file is for teaching kustomize how to substitute name and namespace reference in CRD nameReference: -- kind: Service - version: v1 - fieldSpecs: - - kind: CustomResourceDefinition - group: apiextensions.k8s.io - path: spec/conversion/webhookClientConfig/service/name - -namespace: -- kind: CustomResourceDefinition - group: apiextensions.k8s.io - path: spec/conversion/webhookClientConfig/service/namespace - create: false + - kind: Service + version: v1 + fieldSpecs: + - kind: CustomResourceDefinition + group: apiextensions.k8s.io + path: spec/conversion/webhook/clientConfig/service/name varReference: -- path: metadata/annotations + - path: metadata/annotations diff --git a/app/sidero-controller-manager/config/crd/patches/cainjection_in_environments.yaml b/app/sidero-controller-manager/config/crd/patches/cainjection_in_environments.yaml index 91fc9ab43..c0af1c1ca 100644 --- a/app/sidero-controller-manager/config/crd/patches/cainjection_in_environments.yaml +++ b/app/sidero-controller-manager/config/crd/patches/cainjection_in_environments.yaml @@ -1,6 +1,6 @@ # The following patch adds a directive for certmanager to inject CA into the CRD # CRD conversion requires k8s 1.13 or later. -apiVersion: apiextensions.k8s.io/v1beta1 +apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: diff --git a/app/sidero-controller-manager/config/crd/patches/cainjection_in_serverclasses.yaml b/app/sidero-controller-manager/config/crd/patches/cainjection_in_serverclasses.yaml index 6dc47f854..b6a4bc65a 100644 --- a/app/sidero-controller-manager/config/crd/patches/cainjection_in_serverclasses.yaml +++ b/app/sidero-controller-manager/config/crd/patches/cainjection_in_serverclasses.yaml @@ -1,6 +1,6 @@ # The following patch adds a directive for certmanager to inject CA into the CRD # CRD conversion requires k8s 1.13 or later. -apiVersion: apiextensions.k8s.io/v1beta1 +apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: diff --git a/app/sidero-controller-manager/config/crd/patches/cainjection_in_servers.yaml b/app/sidero-controller-manager/config/crd/patches/cainjection_in_servers.yaml index d5d9a02dd..19bb11845 100644 --- a/app/sidero-controller-manager/config/crd/patches/cainjection_in_servers.yaml +++ b/app/sidero-controller-manager/config/crd/patches/cainjection_in_servers.yaml @@ -1,6 +1,6 @@ # The following patch adds a directive for certmanager to inject CA into the CRD # CRD conversion requires k8s 1.13 or later. -apiVersion: apiextensions.k8s.io/v1beta1 +apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: diff --git a/app/sidero-controller-manager/config/crd/patches/webhook_in_environments.yaml b/app/sidero-controller-manager/config/crd/patches/webhook_in_environments.yaml index 3c264e887..b66be96c2 100644 --- a/app/sidero-controller-manager/config/crd/patches/webhook_in_environments.yaml +++ b/app/sidero-controller-manager/config/crd/patches/webhook_in_environments.yaml @@ -1,17 +1,19 @@ # The following patch enables conversion webhook for CRD # CRD conversion requires k8s 1.13 or later. -apiVersion: apiextensions.k8s.io/v1beta1 +apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: environments.metal.sidero.dev spec: conversion: strategy: Webhook - webhookClientConfig: - # this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank, - # but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager) - caBundle: Cg== - service: - namespace: system - name: webhook-service - path: /convert + webhook: + conversionReviewVersions: ["v1", "v1beta1"] + clientConfig: + # this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank, + # but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager) + caBundle: Cg== + service: + namespace: system + name: webhook-service + path: /convert diff --git a/app/sidero-controller-manager/config/crd/patches/webhook_in_serverclasses.yaml b/app/sidero-controller-manager/config/crd/patches/webhook_in_serverclasses.yaml index f784b1027..73196078f 100644 --- a/app/sidero-controller-manager/config/crd/patches/webhook_in_serverclasses.yaml +++ b/app/sidero-controller-manager/config/crd/patches/webhook_in_serverclasses.yaml @@ -1,17 +1,19 @@ # The following patch enables conversion webhook for CRD # CRD conversion requires k8s 1.13 or later. -apiVersion: apiextensions.k8s.io/v1beta1 +apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: serverclasses.metal.sidero.dev spec: conversion: strategy: Webhook - webhookClientConfig: - # this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank, - # but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager) - caBundle: Cg== - service: - namespace: system - name: webhook-service - path: /convert + webhook: + conversionReviewVersions: ["v1", "v1beta1"] + clientConfig: + # this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank, + # but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager) + caBundle: Cg== + service: + namespace: system + name: webhook-service + path: /convert diff --git a/app/sidero-controller-manager/config/crd/patches/webhook_in_servers.yaml b/app/sidero-controller-manager/config/crd/patches/webhook_in_servers.yaml index 404ad5977..99a9aa48e 100644 --- a/app/sidero-controller-manager/config/crd/patches/webhook_in_servers.yaml +++ b/app/sidero-controller-manager/config/crd/patches/webhook_in_servers.yaml @@ -1,17 +1,19 @@ # The following patch enables conversion webhook for CRD # CRD conversion requires k8s 1.13 or later. -apiVersion: apiextensions.k8s.io/v1beta1 +apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: servers.metal.sidero.dev spec: conversion: strategy: Webhook - webhookClientConfig: - # this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank, - # but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager) - caBundle: Cg== - service: - namespace: system - name: webhook-service - path: /convert + webhook: + conversionReviewVersions: ["v1", "v1beta1"] + clientConfig: + # this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank, + # but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager) + caBundle: Cg== + service: + namespace: system + name: webhook-service + path: /convert diff --git a/app/sidero-controller-manager/config/default/kustomization.yaml b/app/sidero-controller-manager/config/default/kustomization.yaml new file mode 100644 index 000000000..ddfac90f5 --- /dev/null +++ b/app/sidero-controller-manager/config/default/kustomization.yaml @@ -0,0 +1,29 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +namespace: sidero-system + +namePrefix: sidero- + +# Labels to add to all resources and selectors. +commonLabels: + cluster.x-k8s.io/provider: "infrastructure-sidero" + +resources: + - ../crd + - ../rbac + - ../manager +# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. +#- ../prometheus + +#patchesStrategicMerge: + # Protect the /metrics endpoint by putting it behind auth. + # Only one of manager_auth_proxy_patch.yaml and + # manager_prometheus_metrics_patch.yaml should be enabled. + #- manager_auth_proxy_patch.yaml + # If you want your controller-manager to expose the /metrics + # endpoint w/o any authn/z, uncomment the following line and + # comment manager_auth_proxy_patch.yaml. + # Only one of manager_auth_proxy_patch.yaml and + # manager_prometheus_metrics_patch.yaml should be enabled. + #- manager_prometheus_metrics_patch.yaml \ No newline at end of file diff --git a/app/sidero-controller-manager/config/kustomization.yaml b/app/sidero-controller-manager/config/kustomization.yaml deleted file mode 100644 index 2d6c596c0..000000000 --- a/app/sidero-controller-manager/config/kustomization.yaml +++ /dev/null @@ -1,67 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -bases: - - crd - - rbac - - manager -# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in crd/kustomization.yaml -#- ../webhook -# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required. -#- ../certmanager -# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. -#- ../prometheus - -namePrefix: sidero- - -patchesStrategicMerge: - # Protect the /metrics endpoint by putting it behind auth. - # Only one of manager_auth_proxy_patch.yaml and - # manager_prometheus_metrics_patch.yaml should be enabled. - #- manager_auth_proxy_patch.yaml - # If you want your controller-manager to expose the /metrics - # endpoint w/o any authn/z, uncomment the following line and - # comment manager_auth_proxy_patch.yaml. - # Only one of manager_auth_proxy_patch.yaml and - # manager_prometheus_metrics_patch.yaml should be enabled. -#- manager_prometheus_metrics_patch.yaml - -# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in crd/kustomization.yaml -#- manager_webhook_patch.yaml - -# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. -# Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks. -# 'CERTMANAGER' needs to be enabled to use ca injection -#- webhookcainjection_patch.yaml - -# the following config is for teaching kustomize how to do var substitution -vars: -# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix. -#- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR -# objref: -# kind: Certificate -# group: cert-manager.io -# version: v1 -# name: serving-cert # this name should match the one in certificate.yaml -# fieldref: -# fieldpath: metadata.namespace -#- name: CERTIFICATE_NAME -# objref: -# kind: Certificate -# group: cert-manager.io -# version: v1 -# name: serving-cert # this name should match the one in certificate.yaml -#- name: SERVICE_NAMESPACE # namespace of the service -# objref: -# kind: Service -# version: v1 -# name: webhook-service -# fieldref: -# fieldpath: metadata.namespace -#- name: SERVICE_NAME -# objref: -# kind: Service -# version: v1 -# name: webhook-service - -namespace: sidero-system diff --git a/app/sidero-controller-manager/config/manager/manager.yaml b/app/sidero-controller-manager/config/manager/manager.yaml index 62f556d13..d167facc5 100644 --- a/app/sidero-controller-manager/config/manager/manager.yaml +++ b/app/sidero-controller-manager/config/manager/manager.yaml @@ -49,6 +49,8 @@ spec: matchLabels: control-plane: sidero-controller-manager replicas: 1 + strategy: + type: ${SIDERO_CONTROLLER_MANAGER_DEPLOYMENT_STRATEGY:=RollingUpdate} template: metadata: labels: @@ -56,7 +58,10 @@ spec: spec: hostNetwork: ${SIDERO_CONTROLLER_MANAGER_HOST_NETWORK:=false} containers: - - command: + - name: manager + image: controller:latest + imagePullPolicy: Always + command: - /manager args: - --metrics-bind-addr=127.0.0.1:8080 @@ -72,9 +77,6 @@ spec: - --ipmi-pxe-method=${SIDERO_CONTROLLER_MANAGER_IPMI_PXE_METHOD:=uefi} - --test-power-simulated-explicit-failure-prob=${SIDERO_CONTROLLER_MANAGER_TEST_POWER_EXPLICIT_FAILURE:=0} - --test-power-simulated-silent-failure-prob=${SIDERO_CONTROLLER_MANAGER_TEST_POWER_SILENT_FAILURE:=0} - image: controller:latest - imagePullPolicy: Always - name: manager ports: - name: tftp containerPort: 69 @@ -105,14 +107,14 @@ spec: httpGet: path: /healthz port: healthz - - command: + - name: siderolink + image: controller:latest + imagePullPolicy: Always + command: - /siderolink-manager args: - --wireguard-endpoint=${SIDERO_CONTROLLER_MANAGER_SIDEROLINK_ENDPOINT:=-} - --wireguard-port=${SIDERO_CONTROLLER_MANAGER_SIDEROLINK_PORT:=51821} - image: controller:latest - imagePullPolicy: Always - name: siderolink env: - name: API_ENDPOINT valueFrom: @@ -137,11 +139,11 @@ spec: volumeMounts: - mountPath: /dev/net/tun name: dev-tun - - command: - - /log-receiver + - name: serverlogs image: controller:latest imagePullPolicy: Always - name: serverlogs + command: + - /log-receiver resources: limits: cpu: 256m @@ -149,11 +151,11 @@ spec: requests: cpu: 50m memory: 128Mi - - command: - - /events-manager + - name: serverevents image: controller:latest imagePullPolicy: Always - name: serverevents + command: + - /events-manager resources: limits: cpu: 256m @@ -162,8 +164,9 @@ spec: cpu: 50m memory: 128Mi volumes: - - hostPath: + - name: dev-tun + hostPath: path: /dev/net/tun type: CharDevice - name: dev-tun + terminationGracePeriodSeconds: 10 diff --git a/app/sidero-controller-manager/config/manager_webhook_patch.yaml b/app/sidero-controller-manager/config/manager_webhook_patch.yaml deleted file mode 100644 index 738de350b..000000000 --- a/app/sidero-controller-manager/config/manager_webhook_patch.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: controller-manager - namespace: system -spec: - template: - spec: - containers: - - name: manager - ports: - - containerPort: 9443 - name: webhook-server - protocol: TCP - volumeMounts: - - mountPath: /tmp/k8s-webhook-server/serving-certs - name: cert - readOnly: true - volumes: - - name: cert - secret: - defaultMode: 420 - secretName: webhook-server-cert diff --git a/app/sidero-controller-manager/config/prometheus/monitor.yaml b/app/sidero-controller-manager/config/prometheus/monitor.yaml index 77aff0521..028ccd47e 100644 --- a/app/sidero-controller-manager/config/prometheus/monitor.yaml +++ b/app/sidero-controller-manager/config/prometheus/monitor.yaml @@ -3,7 +3,7 @@ apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: labels: - control-plane: caps-controller-manager + control-plane: sidero-controller-manager name: metrics-monitor namespace: system spec: @@ -11,4 +11,4 @@ spec: - path: /metrics port: https selector: - control-plane: caps-controller-manager + control-plane: sidero-controller-manager diff --git a/app/sidero-controller-manager/config/rbac/auth_proxy_service.yaml b/app/sidero-controller-manager/config/rbac/auth_proxy_service.yaml index 7b290b306..41dcd3c90 100644 --- a/app/sidero-controller-manager/config/rbac/auth_proxy_service.yaml +++ b/app/sidero-controller-manager/config/rbac/auth_proxy_service.yaml @@ -2,7 +2,7 @@ apiVersion: v1 kind: Service metadata: labels: - control-plane: caps-controller-manager + control-plane: sidero-controller-manager name: controller-manager-metrics-service namespace: system spec: @@ -11,4 +11,4 @@ spec: port: 8443 targetPort: https selector: - control-plane: caps-controller-manager + control-plane: sidero-controller-manager diff --git a/app/sidero-controller-manager/config/samples/metal_v1alpha1_server.yaml b/app/sidero-controller-manager/config/samples/metal_v1alpha1_server.yaml deleted file mode 100644 index f46b21ae7..000000000 --- a/app/sidero-controller-manager/config/samples/metal_v1alpha1_server.yaml +++ /dev/null @@ -1,27 +0,0 @@ -apiVersion: metal.sidero.dev/v1alpha1 -kind: Server -metadata: - name: 00000000-0000-0000-0000-d05099d333e0 - labels: - common-label: "true" - zone: east - environment: test -spec: - accepted: false - configPatches: - - op: replace - path: /cluster/network/cni - value: - name: custom - urls: - - http://192.168.1.199/assets/cilium.yaml - cpu: - manufacturer: Intel(R) Corporation - version: Intel(R) Atom(TM) CPU C3558 @ 2.20GHz - system: - family: Unknown - manufacturer: Unknown - productName: Unknown - serialNumber: Unknown - skuNumber: Unknown - version: Unknown diff --git a/app/sidero-controller-manager/config/samples/metal_v1alpha1_serverclass.yaml b/app/sidero-controller-manager/config/samples/metal_v1alpha1_serverclass.yaml deleted file mode 100644 index f6260a88e..000000000 --- a/app/sidero-controller-manager/config/samples/metal_v1alpha1_serverclass.yaml +++ /dev/null @@ -1,29 +0,0 @@ -apiVersion: metal.sidero.dev/v1alpha1 -kind: ServerClass -metadata: - name: serverclass-sample -spec: - selector: - matchLabels: - common-label: "true" - matchExpressions: - - key: zone - operator: In - values: - - central - - east - - key: environment - operator: NotIn - values: - - prod - qualifiers: - cpu: - - manufacturer: "Intel(R) Corporation" - version: "Intel(R) Atom(TM) CPU C3558 @ 2.20GHz" - systemInformation: - - family: Unknown - manufacturer: Unknown - productName: Unknown - serialNumber: Unknown - skuNumber: Unknown - version: Unknown diff --git a/app/sidero-controller-manager/config/samples/metal_v1alpha1_environment.yaml b/app/sidero-controller-manager/config/samples/metal_v1alpha2_environment.yaml similarity index 95% rename from app/sidero-controller-manager/config/samples/metal_v1alpha1_environment.yaml rename to app/sidero-controller-manager/config/samples/metal_v1alpha2_environment.yaml index b3790ae53..d0cec81d5 100644 --- a/app/sidero-controller-manager/config/samples/metal_v1alpha1_environment.yaml +++ b/app/sidero-controller-manager/config/samples/metal_v1alpha2_environment.yaml @@ -1,4 +1,4 @@ -apiVersion: metal.sidero.dev/v1alpha1 +apiVersion: metal.sidero.dev/v1alpha2 kind: Environment metadata: name: default diff --git a/app/sidero-controller-manager/config/samples/metal_v1alpha2_server.yaml b/app/sidero-controller-manager/config/samples/metal_v1alpha2_server.yaml new file mode 100644 index 000000000..2ffb570bb --- /dev/null +++ b/app/sidero-controller-manager/config/samples/metal_v1alpha2_server.yaml @@ -0,0 +1,77 @@ +apiVersion: metal.sidero.dev/v1alpha2 +kind: Server +metadata: + name: 00000000-0000-0000-0000-d05099d333e0 + labels: + common-label: "true" + zone: east + environment: test +spec: + accepted: false + configPatches: + - op: replace + path: /cluster/network/cni + value: + name: custom + urls: + - http://192.168.1.199/assets/cilium.yaml + hardware: + system: + manufacturer: Dell Inc. + productName: PowerEdge R630 + serialNumber: 790H8D2 + compute: + totalCoreCount: 8 + totalThreadCount: 16 + processorCount: 1 + processors: + - manufacturer: Intel + productName: Intel(R) Xeon(R) CPU E5-2630 v3 @ 2.40GHz + speed: 2400 + coreCount: 8 + threadCount: 16 + memory: + totalSize: 32 GB + moduleCount: 2 + modules: + - 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: + totalSize: 1116 GB + deviceCount: 1 + devices: + - productName: PERC H730 Mini + type: HDD + name: sda + deviceName: /dev/sda + size: 1199101181952 + wwid: naa.61866da055de070028d8e83307cc6df2 + network: + interfaceCount: 2 + interfaces: + - index: 1 + name: lo + flags: up|loopback + mtu: 65536 + mac: "" + addresses: + - 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: + - 192.168.2.8/24 + - fe80::dcb3:295c:755b:91bb/64 diff --git a/app/sidero-controller-manager/config/samples/metal_v1alpha2_serverclass.yaml b/app/sidero-controller-manager/config/samples/metal_v1alpha2_serverclass.yaml new file mode 100644 index 000000000..ab3c3336f --- /dev/null +++ b/app/sidero-controller-manager/config/samples/metal_v1alpha2_serverclass.yaml @@ -0,0 +1,27 @@ +apiVersion: metal.sidero.dev/v1alpha2 +kind: ServerClass +metadata: + name: serverclass-sample +spec: + selector: + matchLabels: + common-label: "true" + matchExpressions: + - key: zone + operator: In + values: + - central + - east + - key: environment + operator: NotIn + values: + - prod + qualifiers: + - system: + manufacturer: Dell Inc. + compute: + processors: + - manufacturer: "Intel" + productName: "Intel(R) Xeon(R) CPU E5-2630 v3 @ 2.40GHz" + memory: + totalSize: 32 GB diff --git a/app/sidero-controller-manager/config/webhook/kustomization.yaml b/app/sidero-controller-manager/config/webhook/kustomization.yaml deleted file mode 100644 index 7ed6560ae..000000000 --- a/app/sidero-controller-manager/config/webhook/kustomization.yaml +++ /dev/null @@ -1,5 +0,0 @@ -resources: - - service.yaml - -configurations: - - kustomizeconfig.yaml diff --git a/app/sidero-controller-manager/config/webhook/kustomizeconfig.yaml b/app/sidero-controller-manager/config/webhook/kustomizeconfig.yaml deleted file mode 100644 index 25e21e3c9..000000000 --- a/app/sidero-controller-manager/config/webhook/kustomizeconfig.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# the following config is for teaching kustomize where to look at when substituting vars. -# It requires kustomize v2.1.0 or newer to work properly. -nameReference: -- kind: Service - version: v1 - fieldSpecs: - - kind: MutatingWebhookConfiguration - group: admissionregistration.k8s.io - path: webhooks/clientConfig/service/name - - kind: ValidatingWebhookConfiguration - group: admissionregistration.k8s.io - path: webhooks/clientConfig/service/name - -namespace: -- kind: MutatingWebhookConfiguration - group: admissionregistration.k8s.io - path: webhooks/clientConfig/service/namespace - create: true -- kind: ValidatingWebhookConfiguration - group: admissionregistration.k8s.io - path: webhooks/clientConfig/service/namespace - create: true - -varReference: -- path: metadata/annotations diff --git a/app/sidero-controller-manager/config/webhook/service.yaml b/app/sidero-controller-manager/config/webhook/service.yaml deleted file mode 100644 index ad5d8bab7..000000000 --- a/app/sidero-controller-manager/config/webhook/service.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: webhook-service - namespace: system -spec: - ports: - - port: 443 - targetPort: 9443 - selector: - control-plane: caps-controller-manager diff --git a/app/sidero-controller-manager/config/webhookcainjection_patch.yaml b/app/sidero-controller-manager/config/webhookcainjection_patch.yaml deleted file mode 100644 index 7e79bf995..000000000 --- a/app/sidero-controller-manager/config/webhookcainjection_patch.yaml +++ /dev/null @@ -1,15 +0,0 @@ -# This patch add annotation to admission webhook config and -# the variables $(CERTIFICATE_NAMESPACE) and $(CERTIFICATE_NAME) will be substituted by kustomize. -apiVersion: admissionregistration.k8s.io/v1beta1 -kind: MutatingWebhookConfiguration -metadata: - name: mutating-webhook-configuration - annotations: - cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) ---- -apiVersion: admissionregistration.k8s.io/v1beta1 -kind: ValidatingWebhookConfiguration -metadata: - name: validating-webhook-configuration - annotations: - cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) diff --git a/app/sidero-controller-manager/controllers/environment_controller.go b/app/sidero-controller-manager/controllers/environment_controller.go index 32ea581bc..460c21f70 100644 --- a/app/sidero-controller-manager/controllers/environment_controller.go +++ b/app/sidero-controller-manager/controllers/environment_controller.go @@ -24,7 +24,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller" - metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha1" + metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" "github.com/talos-systems/sidero/app/sidero-controller-manager/pkg/constants" ) diff --git a/app/sidero-controller-manager/controllers/server_controller.go b/app/sidero-controller-manager/controllers/server_controller.go index 053ebe2cf..f7b86ce6f 100644 --- a/app/sidero-controller-manager/controllers/server_controller.go +++ b/app/sidero-controller-manager/controllers/server_controller.go @@ -31,7 +31,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/source" infrav1 "github.com/talos-systems/sidero/app/caps-controller-manager/api/v1alpha3" - metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha1" + metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" "github.com/talos-systems/sidero/app/sidero-controller-manager/internal/power" "github.com/talos-systems/sidero/app/sidero-controller-manager/internal/power/metal" "github.com/talos-systems/sidero/app/sidero-controller-manager/pkg/constants" diff --git a/app/sidero-controller-manager/controllers/serverclass_controller.go b/app/sidero-controller-manager/controllers/serverclass_controller.go index 47c8733da..7c494c7f4 100644 --- a/app/sidero-controller-manager/controllers/serverclass_controller.go +++ b/app/sidero-controller-manager/controllers/serverclass_controller.go @@ -20,7 +20,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" "sigs.k8s.io/controller-runtime/pkg/source" - metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha1" + metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" ) // ServerClassReconciler reconciles a ServerClass object. diff --git a/app/sidero-controller-manager/controllers/suite_test.go b/app/sidero-controller-manager/controllers/suite_test.go index 142d78fc1..057160681 100644 --- a/app/sidero-controller-manager/controllers/suite_test.go +++ b/app/sidero-controller-manager/controllers/suite_test.go @@ -18,7 +18,7 @@ import ( logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" - metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha1" + metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" // +kubebuilder:scaffold:imports ) diff --git a/app/sidero-controller-manager/internal/api/api.pb.go b/app/sidero-controller-manager/internal/api/api.pb.go index 614ee0e7f..19861df24 100644 --- a/app/sidero-controller-manager/internal/api/api.pb.go +++ b/app/sidero-controller-manager/internal/api/api.pb.go @@ -21,6 +21,61 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +type StorageType int32 + +const ( + StorageType_Unknown StorageType = 0 + StorageType_SSD StorageType = 1 + StorageType_HDD StorageType = 2 + StorageType_NVMe StorageType = 3 + StorageType_SD StorageType = 4 +) + +// Enum value maps for StorageType. +var ( + StorageType_name = map[int32]string{ + 0: "Unknown", + 1: "SSD", + 2: "HDD", + 3: "NVMe", + 4: "SD", + } + StorageType_value = map[string]int32{ + "Unknown": 0, + "SSD": 1, + "HDD": 2, + "NVMe": 3, + "SD": 4, + } +) + +func (x StorageType) Enum() *StorageType { + p := new(StorageType) + *p = x + return p +} + +func (x StorageType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (StorageType) Descriptor() protoreflect.EnumDescriptor { + return file_api_proto_enumTypes[0].Descriptor() +} + +func (StorageType) Type() protoreflect.EnumType { + return &file_api_proto_enumTypes[0] +} + +func (x StorageType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use StorageType.Descriptor instead. +func (StorageType) EnumDescriptor() ([]byte, []int) { + return file_api_proto_rawDescGZIP(), []int{0} +} + type BMCInfo struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -92,37 +147,605 @@ func (x *BMCInfo) GetPass() string { return "" } -type SystemInformation struct { +type SystemInformation struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` + Manufacturer string `protobuf:"bytes,2,opt,name=manufacturer,proto3" json:"manufacturer,omitempty"` + ProductName string `protobuf:"bytes,3,opt,name=product_name,json=productName,proto3" json:"product_name,omitempty"` + Version string `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"` + SerialNumber string `protobuf:"bytes,5,opt,name=serial_number,json=serialNumber,proto3" json:"serial_number,omitempty"` + SkuNumber string `protobuf:"bytes,6,opt,name=sku_number,json=skuNumber,proto3" json:"sku_number,omitempty"` + Family string `protobuf:"bytes,7,opt,name=family,proto3" json:"family,omitempty"` +} + +func (x *SystemInformation) Reset() { + *x = SystemInformation{} + if protoimpl.UnsafeEnabled { + mi := &file_api_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SystemInformation) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SystemInformation) ProtoMessage() {} + +func (x *SystemInformation) ProtoReflect() protoreflect.Message { + mi := &file_api_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SystemInformation.ProtoReflect.Descriptor instead. +func (*SystemInformation) Descriptor() ([]byte, []int) { + return file_api_proto_rawDescGZIP(), []int{1} +} + +func (x *SystemInformation) GetUuid() string { + if x != nil { + return x.Uuid + } + return "" +} + +func (x *SystemInformation) GetManufacturer() string { + if x != nil { + return x.Manufacturer + } + return "" +} + +func (x *SystemInformation) GetProductName() string { + if x != nil { + return x.ProductName + } + return "" +} + +func (x *SystemInformation) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *SystemInformation) GetSerialNumber() string { + if x != nil { + return x.SerialNumber + } + return "" +} + +func (x *SystemInformation) GetSkuNumber() string { + if x != nil { + return x.SkuNumber + } + return "" +} + +func (x *SystemInformation) GetFamily() string { + if x != nil { + return x.Family + } + return "" +} + +type Processor struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Manufacturer string `protobuf:"bytes,1,opt,name=manufacturer,proto3" json:"manufacturer,omitempty"` + ProductName string `protobuf:"bytes,2,opt,name=product_name,json=productName,proto3" json:"product_name,omitempty"` + SerialNumber string `protobuf:"bytes,3,opt,name=serial_number,json=serialNumber,proto3" json:"serial_number,omitempty"` + Speed uint32 `protobuf:"varint,4,opt,name=speed,proto3" json:"speed,omitempty"` + CoreCount uint32 `protobuf:"varint,5,opt,name=core_count,json=coreCount,proto3" json:"core_count,omitempty"` + ThreadCount uint32 `protobuf:"varint,6,opt,name=thread_count,json=threadCount,proto3" json:"thread_count,omitempty"` +} + +func (x *Processor) Reset() { + *x = Processor{} + if protoimpl.UnsafeEnabled { + mi := &file_api_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Processor) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Processor) ProtoMessage() {} + +func (x *Processor) ProtoReflect() protoreflect.Message { + mi := &file_api_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Processor.ProtoReflect.Descriptor instead. +func (*Processor) Descriptor() ([]byte, []int) { + return file_api_proto_rawDescGZIP(), []int{2} +} + +func (x *Processor) GetManufacturer() string { + if x != nil { + return x.Manufacturer + } + return "" +} + +func (x *Processor) GetProductName() string { + if x != nil { + return x.ProductName + } + return "" +} + +func (x *Processor) GetSerialNumber() string { + if x != nil { + return x.SerialNumber + } + return "" +} + +func (x *Processor) GetSpeed() uint32 { + if x != nil { + return x.Speed + } + return 0 +} + +func (x *Processor) GetCoreCount() uint32 { + if x != nil { + return x.CoreCount + } + return 0 +} + +func (x *Processor) GetThreadCount() uint32 { + if x != nil { + return x.ThreadCount + } + return 0 +} + +type ComputeInformation struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TotalCoreCount uint32 `protobuf:"varint,1,opt,name=total_core_count,json=totalCoreCount,proto3" json:"total_core_count,omitempty"` + TotalThreadCount uint32 `protobuf:"varint,2,opt,name=total_thread_count,json=totalThreadCount,proto3" json:"total_thread_count,omitempty"` + ProcessorCount uint32 `protobuf:"varint,3,opt,name=processor_count,json=processorCount,proto3" json:"processor_count,omitempty"` + Processors []*Processor `protobuf:"bytes,4,rep,name=processors,proto3" json:"processors,omitempty"` +} + +func (x *ComputeInformation) Reset() { + *x = ComputeInformation{} + if protoimpl.UnsafeEnabled { + mi := &file_api_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ComputeInformation) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ComputeInformation) ProtoMessage() {} + +func (x *ComputeInformation) ProtoReflect() protoreflect.Message { + mi := &file_api_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ComputeInformation.ProtoReflect.Descriptor instead. +func (*ComputeInformation) Descriptor() ([]byte, []int) { + return file_api_proto_rawDescGZIP(), []int{3} +} + +func (x *ComputeInformation) GetTotalCoreCount() uint32 { + if x != nil { + return x.TotalCoreCount + } + return 0 +} + +func (x *ComputeInformation) GetTotalThreadCount() uint32 { + if x != nil { + return x.TotalThreadCount + } + return 0 +} + +func (x *ComputeInformation) GetProcessorCount() uint32 { + if x != nil { + return x.ProcessorCount + } + return 0 +} + +func (x *ComputeInformation) GetProcessors() []*Processor { + if x != nil { + return x.Processors + } + return nil +} + +type MemoryModule struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Manufacturer string `protobuf:"bytes,1,opt,name=manufacturer,proto3" json:"manufacturer,omitempty"` + ProductName string `protobuf:"bytes,2,opt,name=product_name,json=productName,proto3" json:"product_name,omitempty"` + SerialNumber string `protobuf:"bytes,3,opt,name=serial_number,json=serialNumber,proto3" json:"serial_number,omitempty"` + Type string `protobuf:"bytes,4,opt,name=type,proto3" json:"type,omitempty"` + Size uint32 `protobuf:"varint,5,opt,name=size,proto3" json:"size,omitempty"` + Speed uint32 `protobuf:"varint,6,opt,name=speed,proto3" json:"speed,omitempty"` +} + +func (x *MemoryModule) Reset() { + *x = MemoryModule{} + if protoimpl.UnsafeEnabled { + mi := &file_api_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MemoryModule) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MemoryModule) ProtoMessage() {} + +func (x *MemoryModule) ProtoReflect() protoreflect.Message { + mi := &file_api_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MemoryModule.ProtoReflect.Descriptor instead. +func (*MemoryModule) Descriptor() ([]byte, []int) { + return file_api_proto_rawDescGZIP(), []int{4} +} + +func (x *MemoryModule) GetManufacturer() string { + if x != nil { + return x.Manufacturer + } + return "" +} + +func (x *MemoryModule) GetProductName() string { + if x != nil { + return x.ProductName + } + return "" +} + +func (x *MemoryModule) GetSerialNumber() string { + if x != nil { + return x.SerialNumber + } + return "" +} + +func (x *MemoryModule) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +func (x *MemoryModule) GetSize() uint32 { + if x != nil { + return x.Size + } + return 0 +} + +func (x *MemoryModule) GetSpeed() uint32 { + if x != nil { + return x.Speed + } + return 0 +} + +type MemoryInformation struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TotalSize uint32 `protobuf:"varint,1,opt,name=total_size,json=totalSize,proto3" json:"total_size,omitempty"` + ModuleCount uint32 `protobuf:"varint,2,opt,name=module_count,json=moduleCount,proto3" json:"module_count,omitempty"` + Modules []*MemoryModule `protobuf:"bytes,3,rep,name=modules,proto3" json:"modules,omitempty"` +} + +func (x *MemoryInformation) Reset() { + *x = MemoryInformation{} + if protoimpl.UnsafeEnabled { + mi := &file_api_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MemoryInformation) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MemoryInformation) ProtoMessage() {} + +func (x *MemoryInformation) ProtoReflect() protoreflect.Message { + mi := &file_api_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MemoryInformation.ProtoReflect.Descriptor instead. +func (*MemoryInformation) Descriptor() ([]byte, []int) { + return file_api_proto_rawDescGZIP(), []int{5} +} + +func (x *MemoryInformation) GetTotalSize() uint32 { + if x != nil { + return x.TotalSize + } + return 0 +} + +func (x *MemoryInformation) GetModuleCount() uint32 { + if x != nil { + return x.ModuleCount + } + return 0 +} + +func (x *MemoryInformation) GetModules() []*MemoryModule { + if x != nil { + return x.Modules + } + return nil +} + +type StorageDevice struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type StorageType `protobuf:"varint,1,opt,name=type,proto3,enum=api.StorageType" json:"type,omitempty"` + Size uint64 `protobuf:"varint,2,opt,name=size,proto3" json:"size,omitempty"` + Model string `protobuf:"bytes,3,opt,name=model,proto3" json:"model,omitempty"` + Serial string `protobuf:"bytes,4,opt,name=serial,proto3" json:"serial,omitempty"` + Name string `protobuf:"bytes,5,opt,name=name,proto3" json:"name,omitempty"` + DeviceName string `protobuf:"bytes,6,opt,name=device_name,json=deviceName,proto3" json:"device_name,omitempty"` + Uuid string `protobuf:"bytes,7,opt,name=uuid,proto3" json:"uuid,omitempty"` + Wwid string `protobuf:"bytes,8,opt,name=wwid,proto3" json:"wwid,omitempty"` +} + +func (x *StorageDevice) Reset() { + *x = StorageDevice{} + if protoimpl.UnsafeEnabled { + mi := &file_api_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *StorageDevice) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StorageDevice) ProtoMessage() {} + +func (x *StorageDevice) ProtoReflect() protoreflect.Message { + mi := &file_api_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StorageDevice.ProtoReflect.Descriptor instead. +func (*StorageDevice) Descriptor() ([]byte, []int) { + return file_api_proto_rawDescGZIP(), []int{6} +} + +func (x *StorageDevice) GetType() StorageType { + if x != nil { + return x.Type + } + return StorageType_Unknown +} + +func (x *StorageDevice) GetSize() uint64 { + if x != nil { + return x.Size + } + return 0 +} + +func (x *StorageDevice) GetModel() string { + if x != nil { + return x.Model + } + return "" +} + +func (x *StorageDevice) GetSerial() string { + if x != nil { + return x.Serial + } + return "" +} + +func (x *StorageDevice) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *StorageDevice) GetDeviceName() string { + if x != nil { + return x.DeviceName + } + return "" +} + +func (x *StorageDevice) GetUuid() string { + if x != nil { + return x.Uuid + } + return "" +} + +func (x *StorageDevice) GetWwid() string { + if x != nil { + return x.Wwid + } + return "" +} + +type StorageInformation struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TotalSize uint64 `protobuf:"varint,1,opt,name=total_size,json=totalSize,proto3" json:"total_size,omitempty"` + DeviceCount uint32 `protobuf:"varint,2,opt,name=device_count,json=deviceCount,proto3" json:"device_count,omitempty"` + Devices []*StorageDevice `protobuf:"bytes,3,rep,name=devices,proto3" json:"devices,omitempty"` +} + +func (x *StorageInformation) Reset() { + *x = StorageInformation{} + if protoimpl.UnsafeEnabled { + mi := &file_api_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *StorageInformation) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StorageInformation) ProtoMessage() {} + +func (x *StorageInformation) ProtoReflect() protoreflect.Message { + mi := &file_api_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StorageInformation.ProtoReflect.Descriptor instead. +func (*StorageInformation) Descriptor() ([]byte, []int) { + return file_api_proto_rawDescGZIP(), []int{7} +} + +func (x *StorageInformation) GetTotalSize() uint64 { + if x != nil { + return x.TotalSize + } + return 0 +} + +func (x *StorageInformation) GetDeviceCount() uint32 { + if x != nil { + return x.DeviceCount + } + return 0 +} + +func (x *StorageInformation) GetDevices() []*StorageDevice { + if x != nil { + return x.Devices + } + return nil +} + +type NetworkInterface struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` - Manufacturer string `protobuf:"bytes,2,opt,name=manufacturer,proto3" json:"manufacturer,omitempty"` - ProductName string `protobuf:"bytes,3,opt,name=product_name,json=productName,proto3" json:"product_name,omitempty"` - Version string `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"` - SerialNumber string `protobuf:"bytes,5,opt,name=serial_number,json=serialNumber,proto3" json:"serial_number,omitempty"` - SkuNumber string `protobuf:"bytes,6,opt,name=sku_number,json=skuNumber,proto3" json:"sku_number,omitempty"` - Family string `protobuf:"bytes,7,opt,name=family,proto3" json:"family,omitempty"` + Index uint32 `protobuf:"varint,1,opt,name=index,proto3" json:"index,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Flags string `protobuf:"bytes,3,opt,name=flags,proto3" json:"flags,omitempty"` + Mtu uint32 `protobuf:"varint,4,opt,name=mtu,proto3" json:"mtu,omitempty"` + Mac string `protobuf:"bytes,5,opt,name=mac,proto3" json:"mac,omitempty"` + Addresses []string `protobuf:"bytes,6,rep,name=addresses,proto3" json:"addresses,omitempty"` } -func (x *SystemInformation) Reset() { - *x = SystemInformation{} +func (x *NetworkInterface) Reset() { + *x = NetworkInterface{} if protoimpl.UnsafeEnabled { - mi := &file_api_proto_msgTypes[1] + mi := &file_api_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *SystemInformation) String() string { +func (x *NetworkInterface) String() string { return protoimpl.X.MessageStringOf(x) } -func (*SystemInformation) ProtoMessage() {} +func (*NetworkInterface) ProtoMessage() {} -func (x *SystemInformation) ProtoReflect() protoreflect.Message { - mi := &file_api_proto_msgTypes[1] +func (x *NetworkInterface) ProtoReflect() protoreflect.Message { + mi := &file_api_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -133,86 +756,137 @@ func (x *SystemInformation) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use SystemInformation.ProtoReflect.Descriptor instead. -func (*SystemInformation) Descriptor() ([]byte, []int) { - return file_api_proto_rawDescGZIP(), []int{1} +// Deprecated: Use NetworkInterface.ProtoReflect.Descriptor instead. +func (*NetworkInterface) Descriptor() ([]byte, []int) { + return file_api_proto_rawDescGZIP(), []int{8} } -func (x *SystemInformation) GetUuid() string { +func (x *NetworkInterface) GetIndex() uint32 { if x != nil { - return x.Uuid + return x.Index } - return "" + return 0 } -func (x *SystemInformation) GetManufacturer() string { +func (x *NetworkInterface) GetName() string { if x != nil { - return x.Manufacturer + return x.Name } return "" } -func (x *SystemInformation) GetProductName() string { +func (x *NetworkInterface) GetFlags() string { if x != nil { - return x.ProductName + return x.Flags } return "" } -func (x *SystemInformation) GetVersion() string { +func (x *NetworkInterface) GetMtu() uint32 { if x != nil { - return x.Version + return x.Mtu } - return "" + return 0 } -func (x *SystemInformation) GetSerialNumber() string { +func (x *NetworkInterface) GetMac() string { if x != nil { - return x.SerialNumber + return x.Mac } return "" } -func (x *SystemInformation) GetSkuNumber() string { +func (x *NetworkInterface) GetAddresses() []string { if x != nil { - return x.SkuNumber + return x.Addresses } - return "" + return nil } -func (x *SystemInformation) GetFamily() string { +type NetworkInformation struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + InterfaceCount uint32 `protobuf:"varint,1,opt,name=interface_count,json=interfaceCount,proto3" json:"interface_count,omitempty"` + Interfaces []*NetworkInterface `protobuf:"bytes,2,rep,name=interfaces,proto3" json:"interfaces,omitempty"` +} + +func (x *NetworkInformation) Reset() { + *x = NetworkInformation{} + if protoimpl.UnsafeEnabled { + mi := &file_api_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NetworkInformation) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NetworkInformation) ProtoMessage() {} + +func (x *NetworkInformation) ProtoReflect() protoreflect.Message { + mi := &file_api_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NetworkInformation.ProtoReflect.Descriptor instead. +func (*NetworkInformation) Descriptor() ([]byte, []int) { + return file_api_proto_rawDescGZIP(), []int{9} +} + +func (x *NetworkInformation) GetInterfaceCount() uint32 { if x != nil { - return x.Family + return x.InterfaceCount } - return "" + return 0 +} + +func (x *NetworkInformation) GetInterfaces() []*NetworkInterface { + if x != nil { + return x.Interfaces + } + return nil } -type CPU struct { +type HardwareInformation struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Manufacturer string `protobuf:"bytes,1,opt,name=manufacturer,proto3" json:"manufacturer,omitempty"` - Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` + System *SystemInformation `protobuf:"bytes,1,opt,name=system,proto3" json:"system,omitempty"` + Compute *ComputeInformation `protobuf:"bytes,2,opt,name=compute,proto3" json:"compute,omitempty"` + Memory *MemoryInformation `protobuf:"bytes,3,opt,name=memory,proto3" json:"memory,omitempty"` + Storage *StorageInformation `protobuf:"bytes,4,opt,name=storage,proto3" json:"storage,omitempty"` + Network *NetworkInformation `protobuf:"bytes,5,opt,name=network,proto3" json:"network,omitempty"` } -func (x *CPU) Reset() { - *x = CPU{} +func (x *HardwareInformation) Reset() { + *x = HardwareInformation{} if protoimpl.UnsafeEnabled { - mi := &file_api_proto_msgTypes[2] + mi := &file_api_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *CPU) String() string { +func (x *HardwareInformation) String() string { return protoimpl.X.MessageStringOf(x) } -func (*CPU) ProtoMessage() {} +func (*HardwareInformation) ProtoMessage() {} -func (x *CPU) ProtoReflect() protoreflect.Message { - mi := &file_api_proto_msgTypes[2] +func (x *HardwareInformation) ProtoReflect() protoreflect.Message { + mi := &file_api_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -223,23 +897,44 @@ func (x *CPU) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use CPU.ProtoReflect.Descriptor instead. -func (*CPU) Descriptor() ([]byte, []int) { - return file_api_proto_rawDescGZIP(), []int{2} +// Deprecated: Use HardwareInformation.ProtoReflect.Descriptor instead. +func (*HardwareInformation) Descriptor() ([]byte, []int) { + return file_api_proto_rawDescGZIP(), []int{10} } -func (x *CPU) GetManufacturer() string { +func (x *HardwareInformation) GetSystem() *SystemInformation { if x != nil { - return x.Manufacturer + return x.System } - return "" + return nil } -func (x *CPU) GetVersion() string { +func (x *HardwareInformation) GetCompute() *ComputeInformation { if x != nil { - return x.Version + return x.Compute } - return "" + return nil +} + +func (x *HardwareInformation) GetMemory() *MemoryInformation { + if x != nil { + return x.Memory + } + return nil +} + +func (x *HardwareInformation) GetStorage() *StorageInformation { + if x != nil { + return x.Storage + } + return nil +} + +func (x *HardwareInformation) GetNetwork() *NetworkInformation { + if x != nil { + return x.Network + } + return nil } type CreateServerRequest struct { @@ -247,15 +942,14 @@ type CreateServerRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - SystemInformation *SystemInformation `protobuf:"bytes,1,opt,name=system_information,json=systemInformation,proto3" json:"system_information,omitempty"` - Cpu *CPU `protobuf:"bytes,2,opt,name=cpu,proto3" json:"cpu,omitempty"` - Hostname string `protobuf:"bytes,3,opt,name=hostname,proto3" json:"hostname,omitempty"` + Hardware *HardwareInformation `protobuf:"bytes,1,opt,name=hardware,proto3" json:"hardware,omitempty"` + Hostname string `protobuf:"bytes,3,opt,name=hostname,proto3" json:"hostname,omitempty"` } func (x *CreateServerRequest) Reset() { *x = CreateServerRequest{} if protoimpl.UnsafeEnabled { - mi := &file_api_proto_msgTypes[3] + mi := &file_api_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -268,7 +962,7 @@ func (x *CreateServerRequest) String() string { func (*CreateServerRequest) ProtoMessage() {} func (x *CreateServerRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_proto_msgTypes[3] + mi := &file_api_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -281,19 +975,12 @@ func (x *CreateServerRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateServerRequest.ProtoReflect.Descriptor instead. func (*CreateServerRequest) Descriptor() ([]byte, []int) { - return file_api_proto_rawDescGZIP(), []int{3} -} - -func (x *CreateServerRequest) GetSystemInformation() *SystemInformation { - if x != nil { - return x.SystemInformation - } - return nil + return file_api_proto_rawDescGZIP(), []int{11} } -func (x *CreateServerRequest) GetCpu() *CPU { +func (x *CreateServerRequest) GetHardware() *HardwareInformation { if x != nil { - return x.Cpu + return x.Hardware } return nil } @@ -317,7 +1004,7 @@ type Address struct { func (x *Address) Reset() { *x = Address{} if protoimpl.UnsafeEnabled { - mi := &file_api_proto_msgTypes[4] + mi := &file_api_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -330,7 +1017,7 @@ func (x *Address) String() string { func (*Address) ProtoMessage() {} func (x *Address) ProtoReflect() protoreflect.Message { - mi := &file_api_proto_msgTypes[4] + mi := &file_api_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -343,7 +1030,7 @@ func (x *Address) ProtoReflect() protoreflect.Message { // Deprecated: Use Address.ProtoReflect.Descriptor instead. func (*Address) Descriptor() ([]byte, []int) { - return file_api_proto_rawDescGZIP(), []int{4} + return file_api_proto_rawDescGZIP(), []int{12} } func (x *Address) GetType() string { @@ -374,7 +1061,7 @@ type CreateServerResponse struct { func (x *CreateServerResponse) Reset() { *x = CreateServerResponse{} if protoimpl.UnsafeEnabled { - mi := &file_api_proto_msgTypes[5] + mi := &file_api_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -387,7 +1074,7 @@ func (x *CreateServerResponse) String() string { func (*CreateServerResponse) ProtoMessage() {} func (x *CreateServerResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_proto_msgTypes[5] + mi := &file_api_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -400,7 +1087,7 @@ func (x *CreateServerResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateServerResponse.ProtoReflect.Descriptor instead. func (*CreateServerResponse) Descriptor() ([]byte, []int) { - return file_api_proto_rawDescGZIP(), []int{5} + return file_api_proto_rawDescGZIP(), []int{13} } func (x *CreateServerResponse) GetWipe() bool { @@ -442,7 +1129,7 @@ type MarkServerAsWipedRequest struct { func (x *MarkServerAsWipedRequest) Reset() { *x = MarkServerAsWipedRequest{} if protoimpl.UnsafeEnabled { - mi := &file_api_proto_msgTypes[6] + mi := &file_api_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -455,7 +1142,7 @@ func (x *MarkServerAsWipedRequest) String() string { func (*MarkServerAsWipedRequest) ProtoMessage() {} func (x *MarkServerAsWipedRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_proto_msgTypes[6] + mi := &file_api_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -468,7 +1155,7 @@ func (x *MarkServerAsWipedRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use MarkServerAsWipedRequest.ProtoReflect.Descriptor instead. func (*MarkServerAsWipedRequest) Descriptor() ([]byte, []int) { - return file_api_proto_rawDescGZIP(), []int{6} + return file_api_proto_rawDescGZIP(), []int{14} } func (x *MarkServerAsWipedRequest) GetUuid() string { @@ -489,7 +1176,7 @@ type HeartbeatRequest struct { func (x *HeartbeatRequest) Reset() { *x = HeartbeatRequest{} if protoimpl.UnsafeEnabled { - mi := &file_api_proto_msgTypes[7] + mi := &file_api_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -502,7 +1189,7 @@ func (x *HeartbeatRequest) String() string { func (*HeartbeatRequest) ProtoMessage() {} func (x *HeartbeatRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_proto_msgTypes[7] + mi := &file_api_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -515,7 +1202,7 @@ func (x *HeartbeatRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use HeartbeatRequest.ProtoReflect.Descriptor instead. func (*HeartbeatRequest) Descriptor() ([]byte, []int) { - return file_api_proto_rawDescGZIP(), []int{7} + return file_api_proto_rawDescGZIP(), []int{15} } func (x *HeartbeatRequest) GetUuid() string { @@ -534,7 +1221,7 @@ type MarkServerAsWipedResponse struct { func (x *MarkServerAsWipedResponse) Reset() { *x = MarkServerAsWipedResponse{} if protoimpl.UnsafeEnabled { - mi := &file_api_proto_msgTypes[8] + mi := &file_api_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -547,7 +1234,7 @@ func (x *MarkServerAsWipedResponse) String() string { func (*MarkServerAsWipedResponse) ProtoMessage() {} func (x *MarkServerAsWipedResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_proto_msgTypes[8] + mi := &file_api_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -560,7 +1247,7 @@ func (x *MarkServerAsWipedResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use MarkServerAsWipedResponse.ProtoReflect.Descriptor instead. func (*MarkServerAsWipedResponse) Descriptor() ([]byte, []int) { - return file_api_proto_rawDescGZIP(), []int{8} + return file_api_proto_rawDescGZIP(), []int{16} } type HeartbeatResponse struct { @@ -572,7 +1259,7 @@ type HeartbeatResponse struct { func (x *HeartbeatResponse) Reset() { *x = HeartbeatResponse{} if protoimpl.UnsafeEnabled { - mi := &file_api_proto_msgTypes[9] + mi := &file_api_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -585,7 +1272,7 @@ func (x *HeartbeatResponse) String() string { func (*HeartbeatResponse) ProtoMessage() {} func (x *HeartbeatResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_proto_msgTypes[9] + mi := &file_api_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -598,7 +1285,7 @@ func (x *HeartbeatResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use HeartbeatResponse.ProtoReflect.Descriptor instead. func (*HeartbeatResponse) Descriptor() ([]byte, []int) { - return file_api_proto_rawDescGZIP(), []int{9} + return file_api_proto_rawDescGZIP(), []int{17} } type UpdateBMCInfoRequest struct { @@ -613,7 +1300,7 @@ type UpdateBMCInfoRequest struct { func (x *UpdateBMCInfoRequest) Reset() { *x = UpdateBMCInfoRequest{} if protoimpl.UnsafeEnabled { - mi := &file_api_proto_msgTypes[10] + mi := &file_api_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -626,7 +1313,7 @@ func (x *UpdateBMCInfoRequest) String() string { func (*UpdateBMCInfoRequest) ProtoMessage() {} func (x *UpdateBMCInfoRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_proto_msgTypes[10] + mi := &file_api_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -639,7 +1326,7 @@ func (x *UpdateBMCInfoRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateBMCInfoRequest.ProtoReflect.Descriptor instead. func (*UpdateBMCInfoRequest) Descriptor() ([]byte, []int) { - return file_api_proto_rawDescGZIP(), []int{10} + return file_api_proto_rawDescGZIP(), []int{18} } func (x *UpdateBMCInfoRequest) GetUuid() string { @@ -665,7 +1352,7 @@ type UpdateBMCInfoResponse struct { func (x *UpdateBMCInfoResponse) Reset() { *x = UpdateBMCInfoResponse{} if protoimpl.UnsafeEnabled { - mi := &file_api_proto_msgTypes[11] + mi := &file_api_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -678,7 +1365,7 @@ func (x *UpdateBMCInfoResponse) String() string { func (*UpdateBMCInfoResponse) ProtoMessage() {} func (x *UpdateBMCInfoResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_proto_msgTypes[11] + mi := &file_api_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -691,7 +1378,7 @@ func (x *UpdateBMCInfoResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateBMCInfoResponse.ProtoReflect.Descriptor instead. func (*UpdateBMCInfoResponse) Descriptor() ([]byte, []int) { - return file_api_proto_rawDescGZIP(), []int{11} + return file_api_proto_rawDescGZIP(), []int{19} } type ReconcileServerAddressesRequest struct { @@ -706,7 +1393,7 @@ type ReconcileServerAddressesRequest struct { func (x *ReconcileServerAddressesRequest) Reset() { *x = ReconcileServerAddressesRequest{} if protoimpl.UnsafeEnabled { - mi := &file_api_proto_msgTypes[12] + mi := &file_api_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -719,7 +1406,7 @@ func (x *ReconcileServerAddressesRequest) String() string { func (*ReconcileServerAddressesRequest) ProtoMessage() {} func (x *ReconcileServerAddressesRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_proto_msgTypes[12] + mi := &file_api_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -732,7 +1419,7 @@ func (x *ReconcileServerAddressesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ReconcileServerAddressesRequest.ProtoReflect.Descriptor instead. func (*ReconcileServerAddressesRequest) Descriptor() ([]byte, []int) { - return file_api_proto_rawDescGZIP(), []int{12} + return file_api_proto_rawDescGZIP(), []int{20} } func (x *ReconcileServerAddressesRequest) GetUuid() string { @@ -758,7 +1445,7 @@ type ReconcileServerAddressesResponse struct { func (x *ReconcileServerAddressesResponse) Reset() { *x = ReconcileServerAddressesResponse{} if protoimpl.UnsafeEnabled { - mi := &file_api_proto_msgTypes[13] + mi := &file_api_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -771,7 +1458,7 @@ func (x *ReconcileServerAddressesResponse) String() string { func (*ReconcileServerAddressesResponse) ProtoMessage() {} func (x *ReconcileServerAddressesResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_proto_msgTypes[13] + mi := &file_api_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -784,7 +1471,7 @@ func (x *ReconcileServerAddressesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ReconcileServerAddressesResponse.ProtoReflect.Descriptor instead. func (*ReconcileServerAddressesResponse) Descriptor() ([]byte, []int) { - return file_api_proto_rawDescGZIP(), []int{13} + return file_api_proto_rawDescGZIP(), []int{21} } var File_api_proto protoreflect.FileDescriptor @@ -810,88 +1497,186 @@ var file_api_proto_rawDesc = []byte{ 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x6b, 0x75, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x6b, 0x75, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x22, 0x43, - 0x0a, 0x03, 0x43, 0x50, 0x55, 0x12, 0x22, 0x0a, 0x0c, 0x6d, 0x61, 0x6e, 0x75, 0x66, 0x61, 0x63, - 0x74, 0x75, 0x72, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x61, 0x6e, - 0x75, 0x66, 0x61, 0x63, 0x74, 0x75, 0x72, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x22, 0x94, 0x01, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x45, 0x0a, 0x12, 0x73, - 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x79, - 0x73, 0x74, 0x65, 0x6d, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x11, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x03, 0x63, 0x70, 0x75, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x08, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x50, 0x55, 0x52, 0x03, 0x63, 0x70, 0x75, 0x12, 0x1a, - 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x37, 0x0a, 0x07, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x22, 0x93, 0x01, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, - 0x77, 0x69, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x77, 0x69, 0x70, 0x65, - 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x5f, 0x77, 0x69, 0x70, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, - 0x65, 0x57, 0x69, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x65, 0x74, 0x75, 0x70, 0x5f, 0x62, - 0x6d, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x73, 0x65, 0x74, 0x75, 0x70, 0x42, - 0x6d, 0x63, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x65, 0x62, 0x6f, 0x6f, 0x74, 0x5f, 0x74, 0x69, 0x6d, - 0x65, 0x6f, 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0d, 0x72, 0x65, 0x62, 0x6f, - 0x6f, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, 0x2e, 0x0a, 0x18, 0x4d, 0x61, 0x72, - 0x6b, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x73, 0x57, 0x69, 0x70, 0x65, 0x64, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x22, 0x26, 0x0a, 0x10, 0x48, 0x65, 0x61, - 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, - 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, - 0x64, 0x22, 0x1b, 0x0a, 0x19, 0x4d, 0x61, 0x72, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, - 0x73, 0x57, 0x69, 0x70, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x13, - 0x0a, 0x11, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x53, 0x0a, 0x14, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x4d, 0x43, - 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x75, - 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, - 0x27, 0x0a, 0x08, 0x62, 0x6d, 0x63, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x42, 0x4d, 0x43, 0x49, 0x6e, 0x66, 0x6f, 0x52, - 0x07, 0x62, 0x6d, 0x63, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x17, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x42, 0x4d, 0x43, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x5d, 0x0a, 0x1f, 0x52, 0x65, 0x63, 0x6f, 0x6e, 0x63, 0x69, 0x6c, 0x65, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x26, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x22, 0x22, 0x0a, 0x20, 0x52, 0x65, 0x63, 0x6f, 0x6e, 0x63, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x8d, 0x03, 0x0a, 0x05, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12, 0x43, - 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x18, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x52, 0x0a, 0x11, 0x4d, 0x61, 0x72, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x41, 0x73, 0x57, 0x69, 0x70, 0x65, 0x64, 0x12, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4d, - 0x61, 0x72, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x73, 0x57, 0x69, 0x70, 0x65, 0x64, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4d, 0x61, - 0x72, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x73, 0x57, 0x69, 0x70, 0x65, 0x64, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x67, 0x0a, 0x18, 0x52, 0x65, 0x63, 0x6f, 0x6e, - 0x63, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x65, 0x73, 0x12, 0x24, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x6e, 0x63, - 0x69, 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x52, 0x65, 0x63, 0x6f, 0x6e, 0x63, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x3a, 0x0a, 0x09, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x12, 0x15, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x48, 0x65, 0x61, 0x72, 0x74, - 0x62, 0x65, 0x61, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x0d, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x4d, 0x43, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x19, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x4d, 0x43, 0x49, 0x6e, 0x66, - 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x55, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x22, 0xcf, + 0x01, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x12, 0x22, 0x0a, 0x0c, + 0x6d, 0x61, 0x6e, 0x75, 0x66, 0x61, 0x63, 0x74, 0x75, 0x72, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x61, 0x6e, 0x75, 0x66, 0x61, 0x63, 0x74, 0x75, 0x72, 0x65, 0x72, + 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4e, + 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x6e, 0x75, + 0x6d, 0x62, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x69, + 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x70, 0x65, 0x65, + 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x73, 0x70, 0x65, 0x65, 0x64, 0x12, 0x1d, + 0x0a, 0x0a, 0x63, 0x6f, 0x72, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x09, 0x63, 0x6f, 0x72, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x21, 0x0a, + 0x0c, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, + 0x22, 0xc5, 0x01, 0x0a, 0x12, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f, + 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x6f, 0x74, 0x61, 0x6c, + 0x5f, 0x63, 0x6f, 0x72, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x0e, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x72, 0x65, 0x43, 0x6f, 0x75, 0x6e, + 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x61, + 0x64, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x10, 0x74, + 0x6f, 0x74, 0x61, 0x6c, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, + 0x27, 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x5f, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, + 0x73, 0x6f, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2e, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x63, + 0x65, 0x73, 0x73, 0x6f, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x52, 0x0a, 0x70, 0x72, + 0x6f, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x73, 0x22, 0xb8, 0x01, 0x0a, 0x0c, 0x4d, 0x65, 0x6d, + 0x6f, 0x72, 0x79, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x6d, 0x61, 0x6e, + 0x75, 0x66, 0x61, 0x63, 0x74, 0x75, 0x72, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0c, 0x6d, 0x61, 0x6e, 0x75, 0x66, 0x61, 0x63, 0x74, 0x75, 0x72, 0x65, 0x72, 0x12, 0x21, 0x0a, + 0x0c, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, + 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, + 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, + 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x14, 0x0a, + 0x05, 0x73, 0x70, 0x65, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x73, 0x70, + 0x65, 0x65, 0x64, 0x22, 0x82, 0x01, 0x0a, 0x11, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x49, 0x6e, + 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x6f, 0x74, + 0x61, 0x6c, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x74, + 0x6f, 0x74, 0x61, 0x6c, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x6f, 0x64, 0x75, + 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, + 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2b, 0x0a, 0x07, 0x6d, + 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x52, + 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x22, 0xd4, 0x01, 0x0a, 0x0d, 0x53, 0x74, 0x6f, + 0x72, 0x61, 0x67, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x24, 0x0a, 0x04, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, + 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, + 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, + 0x73, 0x69, 0x7a, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, + 0x72, 0x69, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x65, 0x72, 0x69, + 0x61, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x77, + 0x77, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x77, 0x77, 0x69, 0x64, 0x22, + 0x84, 0x01, 0x0a, 0x12, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x72, + 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, + 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x6f, 0x74, 0x61, + 0x6c, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x07, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x07, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x22, 0x94, 0x01, 0x0a, 0x10, 0x4e, 0x65, 0x74, 0x77, 0x6f, + 0x72, 0x6b, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x69, + 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, + 0x78, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x6d, + 0x74, 0x75, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x6d, 0x74, 0x75, 0x12, 0x10, 0x0a, + 0x03, 0x6d, 0x61, 0x63, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6d, 0x61, 0x63, 0x12, + 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x22, 0x74, 0x0a, + 0x12, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, + 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x35, 0x0a, 0x0a, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, + 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x52, 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, + 0x63, 0x65, 0x73, 0x22, 0x8e, 0x02, 0x0a, 0x13, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, + 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, 0x06, 0x73, + 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x31, 0x0a, 0x07, 0x63, + 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x12, 0x2e, + 0x0a, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x72, + 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x12, 0x31, + 0x0a, 0x07, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x49, 0x6e, 0x66, + 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, + 0x65, 0x12, 0x31, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, + 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x6e, 0x65, 0x74, + 0x77, 0x6f, 0x72, 0x6b, 0x22, 0x67, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x34, 0x0a, 0x08, 0x68, + 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x49, 0x6e, 0x66, 0x6f, + 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x68, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, + 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x37, 0x0a, + 0x07, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x93, 0x01, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x12, 0x0a, 0x04, 0x77, 0x69, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x77, + 0x69, 0x70, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x5f, + 0x77, 0x69, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x6e, 0x73, 0x65, + 0x63, 0x75, 0x72, 0x65, 0x57, 0x69, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x65, 0x74, 0x75, + 0x70, 0x5f, 0x62, 0x6d, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x73, 0x65, 0x74, + 0x75, 0x70, 0x42, 0x6d, 0x63, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x65, 0x62, 0x6f, 0x6f, 0x74, 0x5f, + 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0d, 0x72, + 0x65, 0x62, 0x6f, 0x6f, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, 0x2e, 0x0a, 0x18, + 0x4d, 0x61, 0x72, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x73, 0x57, 0x69, 0x70, 0x65, + 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x22, 0x26, 0x0a, 0x10, + 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x75, 0x75, 0x69, 0x64, 0x22, 0x1b, 0x0a, 0x19, 0x4d, 0x61, 0x72, 0x6b, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x41, 0x73, 0x57, 0x69, 0x70, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x13, 0x0a, 0x11, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x53, 0x0a, 0x14, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x42, 0x4d, 0x43, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, + 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, + 0x69, 0x64, 0x12, 0x27, 0x0a, 0x08, 0x62, 0x6d, 0x63, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x42, 0x4d, 0x43, 0x49, 0x6e, + 0x66, 0x6f, 0x52, 0x07, 0x62, 0x6d, 0x63, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x17, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x4d, 0x43, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x4c, 0x5a, 0x4a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x74, 0x61, 0x6c, 0x6f, 0x73, 0x2d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, - 0x2f, 0x73, 0x69, 0x64, 0x65, 0x72, 0x6f, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x73, 0x69, 0x64, 0x65, - 0x72, 0x6f, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2d, 0x6d, 0x61, - 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x61, - 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5d, 0x0a, 0x1f, 0x52, 0x65, 0x63, 0x6f, 0x6e, 0x63, 0x69, 0x6c, + 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x26, 0x0a, 0x07, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x22, 0x22, 0x0a, 0x20, 0x52, 0x65, 0x63, 0x6f, 0x6e, 0x63, 0x69, 0x6c, 0x65, + 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2a, 0x3e, 0x0a, 0x0b, 0x53, 0x74, 0x6f, 0x72, 0x61, + 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, + 0x6e, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x53, 0x53, 0x44, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, + 0x48, 0x44, 0x44, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x56, 0x4d, 0x65, 0x10, 0x03, 0x12, + 0x06, 0x0a, 0x02, 0x53, 0x44, 0x10, 0x04, 0x32, 0x8d, 0x03, 0x0a, 0x05, 0x41, 0x67, 0x65, 0x6e, + 0x74, 0x12, 0x43, 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x12, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x52, 0x0a, 0x11, 0x4d, 0x61, 0x72, 0x6b, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x41, 0x73, 0x57, 0x69, 0x70, 0x65, 0x64, 0x12, 0x1d, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x4d, 0x61, 0x72, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x73, 0x57, 0x69, + 0x70, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x4d, 0x61, 0x72, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x73, 0x57, 0x69, 0x70, + 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x67, 0x0a, 0x18, 0x52, 0x65, + 0x63, 0x6f, 0x6e, 0x63, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x24, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65, 0x63, + 0x6f, 0x6e, 0x63, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x6e, 0x63, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x09, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, + 0x12, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x48, 0x65, + 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x46, 0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x4d, 0x43, 0x49, 0x6e, 0x66, 0x6f, + 0x12, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x4d, 0x43, + 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x4d, 0x43, 0x49, 0x6e, 0x66, 0x6f, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x4c, 0x5a, 0x4a, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x61, 0x6c, 0x6f, 0x73, 0x2d, 0x73, 0x79, 0x73, 0x74, + 0x65, 0x6d, 0x73, 0x2f, 0x73, 0x69, 0x64, 0x65, 0x72, 0x6f, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x73, + 0x69, 0x64, 0x65, 0x72, 0x6f, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, + 0x2d, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2f, 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -907,45 +1692,64 @@ func file_api_proto_rawDescGZIP() []byte { } var ( - file_api_proto_msgTypes = make([]protoimpl.MessageInfo, 14) - file_api_proto_goTypes = []interface{}{ - (*BMCInfo)(nil), // 0: api.BMCInfo - (*SystemInformation)(nil), // 1: api.SystemInformation - (*CPU)(nil), // 2: api.CPU - (*CreateServerRequest)(nil), // 3: api.CreateServerRequest - (*Address)(nil), // 4: api.Address - (*CreateServerResponse)(nil), // 5: api.CreateServerResponse - (*MarkServerAsWipedRequest)(nil), // 6: api.MarkServerAsWipedRequest - (*HeartbeatRequest)(nil), // 7: api.HeartbeatRequest - (*MarkServerAsWipedResponse)(nil), // 8: api.MarkServerAsWipedResponse - (*HeartbeatResponse)(nil), // 9: api.HeartbeatResponse - (*UpdateBMCInfoRequest)(nil), // 10: api.UpdateBMCInfoRequest - (*UpdateBMCInfoResponse)(nil), // 11: api.UpdateBMCInfoResponse - (*ReconcileServerAddressesRequest)(nil), // 12: api.ReconcileServerAddressesRequest - (*ReconcileServerAddressesResponse)(nil), // 13: api.ReconcileServerAddressesResponse + file_api_proto_enumTypes = make([]protoimpl.EnumInfo, 1) + file_api_proto_msgTypes = make([]protoimpl.MessageInfo, 22) + file_api_proto_goTypes = []interface{}{ + (StorageType)(0), // 0: api.StorageType + (*BMCInfo)(nil), // 1: api.BMCInfo + (*SystemInformation)(nil), // 2: api.SystemInformation + (*Processor)(nil), // 3: api.Processor + (*ComputeInformation)(nil), // 4: api.ComputeInformation + (*MemoryModule)(nil), // 5: api.MemoryModule + (*MemoryInformation)(nil), // 6: api.MemoryInformation + (*StorageDevice)(nil), // 7: api.StorageDevice + (*StorageInformation)(nil), // 8: api.StorageInformation + (*NetworkInterface)(nil), // 9: api.NetworkInterface + (*NetworkInformation)(nil), // 10: api.NetworkInformation + (*HardwareInformation)(nil), // 11: api.HardwareInformation + (*CreateServerRequest)(nil), // 12: api.CreateServerRequest + (*Address)(nil), // 13: api.Address + (*CreateServerResponse)(nil), // 14: api.CreateServerResponse + (*MarkServerAsWipedRequest)(nil), // 15: api.MarkServerAsWipedRequest + (*HeartbeatRequest)(nil), // 16: api.HeartbeatRequest + (*MarkServerAsWipedResponse)(nil), // 17: api.MarkServerAsWipedResponse + (*HeartbeatResponse)(nil), // 18: api.HeartbeatResponse + (*UpdateBMCInfoRequest)(nil), // 19: api.UpdateBMCInfoRequest + (*UpdateBMCInfoResponse)(nil), // 20: api.UpdateBMCInfoResponse + (*ReconcileServerAddressesRequest)(nil), // 21: api.ReconcileServerAddressesRequest + (*ReconcileServerAddressesResponse)(nil), // 22: api.ReconcileServerAddressesResponse } ) var file_api_proto_depIdxs = []int32{ - 1, // 0: api.CreateServerRequest.system_information:type_name -> api.SystemInformation - 2, // 1: api.CreateServerRequest.cpu:type_name -> api.CPU - 0, // 2: api.UpdateBMCInfoRequest.bmc_info:type_name -> api.BMCInfo - 4, // 3: api.ReconcileServerAddressesRequest.address:type_name -> api.Address - 3, // 4: api.Agent.CreateServer:input_type -> api.CreateServerRequest - 6, // 5: api.Agent.MarkServerAsWiped:input_type -> api.MarkServerAsWipedRequest - 12, // 6: api.Agent.ReconcileServerAddresses:input_type -> api.ReconcileServerAddressesRequest - 7, // 7: api.Agent.Heartbeat:input_type -> api.HeartbeatRequest - 10, // 8: api.Agent.UpdateBMCInfo:input_type -> api.UpdateBMCInfoRequest - 5, // 9: api.Agent.CreateServer:output_type -> api.CreateServerResponse - 8, // 10: api.Agent.MarkServerAsWiped:output_type -> api.MarkServerAsWipedResponse - 13, // 11: api.Agent.ReconcileServerAddresses:output_type -> api.ReconcileServerAddressesResponse - 9, // 12: api.Agent.Heartbeat:output_type -> api.HeartbeatResponse - 11, // 13: api.Agent.UpdateBMCInfo:output_type -> api.UpdateBMCInfoResponse - 9, // [9:14] is the sub-list for method output_type - 4, // [4:9] is the sub-list for method input_type - 4, // [4:4] is the sub-list for extension type_name - 4, // [4:4] is the sub-list for extension extendee - 0, // [0:4] is the sub-list for field type_name + 3, // 0: api.ComputeInformation.processors:type_name -> api.Processor + 5, // 1: api.MemoryInformation.modules:type_name -> api.MemoryModule + 0, // 2: api.StorageDevice.type:type_name -> api.StorageType + 7, // 3: api.StorageInformation.devices:type_name -> api.StorageDevice + 9, // 4: api.NetworkInformation.interfaces:type_name -> api.NetworkInterface + 2, // 5: api.HardwareInformation.system:type_name -> api.SystemInformation + 4, // 6: api.HardwareInformation.compute:type_name -> api.ComputeInformation + 6, // 7: api.HardwareInformation.memory:type_name -> api.MemoryInformation + 8, // 8: api.HardwareInformation.storage:type_name -> api.StorageInformation + 10, // 9: api.HardwareInformation.network:type_name -> api.NetworkInformation + 11, // 10: api.CreateServerRequest.hardware:type_name -> api.HardwareInformation + 1, // 11: api.UpdateBMCInfoRequest.bmc_info:type_name -> api.BMCInfo + 13, // 12: api.ReconcileServerAddressesRequest.address:type_name -> api.Address + 12, // 13: api.Agent.CreateServer:input_type -> api.CreateServerRequest + 15, // 14: api.Agent.MarkServerAsWiped:input_type -> api.MarkServerAsWipedRequest + 21, // 15: api.Agent.ReconcileServerAddresses:input_type -> api.ReconcileServerAddressesRequest + 16, // 16: api.Agent.Heartbeat:input_type -> api.HeartbeatRequest + 19, // 17: api.Agent.UpdateBMCInfo:input_type -> api.UpdateBMCInfoRequest + 14, // 18: api.Agent.CreateServer:output_type -> api.CreateServerResponse + 17, // 19: api.Agent.MarkServerAsWiped:output_type -> api.MarkServerAsWipedResponse + 22, // 20: api.Agent.ReconcileServerAddresses:output_type -> api.ReconcileServerAddressesResponse + 18, // 21: api.Agent.Heartbeat:output_type -> api.HeartbeatResponse + 20, // 22: api.Agent.UpdateBMCInfo:output_type -> api.UpdateBMCInfoResponse + 18, // [18:23] is the sub-list for method output_type + 13, // [13:18] is the sub-list for method input_type + 13, // [13:13] is the sub-list for extension type_name + 13, // [13:13] is the sub-list for extension extendee + 0, // [0:13] is the sub-list for field type_name } func init() { file_api_proto_init() } @@ -979,7 +1783,7 @@ func file_api_proto_init() { } } file_api_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CPU); i { + switch v := v.(*Processor); i { case 0: return &v.state case 1: @@ -991,7 +1795,7 @@ func file_api_proto_init() { } } file_api_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CreateServerRequest); i { + switch v := v.(*ComputeInformation); i { case 0: return &v.state case 1: @@ -1003,7 +1807,7 @@ func file_api_proto_init() { } } file_api_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Address); i { + switch v := v.(*MemoryModule); i { case 0: return &v.state case 1: @@ -1015,7 +1819,7 @@ func file_api_proto_init() { } } file_api_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CreateServerResponse); i { + switch v := v.(*MemoryInformation); i { case 0: return &v.state case 1: @@ -1027,7 +1831,7 @@ func file_api_proto_init() { } } file_api_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*MarkServerAsWipedRequest); i { + switch v := v.(*StorageDevice); i { case 0: return &v.state case 1: @@ -1039,7 +1843,7 @@ func file_api_proto_init() { } } file_api_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HeartbeatRequest); i { + switch v := v.(*StorageInformation); i { case 0: return &v.state case 1: @@ -1051,7 +1855,7 @@ func file_api_proto_init() { } } file_api_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*MarkServerAsWipedResponse); i { + switch v := v.(*NetworkInterface); i { case 0: return &v.state case 1: @@ -1063,7 +1867,7 @@ func file_api_proto_init() { } } file_api_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HeartbeatResponse); i { + switch v := v.(*NetworkInformation); i { case 0: return &v.state case 1: @@ -1075,7 +1879,7 @@ func file_api_proto_init() { } } file_api_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UpdateBMCInfoRequest); i { + switch v := v.(*HardwareInformation); i { case 0: return &v.state case 1: @@ -1087,7 +1891,7 @@ func file_api_proto_init() { } } file_api_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UpdateBMCInfoResponse); i { + switch v := v.(*CreateServerRequest); i { case 0: return &v.state case 1: @@ -1099,7 +1903,7 @@ func file_api_proto_init() { } } file_api_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ReconcileServerAddressesRequest); i { + switch v := v.(*Address); i { case 0: return &v.state case 1: @@ -1111,6 +1915,102 @@ func file_api_proto_init() { } } file_api_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreateServerResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MarkServerAsWipedRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HeartbeatRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MarkServerAsWipedResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HeartbeatResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UpdateBMCInfoRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UpdateBMCInfoResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ReconcileServerAddressesRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ReconcileServerAddressesResponse); i { case 0: return &v.state @@ -1128,13 +2028,14 @@ func file_api_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_api_proto_rawDesc, - NumEnums: 0, - NumMessages: 14, + NumEnums: 1, + NumMessages: 22, NumExtensions: 0, NumServices: 1, }, GoTypes: file_api_proto_goTypes, DependencyIndexes: file_api_proto_depIdxs, + EnumInfos: file_api_proto_enumTypes, MessageInfos: file_api_proto_msgTypes, }.Build() File_api_proto = out.File diff --git a/app/sidero-controller-manager/internal/api/api.proto b/app/sidero-controller-manager/internal/api/api.proto index da142a338..9716201ba 100644 --- a/app/sidero-controller-manager/internal/api/api.proto +++ b/app/sidero-controller-manager/internal/api/api.proto @@ -32,14 +32,86 @@ message SystemInformation { string family = 7; } -message CPU { +message Processor { string manufacturer = 1; - string version = 2; + string product_name = 2; + string serial_number = 3; + uint32 speed = 4; + uint32 core_count = 5; + uint32 thread_count = 6; +} + +message ComputeInformation { + uint32 total_core_count = 1; + uint32 total_thread_count = 2; + uint32 processor_count = 3; + repeated Processor processors = 4; +} + +message MemoryModule { + string manufacturer = 1; + string product_name = 2; + string serial_number = 3; + string type = 4; + uint32 size = 5; + uint32 speed = 6; +} + +message MemoryInformation { + uint32 total_size = 1; + uint32 module_count = 2; + repeated MemoryModule modules = 3; +} + +enum StorageType { + Unknown = 0; + SSD = 1; + HDD = 2; + NVMe = 3; + SD = 4; +} + +message StorageDevice { + StorageType type = 1; + uint64 size = 2; + string model = 3; + string serial = 4; + string name = 5; + string device_name = 6; + string uuid = 7; + string wwid = 8; +} + +message StorageInformation { + uint64 total_size = 1; + uint32 device_count = 2; + repeated StorageDevice devices = 3; +} + +message NetworkInterface { + uint32 index = 1; + string name = 2; + string flags = 3; + uint32 mtu = 4; + string mac = 5; + repeated string addresses = 6; +} + +message NetworkInformation { + uint32 interface_count = 1; + repeated NetworkInterface interfaces = 2; +} + +message HardwareInformation { + SystemInformation system = 1; + ComputeInformation compute = 2; + MemoryInformation memory = 3; + StorageInformation storage = 4; + NetworkInformation network = 5; } message CreateServerRequest { - SystemInformation system_information = 1; - CPU cpu = 2; + HardwareInformation hardware = 1; string hostname = 3; } @@ -55,8 +127,8 @@ message CreateServerResponse { double reboot_timeout = 4; } -message MarkServerAsWipedRequest { string uuid = 1; } -message HeartbeatRequest { string uuid = 1; } +message MarkServerAsWipedRequest {string uuid = 1;} +message HeartbeatRequest {string uuid = 1;} message MarkServerAsWipedResponse {} message HeartbeatResponse {} diff --git a/app/sidero-controller-manager/internal/ipxe/ipxe_server.go b/app/sidero-controller-manager/internal/ipxe/ipxe_server.go index ea290f0fb..16a0b524e 100644 --- a/app/sidero-controller-manager/internal/ipxe/ipxe_server.go +++ b/app/sidero-controller-manager/internal/ipxe/ipxe_server.go @@ -32,7 +32,7 @@ import ( "github.com/talos-systems/talos/pkg/machinery/kernel" infrav1 "github.com/talos-systems/sidero/app/caps-controller-manager/api/v1alpha3" - metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha1" + metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" "github.com/talos-systems/sidero/app/sidero-controller-manager/internal/siderolink" "github.com/talos-systems/sidero/app/sidero-controller-manager/pkg/constants" siderotypes "github.com/talos-systems/sidero/app/sidero-controller-manager/pkg/types" diff --git a/app/sidero-controller-manager/internal/metadata/metadata_server.go b/app/sidero-controller-manager/internal/metadata/metadata_server.go index db976cae3..74ae439ea 100644 --- a/app/sidero-controller-manager/internal/metadata/metadata_server.go +++ b/app/sidero-controller-manager/internal/metadata/metadata_server.go @@ -22,7 +22,7 @@ import ( runtimeclient "sigs.k8s.io/controller-runtime/pkg/client" infrav1 "github.com/talos-systems/sidero/app/caps-controller-manager/api/v1alpha3" - metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha1" + metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" ) type errorWithCode struct { diff --git a/app/sidero-controller-manager/internal/power/api/api.go b/app/sidero-controller-manager/internal/power/api/api.go index 2a45b0f87..da5e08a03 100644 --- a/app/sidero-controller-manager/internal/power/api/api.go +++ b/app/sidero-controller-manager/internal/power/api/api.go @@ -14,7 +14,7 @@ import ( "net/http" "time" - metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha1" + metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" "github.com/talos-systems/sidero/app/sidero-controller-manager/internal/power/metal" ) diff --git a/app/sidero-controller-manager/internal/power/factory.go b/app/sidero-controller-manager/internal/power/factory.go index 840395b20..808415256 100644 --- a/app/sidero-controller-manager/internal/power/factory.go +++ b/app/sidero-controller-manager/internal/power/factory.go @@ -10,7 +10,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" - metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha1" + metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" "github.com/talos-systems/sidero/app/sidero-controller-manager/internal/power/api" "github.com/talos-systems/sidero/app/sidero-controller-manager/internal/power/ipmi" "github.com/talos-systems/sidero/app/sidero-controller-manager/internal/power/metal" diff --git a/app/sidero-controller-manager/internal/power/ipmi/ipmi.go b/app/sidero-controller-manager/internal/power/ipmi/ipmi.go index bfacf3b75..62216c707 100644 --- a/app/sidero-controller-manager/internal/power/ipmi/ipmi.go +++ b/app/sidero-controller-manager/internal/power/ipmi/ipmi.go @@ -9,7 +9,7 @@ import ( goipmi "github.com/pensando/goipmi" - metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha1" + metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" "github.com/talos-systems/sidero/app/sidero-controller-manager/internal/power/metal" ) diff --git a/app/sidero-controller-manager/internal/server/server.go b/app/sidero-controller-manager/internal/server/server.go index b21fef9e8..3bad1203e 100644 --- a/app/sidero-controller-manager/internal/server/server.go +++ b/app/sidero-controller-manager/internal/server/server.go @@ -6,6 +6,7 @@ package server import ( "context" + "fmt" "log" "reflect" "time" @@ -25,7 +26,7 @@ import ( "sigs.k8s.io/cluster-api/util/patch" controllerclient "sigs.k8s.io/controller-runtime/pkg/client" - metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha1" + metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" "github.com/talos-systems/sidero/app/sidero-controller-manager/internal/api" "github.com/talos-systems/sidero/app/sidero-controller-manager/pkg/constants" ) @@ -46,8 +47,9 @@ type server struct { // CreateServer implements api.AgentServer. func (s *server) CreateServer(ctx context.Context, in *api.CreateServerRequest) (*api.CreateServerResponse, error) { obj := &metalv1.Server{} + uuid := in.GetHardware().GetSystem().GetUuid() - if err := s.c.Get(ctx, types.NamespacedName{Name: in.GetSystemInformation().GetUuid()}, obj); err != nil { + if err := s.c.Get(ctx, types.NamespacedName{Name: uuid}, obj); err != nil { if !apierrors.IsNotFound(err) { return nil, err } @@ -58,22 +60,11 @@ func (s *server) CreateServer(ctx context.Context, in *api.CreateServerRequest) APIVersion: metalv1.GroupVersion.Version, }, ObjectMeta: metav1.ObjectMeta{ - Name: in.GetSystemInformation().GetUuid(), + Name: uuid, }, Spec: metalv1.ServerSpec{ + Hardware: MapHardwareInformation(in.GetHardware()), Hostname: in.GetHostname(), - SystemInformation: &metalv1.SystemInformation{ - Manufacturer: in.GetSystemInformation().GetManufacturer(), - ProductName: in.GetSystemInformation().GetProductName(), - Version: in.GetSystemInformation().GetVersion(), - SerialNumber: in.GetSystemInformation().GetSerialNumber(), - SKUNumber: in.GetSystemInformation().GetSkuNumber(), - Family: in.GetSystemInformation().GetFamily(), - }, - CPU: &metalv1.CPUInformation{ - Manufacturer: in.GetCpu().GetManufacturer(), - Version: in.GetCpu().GetVersion(), - }, Accepted: s.autoAccept, }, } @@ -89,7 +80,7 @@ func (s *server) CreateServer(ctx context.Context, in *api.CreateServerRequest) s.recorder.Event(ref, corev1.EventTypeNormal, "Server Registration", "Server auto-registered via API.") - log.Printf("Added %s", in.GetSystemInformation().GetUuid()) + log.Printf("Added %s", uuid) } resp := &api.CreateServerResponse{} @@ -400,3 +391,87 @@ func CreateServer(c controllerclient.Client, recorder record.EventRecorder, sche return s } + +func MapHardwareInformation(hw *api.HardwareInformation) *metalv1.HardwareInformation { + processors := make([]*metalv1.Processor, hw.GetCompute().GetProcessorCount()) + for i, v := range hw.GetCompute().GetProcessors() { + processors[i] = &metalv1.Processor{ + Manufacturer: v.GetManufacturer(), + ProductName: v.GetProductName(), + SerialNumber: v.GetSerialNumber(), + Speed: v.GetSpeed(), + CoreCount: v.GetCoreCount(), + ThreadCount: v.GetThreadCount(), + } + } + + memoryModules := make([]*metalv1.MemoryModule, hw.GetMemory().GetModuleCount()) + for i, v := range hw.GetMemory().GetModules() { + memoryModules[i] = &metalv1.MemoryModule{ + Manufacturer: v.GetManufacturer(), + ProductName: v.GetProductName(), + SerialNumber: v.GetSerialNumber(), + Type: v.GetType(), + Size: v.GetSize(), + Speed: v.GetSpeed(), + } + } + + storageDevices := make([]*metalv1.StorageDevice, hw.GetStorage().GetDeviceCount()) + for i, v := range hw.GetStorage().GetDevices() { + storageDevices[i] = &metalv1.StorageDevice{ + Type: v.GetType().String(), + Size: v.GetSize(), + Model: v.GetModel(), + Serial: v.GetSerial(), + Name: v.GetName(), + DeviceName: v.GetDeviceName(), + UUID: v.GetUuid(), + WWID: v.GetWwid(), + } + } + + networkInterfaces := make([]*metalv1.NetworkInterface, hw.GetNetwork().GetInterfaceCount()) + for i, v := range hw.GetNetwork().GetInterfaces() { + networkInterfaces[i] = &metalv1.NetworkInterface{ + Index: v.GetIndex(), + Name: v.GetName(), + Flags: v.GetFlags(), + MTU: v.GetMtu(), + MAC: v.GetMac(), + Addresses: v.GetAddresses(), + } + } + + return &metalv1.HardwareInformation{ + System: &metalv1.SystemInformation{ + Uuid: hw.GetSystem().GetUuid(), + Manufacturer: hw.GetSystem().GetManufacturer(), + ProductName: hw.GetSystem().GetProductName(), + Version: hw.GetSystem().GetVersion(), + SerialNumber: hw.GetSystem().GetSerialNumber(), + SKUNumber: hw.GetSystem().GetSkuNumber(), + Family: hw.GetSystem().GetFamily(), + }, + Compute: &metalv1.ComputeInformation{ + TotalCoreCount: hw.GetCompute().GetTotalCoreCount(), + TotalThreadCount: hw.GetCompute().GetTotalThreadCount(), + ProcessorCount: hw.GetCompute().GetProcessorCount(), + Processors: processors, + }, + Memory: &metalv1.MemoryInformation{ + TotalSize: fmt.Sprintf("%d GB", hw.GetMemory().GetTotalSize()/1024), + ModuleCount: hw.GetMemory().GetModuleCount(), + Modules: memoryModules, + }, + Storage: &metalv1.StorageInformation{ + TotalSize: fmt.Sprintf("%d GB", hw.GetStorage().GetTotalSize()/1024/1024/1024), + DeviceCount: hw.GetStorage().GetDeviceCount(), + Devices: storageDevices, + }, + Network: &metalv1.NetworkInformation{ + InterfaceCount: hw.GetNetwork().GetInterfaceCount(), + Interfaces: networkInterfaces, + }, + } +} diff --git a/app/sidero-controller-manager/main.go b/app/sidero-controller-manager/main.go index 950ad064f..93e00acbe 100644 --- a/app/sidero-controller-manager/main.go +++ b/app/sidero-controller-manager/main.go @@ -13,7 +13,7 @@ import ( "strings" "time" - debug "github.com/talos-systems/go-debug" + "github.com/talos-systems/go-debug" "golang.org/x/net/http2" "golang.org/x/net/http2/h2c" corev1 "k8s.io/api/core/v1" @@ -23,7 +23,7 @@ import ( typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1" _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" "k8s.io/client-go/tools/record" - capi "sigs.k8s.io/cluster-api/api/v1beta1" + capiv1beta1 "sigs.k8s.io/cluster-api/api/v1beta1" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/log/zap" @@ -31,6 +31,7 @@ import ( infrav1alpha3 "github.com/talos-systems/sidero/app/caps-controller-manager/api/v1alpha3" 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" @@ -61,9 +62,10 @@ var ( //nolint:wsl func init() { _ = clientgoscheme.AddToScheme(scheme) - _ = capi.AddToScheme(scheme) + _ = capiv1beta1.AddToScheme(scheme) _ = metalv1alpha1.AddToScheme(scheme) + _ = metalv1alpha2.AddToScheme(scheme) _ = infrav1alpha3.AddToScheme(scheme) // +kubebuilder:scaffold:scheme } @@ -334,8 +336,8 @@ func setupChecks(mgr ctrl.Manager, httpPort int) { os.Exit(1) } - if err := mgr.AddHealthzCheck("webhook", ipxe.Check(addr)); err != nil { + if err := mgr.AddHealthzCheck("ipxe", ipxe.Check(addr)); err != nil { setupLog.Error(err, "unable to create health check") os.Exit(1) } -} +} \ No newline at end of file diff --git a/app/caps-controller-manager/config/certmanager/certificate.yaml b/app/webhook-server/config/certmanager/certificate.yaml similarity index 64% rename from app/caps-controller-manager/config/certmanager/certificate.yaml rename to app/webhook-server/config/certmanager/certificate.yaml index ffcc81068..cb7caa1bd 100644 --- a/app/caps-controller-manager/config/certmanager/certificate.yaml +++ b/app/webhook-server/config/certmanager/certificate.yaml @@ -14,11 +14,11 @@ metadata: name: serving-cert # this name should match the one appeared in kustomizeconfig.yaml namespace: system spec: - # $(SERVICE_NAME) and $(SERVICE_NAMESPACE) will be substituted by kustomize + # $(WEBHOOK_SERVICE_NAME) and $(WEBHOOK_SERVICE_NAMESPACE) will be substituted by kustomize dnsNames: - - $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc - - $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc.cluster.local + - $(WEBHOOK_SERVICE_NAME).$(WEBHOOK_SERVICE_NAMESPACE).svc + - $(WEBHOOK_SERVICE_NAME).$(WEBHOOK_SERVICE_NAMESPACE).svc.cluster.local issuerRef: kind: Issuer name: selfsigned-issuer - secretName: $(SERVICE_NAME)-cert + secretName: $(WEBHOOK_SERVICE_NAME)-cert diff --git a/app/caps-controller-manager/config/certmanager/kustomization.yaml b/app/webhook-server/config/certmanager/kustomization.yaml similarity index 100% rename from app/caps-controller-manager/config/certmanager/kustomization.yaml rename to app/webhook-server/config/certmanager/kustomization.yaml diff --git a/app/caps-controller-manager/config/certmanager/kustomizeconfig.yaml b/app/webhook-server/config/certmanager/kustomizeconfig.yaml similarity index 100% rename from app/caps-controller-manager/config/certmanager/kustomizeconfig.yaml rename to app/webhook-server/config/certmanager/kustomizeconfig.yaml diff --git a/app/webhook-server/config/default/kustomization.yaml b/app/webhook-server/config/default/kustomization.yaml new file mode 100644 index 000000000..677f08c1c --- /dev/null +++ b/app/webhook-server/config/default/kustomization.yaml @@ -0,0 +1,45 @@ +namespace: sidero-system + +namePrefix: webhook- + +# Labels to add to all resources and selectors. +commonLabels: + cluster.x-k8s.io/provider: "control-plane-talos" + +resources: + - ../certmanager + - ../webhook-server + +#patchesStrategicMerge: +# - webhookcainjection_patch.yaml + +vars: + - name: CERTIFICATE_NAMESPACE # namespace of the certificate CR + objref: + kind: Certificate + group: cert-manager.io + version: v1 + name: serving-cert # this name should match the one in certificate.yaml + fieldref: + fieldpath: metadata.namespace + - name: CERTIFICATE_NAME + objref: + kind: Certificate + group: cert-manager.io + version: v1 + name: serving-cert # this name should match the one in certificate.yaml + - name: WEBHOOK_SERVICE_NAMESPACE # namespace of the service + objref: + kind: Service + version: v1 + name: webhook-service + fieldref: + fieldpath: metadata.namespace + - name: WEBHOOK_SERVICE_NAME + objref: + kind: Service + version: v1 + name: webhook-service + +configurations: + - kustomizeconfig.yaml diff --git a/app/caps-controller-manager/config/webhook/kustomizeconfig.yaml b/app/webhook-server/config/default/kustomizeconfig.yaml similarity index 78% rename from app/caps-controller-manager/config/webhook/kustomizeconfig.yaml rename to app/webhook-server/config/default/kustomizeconfig.yaml index 5e35ba099..2787e5630 100644 --- a/app/caps-controller-manager/config/webhook/kustomizeconfig.yaml +++ b/app/webhook-server/config/default/kustomizeconfig.yaml @@ -1,5 +1,4 @@ -# the following config is for teaching kustomize where to look at when substituting vars. -# It requires kustomize v2.1.0 or newer to work properly. +# This configuration is for teaching kustomize how to update name ref and var substitution nameReference: - kind: Service version: v1 @@ -22,4 +21,5 @@ namespace: create: true varReference: - - path: metadata/annotations + - kind: Deployment + path: spec/template/spec/volumes/secret/secretName diff --git a/app/caps-controller-manager/config/default/webhookcainjection_patch.yaml b/app/webhook-server/config/default/webhookcainjection_patch.yaml similarity index 100% rename from app/caps-controller-manager/config/default/webhookcainjection_patch.yaml rename to app/webhook-server/config/default/webhookcainjection_patch.yaml diff --git a/app/webhook-server/config/webhook-server/kustomization.yaml b/app/webhook-server/config/webhook-server/kustomization.yaml new file mode 100644 index 000000000..3b255d383 --- /dev/null +++ b/app/webhook-server/config/webhook-server/kustomization.yaml @@ -0,0 +1,2 @@ +resources: +- webhook-server.yaml diff --git a/app/webhook-server/config/webhook-server/webhook-server.yaml b/app/webhook-server/config/webhook-server/webhook-server.yaml new file mode 100644 index 000000000..3c2611a3e --- /dev/null +++ b/app/webhook-server/config/webhook-server/webhook-server.yaml @@ -0,0 +1,58 @@ +apiVersion: v1 +kind: Service +metadata: + name: webhook-service + namespace: system +spec: + ports: + - port: 443 + targetPort: 9443 + selector: + control-plane: webhook-server +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: webhook-server + namespace: system + labels: + control-plane: webhook-server +spec: + selector: + matchLabels: + control-plane: webhook-server + replicas: 1 + template: + metadata: + labels: + control-plane: webhook-server + spec: + containers: + - name: webhook-server + image: controller:latest + imagePullPolicy: Always + command: + - /webhook-server + args: + - --metrics-bind-addr=127.0.0.1:8080 + - --webhook-port=9443 + ports: + - containerPort: 9443 + name: webhook-server + protocol: TCP + resources: + limits: + cpu: 256m + memory: 256Mi + requests: + cpu: 50m + memory: 128Mi + volumeMounts: + - mountPath: /tmp/k8s-webhook-server/serving-certs + name: cert + readOnly: true + volumes: + - name: cert + secret: + defaultMode: 420 + secretName: $(WEBHOOK_SERVICE_NAME)-cert diff --git a/app/webhook-server/main.go b/app/webhook-server/main.go new file mode 100644 index 000000000..9fdc503da --- /dev/null +++ b/app/webhook-server/main.go @@ -0,0 +1,108 @@ +// 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 main + +import ( + "flag" + infrav1alpha2 "github.com/talos-systems/sidero/app/caps-controller-manager/api/v1alpha2" + infrav1alpha3 "github.com/talos-systems/sidero/app/caps-controller-manager/api/v1alpha3" + metalv1alpha1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha1" + metalv1alpha2 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" + "k8s.io/apimachinery/pkg/runtime" + clientgoscheme "k8s.io/client-go/kubernetes/scheme" + "log" + capiv1beta1 "sigs.k8s.io/cluster-api/api/v1beta1" + ctrl "sigs.k8s.io/controller-runtime" +) + +var ( + scheme = runtime.NewScheme() +) + +//nolint:wsl +func init() { + _ = clientgoscheme.AddToScheme(scheme) + _ = capiv1beta1.AddToScheme(scheme) + _ = infrav1alpha2.AddToScheme(scheme) + _ = infrav1alpha3.AddToScheme(scheme) + _ = metalv1alpha1.AddToScheme(scheme) + _ = metalv1alpha2.AddToScheme(scheme) + // +kubebuilder:scaffold:scheme +} + +func main() { + var ( + metricsAddr string + healthAddr string + webhookPort int + ) + flag.StringVar(&metricsAddr, "metrics-bind-addr", ":8081", "The address the metric endpoint binds to.") + flag.StringVar(&healthAddr, "health-addr", ":9440", "The address the health endpoint binds to.") + flag.IntVar(&webhookPort, "webhook-port", 9443, "The TCP port the Webhook Server can be reached at.") + + flag.Parse() + + mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ + Scheme: scheme, + MetricsBindAddress: metricsAddr, + LeaderElection: false, + Port: webhookPort, + HealthProbeBindAddress: healthAddr, + }) + if err != nil { + log.Fatal(err, "unable to start manager") + } + + ctx := ctrl.SetupSignalHandler() + + setupWebhooks(mgr) + setupChecks(mgr) + + log.Print("starting manager") + + if err := mgr.Start(ctx); err != nil { + log.Fatal(err, "problem running manager") + } +} + +func setupWebhooks(mgr ctrl.Manager) { + if err := (&infrav1alpha3.MetalCluster{}).SetupWebhookWithManager(mgr); err != nil { + log.Fatal(err, "unable to create webhook", "webhook", "MetalCluster") + } + + if err := (&infrav1alpha3.MetalMachine{}).SetupWebhookWithManager(mgr); err != nil { + log.Fatal(err, "unable to create webhook", "webhook", "MetalMachine") + } + + if err := (&infrav1alpha3.MetalMachineTemplate{}).SetupWebhookWithManager(mgr); err != nil { + log.Fatal(err, "unable to create webhook", "webhook", "MetalMachineTemplate") + } + + if err := (&infrav1alpha3.ServerBinding{}).SetupWebhookWithManager(mgr); err != nil { + log.Fatal(err, "unable to create webhook", "webhook", "ServerBinding") + } + + if err := (&metalv1alpha2.Environment{}).SetupWebhookWithManager(mgr); err != nil { + log.Fatal(err, "unable to create webhook", "webhook", "Environment") + } + + if err := (&metalv1alpha2.Server{}).SetupWebhookWithManager(mgr); err != nil { + log.Fatal(err, "unable to create webhook", "webhook", "Server") + } + + if err := (&metalv1alpha2.ServerClass{}).SetupWebhookWithManager(mgr); err != nil { + log.Fatal(err, "unable to create webhook", "webhook", "ServerClass") + } +} + +func setupChecks(mgr ctrl.Manager) { + if err := mgr.AddReadyzCheck("webhook", mgr.GetWebhookServer().StartedChecker()); err != nil { + log.Fatal(err, "unable to create ready check") + } + + if err := mgr.AddHealthzCheck("webhook", mgr.GetWebhookServer().StartedChecker()); err != nil { + log.Fatal(err, "unable to create health check") + } +} diff --git a/config/kustomization.yaml b/config/kustomization.yaml index 2813e7222..dbda8a1ea 100644 --- a/config/kustomization.yaml +++ b/config/kustomization.yaml @@ -1,9 +1,8 @@ resources: - namespace.yaml - -bases: + - ../app/webhook-server/config/default - ../app/caps-controller-manager/config/default - - ../app/sidero-controller-manager/config + - ../app/sidero-controller-manager/config/default commonLabels: app: sidero diff --git a/go.mod b/go.mod index b02dbfa6c..9050f968e 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/talos-systems/go-kmsg v0.1.1 github.com/talos-systems/go-procfs v0.1.0 github.com/talos-systems/go-retry v0.3.1 - github.com/talos-systems/go-smbios v0.1.1 + github.com/talos-systems/go-smbios v0.1.2-0.20220202124743-3f1e775b7e3e github.com/talos-systems/grpc-proxy v0.2.0 github.com/talos-systems/net v0.3.2 github.com/talos-systems/siderolink v0.1.1-0.20211130121818-9902ad2774f0 diff --git a/go.sum b/go.sum index 81b83e498..08586c767 100644 --- a/go.sum +++ b/go.sum @@ -703,8 +703,8 @@ github.com/talos-systems/go-procfs v0.1.0/go.mod h1:ATyUGFQIW8OnbnmvqefZWVPgL9g+ github.com/talos-systems/go-retry v0.1.1-0.20201113203059-8c63d290a688/go.mod h1:HiXQqyVStZ35uSY/MTLWVvQVmC3lIW2MS5VdDaMtoKM= github.com/talos-systems/go-retry v0.3.1 h1:GjjyHB8i1CJpb1O5qYPMljq74cRQ5uiDoyMaWddA5FA= github.com/talos-systems/go-retry v0.3.1/go.mod h1:HiXQqyVStZ35uSY/MTLWVvQVmC3lIW2MS5VdDaMtoKM= -github.com/talos-systems/go-smbios v0.1.1 h1:Au6obB/Pp0i0JHhvPlzONk5aoNseosO2BUsmvWWi7y8= -github.com/talos-systems/go-smbios v0.1.1/go.mod h1:vk76naUSZaWE8Z95wbDn51FgH0goECM4oK3KY2hYSMU= +github.com/talos-systems/go-smbios v0.1.2-0.20220202124743-3f1e775b7e3e h1:z2ig8zuE00kbVhyWmTQdDWbDIN5HnCKaouyjiTHCMxs= +github.com/talos-systems/go-smbios v0.1.2-0.20220202124743-3f1e775b7e3e/go.mod h1:vk76naUSZaWE8Z95wbDn51FgH0goECM4oK3KY2hYSMU= github.com/talos-systems/goipmi v0.0.0-20211214143420-35f956689e67 h1:1MyiKkPFn0OnpOnmMMVlvFtmeUB/HIRzDVL66DQBOXg= github.com/talos-systems/goipmi v0.0.0-20211214143420-35f956689e67/go.mod h1:Vr1Oadtcem03hG2RUT/dpSQS5md9d6rJ9nA0lUBC91Q= github.com/talos-systems/grpc-proxy v0.2.0 h1:DN75bLfaW4xfhq0r0mwFRnfGhSB+HPhK1LNzuMEs9Pw= diff --git a/internal/client/client.go b/internal/client/client.go index 833ac58f4..ef4ea218b 100644 --- a/internal/client/client.go +++ b/internal/client/client.go @@ -14,7 +14,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" infrav1 "github.com/talos-systems/sidero/app/caps-controller-manager/api/v1alpha3" - metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha1" + metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" ) // NewClient is responsible for creating a controller-runtime k8s client with all schemas. diff --git a/sfyra/go.sum b/sfyra/go.sum index a1fe6e979..8ccbc9968 100644 --- a/sfyra/go.sum +++ b/sfyra/go.sum @@ -1244,6 +1244,7 @@ github.com/talos-systems/go-retry v0.1.1-0.20201113203059-8c63d290a688/go.mod h1 github.com/talos-systems/go-retry v0.3.1 h1:GjjyHB8i1CJpb1O5qYPMljq74cRQ5uiDoyMaWddA5FA= github.com/talos-systems/go-retry v0.3.1/go.mod h1:HiXQqyVStZ35uSY/MTLWVvQVmC3lIW2MS5VdDaMtoKM= github.com/talos-systems/go-smbios v0.1.1/go.mod h1:vk76naUSZaWE8Z95wbDn51FgH0goECM4oK3KY2hYSMU= +github.com/talos-systems/go-smbios v0.1.2-0.20220202124743-3f1e775b7e3e/go.mod h1:vk76naUSZaWE8Z95wbDn51FgH0goECM4oK3KY2hYSMU= github.com/talos-systems/grpc-proxy v0.2.0/go.mod h1:sm97Vc/z2cok3pu6ruNeszQej4KDxFrDgfWs4C1mtC4= github.com/talos-systems/grpc-proxy v0.3.0/go.mod h1:1TNaCLt0NTdFdz48OCnOM+HbPEIkj3DhCi85+z6zSM8= github.com/talos-systems/net v0.3.0/go.mod h1:VreSAyRmxMtqussAHSKMKkJQa1YwBTSVfkmE4Jydam4= diff --git a/sfyra/pkg/capi/capi.go b/sfyra/pkg/capi/capi.go index 71074a4c4..164f0b069 100644 --- a/sfyra/pkg/capi/capi.go +++ b/sfyra/pkg/capi/capi.go @@ -123,6 +123,7 @@ func (clusterAPI *Manager) Install(ctx context.Context) error { // set template environment variables os.Setenv("SIDERO_CONTROLLER_MANAGER_HOST_NETWORK", "true") + os.Setenv("SIDERO_CONTROLLER_MANAGER_DEPLOYMENT_STRATEGY", "Recreate") os.Setenv("SIDERO_CONTROLLER_MANAGER_API_ENDPOINT", clusterAPI.cluster.SideroComponentsIP().String()) os.Setenv("SIDERO_CONTROLLER_MANAGER_SERVER_REBOOT_TIMEOUT", "30s") // wiping/reboot is fast in the test environment os.Setenv("SIDERO_CONTROLLER_MANAGER_TEST_POWER_EXPLICIT_FAILURE", fmt.Sprintf("%f", clusterAPI.options.PowerSimulatedExplicitFailureProb)) diff --git a/sfyra/pkg/capi/cluster.go b/sfyra/pkg/capi/cluster.go index d59cf0804..02df85ad1 100644 --- a/sfyra/pkg/capi/cluster.go +++ b/sfyra/pkg/capi/cluster.go @@ -28,7 +28,7 @@ import ( runtimeclient "sigs.k8s.io/controller-runtime/pkg/client" infrav1 "github.com/talos-systems/sidero/app/caps-controller-manager/api/v1alpha3" - metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha1" + metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" ) // Cluster attaches to the provisioned CAPI cluster and provides talos.Cluster. diff --git a/sfyra/pkg/capi/metalclient.go b/sfyra/pkg/capi/metalclient.go index 67a0be6e1..e2ee8a7ab 100644 --- a/sfyra/pkg/capi/metalclient.go +++ b/sfyra/pkg/capi/metalclient.go @@ -13,7 +13,7 @@ import ( runtimeclient "sigs.k8s.io/controller-runtime/pkg/client" infrav1 "github.com/talos-systems/sidero/app/caps-controller-manager/api/v1alpha3" - metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha1" + metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" ) // GetMetalClient builds k8s client with schemes required to access all the CAPI/Sidero/Talos components. diff --git a/sfyra/pkg/constants/constants.go b/sfyra/pkg/constants/constants.go index f11afb29b..2c9e2eb4d 100644 --- a/sfyra/pkg/constants/constants.go +++ b/sfyra/pkg/constants/constants.go @@ -17,4 +17,4 @@ const MTU = 1500 const BootstrapMaster = "bootstrap-master" // SideroAPIVersion is a string we need for creating Sidero resources. -const SideroAPIVersion = "metal.sidero.dev/v1alpha1" +const SideroAPIVersion = "metal.sidero.dev/v1alpha2" diff --git a/sfyra/pkg/loadbalancer/loadbalancer.go b/sfyra/pkg/loadbalancer/loadbalancer.go index 36621c603..3c5fd8384 100644 --- a/sfyra/pkg/loadbalancer/loadbalancer.go +++ b/sfyra/pkg/loadbalancer/loadbalancer.go @@ -26,7 +26,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" infrav1 "github.com/talos-systems/sidero/app/caps-controller-manager/api/v1alpha3" - metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha1" + metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" ) // ControlPlane implements dynamic loadbalancer for the control plane. diff --git a/sfyra/pkg/tests/compatibility.go b/sfyra/pkg/tests/compatibility.go index 532cb7807..72c93432e 100644 --- a/sfyra/pkg/tests/compatibility.go +++ b/sfyra/pkg/tests/compatibility.go @@ -23,7 +23,7 @@ import ( "github.com/talos-systems/go-retry/retry" "github.com/talos-systems/talos/pkg/machinery/kernel" - metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha1" + metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" "github.com/talos-systems/sidero/sfyra/pkg/capi" "github.com/talos-systems/sidero/sfyra/pkg/constants" "github.com/talos-systems/sidero/sfyra/pkg/talos" @@ -84,9 +84,11 @@ func TestCompatibilityCluster(ctx context.Context, metalClient client.Client, cl serverClassName := envName classSpec := metalv1.ServerClassSpec{ Qualifiers: metalv1.Qualifiers{ - CPU: []metalv1.CPUInformation{ + Hardware: []metalv1.HardwareInformation{ { - Manufacturer: "QEMU", + System: &metalv1.SystemInformation{ + Manufacturer: "QEMU", + }, }, }, }, diff --git a/sfyra/pkg/tests/environment.go b/sfyra/pkg/tests/environment.go index 63b5dc04d..652945dac 100644 --- a/sfyra/pkg/tests/environment.go +++ b/sfyra/pkg/tests/environment.go @@ -18,7 +18,7 @@ import ( "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" - metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha1" + metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" "github.com/talos-systems/sidero/sfyra/pkg/constants" "github.com/talos-systems/sidero/sfyra/pkg/talos" ) diff --git a/sfyra/pkg/tests/match.go b/sfyra/pkg/tests/match.go index 13d8db2ed..d9c6f57ed 100644 --- a/sfyra/pkg/tests/match.go +++ b/sfyra/pkg/tests/match.go @@ -13,7 +13,7 @@ import ( capiv1 "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/controller-runtime/pkg/client" - metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha1" + metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" ) // TestMatchServersMetalMachines verifies that number of metal machines and servers match. diff --git a/sfyra/pkg/tests/reconcile.go b/sfyra/pkg/tests/reconcile.go index ab4b65209..27329329a 100644 --- a/sfyra/pkg/tests/reconcile.go +++ b/sfyra/pkg/tests/reconcile.go @@ -20,7 +20,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" infrav1 "github.com/talos-systems/sidero/app/caps-controller-manager/api/v1alpha3" - metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha1" + metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" ) // TestMachineDeploymentReconcile verifies that machine deployment can reconcile delete machines. diff --git a/sfyra/pkg/tests/reset.go b/sfyra/pkg/tests/reset.go index 5cb3597d3..4471914ff 100644 --- a/sfyra/pkg/tests/reset.go +++ b/sfyra/pkg/tests/reset.go @@ -16,7 +16,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" infrav1 "github.com/talos-systems/sidero/app/caps-controller-manager/api/v1alpha3" - metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha1" + metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" ) // TestServerReset verifies that all the servers got reset. diff --git a/sfyra/pkg/tests/server.go b/sfyra/pkg/tests/server.go index 43ee11949..d4c80d83b 100644 --- a/sfyra/pkg/tests/server.go +++ b/sfyra/pkg/tests/server.go @@ -30,7 +30,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" infrav1 "github.com/talos-systems/sidero/app/caps-controller-manager/api/v1alpha3" - metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha1" + metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" "github.com/talos-systems/sidero/sfyra/pkg/capi" "github.com/talos-systems/sidero/sfyra/pkg/constants" "github.com/talos-systems/sidero/sfyra/pkg/talos" @@ -191,8 +191,14 @@ func TestServerAcceptance(ctx context.Context, metalClient client.Client, vmSet // create dummy servers to test with dummySpec := metalv1.ServerSpec{ - CPU: &metalv1.CPUInformation{ - Manufacturer: "DummyCPU", + Hardware: &metalv1.HardwareInformation{ + Compute: &metalv1.ComputeInformation{ + Processors: []*metalv1.Processor{ + { + Manufacturer: "DummyCPU", + }, + }, + }, }, } @@ -271,8 +277,14 @@ func TestServerCordoned(ctx context.Context, metalClient client.Client, vmSet *v // create dummy servers to test with dummySpec := metalv1.ServerSpec{ - CPU: &metalv1.CPUInformation{ - Manufacturer: "DummyManufacturer", + Hardware: &metalv1.HardwareInformation{ + Compute: &metalv1.ComputeInformation{ + Processors: []*metalv1.Processor{ + { + Manufacturer: "DummyManufacturer", + }, + }, + }, }, } @@ -494,9 +506,11 @@ func TestServerPXEBoot(ctx context.Context, metalClient client.Client, cluster t classSpec := metalv1.ServerClassSpec{ Qualifiers: metalv1.Qualifiers{ - CPU: []metalv1.CPUInformation{ + Hardware: []metalv1.HardwareInformation{ { - Manufacturer: "QEMU", + System: &metalv1.SystemInformation{ + Manufacturer: "QEMU", + }, }, }, }, diff --git a/sfyra/pkg/tests/server_class.go b/sfyra/pkg/tests/server_class.go index 690fafb7e..78444d100 100644 --- a/sfyra/pkg/tests/server_class.go +++ b/sfyra/pkg/tests/server_class.go @@ -31,7 +31,7 @@ import ( capiclient "sigs.k8s.io/cluster-api/cmd/clusterctl/client" "sigs.k8s.io/controller-runtime/pkg/client" - metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha1" + metalv1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha2" "github.com/talos-systems/sidero/sfyra/pkg/capi" "github.com/talos-systems/sidero/sfyra/pkg/constants" "github.com/talos-systems/sidero/sfyra/pkg/talos" @@ -84,9 +84,11 @@ func TestServerClassCreate(ctx context.Context, metalClient client.Client, vmSet return func(t *testing.T) { classSpec := metalv1.ServerClassSpec{ Qualifiers: metalv1.Qualifiers{ - CPU: []metalv1.CPUInformation{ + Hardware: []metalv1.HardwareInformation{ { - Manufacturer: "QEMU", + System: &metalv1.SystemInformation{ + Manufacturer: "QEMU", + }, }, }, }, @@ -139,10 +141,16 @@ func TestServerClassPatch(ctx context.Context, metalClient client.Client, cluste return func(t *testing.T) { // Create dummy serverclass + a server dummySpec := metalv1.ServerSpec{ - CPU: &metalv1.CPUInformation{ - Manufacturer: "DummyCPU", - }, Accepted: true, + Hardware: &metalv1.HardwareInformation{ + Compute: &metalv1.ComputeInformation{ + Processors: []*metalv1.Processor{ + { + Manufacturer: "DummyCPU", + }, + }, + }, + }, } dummyServer, err := createDummyServer(ctx, metalClient, "dummyserver-0", dummySpec) @@ -168,9 +176,15 @@ func TestServerClassPatch(ctx context.Context, metalClient client.Client, cluste }, }, Qualifiers: metalv1.Qualifiers{ - CPU: []metalv1.CPUInformation{ + Hardware: []metalv1.HardwareInformation{ { - Manufacturer: "DummyCPU", + Compute: &metalv1.ComputeInformation{ + Processors: []*metalv1.Processor{ + { + Manufacturer: "DummyCPU", + }, + }, + }, }, }, }, diff --git a/templates/cluster-template-talos-v0.13.4.yaml b/templates/cluster-template-talos-v0.13.4.yaml index a8896a111..f6c010e67 100644 --- a/templates/cluster-template-talos-v0.13.4.yaml +++ b/templates/cluster-template-talos-v0.13.4.yaml @@ -38,7 +38,7 @@ spec: template: spec: serverClassRef: - apiVersion: metal.sidero.dev/v1alpha1 + apiVersion: metal.sidero.dev/v1alpha2 kind: ServerClass name: ${CONTROL_PLANE_SERVERCLASS} --- @@ -102,6 +102,6 @@ spec: template: spec: serverClassRef: - apiVersion: metal.sidero.dev/v1alpha1 + apiVersion: metal.sidero.dev/v1alpha2 kind: ServerClass name: ${WORKER_SERVERCLASS} diff --git a/templates/cluster-template.yaml b/templates/cluster-template.yaml index 1a478bffc..735210e9b 100644 --- a/templates/cluster-template.yaml +++ b/templates/cluster-template.yaml @@ -36,7 +36,7 @@ spec: template: spec: serverClassRef: - apiVersion: metal.sidero.dev/v1alpha1 + apiVersion: metal.sidero.dev/v1alpha2 kind: ServerClass name: ${CONTROL_PLANE_SERVERCLASS} --- @@ -97,6 +97,6 @@ spec: template: spec: serverClassRef: - apiVersion: metal.sidero.dev/v1alpha1 + apiVersion: metal.sidero.dev/v1alpha2 kind: ServerClass name: ${WORKER_SERVERCLASS} diff --git a/website/content/v0.4/Guides/patching.md b/website/content/v0.4/Guides/patching.md index 70609fed3..d46ada807 100644 --- a/website/content/v0.4/Guides/patching.md +++ b/website/content/v0.4/Guides/patching.md @@ -14,7 +14,7 @@ Any patches specified in the server resource are processed by the Sidero control A set of patches may look like this: ```yaml -apiVersion: metal.sidero.dev/v1alpha1 +apiVersion: metal.sidero.dev/v1alpha2 kind: Server metadata: name: 00000000-0000-0000-0000-d05099d33360 diff --git a/website/content/v0.4/Guides/sidero-on-rpi4.md b/website/content/v0.4/Guides/sidero-on-rpi4.md index da0be73b6..96c095efe 100644 --- a/website/content/v0.4/Guides/sidero-on-rpi4.md +++ b/website/content/v0.4/Guides/sidero-on-rpi4.md @@ -104,7 +104,7 @@ kubectl get nodes Install Sidero with host network mode, exposing the endpoints on the node's address: ```bash -SIDERO_CONTROLLER_MANAGER_HOST_NETWORK=true SIDERO_CONTROLLER_MANAGER_API_ENDPOINT=${SIDERO_IP} clusterctl init -i sidero -b talos -c talos +SIDERO_CONTROLLER_MANAGER_HOST_NETWORK=true SIDERO_CONTROLLER_MANAGER_DEPLOYMENT_STRATEGY=Recreate SIDERO_CONTROLLER_MANAGER_API_ENDPOINT=${SIDERO_IP} clusterctl init -i sidero -b talos -c talos ``` Watch the progress of installation with: diff --git a/website/content/v0.4/Resource Configuration/metadata.md b/website/content/v0.4/Resource Configuration/metadata.md index 6cdeccdc1..7e7dfab07 100644 --- a/website/content/v0.4/Resource Configuration/metadata.md +++ b/website/content/v0.4/Resource Configuration/metadata.md @@ -92,7 +92,7 @@ and finally in the control plane `ServerClass` custom resource we augment the ne ```yaml --- -apiVersion: metal.sidero.dev/v1alpha1 +apiVersion: metal.sidero.dev/v1alpha2 kind: ServerClass metadata: name: cp.small.x86 @@ -112,10 +112,13 @@ spec: interface: eth1 dhcp: true qualifiers: - cpu: - - version: Intel(R) Xeon(R) E-2124G CPU @ 3.40GHz - systemInformation: - - manufacturer: Supermicro + - system: + manufacturer: Supermicro + compute: + processors: + - productName: Intel(R) Xeon(R) E-2124G CPU @ 3.40GHz + memory: + totalSize: 8 GB selector: matchLabels: metal.sidero.dev/serverclass: cp.small.x86 @@ -125,7 +128,7 @@ the workload `ServerClass` defines the complete networking config ```yaml --- -apiVersion: metal.sidero.dev/v1alpha1 +apiVersion: metal.sidero.dev/v1alpha2 kind: ServerClass metadata: name: general.medium.x86 @@ -148,10 +151,13 @@ spec: - interface: eth1 dhcp: true qualifiers: - cpu: - - version: Intel(R) Xeon(R) E-2136 CPU @ 3.30GHz - systemInformation: - - manufacturer: Supermicro + - system: + manufacturer: Supermicro + compute: + processors: + - productName: Intel(R) Xeon(R) E-2136 CPU @ 3.30GHz + memory: + totalSize: 16 GB selector: matchLabels: metal.sidero.dev/serverclass: general.medium.x86 diff --git a/website/content/v0.5/Getting Started/install-clusterapi.md b/website/content/v0.5/Getting Started/install-clusterapi.md index 0dfca1698..8cc17e02e 100644 --- a/website/content/v0.5/Getting Started/install-clusterapi.md +++ b/website/content/v0.5/Getting Started/install-clusterapi.md @@ -24,6 +24,7 @@ options. ```bash export SIDERO_CONTROLLER_MANAGER_HOST_NETWORK=true +export SIDERO_CONTROLLER_MANAGER_DEPLOYMENT_STRATEGY=Recreate export SIDERO_CONTROLLER_MANAGER_API_ENDPOINT=192.168.1.150 export SIDERO_CONTROLLER_MANAGER_SIDEROLINK_ENDPOINT=192.168.1.150 diff --git a/website/content/v0.5/Guides/bootstrapping.md b/website/content/v0.5/Guides/bootstrapping.md index 418f10641..bbb56fb3b 100644 --- a/website/content/v0.5/Guides/bootstrapping.md +++ b/website/content/v0.5/Guides/bootstrapping.md @@ -147,6 +147,7 @@ To install Sidero and the other Talos providers, simply issue: ```bash SIDERO_CONTROLLER_MANAGER_HOST_NETWORK=true \ + SIDERO_CONTROLLER_MANAGER_DEPLOYMENT_STRATEGY=Recreate \ SIDERO_CONTROLLER_MANAGER_API_ENDPOINT=$PUBLIC_IP \ clusterctl init -b talos -c talos -i sidero ``` diff --git a/website/content/v0.5/Overview/installation.md b/website/content/v0.5/Overview/installation.md index f7ffce91a..82d5e3f3c 100644 --- a/website/content/v0.5/Overview/installation.md +++ b/website/content/v0.5/Overview/installation.md @@ -14,6 +14,7 @@ Sidero supports several variables to configure the installation, these variables variables or as variables in the `clusterctl` configuration: - `SIDERO_CONTROLLER_MANAGER_HOST_NETWORK` (`false`): run `sidero-controller-manager` on host network +- `SIDERO_CONTROLLER_MANAGER_DEPLOYMENT_STRATEGY` (`RollingUpdate`): strategy to use when updating `sidero-controller-manager`, use `Recreate` when using a single node and `SIDERO_CONTROLLER_MANAGER_HOST_NETWORK` is `true` - `SIDERO_CONTROLLER_MANAGER_API_ENDPOINT` (empty): specifies the IP address controller manager API service can be reached on, defaults to the node IP (TCP) - `SIDERO_CONTROLLER_MANAGER_API_PORT` (8081): specifies the port controller manager can be reached on - `SIDERO_CONTROLLER_MANAGER_CONTAINER_API_PORT` (8081): specifies the controller manager internal container port diff --git a/website/content/v0.5/Resource Configuration/environments.md b/website/content/v0.5/Resource Configuration/environments.md index 3545d9f75..226b1b7b9 100644 --- a/website/content/v0.5/Resource Configuration/environments.md +++ b/website/content/v0.5/Resource Configuration/environments.md @@ -20,7 +20,7 @@ The hierarchy from most to least respected is: A sample environment definition looks like this: ```yaml -apiVersion: metal.sidero.dev/v1alpha1 +apiVersion: metal.sidero.dev/v1alpha2 kind: Environment metadata: name: default @@ -52,7 +52,7 @@ spec: Example of overriding `"default"` `Environment` at the `Server` level: ```yaml -apiVersion: metal.sidero.dev/v1alpha1 +apiVersion: metal.sidero.dev/v1alpha2 kind: Server ... spec: @@ -65,7 +65,7 @@ spec: Example of overriding `"default"` `Environment` at the `ServerClass` level: ```yaml -apiVersion: metal.sidero.dev/v1alpha1 +apiVersion: metal.sidero.dev/v1alpha2 kind: ServerClass ... spec: diff --git a/website/content/v0.5/Resource Configuration/serverclasses.md b/website/content/v0.5/Resource Configuration/serverclasses.md index 272bdb858..350589186 100644 --- a/website/content/v0.5/Resource Configuration/serverclasses.md +++ b/website/content/v0.5/Resource Configuration/serverclasses.md @@ -16,15 +16,14 @@ The [Kubernetes documentation][label-selector-docs] has more information on how ## `qualifiers` -There are currently two keys: `cpu`, `systemInformation`. -Each of these keys accepts a list of entries. -The top level keys are a "logical `AND`", while the lists under each key are a "logical `OR`". +A list of hardware criteria, where each entry in the list is interpreted as a logical `OR`. +All criteria inside each entry is interpreted as a logical `AND`. Qualifiers that are not specified are not evaluated. An example: ```yaml -apiVersion: metal.sidero.dev/v1alpha1 +apiVersion: metal.sidero.dev/v1alpha2 kind: ServerClass metadata: name: serverclass-sample @@ -43,20 +42,28 @@ spec: values: - prod qualifiers: - cpu: - - manufacturer: "Intel(R) Corporation" - version: "Intel(R) Atom(TM) CPU C3558 @ 2.20GHz" - - manufacturer: Advanced Micro Devices, Inc. - version: AMD Ryzen 7 2700X Eight-Core Processor - systemInformation: - - manufacturer: Dell Inc. + hardware: + - system: + manufacturer: Dell Inc. + compute: + processors: + - manufacturer: Advanced Micro Devices, Inc. + productName: AMD Ryzen 7 2700X Eight-Core Processor + - compute: + processors: + - manufacturer: "Intel(R) Corporation" + productName: "Intel(R) Atom(TM) CPU C3558 @ 2.20GHz" + memory: + totalSize: "8 GB" ``` Servers would only be added to the above class if they: -- had _EITHER_ CPU info -- _AND_ the label key/value in `matchLabels` +- have the label `common-label` with value `true` - _AND_ match the `matchExpressions` +- _AND_ match either 1 of the following criteria: + - has a system manufactured by `Dell Inc.` _AND_ has at least 1 processor that is an `AMD Ryzen 7 2700X Eight-Core Processor` + - has at least 1 processor that is an `Intel(R) Atom(TM) CPU C3558 @ 2.20GHz` _AND_ has exactly 8 GB of total memory Additionally, Sidero automatically creates and maintains a server class called `"any"` that includes all (accepted) servers. Attempts to add qualifiers to it will be reverted. @@ -71,7 +78,7 @@ See [patching](../guides/patching) for more information on how this works. An example of settings the default install disk for all servers matching a server class: ```yaml -apiVersion: metal.sidero.dev/v1alpha1 +apiVersion: metal.sidero.dev/v1alpha2 kind: ServerClass ... spec: diff --git a/website/content/v0.5/Resource Configuration/servers.md b/website/content/v0.5/Resource Configuration/servers.md index 969991765..14cd19e95 100644 --- a/website/content/v0.5/Resource Configuration/servers.md +++ b/website/content/v0.5/Resource Configuration/servers.md @@ -10,7 +10,7 @@ These are created by PXE booting the servers and allowing them to send a registr An example server may look like the following: ```yaml -apiVersion: metal.sidero.dev/v1alpha1 +apiVersion: metal.sidero.dev/v1alpha2 kind: Server metadata: name: 00000000-0000-0000-0000-d05099d333e0 @@ -27,11 +27,66 @@ spec: name: custom urls: - http://192.168.1.199/assets/cilium.yaml - cpu: - manufacturer: Intel(R) Corporation - version: Intel(R) Atom(TM) CPU C3558 @ 2.20GHz - system: - manufacturer: Dell Inc. + hardware: + system: + manufacturer: Dell Inc. + productName: PowerEdge R630 + serialNumber: 790H8D2 + compute: + totalCoreCount: 8 + totalThreadCount: 16 + processorCount: 1 + processors: + - manufacturer: Intel + productName: Intel(R) Xeon(R) CPU E5-2630 v3 @ 2.40GHz + speed: 2400 + coreCount: 8 + threadCount: 16 + memory: + totalSize: 32 GB + moduleCount: 2 + modules: + - 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: + totalSize: 1116 GB + deviceCount: 1 + devices: + - productName: PERC H730 Mini + type: HDD + name: sda + deviceName: /dev/sda + size: 1199101181952 + wwid: naa.61866da055de070028d8e83307cc6df2 + network: + interfaceCount: 2 + interfaces: + - index: 1 + name: lo + flags: up|loopback + mtu: 65536 + mac: "" + addresses: + - 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: + - 192.168.2.8/24 + - fe80::dcb3:295c:755b:91bb/64 ``` ## Installation Disk @@ -40,7 +95,7 @@ An installation disk is required by Talos on bare metal. This can be specified in a `configPatch`: ```yaml -apiVersion: metal.sidero.dev/v1alpha1 +apiVersion: metal.sidero.dev/v1alpha2 kind: Server ... spec: @@ -54,7 +109,7 @@ spec: The install disk patch can also be set on the `ServerClass`: ```yaml -apiVersion: metal.sidero.dev/v1alpha1 +apiVersion: metal.sidero.dev/v1alpha2 kind: ServerClass ... spec: @@ -96,7 +151,7 @@ Users wishing to turn off this feature can pass the `--auto-bmc-setup=false` fla IMPI connection information can also be set manually in the `Server` spec after initial registration: ```yaml -apiVersion: metal.sidero.dev/v1alpha1 +apiVersion: metal.sidero.dev/v1alpha2 kind: Server ... spec: @@ -115,7 +170,7 @@ Without IPMI info, Sidero can still register servers, wipe them and provision cl Sidero can also fetch IPMI credentials via the `Secret` reference: ```yaml -apiVersion: metal.sidero.dev/v1alpha1 +apiVersion: metal.sidero.dev/v1alpha2 kind: Server ... spec: