Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions api/v1alpha1/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and IronCore contributors
// SPDX-License-Identifier: Apache-2.0

package v1alpha1

const (
DefaultIgnitionKey = "ignition" // Key for accessing Ignition configuration data within a Kubernetes Secret object.
DefaultIPXEScriptKey = "ipxe-script" // Key for accessing iPXE script data within the iPXE-specific Secret object.
SystemUUIDIndexKey = "spec.systemUUID" // Field to index resources by their system UUID.
SystemIPIndexKey = "spec.systemIPs" // Field to index resources by their system IP addresses.
DefaultFormatKey = "format" // Key for determining the format of the data stored in a Secret, such as fcos or plain-ignition.
IgnitionV2Format = "ignitionv2" // Specifies the format value corresponding to Ignition config version 2.
IgnitionV3Format = "ignitionv3" // Specifies the format value corresponding to Ignition config version 3.
FCOSFormat = "fcos" // Specifies the format value used for Fedora CoreOS specific configurations.
)
7 changes: 0 additions & 7 deletions api/v1alpha1/ipxebootconfig_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,6 @@ type IPXEBootConfigList struct {
Items []IPXEBootConfig `json:"items"`
}

const (
DefaultIgnitionKey = "ignition"
DefaultIPXEScriptKey = "ipxe-script"
SystemUUIDIndexKey = "spec.systemUUID"
SystemIPIndexKey = "spec.systemIPs"
)

func init() {
SchemeBuilder.Register(&IPXEBootConfig{}, &IPXEBootConfigList{})
}
84 changes: 53 additions & 31 deletions server/bootserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package server

import (
"context"
"encoding/json"
"fmt"
"net"
Expand All @@ -14,6 +15,7 @@ import (
"text/template"

corev1 "k8s.io/api/core/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"

Expand Down Expand Up @@ -157,28 +159,32 @@ func handleIgnitionIPXEBoot(w http.ResponseWriter, r *http.Request, k8sClient cl
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
ignitionSecret := corev1.Secret{
ObjectMeta: v1.ObjectMeta{
Name: ipxeBootConfig.Spec.IgnitionSecretRef.Name,
Namespace: ipxeBootConfig.Namespace,
},
}

ignitionData, ok := ignitionSecret.Data[bootv1alpha1.DefaultIgnitionKey]
if !ok {
ignitionData, ignitionFormat, err := fetchIgnitionData(ctx, k8sClient, ignitionSecret)
if err != nil {
http.Error(w, "Resource Not Found", http.StatusNotFound)
log.Info("Error: Ignition data not found in secret")
log.Info("Failed to fetch IgnitionData", "error", err.Error())
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
var ignitionJSONData []byte
switch strings.TrimSpace(ignitionFormat) {
case bootv1alpha1.FCOSFormat:
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
}
default:
ignitionJSONData = ignitionData
}

w.WriteHeader(http.StatusOK)
Expand Down Expand Up @@ -222,28 +228,32 @@ func handleIgnitionHTTPBoot(w http.ResponseWriter, r *http.Request, k8sClient cl
return
}

// TODO: Assuming UUID is unique.
HTTPBootConfig := HTTPBootConfigList.Items[0]
httpBootConfig := HTTPBootConfigList.Items[0]

ignitionSecret := &corev1.Secret{}
if err := k8sClient.Get(ctx, client.ObjectKey{Name: HTTPBootConfig.Spec.IgnitionSecretRef.Name, Namespace: HTTPBootConfig.Spec.IgnitionSecretRef.Namespace}, ignitionSecret); err != nil {
http.Error(w, "Resource Not Found", http.StatusNotFound)
log.Info("Error: Failed to get Ignition secret", "error", err.Error())
return
ignitionSecret := corev1.Secret{
ObjectMeta: v1.ObjectMeta{
Name: httpBootConfig.Spec.IgnitionSecretRef.Name,
Namespace: httpBootConfig.Spec.IgnitionSecretRef.Namespace,
},
}

ignitionData, ok := ignitionSecret.Data[bootv1alpha1.DefaultIgnitionKey]
if !ok {
ignitionData, ignitionFormat, err := fetchIgnitionData(ctx, k8sClient, ignitionSecret)
if err != nil {
http.Error(w, "Resource Not Found", http.StatusNotFound)
log.Info("Error: Ignition data not found in secret")
log.Info("Failed to fetch IgnitionData", "error", err.Error())
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
var ignitionJSONData []byte
switch strings.TrimSpace(ignitionFormat) {
case bootv1alpha1.FCOSFormat:
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
}
default:
ignitionJSONData = ignitionData
}

w.WriteHeader(http.StatusOK)
Expand All @@ -255,6 +265,18 @@ func handleIgnitionHTTPBoot(w http.ResponseWriter, r *http.Request, k8sClient cl
}
}

func fetchIgnitionData(ctx context.Context, k8sClient client.Client, ignitionSecret corev1.Secret) ([]byte, string, error) {
secretObj := &corev1.Secret{}
if err := k8sClient.Get(ctx, client.ObjectKey{Name: ignitionSecret.Name, Namespace: ignitionSecret.Namespace}, secretObj); err != nil {
return nil, "", fmt.Errorf("failed to get the Ignition Secret %w", err)
}
ignitionData, ok := secretObj.Data[bootv1alpha1.DefaultIgnitionKey]
if !ok {
return nil, "", fmt.Errorf("secret data-key:ignition not found")
}
return ignitionData, string(secretObj.Data[bootv1alpha1.DefaultFormatKey]), nil
}

func renderIgnition(yamlData []byte) ([]byte, error) {
translateOptions := butanecommon.TranslateBytesOptions{
Raw: true,
Expand Down