mirror of
https://github.com/siderolabs/image-factory.git
synced 2025-09-21 13:51:08 +02:00
S3 does not set proper Content-Disposition, and this header might be ignored by e.g. browsers if set before redirect. We need to include it when adding new object to the cache. Additionally, if the object was previously cached, we need to ensure that Content-Disposition header will be properly updated. Signed-off-by: Mateusz Urbanek <mateusz.urbanek@siderolabs.com>
111 lines
2.8 KiB
Go
111 lines
2.8 KiB
Go
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
package http
|
|
|
|
import (
|
|
"context"
|
|
_ "embed"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"strings"
|
|
"text/template"
|
|
|
|
"github.com/blang/semver/v4"
|
|
"github.com/julienschmidt/httprouter"
|
|
"github.com/siderolabs/gen/ensure"
|
|
|
|
"github.com/siderolabs/image-factory/internal/profile"
|
|
)
|
|
|
|
//go:embed standard.ipxe
|
|
var standardIPXE string
|
|
|
|
//go:embed secureboot.ipxe
|
|
var securebootIPXE string
|
|
|
|
// handlePXE delivers a PXE script to boot Talos.
|
|
func (f *Frontend) handlePXE(ctx context.Context, w http.ResponseWriter, _ *http.Request, p httprouter.Params) error {
|
|
schematicID := p.ByName("schematic")
|
|
|
|
schematic, err := f.schematicFactory.Get(ctx, schematicID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
versionTag := p.ByName("version")
|
|
if !strings.HasPrefix(versionTag, "v") {
|
|
versionTag = "v" + versionTag
|
|
}
|
|
|
|
version, err := semver.Parse(versionTag[1:])
|
|
if err != nil {
|
|
return fmt.Errorf("error parsing version: %w", err)
|
|
}
|
|
|
|
// the PXE format is just platform+arch, so if we append cmdline, it should parse
|
|
path := "cmdline-" + p.ByName("path")
|
|
|
|
prof, err := profile.ParseFromPath(path, version.String())
|
|
if err != nil {
|
|
return fmt.Errorf("error parsing profile from path: %w", err)
|
|
}
|
|
|
|
prof, err = profile.EnhanceFromSchematic(ctx, prof, schematic, f.artifactsManager, f.secureBootService, versionTag)
|
|
if err != nil {
|
|
return fmt.Errorf("error enhancing profile from schematic: %w", err)
|
|
}
|
|
|
|
if err = prof.Validate(); err != nil {
|
|
return fmt.Errorf("error validating profile: %w", err)
|
|
}
|
|
|
|
// build the cmdline
|
|
asset, err := f.assetBuilder.Build(ctx, prof, version.String(), path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
reader, err := asset.Reader()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
defer reader.Close() //nolint:errcheck
|
|
|
|
cmdline, err := io.ReadAll(reader)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if prof.SecureBootEnabled() {
|
|
return ensure.Value(template.New("secureboot.ipxe").
|
|
Parse(securebootIPXE)).
|
|
Execute(w,
|
|
struct {
|
|
UKIURL string
|
|
Cmdline string
|
|
}{
|
|
UKIURL: f.options.ExternalPXEURL.JoinPath("image", schematicID, versionTag, fmt.Sprintf("%s-%s-secureboot-uki.efi", prof.Platform, prof.Arch)).String(),
|
|
Cmdline: string(cmdline),
|
|
},
|
|
)
|
|
}
|
|
|
|
return ensure.Value(template.New("standard.ipxe").
|
|
Parse(standardIPXE)).
|
|
Execute(w,
|
|
struct {
|
|
KernelURL string
|
|
Cmdline string
|
|
InitramfsURL string
|
|
}{
|
|
KernelURL: f.options.ExternalPXEURL.JoinPath("image", schematicID, versionTag, fmt.Sprintf("kernel-%s", prof.Arch)).String(),
|
|
Cmdline: string(cmdline),
|
|
InitramfsURL: f.options.ExternalPXEURL.JoinPath("image", schematicID, versionTag, fmt.Sprintf("initramfs-%s.xz", prof.Arch)).String(),
|
|
},
|
|
)
|
|
}
|