From 034893823ee843f4de5295e1cdff81572ae24269 Mon Sep 17 00:00:00 2001 From: Hardik Dodiya Date: Fri, 14 Jun 2024 14:26:43 +0000 Subject: [PATCH 1/3] Remove IPXE Boot --- api/v1alpha1/ipxebootconfig_types.go | 77 ------- cmd/main.go | 95 +------- .../controller/ipxebootconfig_controller.go | 149 ------------ .../ipxebootconfig_controller_test.go | 69 ------ .../serverbootconfiguration_pxe_controller.go | 199 ---------------- ...erbootconfiguration_pxe_controller_test.go | 98 -------- server/bootserver.go | 167 +------------- server/imageproxyserver.go | 216 ------------------ templates/ipxe-script.tpl | 13 -- 9 files changed, 2 insertions(+), 1081 deletions(-) delete mode 100644 api/v1alpha1/ipxebootconfig_types.go delete mode 100644 internal/controller/ipxebootconfig_controller.go delete mode 100644 internal/controller/ipxebootconfig_controller_test.go delete mode 100644 internal/controller/serverbootconfiguration_pxe_controller.go delete mode 100644 internal/controller/serverbootconfiguration_pxe_controller_test.go delete mode 100644 server/imageproxyserver.go delete mode 100644 templates/ipxe-script.tpl diff --git a/api/v1alpha1/ipxebootconfig_types.go b/api/v1alpha1/ipxebootconfig_types.go deleted file mode 100644 index b9d96a9b..00000000 --- a/api/v1alpha1/ipxebootconfig_types.go +++ /dev/null @@ -1,77 +0,0 @@ -// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and IronCore contributors -// SPDX-License-Identifier: Apache-2.0 - -package v1alpha1 - -import ( - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! -// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. - -// IPXEBootConfigSpec defines the desired state of IPXEBootConfig -type IPXEBootConfigSpec struct { - // Important: Run "make" to regenerate code after modifying this file - SystemUUID string `json:"systemUUID,omitempty"` - SystemIPs []string `json:"systemIPs,omitempty"` // TODO: Add the custom serialization. For now validate at the controller. - // TODO: remove image as this is not needed - Image string `json:"image,omitempty"` - KernelURL string `json:"kernelURL,omitempty"` - InitrdURL string `json:"initrdURL,omitempty"` - SquashfsURL string `json:"squashfsURL,omitempty"` - // TODO: remove later - IPXEServerURL string `json:"ipxeServerURL,omitempty"` - IgnitionSecretRef *corev1.LocalObjectReference `json:"ignitionSecretRef,omitempty"` - IPXEScriptSecretRef *corev1.LocalObjectReference `json:"ipxeScriptSecretRef,omitempty"` -} - -type IPXEBootConfigState string - -const ( - IPXEBootConfigStateReady IPXEBootConfigState = "Ready" - IPXEBootConfigStatePending IPXEBootConfigState = "Pending" - IPXEBootConfigStateError IPXEBootConfigState = "Error" -) - -// IPXEBootConfigStatus defines the observed state of IPXEBootConfig -type IPXEBootConfigStatus struct { - // Important: Run "make" to regenerate code after modifying this file - State IPXEBootConfigState `json:"state,omitempty"` -} - -//+kubebuilder:object:root=true -//+kubebuilder:subresource:status -//+kubebuilder:printcolumn:name="State",type=string,JSONPath=`.status.state` -//+kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` -// +genclient - -// IPXEBootConfig is the Schema for the ipxebootconfigs API -type IPXEBootConfig struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec IPXEBootConfigSpec `json:"spec,omitempty"` - Status IPXEBootConfigStatus `json:"status,omitempty"` -} - -//+kubebuilder:object:root=true - -// IPXEBootConfigList contains a list of IPXEBootConfig -type IPXEBootConfigList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []IPXEBootConfig `json:"items"` -} - -const ( - DefaultIgnitionKey = "ignition" - DefaultIPXEScriptKey = "ipxe-script" - SystemUUIDIndexKey = "spec.systemUUID" - SystemIPIndexKey = "spec.systemIPs" -) - -func init() { - SchemeBuilder.Register(&IPXEBootConfig{}, &IPXEBootConfigList{}) -} diff --git a/cmd/main.go b/cmd/main.go index 58e6714e..ba5cd1e8 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -57,7 +57,6 @@ func init() { func main() { ctx := ctrl.LoggerInto(ctrl.SetupSignalHandler(), setupLog) - defaultIpxeTemplateData := NewDefaultIPXETemplateData() defaultHttpUKIURL := NewDefaultHTTPBootData() var metricsAddr string @@ -65,21 +64,9 @@ func main() { var probeAddr string var secureMetrics bool var enableHTTP2 bool - var ipxeServerAddr string - var imageProxyServerAddr string - var ipxeServiceURL string - var ipxeServiceProtocol string - var ipxeServicePort int - var imageServerURL string - - flag.IntVar(&ipxeServicePort, "ipxe-service-port", 5000, "IPXE Service port to listen on.") - flag.StringVar(&ipxeServiceProtocol, "ipxe-service-protocol", "http", "IPXE Service Protocol.") - flag.StringVar(&ipxeServiceURL, "ipxe-service-url", "", "IPXE Service URL.") - flag.StringVar(&imageServerURL, "image-server-url", "", "OS Image Server URL.") + flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.") flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.") - flag.StringVar(&ipxeServerAddr, "ipxe-server-address", ":8082", "The address the ipxe-server binds to.") - flag.StringVar(&imageProxyServerAddr, "image-proxy-server-address", ":8083", "The address the image-proxy-server binds to.") flag.BoolVar(&enableLeaderElection, "leader-elect", false, "Enable leader election for controller manager. "+ "Enabling this will ensure there is only one active controller manager.") @@ -90,8 +77,6 @@ func main() { controllers := switches.New( // core controllers - ipxeBootConfigController, - serverBootConfigControllerPxe, serverBootConfigControllerHttp, httpBootConfigController, ) @@ -111,17 +96,6 @@ func main() { ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts))) - // set the correct ipxe service URL by getting the address from the environment - var ipxeServiceAddr string - if ipxeServiceURL == "" { - ipxeServiceAddr = os.Getenv("IPXE_SERVER_ADDRESS") - if ipxeServiceAddr == "" { - setupLog.Error(nil, "failed to set the ipxe service URL as no address is provided") - os.Exit(1) - } - ipxeServiceURL = fmt.Sprintf("%s://%s:%d", ipxeServiceProtocol, ipxeServiceAddr, ipxeServicePort) - } - // if the enable-http2 flag is false (the default), http/2 should be disabled // due to its vulnerabilities. More specifically, disabling http/2 will // prevent from being vulnerable to the HTTP/2 Stream Cancelation and @@ -170,27 +144,6 @@ func main() { os.Exit(1) } - if controllers.Enabled(ipxeBootConfigController) { - if err = (&controller.IPXEBootConfigReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - }).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "IPXEBootConfig") - os.Exit(1) - } - } - - if controllers.Enabled(serverBootConfigControllerPxe) { - if err = (&controller.ServerBootConfigurationPXEReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - IPXEServiceURL: ipxeServiceURL, - }).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "ServerBootConfigPxe") - os.Exit(1) - } - } - if controllers.Enabled(serverBootConfigControllerHttp) { if err = (&controller.ServerBootConfigurationHTTPReconciler{ Client: mgr.GetClient(), @@ -223,21 +176,11 @@ func main() { os.Exit(1) } - if err := IndexIPXEBootConfigBySystemUUID(ctx, mgr); err != nil { - setupLog.Error(err, "unable to set up indexer for IPXEBootConfig SystemUUID") - os.Exit(1) - } - if err := IndexHTTPBootConfigBySystemUUID(ctx, mgr); err != nil { setupLog.Error(err, "unable to set up indexer for HTTPBootConfig SystemUUID") os.Exit(1) } - if err := IndexIPXEBootConfigBySystemIPs(ctx, mgr); err != nil { - setupLog.Error(err, "unable to set up indexer for IPXEBootConfig SystemIPs") - os.Exit(1) - } - if err := IndexHTTPBootConfigBySystemIPs(ctx, mgr); err != nil { setupLog.Error(err, "unable to set up indexer for HTTPBootConfig SystemIP") os.Exit(1) @@ -246,9 +189,6 @@ func main() { setupLog.Info("starting boot-server") go bootserver.RunBootServer(ipxeServerAddr, ipxeServiceURL, mgr.GetClient(), serverLog.WithName("bootserver"), *defaultIpxeTemplateData, *defaultHttpUKIURL) - setupLog.Info("starting image-proxy-server") - go bootserver.RunImageProxyServer(imageProxyServerAddr, mgr.GetClient(), serverLog.WithName("imageproxyserver")) - setupLog.Info("starting manager") if err := mgr.Start(ctx); err != nil { setupLog.Error(err, "problem running manager") @@ -256,29 +196,6 @@ func main() { } } -func IndexIPXEBootConfigBySystemUUID(ctx context.Context, mgr ctrl.Manager) error { - return mgr.GetFieldIndexer().IndexField( - ctx, - &bootv1alpha1.IPXEBootConfig{}, - bootv1alpha1.SystemUUIDIndexKey, - func(Obj client.Object) []string { - ipxeBootConfig := Obj.(*bootv1alpha1.IPXEBootConfig) - return []string{ipxeBootConfig.Spec.SystemUUID} - }, - ) -} - -func IndexIPXEBootConfigBySystemIPs(ctx context.Context, mgr ctrl.Manager) error { - return mgr.GetFieldIndexer().IndexField( - ctx, &bootv1alpha1.IPXEBootConfig{}, - bootv1alpha1.SystemIPIndexKey, - func(Obj client.Object) []string { - ipxeBootConfig := Obj.(*bootv1alpha1.IPXEBootConfig) - return ipxeBootConfig.Spec.SystemIPs - }, - ) -} - func IndexHTTPBootConfigBySystemUUID(ctx context.Context, mgr ctrl.Manager) error { return mgr.GetFieldIndexer().IndexField( ctx, @@ -303,16 +220,6 @@ func IndexHTTPBootConfigBySystemIPs(ctx context.Context, mgr ctrl.Manager) error ) } -func NewDefaultIPXETemplateData() *bootserver.IPXETemplateData { - var cfg bootserver.IPXETemplateData - flag.StringVar(&cfg.KernelURL, "default-kernel-url", "", "Default URL for the kernel") - flag.StringVar(&cfg.InitrdURL, "default-initrd-url", "", "Default URL for the initrd") - flag.StringVar(&cfg.SquashfsURL, "default-squashfs-url", "", "Default URL for the squashfs") - flag.StringVar(&cfg.IPXEServerURL, "default-ipxe-server-url", "", "Default IPXE Server URL to while generating ipxe-script") - - return &cfg -} - func NewDefaultHTTPBootData() *string { var defaultUKIURL string flag.StringVar(&defaultUKIURL, "default-httpboot-uki-url", "", "Default UKI URL for http boot") diff --git a/internal/controller/ipxebootconfig_controller.go b/internal/controller/ipxebootconfig_controller.go deleted file mode 100644 index 06d33886..00000000 --- a/internal/controller/ipxebootconfig_controller.go +++ /dev/null @@ -1,149 +0,0 @@ -// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and IronCore contributors -// SPDX-License-Identifier: Apache-2.0 - -package controller - -import ( - "context" - "fmt" - - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/handler" - "sigs.k8s.io/controller-runtime/pkg/log" - "sigs.k8s.io/controller-runtime/pkg/reconcile" - - "github.com/go-logr/logr" - bootv1alpha1 "github.com/ironcore-dev/ipxe-operator/api/v1alpha1" - corev1 "k8s.io/api/core/v1" -) - -// IPXEBootConfigReconciler reconciles a IPXEBootConfig object -type IPXEBootConfigReconciler struct { - client.Client - Scheme *runtime.Scheme -} - -//+kubebuilder:rbac:groups=boot.ironcore.dev,resources=ipxebootconfigs,verbs=get;list;watch;create;update;patch;delete -//+kubebuilder:rbac:groups=boot.ironcore.dev,resources=ipxebootconfigs/status,verbs=get;update;patch -//+kubebuilder:rbac:groups=boot.ironcore.dev,resources=ipxebootconfigs/finalizers,verbs=update -//+kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch - -func (r *IPXEBootConfigReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - log := log.FromContext(ctx) - IPXEBootConfig := &bootv1alpha1.IPXEBootConfig{} - if err := r.Get(ctx, req.NamespacedName, IPXEBootConfig); err != nil { - return ctrl.Result{}, client.IgnoreNotFound(err) - } - - return r.reconcileExists(ctx, log, IPXEBootConfig) -} - -func (r *IPXEBootConfigReconciler) reconcileExists(ctx context.Context, log logr.Logger, IPXEBootConfig *bootv1alpha1.IPXEBootConfig) (ctrl.Result, error) { - if !IPXEBootConfig.DeletionTimestamp.IsZero() { - return r.delete(ctx, log, IPXEBootConfig) - } - - return r.reconcile(ctx, log, IPXEBootConfig) -} - -func (r *IPXEBootConfigReconciler) reconcile(ctx context.Context, log logr.Logger, ipxeBootConfig *bootv1alpha1.IPXEBootConfig) (ctrl.Result, error) { - log.V(1).Info("Ensuring Ignition") - state, ignitionErr := r.ensureIgnition(ctx, log, ipxeBootConfig) - if ignitionErr != nil { - patchError := r.patchStatus(ctx, ipxeBootConfig, state) - if patchError != nil { - return ctrl.Result{}, fmt.Errorf("failed to patch status %w %w", ignitionErr, patchError) - } - - log.V(1).Info("Failed to Ensure Ignition", "Error", ignitionErr) - return ctrl.Result{}, nil - } - - patchErr := r.patchStatus(ctx, ipxeBootConfig, state) - if patchErr != nil { - return ctrl.Result{}, fmt.Errorf("failed to patch status %w", patchErr) - } - - return ctrl.Result{}, nil -} - -func (r *IPXEBootConfigReconciler) ensureIgnition(ctx context.Context, _ logr.Logger, ipxeBootConfig *bootv1alpha1.IPXEBootConfig) (bootv1alpha1.IPXEBootConfigState, error) { - // Verify if the IgnitionRef is set, and it has the intended data key. - if ipxeBootConfig.Spec.IgnitionSecretRef != nil { - IgnitionSecret := &corev1.Secret{} - if err := r.Get(ctx, client.ObjectKey{Name: ipxeBootConfig.Spec.IgnitionSecretRef.Name, Namespace: ipxeBootConfig.Namespace}, IgnitionSecret); err != nil { - return bootv1alpha1.IPXEBootConfigStateError, err - // TODO: Add some validation steps to ensure that the IgntionData is compliant, if necessary. - // Assume for now, that it's going to json format. - } - if IgnitionSecret.Data[bootv1alpha1.DefaultIgnitionKey] == nil { - return bootv1alpha1.IPXEBootConfigStateError, fmt.Errorf("ignition data is missing") - } - } - - return bootv1alpha1.IPXEBootConfigStateReady, nil -} - -func (r *IPXEBootConfigReconciler) delete(_ context.Context, log logr.Logger, _ *bootv1alpha1.IPXEBootConfig) (ctrl.Result, error) { - log.V(1).Info("Deleting ipxeBootConfig") - - // TODO - - return ctrl.Result{}, nil -} - -// SetupWithManager sets up the controller with the Manager. -func (r *IPXEBootConfigReconciler) SetupWithManager(mgr ctrl.Manager) error { - return ctrl.NewControllerManagedBy(mgr). - For(&bootv1alpha1.IPXEBootConfig{}). - Watches( - &corev1.Secret{}, - handler.EnqueueRequestsFromMapFunc(r.enqueueIPXEBootConfigReferencingIgnitionSecret), - ). - Complete(r) -} - -func (r *IPXEBootConfigReconciler) patchStatus( - ctx context.Context, - ipxeBootConfig *bootv1alpha1.IPXEBootConfig, - state bootv1alpha1.IPXEBootConfigState, -) error { - base := ipxeBootConfig.DeepCopy() - ipxeBootConfig.Status.State = state - - if err := r.Status().Patch(ctx, ipxeBootConfig, client.MergeFrom(base)); err != nil { - return fmt.Errorf("error patching ipxeBootConfig: %w", err) - } - return nil -} - -func (r *IPXEBootConfigReconciler) enqueueIPXEBootConfigReferencingIgnitionSecret(ctx context.Context, secret client.Object) []reconcile.Request { - log := log.Log.WithValues("secret", secret.GetName()) - secretObj, ok := secret.(*corev1.Secret) - if !ok { - log.Error(nil, "cant decode object into Secret", secret) - return nil - } - - list := &bootv1alpha1.IPXEBootConfigList{} - if err := r.Client.List(ctx, list, client.InNamespace(secretObj.Namespace)); err != nil { - log.Error(err, "failed to list IPXEBootConfig for secret", secret) - return nil - } - - var requests []reconcile.Request - for _, ipxeBootConfig := range list.Items { - if ipxeBootConfig.Spec.IgnitionSecretRef != nil && ipxeBootConfig.Spec.IgnitionSecretRef.Name == secretObj.Name { - requests = append(requests, reconcile.Request{ - NamespacedName: types.NamespacedName{ - Name: ipxeBootConfig.Name, - Namespace: ipxeBootConfig.Namespace, - }, - }) - } - } - return requests -} diff --git a/internal/controller/ipxebootconfig_controller_test.go b/internal/controller/ipxebootconfig_controller_test.go deleted file mode 100644 index 945e603f..00000000 --- a/internal/controller/ipxebootconfig_controller_test.go +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and IronCore contributors -// SPDX-License-Identifier: Apache-2.0 - -package controller - -import ( - "context" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/controller-runtime/pkg/reconcile" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - bootv1alpha1 "github.com/ironcore-dev/ipxe-operator/api/v1alpha1" -) - -var _ = Describe("IPXEBootConfig Controller", func() { - Context("When reconciling a resource", func() { - const resourceName = "test-resource" - - ctx := context.Background() - - typeNamespacedName := types.NamespacedName{ - Name: resourceName, - Namespace: "default", // TODO(user):Modify as needed - } - ipxebootconfig := &bootv1alpha1.IPXEBootConfig{} - - BeforeEach(func() { - By("creating the custom resource for the Kind IPXEBootConfig") - err := k8sClient.Get(ctx, typeNamespacedName, ipxebootconfig) - if err != nil && errors.IsNotFound(err) { - resource := &bootv1alpha1.IPXEBootConfig{ - ObjectMeta: metav1.ObjectMeta{ - Name: resourceName, - Namespace: "default", - }, - // TODO(user): Specify other spec details if needed. - } - Expect(k8sClient.Create(ctx, resource)).To(Succeed()) - } - }) - - AfterEach(func() { - // TODO(user): Cleanup logic after each test, like removing the resource instance. - resource := &bootv1alpha1.IPXEBootConfig{} - err := k8sClient.Get(ctx, typeNamespacedName, resource) - Expect(err).NotTo(HaveOccurred()) - - By("Cleanup the specific resource instance IPXEBootConfig") - Expect(k8sClient.Delete(ctx, resource)).To(Succeed()) - }) - It("should successfully reconcile the resource", func() { - By("Reconciling the created resource") - controllerReconciler := &IPXEBootConfigReconciler{ - Client: k8sClient, - Scheme: k8sClient.Scheme(), - } - - _, err := controllerReconciler.Reconcile(ctx, reconcile.Request{ - NamespacedName: typeNamespacedName, - }) - Expect(err).NotTo(HaveOccurred()) - }) - }) -}) diff --git a/internal/controller/serverbootconfiguration_pxe_controller.go b/internal/controller/serverbootconfiguration_pxe_controller.go deleted file mode 100644 index dba3fd9a..00000000 --- a/internal/controller/serverbootconfiguration_pxe_controller.go +++ /dev/null @@ -1,199 +0,0 @@ -/* -Copyright 2024. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package controller - -import ( - "context" - "fmt" - "strings" - - "github.com/ironcore-dev/ipxe-operator/api/v1alpha1" - ironcoreimage "github.com/ironcore-dev/ironcore-image" - v1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - - metalv1alpha1 "github.com/afritzler/metal-operator/api/v1alpha1" - "github.com/go-logr/logr" - "k8s.io/apimachinery/pkg/runtime" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" -) - -type ServerBootConfigurationPXEReconciler struct { - client.Client - Scheme *runtime.Scheme - IPXEServiceURL string -} - -//+kubebuilder:rbac:groups=metal.ironcore.dev,resources=serverbootconfigurations,verbs=get;list;watch -//+kubebuilder:rbac:groups=metal.ironcore.dev,resources=serverbootconfigurations/status,verbs=get;update;patch -//+kubebuilder:rbac:groups=metal.ironcore.dev,resources=serverbootconfigurations/finalizers,verbs=update -//+kubebuilder:rbac:groups=boot.ironcore.dev,resources=ipxebootconfig,verbs=get;list;watch;create;delete;patch -//+kubebuilder:rbac:groups=boot.ironcore.dev,resources=ipxebootconfig/status,verbs=get -//+kubebuilder:rbac:groups=metal.ironcore.dev,resources=servers,verbs=get;list;watch - -// Reconcile is part of the main kubernetes reconciliation loop which aims to -// move the current state of the cluster closer to the desired state. -func (r *ServerBootConfigurationPXEReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - log := ctrl.LoggerFrom(ctx) - bootConfig := &metalv1alpha1.ServerBootConfiguration{} - if err := r.Get(ctx, req.NamespacedName, bootConfig); err != nil { - return ctrl.Result{}, client.IgnoreNotFound(err) - } - - return r.reconcileExists(ctx, log, bootConfig) -} - -func (r *ServerBootConfigurationPXEReconciler) reconcileExists(ctx context.Context, log logr.Logger, config *metalv1alpha1.ServerBootConfiguration) (ctrl.Result, error) { - if !config.DeletionTimestamp.IsZero() { - return r.delete(ctx, log, config) - } - return r.reconcile(ctx, log, config) -} - -func (r *ServerBootConfigurationPXEReconciler) delete(ctx context.Context, log logr.Logger, config *metalv1alpha1.ServerBootConfiguration) (ctrl.Result, error) { - return ctrl.Result{}, nil -} - -func (r *ServerBootConfigurationPXEReconciler) reconcile(ctx context.Context, log logr.Logger, config *metalv1alpha1.ServerBootConfiguration) (ctrl.Result, error) { - log.V(1).Info("Reconciling ServerBootConfiguration") - - systemUUID, err := r.getSystemUUIDFromBootConfig(ctx, config) - if err != nil { - return ctrl.Result{}, fmt.Errorf("failed to get system UUID from BootConfig: %w", err) - } - log.V(1).Info("Got system UUID from BootConfig", "systemUUID", systemUUID) - - systemIPs, err := r.getSystemIPFromBootConfig(ctx, config) - if err != nil { - return ctrl.Result{}, fmt.Errorf("failed to get system IP from BootConfig: %w", err) - } - log.V(1).Info("Got system IP from BootConfig", "systemIPs", systemIPs) - - kernelURL, initrdURL, squashFSURL, err := r.getImageDetailsFromConfig(ctx, config) - if err != nil { - return ctrl.Result{}, fmt.Errorf("failed to get image details from BootConfig: %w", err) - } - log.V(1).Info("Extracted OS image layer details") - - ipxeConfig := &v1alpha1.IPXEBootConfig{ - TypeMeta: metav1.TypeMeta{ - APIVersion: "boot.ironcore.dev/v1alpha1", - Kind: "IPXEBootConfig", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: config.Namespace, - Name: config.Name, - }, - Spec: v1alpha1.IPXEBootConfigSpec{ - SystemUUID: systemUUID, - SystemIPs: systemIPs, - KernelURL: kernelURL, - InitrdURL: initrdURL, - SquashfsURL: squashFSURL, - IgnitionSecretRef: &v1.LocalObjectReference{Name: config.Spec.IgnitionSecretRef.Name}, - }, - } - - if err := controllerutil.SetControllerReference(config, ipxeConfig, r.Scheme); err != nil { - return ctrl.Result{}, fmt.Errorf("failed to set controller reference: %w", err) - } - log.V(1).Info("Set controller reference") - - if err := r.Patch(ctx, ipxeConfig, client.Apply, fieldOwner, client.ForceOwnership); err != nil { - return ctrl.Result{}, fmt.Errorf("failed to apply IPXE config: %w", err) - } - log.V(1).Info("Applied IPXE config for server boot config") - - if err := r.Get(ctx, client.ObjectKey{Namespace: config.Namespace, Name: config.Name}, ipxeConfig); err != nil { - return ctrl.Result{}, fmt.Errorf("failed to get IPXE config: %w", err) - } - - if err := r.patchConfigStateFromIPXEState(ctx, ipxeConfig, config); err != nil { - return ctrl.Result{}, fmt.Errorf("failed to patch server boot config state to %s: %w", ipxeConfig.Status.State, err) - } - log.V(1).Info("Patched server boot config state") - - log.V(1).Info("Reconciled ServerBootConfiguration") - return ctrl.Result{}, nil -} - -func (r *ServerBootConfigurationPXEReconciler) patchConfigStateFromIPXEState(ctx context.Context, ipxeConfig *v1alpha1.IPXEBootConfig, config *metalv1alpha1.ServerBootConfiguration) error { - if ipxeConfig.Status.State == v1alpha1.IPXEBootConfigStateReady { - return r.patchState(ctx, config, metalv1alpha1.ServerBootConfigurationStateReady) - } - - if ipxeConfig.Status.State == v1alpha1.IPXEBootConfigStateError { - return r.patchState(ctx, config, metalv1alpha1.ServerBootConfigurationStateError) - } - return nil -} - -func (r *ServerBootConfigurationPXEReconciler) patchState(ctx context.Context, config *metalv1alpha1.ServerBootConfiguration, state metalv1alpha1.ServerBootConfigurationState) error { - configBase := config.DeepCopy() - config.Status.State = state - if err := r.Status().Patch(ctx, config, client.MergeFrom(configBase)); err != nil { - return err - } - return nil -} - -func (r *ServerBootConfigurationPXEReconciler) getSystemUUIDFromBootConfig(ctx context.Context, config *metalv1alpha1.ServerBootConfiguration) (string, error) { - server := &metalv1alpha1.Server{} - if err := r.Get(ctx, client.ObjectKey{Name: config.Spec.ServerRef.Name}, server); err != nil { - return "", fmt.Errorf("failed to get Server: %w", err) - } - - return server.Spec.UUID, nil -} - -func (r *ServerBootConfigurationPXEReconciler) getSystemIPFromBootConfig(ctx context.Context, config *metalv1alpha1.ServerBootConfiguration) ([]string, error) { - server := &metalv1alpha1.Server{} - if err := r.Get(ctx, client.ObjectKey{Name: config.Spec.ServerRef.Name}, server); err != nil { - return nil, fmt.Errorf("failed to get Server: %w", err) - } - - systemIPs := []string{} - for _, nic := range server.Status.NetworkInterfaces { - systemIPs = append(systemIPs, nic.IP.String()) - } - - return systemIPs, nil -} - -func (r *ServerBootConfigurationPXEReconciler) getImageDetailsFromConfig(ctx context.Context, config *metalv1alpha1.ServerBootConfiguration) (string, string, string, error) { - imageDetails := strings.Split(config.Spec.Image, ":") - if len(imageDetails) != 2 { - return "", "", "", fmt.Errorf("invalid image format") - } - kernelURL := fmt.Sprintf("%s/image?imageName=%s&version=%s&layerName=%s", r.IPXEServiceURL, imageDetails[0], imageDetails[1], ironcoreimage.KernelLayerMediaType) - initrdURL := fmt.Sprintf("%s/image?imageName=%s&version=%s&layerName=%s", r.IPXEServiceURL, imageDetails[0], imageDetails[1], ironcoreimage.InitRAMFSLayerMediaType) - // TODO: move this const to ironcore-image - const squashFSMediaTypeLayer = "application/vnd.ironcore.image.squashfs.v1alpha1.squashfs" - squashFSURL := fmt.Sprintf("%s/image?imageName=%s&version=%s&layerName=%s", r.IPXEServiceURL, imageDetails[0], imageDetails[1], squashFSMediaTypeLayer) - - return kernelURL, initrdURL, squashFSURL, nil -} - -// SetupWithManager sets up the controller with the Manager. -func (r *ServerBootConfigurationPXEReconciler) SetupWithManager(mgr ctrl.Manager) error { - return ctrl.NewControllerManagedBy(mgr). - For(&metalv1alpha1.ServerBootConfiguration{}). - Owns(&v1alpha1.IPXEBootConfig{}). - Complete(r) -} diff --git a/internal/controller/serverbootconfiguration_pxe_controller_test.go b/internal/controller/serverbootconfiguration_pxe_controller_test.go deleted file mode 100644 index fca2a6a3..00000000 --- a/internal/controller/serverbootconfiguration_pxe_controller_test.go +++ /dev/null @@ -1,98 +0,0 @@ -/* -Copyright 2024. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package controller - -import ( - metalv1alpha1 "github.com/afritzler/metal-operator/api/v1alpha1" - "github.com/ironcore-dev/ipxe-operator/api/v1alpha1" - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - "k8s.io/utils/ptr" - . "sigs.k8s.io/controller-runtime/pkg/envtest/komega" - - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -var _ = Describe("ServerBootConfiguration Controller", func() { - ns := SetupTest() - - It("should map a new ServerBootConfiguration", func(ctx SpecContext) { - By("creating a new Server object") - server := &metalv1alpha1.Server{ - ObjectMeta: metav1.ObjectMeta{ - GenerateName: "server-", - }, - Spec: metalv1alpha1.ServerSpec{ - UUID: "12345", - }, - } - Expect(k8sClient.Create(ctx, server)).To(Succeed()) - DeferCleanup(k8sClient.Delete, server) - - By("patching the Server NICs in Server status") - Eventually(UpdateStatus(server, func() { - server.Status.NetworkInterfaces = []metalv1alpha1.NetworkInterface{ - { - Name: "foo", - IP: metalv1alpha1.MustParseIP("1.1.1.1"), - MACAddress: "abcd", - }, - } - })).Should(Succeed()) - - By("creating a new ServerBootConfiguration") - config := &metalv1alpha1.ServerBootConfiguration{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: ns.Name, - GenerateName: "test-", - }, - Spec: metalv1alpha1.ServerBootConfigurationSpec{ - ServerRef: corev1.LocalObjectReference{ - Name: server.Name, - }, - Image: "foo:bar", - IgnitionSecretRef: &corev1.LocalObjectReference{Name: "foo"}, - }, - } - Expect(k8sClient.Create(ctx, config)).To(Succeed()) - - By("ensuring that the ipxe boot configuration is correct") - bootConfig := &v1alpha1.IPXEBootConfig{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: ns.Name, - Name: config.Name, - }, - } - Eventually(Object(bootConfig)).Should(SatisfyAll( - HaveField("OwnerReferences", ContainElement(metav1.OwnerReference{ - APIVersion: "metal.ironcore.dev/v1alpha1", - Kind: "ServerBootConfiguration", - Name: config.Name, - UID: config.UID, - Controller: ptr.To(true), - BlockOwnerDeletion: ptr.To(true), - })), - HaveField("Spec.SystemUUID", server.Spec.UUID), - HaveField("Spec.SystemIPs", ContainElement("1.1.1.1")), - HaveField("Spec.KernelURL", "http://localhost:5000/image?imageName=foo&version=bar&layerName=application/vnd.ironcore.image.vmlinuz.v1alpha1.vmlinuz"), - HaveField("Spec.InitrdURL", "http://localhost:5000/image?imageName=foo&version=bar&layerName=application/vnd.ironcore.image.initramfs.v1alpha1.initramfs"), - HaveField("Spec.SquashfsURL", "http://localhost:5000/image?imageName=foo&version=bar&layerName=application/vnd.ironcore.image.squashfs.v1alpha1.squashfs"), - HaveField("Spec.IgnitionSecretRef.Name", "foo"), - )) - }) -}) diff --git a/server/bootserver.go b/server/bootserver.go index d15848e7..90edda17 100644 --- a/server/bootserver.go +++ b/server/bootserver.go @@ -9,34 +9,18 @@ import ( "net" "net/http" "path" - "path/filepath" "strings" - "text/template" corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" butaneconfig "github.com/coreos/butane/config" butanecommon "github.com/coreos/butane/config/common" "github.com/go-logr/logr" - "github.com/ironcore-dev/ipxe-operator/api/v1alpha1" bootv1alpha1 "github.com/ironcore-dev/ipxe-operator/api/v1alpha1" ) -type IPXETemplateData struct { - KernelURL string - InitrdURL string - SquashfsURL string - RegistryURL string - IPXEServerURL string -} - func RunBootServer(ipxeServerAddr string, ipxeServiceURL string, k8sClient client.Client, log logr.Logger, defaultIpxeTemplateData IPXETemplateData, defaultUKIURL string) { - http.HandleFunc("/ipxe", func(w http.ResponseWriter, r *http.Request) { - handleIPXE(w, r, k8sClient, log, ipxeServiceURL, defaultIpxeTemplateData) - }) - http.HandleFunc("/httpboot", func(w http.ResponseWriter, r *http.Request) { handleHTTPBoot(w, r, k8sClient, log, defaultUKIURL) }) @@ -47,20 +31,7 @@ func RunBootServer(ipxeServerAddr string, ipxeServiceURL string, k8sClient clien http.Error(w, "Bad Request: UUID is required", http.StatusBadRequest) return } - - ipxeBootConfigList := &bootv1alpha1.IPXEBootConfigList{} - err := k8sClient.List(r.Context(), ipxeBootConfigList, client.MatchingFields{bootv1alpha1.SystemUUIDIndexKey: uuid}) - if client.IgnoreNotFound(err) != nil { - http.Error(w, "Internal Server Error", http.StatusInternalServerError) - return - } - - if len(ipxeBootConfigList.Items) == 0 { - log.Info("No IPXEBootConfig found with given UUID. Trying HTTPBootConfig") - handleIgnitionHTTPBoot(w, r, k8sClient, log, uuid) - } else { - handleIgnitionIPXEBoot(w, r, k8sClient, log, uuid) - } + handleIgnitionHTTPBoot(w, r, k8sClient, log, uuid) }) log.Info("Starting boot server", "address", ipxeServerAddr) @@ -70,142 +41,6 @@ func RunBootServer(ipxeServerAddr string, ipxeServiceURL string, k8sClient clien } } -func handleIPXE(w http.ResponseWriter, r *http.Request, k8sClient client.Client, log logr.Logger, ipxeServiceURL string, defaultIpxeTemplateData IPXETemplateData) { - log.Info("Processing IPXE request", "method", r.Method, "path", r.URL.Path, "clientIP", r.RemoteAddr) - ctx := r.Context() - - clientIP, _, err := net.SplitHostPort(r.RemoteAddr) - if err != nil { - log.Error(err, "Failed to parse client IP address", "clientIP", r.RemoteAddr) - http.Error(w, "Internal Server Error", http.StatusInternalServerError) - return - } - - clientIPs := []string{clientIP} - if xff := r.Header.Get("X-Forwarded-For"); xff != "" { - for _, ip := range strings.Split(xff, ",") { - trimmedIP := strings.TrimSpace(ip) - if trimmedIP != "" { - clientIPs = append(clientIPs, trimmedIP) - } - } - } - - var ipxeConfigs bootv1alpha1.IPXEBootConfigList - for _, ip := range clientIPs { - if err := k8sClient.List(ctx, &ipxeConfigs, client.MatchingFields{bootv1alpha1.SystemIPIndexKey: ip}); err != nil { - log.Info("Failed to list IPXEBootConfig for IP", "IP", ip, "error", err) - continue - } - - if len(ipxeConfigs.Items) > 0 { - log.Info("Found IPXEBootConfig", "IP", ip) - break - } - } - - if len(ipxeConfigs.Items) == 0 { - log.Info("No IPXEBootConfig found for client IP, delivering default script", "clientIP", clientIP) - serveDefaultIPXETemplate(w, log, ipxeServiceURL, defaultIpxeTemplateData) - } else { - config := ipxeConfigs.Items[0] - if config.Spec.IPXEScriptSecretRef != nil { - secret := &corev1.Secret{} - err := k8sClient.Get(ctx, types.NamespacedName{Name: config.Spec.IPXEScriptSecretRef.Name, Namespace: config.Namespace}, secret) - if err != nil { - log.Error(err, "Failed to fetch IPXE script from secret", "SecretName", config.Spec.IPXEScriptSecretRef.Name) - http.Error(w, "Internal Server Error", http.StatusInternalServerError) - return - } - - ipxeScript, exists := secret.Data[v1alpha1.DefaultIPXEScriptKey] - if !exists { - log.Info("IPXE script not found in the secret", "ExpectedKey", v1alpha1.DefaultIPXEScriptKey) - http.Error(w, "Internal Server Error", http.StatusInternalServerError) - return - } - - if _, err := w.Write(ipxeScript); err != nil { - log.Info("Failed to write custom IPXE script", "error", err) - http.Error(w, "Internal Server Error", http.StatusInternalServerError) - } - return - } - - serveDefaultIPXETemplate(w, log, ipxeServiceURL, IPXETemplateData{ - KernelURL: config.Spec.KernelURL, - InitrdURL: config.Spec.InitrdURL, - SquashfsURL: config.Spec.SquashfsURL, - IPXEServerURL: ipxeServiceURL, - }) - } -} - -func handleIgnitionIPXEBoot(w http.ResponseWriter, r *http.Request, k8sClient client.Client, log logr.Logger, uuid string) { - log.Info("Processing Ignition request", "method", r.Method, "path", r.URL.Path, "clientIP", r.RemoteAddr) - ctx := r.Context() - - ipxeBootConfigList := &bootv1alpha1.IPXEBootConfigList{} - if err := k8sClient.List(ctx, ipxeBootConfigList, client.MatchingFields{bootv1alpha1.SystemUUIDIndexKey: uuid}); err != nil { - http.Error(w, "Resource Not Found", http.StatusNotFound) - log.Info("Failed to find IPXEBootConfig", "error", err.Error()) - return - } - - if len(ipxeBootConfigList.Items) == 0 { - http.Error(w, "Resource Not Found", http.StatusNotFound) - log.Info("No IPXEBootConfig found with given UUID") - return - } - - // TODO: Assuming UUID is unique. - ipxeBootConfig := ipxeBootConfigList.Items[0] - - ignitionSecret := &corev1.Secret{} - if err := k8sClient.Get(ctx, client.ObjectKey{Name: ipxeBootConfig.Spec.IgnitionSecretRef.Name, Namespace: ipxeBootConfig.Namespace}, ignitionSecret); err != nil { - http.Error(w, "Resource Not Found", http.StatusNotFound) - log.Info("Error: Failed to get Ignition secret", "error", err.Error()) - return - } - - ignitionData, ok := ignitionSecret.Data[bootv1alpha1.DefaultIgnitionKey] - if !ok { - http.Error(w, "Resource Not Found", http.StatusNotFound) - log.Info("Error: Ignition data not found in secret") - return - } - - ignitionJSONData, err := renderIgnition(ignitionData) - if err != nil { - log.Info("Failed to render the ignition data to json", "error", err) - http.Error(w, "Internal Server Error", http.StatusInternalServerError) - return - } - - w.WriteHeader(http.StatusOK) - _, err = w.Write(ignitionJSONData) - if err != nil { - log.Info("Failed to write the ignition http response", "error", err) - http.Error(w, "Internal Server Error", http.StatusInternalServerError) - return - } -} - -func serveDefaultIPXETemplate(w http.ResponseWriter, log logr.Logger, ipxeServiceURL string, data IPXETemplateData) { - tmplPath := filepath.Join("templates", "ipxe-script.tpl") - tmpl, err := template.ParseFiles(tmplPath) - if err != nil { - log.Info("Failed to parse iPXE script template", "error", err) - http.Error(w, "Internal Server Error", http.StatusInternalServerError) - return - } - - if err := tmpl.Execute(w, data); err != nil { - log.Info("Failed to execute template", "error", err) - http.Error(w, "Internal Server Error", http.StatusInternalServerError) - } -} - func handleIgnitionHTTPBoot(w http.ResponseWriter, r *http.Request, k8sClient client.Client, log logr.Logger, uuid string) { log.Info("Processing Ignition request", "method", r.Method, "path", r.URL.Path, "clientIP", r.RemoteAddr) ctx := r.Context() diff --git a/server/imageproxyserver.go b/server/imageproxyserver.go deleted file mode 100644 index c1ad8b1e..00000000 --- a/server/imageproxyserver.go +++ /dev/null @@ -1,216 +0,0 @@ -// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and IronCore contributors -// SPDX-License-Identifier: Apache-2.0 - -package server - -import ( - "encoding/json" - "fmt" - "io" - "net/http" - "net/http/httputil" - "net/url" - "strings" - - "github.com/go-logr/logr" - ociimage "github.com/opencontainers/image-spec/specs-go/v1" - "sigs.k8s.io/controller-runtime/pkg/client" -) - -const ( - ghcrIOKey = "ghcr.io/" - imageKey = "imageName" - layerKey = "layerName" - versionKey = "version" -) - -type TokenResponse struct { - Token string `json:"token"` -} - -type ImageDetails struct { - OCIImageName string - RepositoryName string - LayerName string - Version string -} - -func RunImageProxyServer(imageProxyServerAddr string, k8sClient client.Client, log logr.Logger) { - http.HandleFunc("/image", func(w http.ResponseWriter, r *http.Request) { - imageDetails, err := parseImageURL(r.URL.Query()) - if err != nil { - http.Error(w, "Resource Not Found", http.StatusNotFound) - log.Info("Error: Failed to parse the image url", "URL", r.URL.Path, "Error", err) - return - } - - if strings.HasPrefix(imageDetails.OCIImageName, ghcrIOKey) { - handleGHCR(w, r, &imageDetails, log) - } else { - http.Error(w, "Bad Request", http.StatusBadRequest) - log.Info("Unsupported registry") - } - }) - - log.Info("Starting image proxy server", "address", imageProxyServerAddr) - if err := http.ListenAndServe(imageProxyServerAddr, nil); err != nil { - log.Error(err, "failed to start image proxy server") - panic(err) - } -} - -func handleGHCR(w http.ResponseWriter, r *http.Request, imageDetails *ImageDetails, log logr.Logger) { - log.Info("Processing Image Proxy request", "method", r.Method, "path", r.URL.Path, "clientIP", r.RemoteAddr) - - bearerToken, err := imageDetails.getBearerToken() - if err != nil { - http.Error(w, "Internal Server Error", http.StatusInternalServerError) - log.Info("Error: Failed to obtain the bearer token", "error", err) - return - } - - digest, err := imageDetails.getLayerDigest(bearerToken) - if err != nil { - http.Error(w, "Resource Not Found", http.StatusNotFound) - log.Info("Error: Failed to obtain layer digest", "error", err) - return - } - - targetURL := fmt.Sprintf("https://ghcr.io/v2/%s/blobs/%s", imageDetails.RepositoryName, digest) - proxyURL, _ := url.Parse(targetURL) - - proxy := &httputil.ReverseProxy{ - Director: imageDetails.modifyDirector(proxyURL, bearerToken, digest), - ModifyResponse: modifyProxyResponse(bearerToken), - } - - r.URL.Host = proxyURL.Host - r.URL.Scheme = proxyURL.Scheme - r.Host = proxyURL.Host - - proxy.ServeHTTP(w, r) -} - -func (imageDetails ImageDetails) getBearerToken() (string, error) { - url := fmt.Sprintf("https://ghcr.io/token?scope=repository:%s:pull", imageDetails.RepositoryName) - resp, err := http.Get(url) - if err != nil { - return "", err - } - defer resp.Body.Close() - - body, err := io.ReadAll(resp.Body) - if err != nil { - return "", err - } - - var tokenResponse TokenResponse - if err := json.Unmarshal(body, &tokenResponse); err != nil { - return "", err - } - - return tokenResponse.Token, nil -} - -func modifyProxyResponse(bearerToken string) func(*http.Response) error { - return func(resp *http.Response) error { - resp.Header.Set("Authorization", "Bearer "+bearerToken) - if resp.StatusCode == http.StatusTemporaryRedirect { - location, err := resp.Location() - if err != nil { - return err - } - - client := &http.Client{} - redirectReq, err := http.NewRequest("GET", location.String(), nil) - if err != nil { - return err - } - - copyHeaders(resp.Request.Header, redirectReq.Header) - - redirectResp, err := client.Do(redirectReq) - if err != nil { - return err - } - - replaceResponse(resp, redirectResp) - } - return nil - } -} - -func copyHeaders(source http.Header, destination http.Header) { - for name, values := range source { - for _, value := range values { - destination.Add(name, value) - } - } -} - -func replaceResponse(originalResp, redirectResp *http.Response) { - for name, values := range redirectResp.Header { - for _, value := range values { - originalResp.Header.Set(name, value) - } - } - originalResp.Body = redirectResp.Body - originalResp.StatusCode = redirectResp.StatusCode -} - -func parseImageURL(queries url.Values) (imageDetails ImageDetails, err error) { - ociImageName := queries.Get(imageKey) - layerName := queries.Get(layerKey) - version := queries.Get(versionKey) - repositoryName := strings.TrimPrefix(ociImageName, ghcrIOKey) - - if ociImageName == "" || layerName == "" || version == "" { - return ImageDetails{}, fmt.Errorf("missing required query parameters 'image' or 'layer' or 'version'") - } - - return ImageDetails{ - OCIImageName: ociImageName, - RepositoryName: repositoryName, - LayerName: layerName, - Version: version, - }, nil -} - -func (ImageDetails ImageDetails) modifyDirector(proxyURL *url.URL, bearerToken string, digest string) func(*http.Request) { - return func(req *http.Request) { - req.URL.Scheme = proxyURL.Scheme - req.URL.Host = proxyURL.Host - req.URL.Path = fmt.Sprintf("/v2/%s/blobs/%s", ImageDetails.RepositoryName, digest) - req.Header.Set("Authorization", "Bearer "+bearerToken) - } -} - -func (imageDetails ImageDetails) getLayerDigest(token string) (string, error) { - url := fmt.Sprintf("https://ghcr.io/v2/%s/manifests/%s", imageDetails.RepositoryName, imageDetails.Version) - req, err := http.NewRequest("GET", url, nil) - if err != nil { - return "", fmt.Errorf("http request to fetch manifest failed %w", err) - } - - req.Header.Set("Authorization", "Bearer "+token) - req.Header.Set("Accept", "application/vnd.oci.image.manifest.v1+json") - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return "", fmt.Errorf("http client connection failed %w", err) - } - defer resp.Body.Close() - - var manifest ociimage.Manifest - if err := json.NewDecoder(resp.Body).Decode(&manifest); err != nil { - return "", fmt.Errorf("unable to decode the manifest %w", err) - } - - for _, layer := range manifest.Layers { - if strings.Contains(layer.MediaType, imageDetails.LayerName) { - return string(layer.Digest), nil - } - } - - return "", fmt.Errorf("%s layer not found in the manifest", imageDetails.LayerName) -} diff --git a/templates/ipxe-script.tpl b/templates/ipxe-script.tpl deleted file mode 100644 index 128ff587..00000000 --- a/templates/ipxe-script.tpl +++ /dev/null @@ -1,13 +0,0 @@ -#!ipxe - -set ipxe-svc {{.IPXEServerURL}} -set kernel-url {{.KernelURL}} -set initrd-url {{.InitrdURL}} -set squashfs-url {{.SquashfsURL}} - -echo Loading kernel... -kernel ${kernel-url} initrd=initrd gl.ovl=/:tmpfs gl.url=${squashfs-url} gl.live=1 ip=dhcp ignition.firstboot=1 ignition.config.url=${ipxe-svc}/ignition/${uuid} ignition.platform.id=metal console=ttyS0,115200 console=tty0 earlyprintk=ttyS0,115200 consoleblank=0 -echo Loading initrd... -initrd ${initrd-url} -echo Booting... -boot \ No newline at end of file From 0614659c9640d8fdd8b05b8164cfc2fd84280927 Mon Sep 17 00:00:00 2001 From: Hardik Dodiya Date: Mon, 17 Jun 2024 13:08:09 +0000 Subject: [PATCH 2/3] Remove API and CRD related to IPXE Boot --- api/v1alpha1/httpbootconfig_types.go | 6 + api/v1alpha1/zz_generated.deepcopy.go | 104 --------------- cmd/main.go | 7 +- .../boot.ironcore.dev_ipxebootconfigs.yaml | 118 ------------------ config/crd/kustomization.yaml | 1 - config/rbac/ipxebootconfig_editor_role.yaml | 31 ----- config/rbac/ipxebootconfig_viewer_role.yaml | 27 ---- config/rbac/role.yaml | 43 ------- config/samples/httpbootconfig.yaml | 4 +- config/samples/ipxebootconfig.yaml | 19 --- config/samples/kustomization.yaml | 1 - go.mod | 13 +- go.sum | 24 ---- internal/controller/suite_test.go | 4 +- server/bootserver.go | 6 +- 15 files changed, 18 insertions(+), 390 deletions(-) delete mode 100644 config/crd/bases/boot.ironcore.dev_ipxebootconfigs.yaml delete mode 100644 config/rbac/ipxebootconfig_editor_role.yaml delete mode 100644 config/rbac/ipxebootconfig_viewer_role.yaml delete mode 100644 config/samples/ipxebootconfig.yaml diff --git a/api/v1alpha1/httpbootconfig_types.go b/api/v1alpha1/httpbootconfig_types.go index f839aa67..d77c2086 100644 --- a/api/v1alpha1/httpbootconfig_types.go +++ b/api/v1alpha1/httpbootconfig_types.go @@ -53,6 +53,12 @@ type HTTPBootConfigList struct { Items []HTTPBootConfig `json:"items"` } +const ( + DefaultIgnitionKey = "ignition" + SystemUUIDIndexKey = "spec.systemUUID" + SystemIPIndexKey = "spec.systemIPs" +) + func init() { SchemeBuilder.Register(&HTTPBootConfig{}, &HTTPBootConfigList{}) } diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index edf75dba..2a926ef2 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -110,107 +110,3 @@ func (in *HTTPBootConfigStatus) DeepCopy() *HTTPBootConfigStatus { in.DeepCopyInto(out) return out } - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *IPXEBootConfig) DeepCopyInto(out *IPXEBootConfig) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) - out.Status = in.Status -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IPXEBootConfig. -func (in *IPXEBootConfig) DeepCopy() *IPXEBootConfig { - if in == nil { - return nil - } - out := new(IPXEBootConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *IPXEBootConfig) 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 *IPXEBootConfigList) DeepCopyInto(out *IPXEBootConfigList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]IPXEBootConfig, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IPXEBootConfigList. -func (in *IPXEBootConfigList) DeepCopy() *IPXEBootConfigList { - if in == nil { - return nil - } - out := new(IPXEBootConfigList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *IPXEBootConfigList) 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 *IPXEBootConfigSpec) DeepCopyInto(out *IPXEBootConfigSpec) { - *out = *in - if in.SystemIPs != nil { - in, out := &in.SystemIPs, &out.SystemIPs - *out = make([]string, len(*in)) - copy(*out, *in) - } - if in.IgnitionSecretRef != nil { - in, out := &in.IgnitionSecretRef, &out.IgnitionSecretRef - *out = new(v1.LocalObjectReference) - **out = **in - } - if in.IPXEScriptSecretRef != nil { - in, out := &in.IPXEScriptSecretRef, &out.IPXEScriptSecretRef - *out = new(v1.LocalObjectReference) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IPXEBootConfigSpec. -func (in *IPXEBootConfigSpec) DeepCopy() *IPXEBootConfigSpec { - if in == nil { - return nil - } - out := new(IPXEBootConfigSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *IPXEBootConfigStatus) DeepCopyInto(out *IPXEBootConfigStatus) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IPXEBootConfigStatus. -func (in *IPXEBootConfigStatus) DeepCopy() *IPXEBootConfigStatus { - if in == nil { - return nil - } - out := new(IPXEBootConfigStatus) - in.DeepCopyInto(out) - return out -} diff --git a/cmd/main.go b/cmd/main.go index ba5cd1e8..9af080ad 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -41,7 +41,6 @@ var ( const ( // core controllers - ipxeBootConfigController = "ipxebootconfig" serverBootConfigControllerPxe = "serverbootconfigpxe" httpBootConfigController = "httpbootconfig" serverBootConfigControllerHttp = "serverbootconfighttp" @@ -64,9 +63,13 @@ func main() { var probeAddr string var secureMetrics bool var enableHTTP2 bool + var bootserverAddr string + var imageServerURL string + flag.StringVar(&imageServerURL, "image-server-url", "", "OS Image Server URL.") flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.") flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.") + flag.StringVar(&bootserverAddr, "boot-server-address", ":8082", "The address the ipxe-server binds to.") flag.BoolVar(&enableLeaderElection, "leader-elect", false, "Enable leader election for controller manager. "+ "Enabling this will ensure there is only one active controller manager.") @@ -187,7 +190,7 @@ func main() { } setupLog.Info("starting boot-server") - go bootserver.RunBootServer(ipxeServerAddr, ipxeServiceURL, mgr.GetClient(), serverLog.WithName("bootserver"), *defaultIpxeTemplateData, *defaultHttpUKIURL) + go bootserver.RunBootServer(mgr.GetClient(), serverLog.WithName("bootserver"), bootserverAddr, *defaultHttpUKIURL) setupLog.Info("starting manager") if err := mgr.Start(ctx); err != nil { diff --git a/config/crd/bases/boot.ironcore.dev_ipxebootconfigs.yaml b/config/crd/bases/boot.ironcore.dev_ipxebootconfigs.yaml deleted file mode 100644 index 85dc32e7..00000000 --- a/config/crd/bases/boot.ironcore.dev_ipxebootconfigs.yaml +++ /dev/null @@ -1,118 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: ipxebootconfigs.boot.ironcore.dev -spec: - group: boot.ironcore.dev - names: - kind: IPXEBootConfig - listKind: IPXEBootConfigList - plural: ipxebootconfigs - singular: ipxebootconfig - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .status.state - name: State - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1alpha1 - schema: - openAPIV3Schema: - description: IPXEBootConfig is the Schema for the ipxebootconfigs 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: IPXEBootConfigSpec defines the desired state of IPXEBootConfig - properties: - ignitionSecretRef: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - image: - description: 'TODO: remove image as this is not needed' - type: string - initrdURL: - type: string - ipxeScriptSecretRef: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - ipxeServerURL: - description: 'TODO: remove later' - type: string - kernelURL: - type: string - squashfsURL: - type: string - systemIPs: - items: - type: string - type: array - systemUUID: - description: 'Important: Run "make" to regenerate code after modifying - this file' - type: string - type: object - status: - description: IPXEBootConfigStatus defines the observed state of IPXEBootConfig - properties: - state: - description: 'Important: Run "make" to regenerate code after modifying - this file' - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index 3f594f7e..4a716978 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -2,7 +2,6 @@ # since it depends on service name and namespace that are out of this kustomize package. # It should be run by config/default resources: -- bases/boot.ironcore.dev_ipxebootconfigs.yaml - bases/boot.ironcore.dev_httpbootconfigs.yaml #+kubebuilder:scaffold:crdkustomizeresource diff --git a/config/rbac/ipxebootconfig_editor_role.yaml b/config/rbac/ipxebootconfig_editor_role.yaml deleted file mode 100644 index 5c5ead0b..00000000 --- a/config/rbac/ipxebootconfig_editor_role.yaml +++ /dev/null @@ -1,31 +0,0 @@ -# permissions for end users to edit ipxebootconfigs. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/name: clusterrole - app.kubernetes.io/instance: ipxebootconfig-editor-role - app.kubernetes.io/component: rbac - app.kubernetes.io/created-by: ipxe-operator - app.kubernetes.io/part-of: ipxe-operator - app.kubernetes.io/managed-by: kustomize - name: ipxebootconfig-editor-role -rules: -- apiGroups: - - boot.ironcore.dev - resources: - - ipxebootconfigs - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - boot.ironcore.dev - resources: - - ipxebootconfigs/status - verbs: - - get diff --git a/config/rbac/ipxebootconfig_viewer_role.yaml b/config/rbac/ipxebootconfig_viewer_role.yaml deleted file mode 100644 index 7eff48ad..00000000 --- a/config/rbac/ipxebootconfig_viewer_role.yaml +++ /dev/null @@ -1,27 +0,0 @@ -# permissions for end users to view ipxebootconfigs. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/name: clusterrole - app.kubernetes.io/instance: ipxebootconfig-viewer-role - app.kubernetes.io/component: rbac - app.kubernetes.io/created-by: ipxe-operator - app.kubernetes.io/part-of: ipxe-operator - app.kubernetes.io/managed-by: kustomize - name: ipxebootconfig-viewer-role -rules: -- apiGroups: - - boot.ironcore.dev - resources: - - ipxebootconfigs - verbs: - - get - - list - - watch -- apiGroups: - - boot.ironcore.dev - resources: - - ipxebootconfigs/status - verbs: - - get diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 781af475..398122f0 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -55,49 +55,6 @@ rules: - get - patch - update -- apiGroups: - - boot.ironcore.dev - resources: - - ipxebootconfig - verbs: - - create - - delete - - get - - list - - patch - - watch -- apiGroups: - - boot.ironcore.dev - resources: - - ipxebootconfig/status - verbs: - - get -- apiGroups: - - boot.ironcore.dev - resources: - - ipxebootconfigs - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - boot.ironcore.dev - resources: - - ipxebootconfigs/finalizers - verbs: - - update -- apiGroups: - - boot.ironcore.dev - resources: - - ipxebootconfigs/status - verbs: - - get - - patch - - update - apiGroups: - metal.ironcore.dev resources: diff --git a/config/samples/httpbootconfig.yaml b/config/samples/httpbootconfig.yaml index 0cd2aaa8..54f741db 100644 --- a/config/samples/httpbootconfig.yaml +++ b/config/samples/httpbootconfig.yaml @@ -14,7 +14,5 @@ spec: - 1.2.3.4 ignitionSecretRef: name: ignition-sample - kernelURL: "10.0.0.1/ipxe/rootfs.vmlinuz" - initrdURL: "10.0.0.1/ipxe/rootfs.initrd" - squashfsURL: "10.0.0.1/ipxe/root.squashfs" + ukiURL: http://1.2.3.4/uki.efi diff --git a/config/samples/ipxebootconfig.yaml b/config/samples/ipxebootconfig.yaml deleted file mode 100644 index 65b6ac32..00000000 --- a/config/samples/ipxebootconfig.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: boot.ironcore.dev/v1alpha1 -kind: IPXEBootConfig -metadata: - labels: - app.kubernetes.io/name: ipxebootconfig - app.kubernetes.io/instance: ipxebootconfig-sample - app.kubernetes.io/part-of: ipxe-operator - app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/created-by: ipxe-operator - name: ipxebootconfig-sample -spec: - systemUUID: "1234" - systemIP: "10.0.0.2" - ignitionSecretRef: - name: ignition-sample - image: gardenlinux:latest - kernelURL: "10.0.0.1/ipxe/rootfs.vmlinuz" - initrdURL: "10.0.0.1/ipxe/rootfs.initrd" - squashfsURL: "10.0.0.1/ipxe/root.squashfs" \ No newline at end of file diff --git a/config/samples/kustomization.yaml b/config/samples/kustomization.yaml index 79cf5cc8..f6f68cf4 100644 --- a/config/samples/kustomization.yaml +++ b/config/samples/kustomization.yaml @@ -1,5 +1,4 @@ ## Append samples of your project ## resources: -- boot_v1alpha1_ipxebootconfig.yaml - boot_v1alpha1_httpbootconfig.yaml #+kubebuilder:scaffold:manifestskustomizesamples diff --git a/go.mod b/go.mod index 6e7b2623..a28888d0 100644 --- a/go.mod +++ b/go.mod @@ -7,25 +7,19 @@ require ( github.com/coreos/butane v0.21.0 github.com/go-logr/logr v1.4.2 github.com/ironcore-dev/controller-utils v0.9.3 - github.com/ironcore-dev/ironcore-image v0.2.1 github.com/onsi/ginkgo/v2 v2.19.0 github.com/onsi/gomega v1.33.1 - github.com/opencontainers/image-spec v1.1.0 k8s.io/api v0.30.2 k8s.io/apimachinery v0.30.2 k8s.io/client-go v0.30.2 - k8s.io/utils v0.0.0-20231127182322-b307cd553661 sigs.k8s.io/controller-runtime v0.18.4 ) require ( - github.com/Microsoft/hcsshim v0.11.4 // indirect github.com/aws/aws-sdk-go v1.50.25 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/clarketm/json v1.17.1 // indirect - github.com/containerd/containerd v1.7.14 // indirect - github.com/containerd/log v0.1.0 // indirect github.com/coreos/go-json v0.0.0-20230131223807-18775e0fb4fb // indirect github.com/coreos/go-semver v0.3.1 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect @@ -51,20 +45,17 @@ require ( github.com/imdario/mergo v0.3.13 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.16.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/opencontainers/go-digest v1.0.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.18.0 // indirect github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/common v0.45.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect - github.com/sirupsen/logrus v1.9.3 // indirect github.com/spf13/pflag v1.0.6-0.20210604193023-d5e0c0615ace // indirect github.com/stretchr/testify v1.9.0 // indirect github.com/vincent-petithory/dataurl v1.0.0 // indirect @@ -73,7 +64,6 @@ require ( golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect golang.org/x/net v0.25.0 // indirect golang.org/x/oauth2 v0.17.0 // indirect - golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.20.0 // indirect golang.org/x/term v0.20.0 // indirect golang.org/x/text v0.15.0 // indirect @@ -81,8 +71,6 @@ require ( golang.org/x/tools v0.21.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240213162025-012b6fc9bca9 // indirect - google.golang.org/grpc v1.61.1 // indirect google.golang.org/protobuf v1.33.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect @@ -90,6 +78,7 @@ require ( k8s.io/apiextensions-apiserver v0.30.1 // indirect k8s.io/klog/v2 v2.120.1 // indirect k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect + k8s.io/utils v0.0.0-20231127182322-b307cd553661 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect sigs.k8s.io/yaml v1.4.0 // indirect diff --git a/go.sum b/go.sum index 5f9f51fa..cd901fb7 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,3 @@ -github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= -github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= github.com/afritzler/metal-operator v0.0.0-20240424135741-4d378a6dc7b7 h1:sQS81jw4cTOo3har9FLoeRFfq/H+psLCOG2WJFj2cjg= github.com/afritzler/metal-operator v0.0.0-20240424135741-4d378a6dc7b7/go.mod h1:7PTGK5V1n/Oxqvtae6faXGk7FbSueVCa5OMSOJxhaXs= github.com/aws/aws-sdk-go v1.50.25 h1:vhiHtLYybv1Nhx3Kv18BBC6L0aPJHaG9aeEsr92W99c= @@ -10,10 +8,6 @@ github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/clarketm/json v1.17.1 h1:U1IxjqJkJ7bRK4L6dyphmoO840P6bdhPdbbLySourqI= github.com/clarketm/json v1.17.1/go.mod h1:ynr2LRfb0fQU34l07csRNBTcivjySLLiY1YzQqKVfdo= -github.com/containerd/containerd v1.7.14 h1:H/XLzbnGuenZEGK+v0RkwTdv2u1QFAruMe5N0GNPJwA= -github.com/containerd/containerd v1.7.14/go.mod h1:YMC9Qt5yzNqXx/fO4j/5yYVIHXSRrlB3H7sxkUTvspg= -github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= -github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/coreos/butane v0.21.0 h1:GDi6XBheEfvxaq7Ez3wxdN+0IraAz3U7QvpVGcbHd84= github.com/coreos/butane v0.21.0/go.mod h1:3OKS5qaH58O2yLAKgAtOgBpUQSm7aIOU09IpG+IvmF4= github.com/coreos/go-json v0.0.0-20230131223807-18775e0fb4fb h1:rmqyI19j3Z/74bIRhuC59RB442rXUazKNueVpfJPxg4= @@ -76,16 +70,12 @@ github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= github.com/ironcore-dev/controller-utils v0.9.3 h1:sTrnxSzX5RrLf4B8KrAH2axSC+gxfJXphkV6df2GSsw= github.com/ironcore-dev/controller-utils v0.9.3/go.mod h1:djKnxDs0Hwxhhc0VmVY8tZnrOrElvrRV2jov/LiCZ2Y= -github.com/ironcore-dev/ironcore-image v0.2.1 h1:7LsIftIRX5btnSieo1J+xUSnW1tSIsGzYgD6NnpObyY= -github.com/ironcore-dev/ironcore-image v0.2.1/go.mod h1:BNaacvN5++9zGiTDJea4vvGDwHvPJE6S9Xb3G7hsFQU= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4= -github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -108,10 +98,6 @@ github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= -github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= -github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= -github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -126,15 +112,12 @@ github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spf13/pflag v1.0.6-0.20210604193023-d5e0c0615ace h1:9PNP1jnUjRhfmGMlkXHjYPishpcw4jpSt/V/xYY3FMA= github.com/spf13/pflag v1.0.6-0.20210604193023-d5e0c0615ace/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= @@ -174,15 +157,12 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= @@ -213,10 +193,6 @@ gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240213162025-012b6fc9bca9 h1:hZB7eLIaYlW9qXRfCq/qDaPdbeY3757uARz5Vvfv+cY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:YUWgXUFRPfoYK1IHMuxH5K6nPEXSCzIMljnQ59lLRCk= -google.golang.org/grpc v1.61.1 h1:kLAiWrZs7YeDM6MumDe7m3y4aM6wacLzM1Y/wiLP9XY= -google.golang.org/grpc v1.61.1/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= diff --git a/internal/controller/suite_test.go b/internal/controller/suite_test.go index 2891d686..8257e656 100644 --- a/internal/controller/suite_test.go +++ b/internal/controller/suite_test.go @@ -121,10 +121,10 @@ func SetupTest() *corev1.Namespace { }) Expect(err).ToNot(HaveOccurred()) - Expect((&ServerBootConfigurationPXEReconciler{ + Expect((&ServerBootConfigurationHTTPReconciler{ Client: k8sManager.GetClient(), Scheme: k8sManager.GetScheme(), - IPXEServiceURL: "http://localhost:5000", + ImageServerURL: "http://localhost:5000", }).SetupWithManager(k8sManager)).To(Succeed()) go func() { diff --git a/server/bootserver.go b/server/bootserver.go index 90edda17..5f63ef81 100644 --- a/server/bootserver.go +++ b/server/bootserver.go @@ -20,7 +20,7 @@ import ( bootv1alpha1 "github.com/ironcore-dev/ipxe-operator/api/v1alpha1" ) -func RunBootServer(ipxeServerAddr string, ipxeServiceURL string, k8sClient client.Client, log logr.Logger, defaultIpxeTemplateData IPXETemplateData, defaultUKIURL string) { +func RunBootServer(k8sClient client.Client, log logr.Logger, bootserverAddr string, defaultUKIURL string) { http.HandleFunc("/httpboot", func(w http.ResponseWriter, r *http.Request) { handleHTTPBoot(w, r, k8sClient, log, defaultUKIURL) }) @@ -34,8 +34,8 @@ func RunBootServer(ipxeServerAddr string, ipxeServiceURL string, k8sClient clien handleIgnitionHTTPBoot(w, r, k8sClient, log, uuid) }) - log.Info("Starting boot server", "address", ipxeServerAddr) - if err := http.ListenAndServe(ipxeServerAddr, nil); err != nil { + log.Info("Starting boot server", "address", bootserverAddr) + if err := http.ListenAndServe(bootserverAddr, nil); err != nil { log.Error(err, "failed to start boot server") panic(err) } From 610587da30f71897cbcdc8e1282ac616a9f4993f Mon Sep 17 00:00:00 2001 From: Hardik Dodiya Date: Mon, 17 Jun 2024 13:15:06 +0000 Subject: [PATCH 3/3] Fix the Dockerfile and remove helper file --- Dockerfile | 2 -- internal/controller/helper.go | 23 ----------------------- 2 files changed, 25 deletions(-) delete mode 100644 internal/controller/helper.go diff --git a/Dockerfile b/Dockerfile index df006c17..2443ff4d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,7 +16,6 @@ COPY cmd/main.go cmd/main.go COPY api/ api/ COPY internal/controller/ internal/controller/ COPY server/ server/ -COPY templates/ templates/ # Build # the GOARCH has not a default value to allow the binary be built according to the host where the command @@ -30,7 +29,6 @@ RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o ma FROM gcr.io/distroless/static:nonroot WORKDIR / COPY --from=builder /workspace/manager . -COPY --from=builder /workspace/templates/ templates/ USER 65532:65532 ENTRYPOINT ["/manager"] diff --git a/internal/controller/helper.go b/internal/controller/helper.go deleted file mode 100644 index 6137b1f2..00000000 --- a/internal/controller/helper.go +++ /dev/null @@ -1,23 +0,0 @@ -/* -Copyright 2024. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package controller - -import "sigs.k8s.io/controller-runtime/pkg/client" - -const ( - fieldOwner = client.FieldOwner("boot.ironcore.dev/controller-manager") -)