feat: imager overlay
Support overlays for imager. The `Install` interface is not wired yet, it will be done as a different PR. This should be a no-op for existing imager. Part of: #8350 Signed-off-by: Noel Georgi <git@frezbo.dev>
This commit is contained in:
parent
0b9b4da12a
commit
8125e754b8
@ -37,6 +37,8 @@ var cmdFlags struct {
|
||||
OutputPath string
|
||||
OutputKind string
|
||||
TarToStdout bool
|
||||
OverlayName string
|
||||
OverlayImage string
|
||||
}
|
||||
|
||||
// rootCmd represents the base command when called without any subcommands.
|
||||
@ -74,6 +76,15 @@ var rootCmd = &cobra.Command{
|
||||
},
|
||||
}
|
||||
|
||||
if cmdFlags.OverlayName != "" || cmdFlags.OverlayImage != "" {
|
||||
prof.Overlay = &profile.OverlayOptions{
|
||||
Name: cmdFlags.OverlayName,
|
||||
Image: profile.ContainerAsset{
|
||||
ImageRef: cmdFlags.OverlayImage,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
prof.Input.SystemExtensions = xslices.Map(
|
||||
cmdFlags.SystemExtensionImages,
|
||||
func(imageRef string) profile.ContainerAsset {
|
||||
@ -163,4 +174,8 @@ func init() {
|
||||
rootCmd.PersistentFlags().StringVar(&cmdFlags.OutputPath, "output", "/out", "The output directory path")
|
||||
rootCmd.PersistentFlags().StringVar(&cmdFlags.OutputKind, "output-kind", "", "Override output kind")
|
||||
rootCmd.PersistentFlags().BoolVar(&cmdFlags.TarToStdout, "tar-to-stdout", false, "Tar output and send to stdout")
|
||||
rootCmd.PersistentFlags().StringVar(&cmdFlags.OverlayName, "overlay-name", "", "The name of the overlay to use")
|
||||
rootCmd.PersistentFlags().StringVar(&cmdFlags.OverlayImage, "overlay-image", "", "The image reference to the overlay")
|
||||
rootCmd.MarkFlagsMutuallyExclusive("board", "overlay-name")
|
||||
rootCmd.MarkFlagsMutuallyExclusive("board", "overlay-image")
|
||||
}
|
||||
|
@ -10,21 +10,26 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/siderolabs/go-procfs/procfs"
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"github.com/siderolabs/talos/internal/app/machined/pkg/runtime"
|
||||
talosruntime "github.com/siderolabs/talos/internal/app/machined/pkg/runtime"
|
||||
"github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/board"
|
||||
"github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/platform"
|
||||
"github.com/siderolabs/talos/internal/pkg/secureboot/uki"
|
||||
"github.com/siderolabs/talos/pkg/imager/extensions"
|
||||
"github.com/siderolabs/talos/pkg/imager/internal/overlay/executor"
|
||||
"github.com/siderolabs/talos/pkg/imager/profile"
|
||||
"github.com/siderolabs/talos/pkg/imager/quirks"
|
||||
"github.com/siderolabs/talos/pkg/imager/utils"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/merge"
|
||||
"github.com/siderolabs/talos/pkg/machinery/constants"
|
||||
"github.com/siderolabs/talos/pkg/machinery/kernel"
|
||||
"github.com/siderolabs/talos/pkg/machinery/overlay"
|
||||
"github.com/siderolabs/talos/pkg/reporter"
|
||||
"github.com/siderolabs/talos/pkg/version"
|
||||
)
|
||||
@ -33,6 +38,8 @@ import (
|
||||
type Imager struct {
|
||||
prof profile.Profile
|
||||
|
||||
overlayInstaller overlay.Installer
|
||||
|
||||
tempDir string
|
||||
|
||||
// boot assets
|
||||
@ -45,34 +52,6 @@ type Imager struct {
|
||||
|
||||
// New creates a new Imager.
|
||||
func New(prof profile.Profile) (*Imager, error) {
|
||||
// resolve the profile if it contains a base name
|
||||
if prof.BaseProfileName != "" {
|
||||
baseProfile, ok := profile.Default[prof.BaseProfileName]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unknown base profile: %s", prof.BaseProfileName)
|
||||
}
|
||||
|
||||
baseProfile = baseProfile.DeepCopy()
|
||||
|
||||
// merge the profiles
|
||||
if err := merge.Merge(&baseProfile, &prof); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
prof = baseProfile
|
||||
prof.BaseProfileName = ""
|
||||
}
|
||||
|
||||
if prof.Version == "" {
|
||||
prof.Version = version.Tag
|
||||
}
|
||||
|
||||
if err := prof.Validate(); err != nil {
|
||||
return nil, fmt.Errorf("profile is invalid: %w", err)
|
||||
}
|
||||
|
||||
prof.Input.FillDefaults(prof.Arch, prof.Version, prof.SecureBootEnabled())
|
||||
|
||||
return &Imager{
|
||||
prof: prof,
|
||||
}, nil
|
||||
@ -89,22 +68,31 @@ func (i *Imager) Execute(ctx context.Context, outputPath string, report *reporte
|
||||
|
||||
defer os.RemoveAll(i.tempDir) //nolint:errcheck
|
||||
|
||||
// 0. Handle overlays first
|
||||
if err = i.handleOverlay(ctx, report); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err = i.handleProf(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
report.Report(reporter.Update{
|
||||
Message: "profile ready:",
|
||||
Status: reporter.StatusSucceeded,
|
||||
})
|
||||
|
||||
// 0. Dump the profile.
|
||||
// 1. Dump the profile.
|
||||
if err = i.prof.Dump(os.Stderr); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// 1. Transform `initramfs.xz` with system extensions
|
||||
// 2. Transform `initramfs.xz` with system extensions
|
||||
if err = i.buildInitramfs(ctx, report); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// 2. Prepare kernel arguments.
|
||||
// 3. Prepare kernel arguments.
|
||||
if err = i.buildCmdline(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -114,14 +102,14 @@ func (i *Imager) Execute(ctx context.Context, outputPath string, report *reporte
|
||||
Status: reporter.StatusSucceeded,
|
||||
})
|
||||
|
||||
// 3. Build UKI if Secure Boot is enabled.
|
||||
// 4. Build UKI if Secure Boot is enabled.
|
||||
if i.prof.SecureBootEnabled() {
|
||||
if err = i.buildUKI(ctx, report); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Build the output.
|
||||
// 5. Build the output.
|
||||
outputAssetPath = filepath.Join(outputPath, i.prof.OutputPath())
|
||||
|
||||
switch i.prof.Output.Kind {
|
||||
@ -154,7 +142,7 @@ func (i *Imager) Execute(ctx context.Context, outputPath string, report *reporte
|
||||
Status: reporter.StatusSucceeded,
|
||||
})
|
||||
|
||||
// 5. Post-process the output.
|
||||
// 6. Post-process the output.
|
||||
switch i.prof.Output.OutFormat {
|
||||
case profile.OutFormatRaw:
|
||||
// do nothing
|
||||
@ -172,6 +160,92 @@ func (i *Imager) Execute(ctx context.Context, outputPath string, report *reporte
|
||||
}
|
||||
}
|
||||
|
||||
func (i *Imager) handleOverlay(ctx context.Context, report *reporter.Reporter) error {
|
||||
if i.prof.Overlay == nil {
|
||||
report.Report(reporter.Update{
|
||||
Message: "skipped pulling overlay (no overlay)",
|
||||
Status: reporter.StatusSkip,
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
tempOverlayPath := filepath.Join(i.tempDir, "overlay")
|
||||
|
||||
if err := os.MkdirAll(tempOverlayPath, 0o755); err != nil {
|
||||
return fmt.Errorf("failed to create overlay directory: %w", err)
|
||||
}
|
||||
|
||||
if err := i.prof.Overlay.Image.Extract(ctx, tempOverlayPath, runtime.GOARCH, progressPrintf(report, reporter.Update{Message: "pulling overlay...", Status: reporter.StatusRunning})); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// find all *.yaml files in the tempOverlayPath/profiles/ directory
|
||||
profileYAMLs, err := filepath.Glob(filepath.Join(tempOverlayPath, "profiles", "*.yaml"))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to find profiles: %w", err)
|
||||
}
|
||||
|
||||
installerName := i.prof.Overlay.Name
|
||||
|
||||
if installerName == "" {
|
||||
installerName = "default"
|
||||
}
|
||||
|
||||
i.overlayInstaller = executor.New(filepath.Join(tempOverlayPath, "installers", installerName))
|
||||
|
||||
for _, profilePath := range profileYAMLs {
|
||||
profileName := strings.TrimSuffix(filepath.Base(profilePath), ".yaml")
|
||||
|
||||
var overlayProfile profile.Profile
|
||||
|
||||
profileDataBytes, err := os.ReadFile(profilePath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read profile: %w", err)
|
||||
}
|
||||
|
||||
if err := yaml.Unmarshal(profileDataBytes, &overlayProfile); err != nil {
|
||||
return fmt.Errorf("failed to unmarshal profile: %w", err)
|
||||
}
|
||||
|
||||
profile.Default[profileName] = overlayProfile
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *Imager) handleProf() error {
|
||||
// resolve the profile if it contains a base name
|
||||
if i.prof.BaseProfileName != "" {
|
||||
baseProfile, ok := profile.Default[i.prof.BaseProfileName]
|
||||
if !ok {
|
||||
return fmt.Errorf("unknown base profile: %s", i.prof.BaseProfileName)
|
||||
}
|
||||
|
||||
baseProfile = baseProfile.DeepCopy()
|
||||
|
||||
// merge the profiles
|
||||
if err := merge.Merge(&baseProfile, &i.prof); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
i.prof = baseProfile
|
||||
i.prof.BaseProfileName = ""
|
||||
}
|
||||
|
||||
if i.prof.Version == "" {
|
||||
i.prof.Version = version.Tag
|
||||
}
|
||||
|
||||
if err := i.prof.Validate(); err != nil {
|
||||
return fmt.Errorf("profile is invalid: %w", err)
|
||||
}
|
||||
|
||||
i.prof.Input.FillDefaults(i.prof.Arch, i.prof.Version, i.prof.SecureBootEnabled())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// buildInitramfs transforms `initramfs.xz` with system extensions.
|
||||
func (i *Imager) buildInitramfs(ctx context.Context, report *reporter.Reporter) error {
|
||||
if len(i.prof.Input.SystemExtensions) == 0 {
|
||||
@ -238,6 +312,8 @@ func (i *Imager) buildInitramfs(ctx context.Context, report *reporter.Reporter)
|
||||
}
|
||||
|
||||
// buildCmdline builds the kernel command line.
|
||||
//
|
||||
//nolint:gocyclo
|
||||
func (i *Imager) buildCmdline() error {
|
||||
p, err := platform.NewPlatform(i.prof.Platform)
|
||||
if err != nil {
|
||||
@ -251,8 +327,9 @@ func (i *Imager) buildCmdline() error {
|
||||
cmdline.SetAll(p.KernelArgs().Strings())
|
||||
|
||||
// board kernel args
|
||||
// TODO: check if supports overlay quirk
|
||||
if i.prof.Board != "" {
|
||||
var b runtime.Board
|
||||
var b talosruntime.Board
|
||||
|
||||
b, err = board.NewBoard(i.prof.Board)
|
||||
if err != nil {
|
||||
@ -263,6 +340,16 @@ func (i *Imager) buildCmdline() error {
|
||||
cmdline.SetAll(b.KernelArgs().Strings())
|
||||
}
|
||||
|
||||
// overlay kernel args
|
||||
if i.overlayInstaller != nil {
|
||||
options, optsErr := i.overlayInstaller.GetOptions(i.prof.Overlay.Options)
|
||||
if optsErr != nil {
|
||||
return optsErr
|
||||
}
|
||||
|
||||
cmdline.SetAll(options.KernelArgs)
|
||||
}
|
||||
|
||||
// first defaults, then extra kernel args to allow extra kernel args to override defaults
|
||||
if err = cmdline.AppendAll(kernel.DefaultArgs); err != nil {
|
||||
return err
|
||||
|
83
pkg/imager/internal/overlay/executor/executor.go
Normal file
83
pkg/imager/internal/overlay/executor/executor.go
Normal file
@ -0,0 +1,83 @@
|
||||
// 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 executor implements overlay.Installer
|
||||
package executor
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os/exec"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
"github.com/siderolabs/talos/pkg/machinery/overlay"
|
||||
)
|
||||
|
||||
var _ overlay.Installer = (*Options)(nil)
|
||||
|
||||
// Options executor options.
|
||||
type Options struct {
|
||||
commandPath string
|
||||
}
|
||||
|
||||
// New returns a new overlay installer executor.
|
||||
func New(commandPath string) *Options {
|
||||
return &Options{
|
||||
commandPath: commandPath,
|
||||
}
|
||||
}
|
||||
|
||||
// GetOptions returns the options for the overlay installer.
|
||||
func (o *Options) GetOptions(extra overlay.InstallExtraOptions) (overlay.Options, error) {
|
||||
// parse extra as yaml
|
||||
extraYAML, err := yaml.Marshal(extra)
|
||||
if err != nil {
|
||||
return overlay.Options{}, fmt.Errorf("failed to marshal extra: %w", err)
|
||||
}
|
||||
|
||||
out, err := o.execute(bytes.NewReader(extraYAML), "get-options")
|
||||
if err != nil {
|
||||
return overlay.Options{}, fmt.Errorf("failed to run overlay installer: %w", err)
|
||||
}
|
||||
|
||||
var options overlay.Options
|
||||
|
||||
if err := yaml.Unmarshal(out, &options); err != nil {
|
||||
return overlay.Options{}, fmt.Errorf("failed to unmarshal overlay options: %w", err)
|
||||
}
|
||||
|
||||
return options, nil
|
||||
}
|
||||
|
||||
// Install installs the overlay.
|
||||
func (o *Options) Install(options overlay.InstallOptions) error {
|
||||
optionsBytes, err := yaml.Marshal(&options)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal options: %w", err)
|
||||
}
|
||||
|
||||
if _, err := o.execute(bytes.NewReader(optionsBytes), "install"); err != nil {
|
||||
return fmt.Errorf("failed to run overlay installer: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *Options) execute(stdin io.Reader, args ...string) ([]byte, error) {
|
||||
cmd := exec.Command(o.commandPath, args...)
|
||||
cmd.Stdin = stdin
|
||||
|
||||
var stdOut, stdErr bytes.Buffer
|
||||
|
||||
cmd.Stdout = &stdOut
|
||||
cmd.Stderr = &stdErr
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return nil, fmt.Errorf("failed to run overlay installer: %w, stdErr: %s", err, stdErr.Bytes())
|
||||
}
|
||||
|
||||
return stdOut.Bytes(), nil
|
||||
}
|
@ -33,6 +33,16 @@ func (o Profile) DeepCopy() Profile {
|
||||
cp.Input.SystemExtensions = make([]ContainerAsset, len(o.Input.SystemExtensions))
|
||||
copy(cp.Input.SystemExtensions, o.Input.SystemExtensions)
|
||||
}
|
||||
if o.Overlay != nil {
|
||||
cp.Overlay = new(OverlayOptions)
|
||||
*cp.Overlay = *o.Overlay
|
||||
if o.Overlay.Options != nil {
|
||||
cp.Overlay.Options = make(map[string]any, len(o.Overlay.Options))
|
||||
for k4, v4 := range o.Overlay.Options {
|
||||
cp.Overlay.Options[k4] = v4
|
||||
}
|
||||
}
|
||||
}
|
||||
if o.Output.ImageOptions != nil {
|
||||
cp.Output.ImageOptions = new(ImageOptions)
|
||||
*cp.Output.ImageOptions = *o.Output.ImageOptions
|
||||
|
@ -26,6 +26,7 @@ import (
|
||||
"github.com/siderolabs/talos/pkg/imager/profile/internal/signer/aws"
|
||||
"github.com/siderolabs/talos/pkg/imager/profile/internal/signer/azure"
|
||||
"github.com/siderolabs/talos/pkg/imager/profile/internal/signer/file"
|
||||
"github.com/siderolabs/talos/pkg/imager/quirks"
|
||||
"github.com/siderolabs/talos/pkg/images"
|
||||
"github.com/siderolabs/talos/pkg/machinery/constants"
|
||||
)
|
||||
@ -166,7 +167,7 @@ const defaultSecureBootPrefix = "/secureboot"
|
||||
|
||||
// FillDefaults fills default values for the input.
|
||||
//
|
||||
//nolint:gocyclo
|
||||
//nolint:gocyclo,cyclop
|
||||
func (i *Input) FillDefaults(arch, version string, secureboot bool) {
|
||||
var (
|
||||
zeroFileAsset FileAsset
|
||||
@ -181,7 +182,7 @@ func (i *Input) FillDefaults(arch, version string, secureboot bool) {
|
||||
i.Initramfs.Path = fmt.Sprintf(constants.InitramfsAssetPath, arch)
|
||||
}
|
||||
|
||||
if arch == arm64 {
|
||||
if arch == arm64 && !quirks.New(version).SupportsOverlay() {
|
||||
if i.DTB == zeroFileAsset {
|
||||
i.DTB.Path = fmt.Sprintf(constants.DTBAssetPath, arch)
|
||||
}
|
||||
|
@ -37,10 +37,22 @@ type Profile struct {
|
||||
|
||||
// Input describes inputs for image generation.
|
||||
Input Input `yaml:"input"`
|
||||
// Overlay describes overlay options for image generation.
|
||||
Overlay *OverlayOptions `yaml:"overlay,omitempty"`
|
||||
// Output describes image generation result.
|
||||
Output Output `yaml:"output"`
|
||||
}
|
||||
|
||||
// OverlayOptions describes overlay options for image generation.
|
||||
type OverlayOptions struct {
|
||||
// Name of the overlay installer, defaults to `default` if not set.
|
||||
Name string `yaml:"name"`
|
||||
// Image to use for the overlay.
|
||||
Image ContainerAsset `yaml:"image"`
|
||||
// Options for the overlay.
|
||||
Options map[string]any `yaml:"options,omitempty"`
|
||||
}
|
||||
|
||||
// CustomizationProfile describes customizations that can be applied to the image.
|
||||
type CustomizationProfile struct {
|
||||
// ExtraKernelArgs is a list of extra kernel arguments.
|
||||
@ -67,7 +79,11 @@ func (p *Profile) Validate() error {
|
||||
}
|
||||
|
||||
if p.Board != "" {
|
||||
if !(p.Arch == arm64 && p.Platform == "metal") {
|
||||
if p.Overlay != nil {
|
||||
return errors.New("overlay is not supported with board options")
|
||||
}
|
||||
|
||||
if p.Arch != arm64 || p.Platform != "metal" {
|
||||
return errors.New("board is only supported for metal arm64")
|
||||
}
|
||||
}
|
||||
|
@ -45,3 +45,15 @@ func (q Quirks) SupportsCompressedEncodedMETA() bool {
|
||||
|
||||
return q.v.GTE(minVersionCompressedMETA)
|
||||
}
|
||||
|
||||
var minVersionOverlay = semver.MustParse("1.7.0")
|
||||
|
||||
// SupportsOverlay returns true if the Talos imager version supports overlay.
|
||||
func (q Quirks) SupportsOverlay() bool {
|
||||
// if the version doesn't parse, we assume it's latest Talos
|
||||
if q.v == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
return q.v.GTE(minVersionOverlay)
|
||||
}
|
||||
|
66
pkg/machinery/overlay/adapter/adapter.go
Normal file
66
pkg/machinery/overlay/adapter/adapter.go
Normal file
@ -0,0 +1,66 @@
|
||||
// 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 adapter provides an adapter for the overlay installer.
|
||||
package adapter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"github.com/siderolabs/talos/pkg/machinery/overlay"
|
||||
)
|
||||
|
||||
// Execute executes the overlay installer.
|
||||
func Execute(installer overlay.Installer) {
|
||||
if len(os.Args) < 2 {
|
||||
fmt.Fprint(os.Stderr, "missing command")
|
||||
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
switch os.Args[1] {
|
||||
case "install":
|
||||
install(installer)
|
||||
case "get-options":
|
||||
getOptions(installer)
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "unknown command: %s", os.Args[1])
|
||||
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func getOptions(installer overlay.Installer) {
|
||||
var opts overlay.InstallExtraOptions
|
||||
|
||||
withErrorHandler(yaml.NewDecoder(os.Stdin).Decode(&opts))
|
||||
|
||||
opt, err := installer.GetOptions(opts)
|
||||
if err != nil {
|
||||
fmt.Fprint(os.Stderr, err.Error())
|
||||
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
withErrorHandler(yaml.NewEncoder(os.Stdout).Encode(opt))
|
||||
}
|
||||
|
||||
func install(installer overlay.Installer) {
|
||||
var opts overlay.InstallOptions
|
||||
|
||||
withErrorHandler(yaml.NewDecoder(os.Stdin).Decode(&opts))
|
||||
|
||||
withErrorHandler(installer.Install(opts))
|
||||
}
|
||||
|
||||
func withErrorHandler(err error) {
|
||||
if err != nil {
|
||||
fmt.Fprint(os.Stderr, err.Error())
|
||||
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
32
pkg/machinery/overlay/overlay.go
Normal file
32
pkg/machinery/overlay/overlay.go
Normal file
@ -0,0 +1,32 @@
|
||||
// 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 overlay provides an interface for overlay installers.
|
||||
package overlay
|
||||
|
||||
// Installer is an interface for overlay installers.
|
||||
type Installer interface {
|
||||
GetOptions(extra InstallExtraOptions) (Options, error)
|
||||
Install(options InstallOptions) error
|
||||
}
|
||||
|
||||
// Options for the overlay installer.
|
||||
type Options struct {
|
||||
Name string `yaml:"name"`
|
||||
KernelArgs []string `yaml:"kernelArgs,omitempty"`
|
||||
PartitionOptions struct {
|
||||
Offset uint64
|
||||
} `yaml:"partitionOptions,omitempty"`
|
||||
}
|
||||
|
||||
// InstallOptions for the overlay installer.
|
||||
type InstallOptions struct {
|
||||
InstallDisk string `yaml:"installDisk"`
|
||||
MountPrefix string `yaml:"mountPrefix"`
|
||||
ArtifactsPath string `yaml:"artifactsPath"`
|
||||
ExtraOptions InstallExtraOptions `yaml:"extraOptions,omitempty"`
|
||||
}
|
||||
|
||||
// InstallExtraOptions for the overlay installer.
|
||||
type InstallExtraOptions map[string]any
|
Loading…
x
Reference in New Issue
Block a user