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
53 changes: 30 additions & 23 deletions internal/controller/serverbootconfiguration_pxe_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,42 +219,49 @@ func (r *ServerBootConfigurationPXEReconciler) getLayerDigestsFromNestedManifest
return "", "", "", fmt.Errorf("failed to resolve image reference: %w", err)
}

indexData, err := fetchContent(ctx, resolver, name, desc)
targetManifestDesc := desc
manifestData, err := fetchContent(ctx, resolver, name, desc)
if err != nil {
return "", "", "", fmt.Errorf("failed to fetch index manifest: %w", err)
return "", "", "", fmt.Errorf("failed to fetch manifest data: %w", err)
}

var indexManifest ocispec.Index
if err := json.Unmarshal(indexData, &indexManifest); err != nil {
var manifest ocispec.Manifest
if err := json.Unmarshal(manifestData, &manifest); err != nil {
return "", "", "", fmt.Errorf("failed to unmarshal index manifest: %w", err)
}

var targetManifestDesc ocispec.Descriptor
for _, manifest := range indexManifest.Manifests {
if strings.HasPrefix(manifest.Annotations["cname"], CNAMEPrefixMetalPXE) {
if manifest.Annotations["architecture"] == r.Architecture {
targetManifestDesc = manifest
break
}
if desc.MediaType == ocispec.MediaTypeImageIndex {
var indexManifest ocispec.Index
if err := json.Unmarshal(manifestData, &indexManifest); err != nil {
return "", "", "", fmt.Errorf("failed to unmarshal index manifest: %w", err)
}
}

if targetManifestDesc.Digest == "" {
return "", "", "", fmt.Errorf("failed to find target manifest with cname annotation")
}
for _, manifest := range indexManifest.Manifests {
if strings.HasPrefix(manifest.Annotations["cname"], CNAMEPrefixMetalPXE) {
if manifest.Annotations["architecture"] == r.Architecture {
targetManifestDesc = manifest
break
}
}
}
if targetManifestDesc.Digest == "" {
return "", "", "", fmt.Errorf("failed to find target manifest with cname annotation")
}

nestedData, err := fetchContent(ctx, resolver, name, targetManifestDesc)
if err != nil {
return "", "", "", fmt.Errorf("failed to fetch nested manifest: %w", err)
}
nestedData, err := fetchContent(ctx, resolver, name, targetManifestDesc)
if err != nil {
return "", "", "", fmt.Errorf("failed to fetch nested manifest: %w", err)
}

var nestedManifest ocispec.Manifest
if err := json.Unmarshal(nestedData, &nestedManifest); err != nil {
return "", "", "", fmt.Errorf("failed to unmarshal nested manifest: %w", err)
var nestedManifest ocispec.Manifest
if err := json.Unmarshal(nestedData, &nestedManifest); err != nil {
return "", "", "", fmt.Errorf("failed to unmarshal nested manifest: %w", err)
}
manifest = nestedManifest
}

var kernelDigest, initrdDigest, squashFSDigest string
for _, layer := range nestedManifest.Layers {
for _, layer := range manifest.Layers {
if layer.Annotations[AnnotationArchitecture] == r.Architecture {
switch layer.MediaType {
case MediaTypeKernel:
Expand Down
61 changes: 61 additions & 0 deletions internal/controller/serverbootconfiguration_pxe_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,65 @@ var _ = Describe("ServerBootConfiguration Controller", func() {
HaveField("Spec.IgnitionSecretRef.Name", "foo"),
))
})

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())

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: "ghcr.io/gardenlinux/gardenlinux:1770.0-metal_pxe-arm64-1770.0-60d819dd-arm64",
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.IgnitionSecretRef.Name", "foo"),
))
})
})
2 changes: 1 addition & 1 deletion internal/controller/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ func SetupTest() *corev1.Namespace {
Client: k8sManager.GetClient(),
Scheme: k8sManager.GetScheme(),
IPXEServiceURL: "http://localhost:5000",
Architecture: "amd64",
Architecture: "arm64",
}).SetupWithManager(k8sManager)).To(Succeed())

Expect((&ServerBootConfigurationHTTPReconciler{
Expand Down