Skip to content

Commit

Permalink
Support multiple ignition formats
Browse files Browse the repository at this point in the history
  • Loading branch information
hardikdr committed Aug 6, 2024
1 parent 4efcb4e commit 74a3dc0
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 38 deletions.
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

0 comments on commit 74a3dc0

Please sign in to comment.