Skip to content

Commit a19e9d4

Browse files
committed
Construct UKIURL from the OCI format for the HTTPBoot
1 parent c18df2f commit a19e9d4

File tree

1 file changed

+49
-9
lines changed

1 file changed

+49
-9
lines changed

internal/controller/serverbootconfiguration_http_controller.go

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ package controller
55

66
import (
77
"context"
8+
"encoding/json"
89
"fmt"
10+
"github.com/containerd/containerd/remotes/docker"
11+
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
912
"strings"
1013

1114
corev1 "k8s.io/api/core/v1"
@@ -25,6 +28,10 @@ import (
2528
metalv1alpha1 "github.com/ironcore-dev/metal-operator/api/v1alpha1"
2629
)
2730

31+
const (
32+
MediaTypeUKI = "application/vnd.ironcore.image.uki"
33+
)
34+
2835
type ServerBootConfigurationHTTPReconciler struct {
2936
client.Client
3037
Scheme *runtime.Scheme
@@ -75,7 +82,10 @@ func (r *ServerBootConfigurationHTTPReconciler) reconcile(ctx context.Context, l
7582
}
7683
log.V(1).Info("Got system IPs from Server", "systemIPs", systemIPs)
7784

78-
ukiURL := r.constructUKIURL(config.Spec.Image)
85+
ukiURL, err := r.constructUKIURL(ctx, config.Spec.Image)
86+
if err != nil {
87+
return ctrl.Result{}, fmt.Errorf("failed to construct UKI URL: %w", err)
88+
}
7989
log.V(1).Info("Extracted UKI URL for boot")
8090

8191
httpBootConfig := &bootv1alpha1.HTTPBootConfig{
@@ -166,16 +176,46 @@ func (r *ServerBootConfigurationHTTPReconciler) getSystemIPFromServer(ctx contex
166176
return systemIPs, nil
167177
}
168178

169-
func (r *ServerBootConfigurationHTTPReconciler) constructUKIURL(image string) string {
170-
sanitizedImage := strings.ReplaceAll(image, "/", "-")
171-
sanitizedImage = strings.ReplaceAll(sanitizedImage, ":", "-")
172-
sanitizedImage = strings.ReplaceAll(sanitizedImage, "https://", "")
173-
sanitizedImage = strings.ReplaceAll(sanitizedImage, "http://", "")
179+
func (r *ServerBootConfigurationHTTPReconciler) constructUKIURL(ctx context.Context, image string) (string, error) {
180+
imageDetails := strings.Split(image, ":")
181+
if len(imageDetails) != 2 {
182+
return "", fmt.Errorf("invalid image format")
183+
}
184+
185+
ukiDigest, err := r.getUKIDigestFromNestedManifest(ctx, imageDetails[0], imageDetails[1])
186+
if err != nil {
187+
return "", fmt.Errorf("failed to fetch UKI layer digest: %w", err)
188+
}
189+
190+
ukiURL := fmt.Sprintf("%s/image?imageName=%s&version=%s&layerDigest=%s", r.ImageServerURL, imageDetails[0], imageDetails[1], ukiDigest)
191+
return ukiURL, nil
192+
}
193+
194+
func (r *ServerBootConfigurationHTTPReconciler) getUKIDigestFromNestedManifest(ctx context.Context, imageName, imageVersion string) (string, error) {
195+
resolver := docker.NewResolver(docker.ResolverOptions{})
196+
imageRef := fmt.Sprintf("%s:%s", imageName, imageVersion)
197+
name, desc, err := resolver.Resolve(ctx, imageRef)
198+
if err != nil {
199+
return "", fmt.Errorf("failed to resolve image reference: %w", err)
200+
}
201+
202+
manifestData, err := fetchContent(ctx, resolver, name, desc)
203+
if err != nil {
204+
return "", fmt.Errorf("failed to fetch manifest data: %w", err)
205+
}
206+
207+
var manifest ocispec.Manifest
208+
if err := json.Unmarshal(manifestData, &manifest); err != nil {
209+
return "", fmt.Errorf("failed to unmarshal manifest: %w", err)
210+
}
174211

175-
filename := fmt.Sprintf("%s-uki.efi", sanitizedImage)
212+
for _, layer := range manifest.Layers {
213+
if layer.MediaType == MediaTypeUKI {
214+
return layer.Digest.String(), nil
215+
}
216+
}
176217

177-
ukiURL := fmt.Sprintf("%s/%s", r.ImageServerURL, filename)
178-
return ukiURL
218+
return "", fmt.Errorf("UKI layer digest not found")
179219
}
180220

181221
// SetupWithManager sets up the controller with the Manager.

0 commit comments

Comments
 (0)