refactor: extract platform metadata into Talos machinery

It will be used across Image Factory, Terraform Provider and Omni.

Fixes #10108

See https://github.com/siderolabs/image-factory/pull/189

Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com>
This commit is contained in:
Andrey Smirnov 2025-01-20 16:07:06 +04:00
parent 79987c05dc
commit e1efbf656a
No known key found for this signature in database
GPG Key ID: FE042E3D4085A811
4 changed files with 741 additions and 0 deletions

View File

@ -0,0 +1,386 @@
// 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 platforms provides meta information about supported Talos platforms, boards, etc.
package platforms
import (
"fmt"
"github.com/blang/semver/v4"
)
// Arch represents an architecture supported by Talos.
type Arch = string
// Architecture constants.
const (
ArchAmd64 = "amd64"
ArchArm64 = "arm64"
)
// BootMethod represents a boot method supported by Talos.
type BootMethod = string
// BootMethod constants.
const (
BootMethodDiskImage = "disk-image"
BootMethodISO = "iso"
BootMethodPXE = "pxe"
)
// Platform represents a platform supported by Talos.
type Platform struct {
Name string
Label string
Description string
MinVersion semver.Version
Architectures []Arch
Documentation string
DiskImageSuffix string
BootMethods []BootMethod
SecureBootSupported bool
}
// NotOnlyDiskImage is true if the platform supports boot methods other than disk-image.
func (p Platform) NotOnlyDiskImage() bool {
if len(p.BootMethods) == 1 && p.BootMethods[0] == BootMethodDiskImage {
return false
}
return true
}
// DiskImageDefaultPath returns the path to the disk image for the platform.
func (p Platform) DiskImageDefaultPath(arch Arch) string {
return p.DiskImagePath(arch, p.DiskImageSuffix)
}
// SecureBootDiskImageDefaultPath returns the path to the SecureBoot disk image for the platform.
func (p Platform) SecureBootDiskImageDefaultPath(arch Arch) string {
return p.SecureBootDiskImagePath(arch, p.DiskImageSuffix)
}
// DiskImagePath returns the path to the disk image for the platform and suffix.
func (p Platform) DiskImagePath(arch Arch, suffix string) string {
return fmt.Sprintf("%s-%s.%s", p.Name, arch, suffix)
}
// SecureBootDiskImagePath returns the path to the SecureBoot disk image for the platform and suffix.
func (p Platform) SecureBootDiskImagePath(arch Arch, suffix string) string {
return fmt.Sprintf("%s-%s-secureboot.%s", p.Name, arch, suffix)
}
// ISOPath returns the path to the ISO for the platform.
func (p Platform) ISOPath(arch Arch) string {
return fmt.Sprintf("%s-%s.iso", p.Name, arch)
}
// SecureBootISOPath returns the path to the SecureBoot ISO for the platform.
func (p Platform) SecureBootISOPath(arch Arch) string {
return fmt.Sprintf("%s-%s-secureboot.iso", p.Name, arch)
}
// PXEScriptPath returns the path to the PXE script for the platform.
func (p Platform) PXEScriptPath(arch Arch) string {
return fmt.Sprintf("%s-%s", p.Name, arch)
}
// SecureBootPXEScriptPath returns the path to the SecureBoot PXE script for the platform.
func (p Platform) SecureBootPXEScriptPath(arch Arch) string {
return fmt.Sprintf("%s-%s-secureboot", p.Name, arch)
}
// UKIPath returns the path to the UKI for the platform.
func (p Platform) UKIPath(arch Arch) string {
return fmt.Sprintf("%s-%s-uki.efi", p.Name, arch)
}
// SecureBootUKIPath returns the path to the SecureBoot UKI for the platform.
func (p Platform) SecureBootUKIPath(arch Arch) string {
return fmt.Sprintf("%s-%s-secureboot-uki.efi", p.Name, arch)
}
// KernelPath returns the path to the kernel for the platform.
//
// NB: Kernel path doesn't depend on the platform.
func (p Platform) KernelPath(arch Arch) string {
return fmt.Sprintf("kernel-%s", arch)
}
// InitramfsPath returns the path to the initramfs for the platform.
//
// NB: Initramfs path doesn't depend on the platform.
func (p Platform) InitramfsPath(arch Arch) string {
return fmt.Sprintf("initramfs-%s.xz", arch)
}
// CmdlinePath returns the path to the cmdline for the platform.
func (p Platform) CmdlinePath(arch Arch) string {
return fmt.Sprintf("cmdline-%s-%s", p.Name, arch)
}
// MetalPlatform returns a metal platform.
func MetalPlatform() Platform {
return Platform{
Name: "metal",
Label: "Bare Metal",
Description: "Runs on bare-metal servers",
Architectures: []Arch{ArchAmd64, ArchArm64},
Documentation: "/talos-guides/install/bare-metal-platforms/",
DiskImageSuffix: "raw.zst",
BootMethods: []BootMethod{
BootMethodISO,
BootMethodDiskImage,
BootMethodPXE,
},
}
}
// CloudPlatforms returns a list of supported cloud platforms.
func CloudPlatforms() []Platform {
// metal platform is not listed here, as it is handled separately.
return []Platform{
// Tier 1
{
Name: "aws",
Label: "Amazon Web Services (AWS)",
Description: "Runs on AWS VMs booted from an AMI",
Architectures: []Arch{ArchAmd64, ArchArm64},
Documentation: "/talos-guides/install/cloud-platforms/aws/",
DiskImageSuffix: "raw.xz",
BootMethods: []BootMethod{
BootMethodDiskImage,
},
},
{
Name: "gcp",
Label: "Google Cloud (GCP)",
Description: "Runs on Google Cloud VMs booted from a disk image",
Architectures: []Arch{ArchAmd64, ArchArm64},
Documentation: "/talos-guides/install/cloud-platforms/gcp/",
DiskImageSuffix: "raw.tar.gz",
BootMethods: []BootMethod{
BootMethodDiskImage,
},
},
{
Name: "equinixMetal",
Label: "Equinix Metal",
Description: "Runs on Equinix Metal bare-metal servers",
Architectures: []Arch{ArchAmd64, ArchArm64},
Documentation: "/talos-guides/install/bare-metal-platforms/equinix-metal/",
BootMethods: []BootMethod{
BootMethodPXE,
},
},
// Tier 2
{
Name: "azure",
Label: "Microsoft Azure",
Description: "Runs on Microsoft Azure Linux Virtual Machines",
Architectures: []Arch{ArchAmd64, ArchArm64},
Documentation: "/talos-guides/install/cloud-platforms/azure/",
DiskImageSuffix: "vhd.xz",
BootMethods: []BootMethod{
BootMethodDiskImage,
},
},
{
Name: "digital-ocean",
Label: "Digital Ocean",
Description: "Runs on Digital Ocean droplets",
Architectures: []Arch{ArchAmd64},
Documentation: "/talos-guides/install/cloud-platforms/digitalocean/",
DiskImageSuffix: "raw.gz",
BootMethods: []BootMethod{
BootMethodDiskImage,
},
},
{
Name: "nocloud",
Label: "Nocloud",
Description: "Runs on various hypervisors supporting 'nocloud' metadata (Proxmox, Oxide Computer, etc.)",
Architectures: []Arch{ArchAmd64, ArchArm64},
Documentation: "/talos-guides/install/cloud-platforms/nocloud/",
DiskImageSuffix: "raw.xz",
BootMethods: []BootMethod{
BootMethodDiskImage,
BootMethodISO,
BootMethodPXE,
},
SecureBootSupported: true,
},
{
Name: "openstack",
Label: "OpenStack",
Description: "Runs on OpenStack virtual machines",
Architectures: []Arch{ArchAmd64, ArchArm64},
Documentation: "/talos-guides/install/cloud-platforms/openstack/",
DiskImageSuffix: "raw.xz",
BootMethods: []BootMethod{
BootMethodDiskImage,
BootMethodISO,
BootMethodPXE,
},
},
{
Name: "vmware",
Label: "VMWare",
Description: "Runs on VMWare ESXi virtual machines",
Architectures: []Arch{ArchAmd64},
Documentation: "/talos-guides/install/virtualized-platforms/vmware/",
DiskImageSuffix: "ova",
BootMethods: []BootMethod{
BootMethodDiskImage,
BootMethodISO,
},
},
// Tier 3
{
Name: "akamai",
Label: "Akamai",
Description: "Runs on Akamai Cloud (Linode) virtual machines",
Architectures: []Arch{ArchAmd64},
MinVersion: semver.MustParse("1.7.0"),
Documentation: "/talos-guides/install/cloud-platforms/akamai/",
DiskImageSuffix: "raw.gz",
BootMethods: []BootMethod{
BootMethodDiskImage,
},
},
{
Name: "cloudstack",
Label: "Apache CloudStack",
Description: "Runs on Apache CloudStack virtual machines",
Architectures: []Arch{ArchAmd64, ArchArm64},
Documentation: "/talos-guides/install/cloud-platforms/cloudstack/",
DiskImageSuffix: "raw.gz",
BootMethods: []BootMethod{
BootMethodDiskImage,
},
MinVersion: semver.MustParse("1.8.0-alpha.2"),
},
{
Name: "hcloud",
Label: "Hetzner",
Description: "Runs on Hetzner virtual machines",
Architectures: []Arch{ArchAmd64},
Documentation: "/talos-guides/install/cloud-platforms/hetzner/",
DiskImageSuffix: "raw.xz",
BootMethods: []BootMethod{
BootMethodDiskImage,
},
},
{
Name: "oracle",
Label: "Oracle Cloud",
Description: "Runs on Oracle Cloud virtual machines",
Architectures: []Arch{ArchAmd64, ArchArm64},
Documentation: "/talos-guides/install/cloud-platforms/oracle/",
DiskImageSuffix: "raw.xz",
BootMethods: []BootMethod{
BootMethodDiskImage,
},
},
{
Name: "upcloud",
Label: "UpCloud",
Description: "Runs on UpCloud virtual machines",
Architectures: []Arch{ArchAmd64},
Documentation: "/talos-guides/install/cloud-platforms/ucloud/",
DiskImageSuffix: "raw.xz",
BootMethods: []BootMethod{
BootMethodDiskImage,
},
},
{
Name: "vultr",
Label: "Vultr",
Description: "Runs on Vultr Cloud Compute virtual machines",
Architectures: []Arch{ArchAmd64},
Documentation: "/talos-guides/install/cloud-platforms/vultr/",
BootMethods: []BootMethod{
BootMethodISO,
BootMethodPXE,
},
},
// Tier 4 (no documentation).
{
Name: "exoscale",
Label: "Exoscale",
Description: "Runs on Exoscale virtual machines",
Architectures: []Arch{ArchAmd64, ArchArm64},
Documentation: "/talos-guides/install/cloud-platforms/exoscale/",
DiskImageSuffix: "qcow2",
BootMethods: []BootMethod{
BootMethodDiskImage,
},
MinVersion: semver.MustParse("1.3.0"),
},
{
Name: "opennebula",
Label: "OpenNebula",
Description: "Runs on OpenNebula virtual machines",
Architectures: []Arch{ArchAmd64, ArchArm64},
DiskImageSuffix: "raw.zst",
Documentation: "/talos-guides/install/virtualized-platforms/opennebula/",
BootMethods: []BootMethod{
BootMethodDiskImage,
BootMethodISO,
},
MinVersion: semver.MustParse("1.7.0"),
},
{
Name: "scaleway",
Label: "Scaleway",
Description: "Runs on Scaleway virtual machines",
Architectures: []Arch{ArchAmd64, ArchArm64},
DiskImageSuffix: "raw.zst",
Documentation: "/talos-guides/install/cloud-platforms/scaleway/",
BootMethods: []BootMethod{
BootMethodDiskImage,
BootMethodISO,
},
},
}
}

View File

@ -0,0 +1,86 @@
// 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 platforms_test
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/siderolabs/talos/pkg/machinery/platforms"
)
func TestPlatform(t *testing.T) {
t.Parallel()
for _, test := range []struct {
name string
platform platforms.Platform
expectedDefaultDiskImagePath string
expectedISOPath string
expectedSecureBootISOPath string
expectedPXEPath string
expectedSecureBootPXEPath string
expectedUKIPath string
expectedSecureBootUKIPath string
expectedKernelPath string
expectedInitramfsPath string
expectedCmdlinePath string
expectedNotOnlyDiskImage bool
}{
{
name: "metal",
platform: platforms.MetalPlatform(),
expectedDefaultDiskImagePath: "metal-amd64.raw.zst",
expectedISOPath: "metal-amd64.iso",
expectedSecureBootISOPath: "metal-amd64-secureboot.iso",
expectedPXEPath: "metal-amd64",
expectedSecureBootPXEPath: "metal-amd64-secureboot",
expectedUKIPath: "metal-amd64-uki.efi",
expectedSecureBootUKIPath: "metal-amd64-secureboot-uki.efi",
expectedKernelPath: "kernel-amd64",
expectedInitramfsPath: "initramfs-amd64.xz",
expectedCmdlinePath: "cmdline-metal-amd64",
expectedNotOnlyDiskImage: true,
},
{
name: "aws",
platform: platforms.CloudPlatforms()[0],
expectedDefaultDiskImagePath: "aws-amd64.raw.xz",
expectedISOPath: "aws-amd64.iso",
expectedSecureBootISOPath: "aws-amd64-secureboot.iso",
expectedPXEPath: "aws-amd64",
expectedSecureBootPXEPath: "aws-amd64-secureboot",
expectedUKIPath: "aws-amd64-uki.efi",
expectedSecureBootUKIPath: "aws-amd64-secureboot-uki.efi",
expectedKernelPath: "kernel-amd64",
expectedInitramfsPath: "initramfs-amd64.xz",
expectedCmdlinePath: "cmdline-aws-amd64",
expectedNotOnlyDiskImage: false,
},
} {
t.Run(test.name, func(t *testing.T) {
t.Parallel()
assert.Equal(t, test.expectedDefaultDiskImagePath, test.platform.DiskImageDefaultPath(platforms.ArchAmd64))
assert.Equal(t, test.expectedISOPath, test.platform.ISOPath(platforms.ArchAmd64))
assert.Equal(t, test.expectedSecureBootISOPath, test.platform.SecureBootISOPath(platforms.ArchAmd64))
assert.Equal(t, test.expectedPXEPath, test.platform.PXEScriptPath(platforms.ArchAmd64))
assert.Equal(t, test.expectedSecureBootPXEPath, test.platform.SecureBootPXEScriptPath(platforms.ArchAmd64))
assert.Equal(t, test.expectedUKIPath, test.platform.UKIPath(platforms.ArchAmd64))
assert.Equal(t, test.expectedSecureBootUKIPath, test.platform.SecureBootUKIPath(platforms.ArchAmd64))
assert.Equal(t, test.expectedKernelPath, test.platform.KernelPath(platforms.ArchAmd64))
assert.Equal(t, test.expectedInitramfsPath, test.platform.InitramfsPath(platforms.ArchAmd64))
assert.Equal(t, test.expectedCmdlinePath, test.platform.CmdlinePath(platforms.ArchAmd64))
assert.Equal(t, test.expectedNotOnlyDiskImage, test.platform.NotOnlyDiskImage())
})
}
}

View File

@ -0,0 +1,220 @@
// 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 platforms
import (
"github.com/blang/semver/v4"
"github.com/siderolabs/talos/pkg/machinery/imager/quirks"
)
// SBC describes a Single Board Computer configuration.
type SBC struct {
Name string
// For Talos < 1.7.
BoardName string
// For Talos 1.7+
OverlayName string
OverlayImage string
Label string
Documentation string
MinVersion semver.Version
}
// DiskImagePath returns the path to the disk image for the SBC.
func (s SBC) DiskImagePath(talosVersion string) string {
if quirks.New(talosVersion).SupportsOverlay() {
return "metal-arm64.raw.xz"
}
return "metal-" + s.BoardName + "-arm64.raw.xz"
}
// SBCs returns a list of supported Single Board Computers.
func SBCs() []SBC {
return []SBC{
{
Name: "rpi_generic",
BoardName: "rpi_generic",
OverlayName: "rpi_generic",
OverlayImage: "siderolabs/sbc-raspberrypi",
Label: "Raspberry Pi Series",
Documentation: "/talos-guides/install/single-board-computers/rpi_generic/",
},
{
Name: "bananapi_m64",
BoardName: "bananapi_m64",
OverlayName: "bananapi_m64",
OverlayImage: "siderolabs/sbc-allwinner",
Label: "Banana Pi M64",
Documentation: "/talos-guides/install/single-board-computers/bananapi_m64/",
},
{
Name: "nanopi_r4s",
BoardName: "rockpi_4",
OverlayName: "nanopi-r4s",
OverlayImage: "siderolabs/sbc-rockchip",
Label: "Friendlyelec Nano PI R4S",
Documentation: "/talos-guides/install/single-board-computers/nanopi_r4s/",
MinVersion: semver.MustParse("1.3.0"),
},
{
Name: "nanopi_r5s",
OverlayName: "nanopi-r5s",
OverlayImage: "siderolabs/sbc-rockchip",
Label: "Friendlyelec Nano PI R5S",
MinVersion: semver.MustParse("1.8.0-alpha.2"),
},
{
Name: "jetson_nano",
BoardName: "jetson_nano",
OverlayName: "jetson_nano",
OverlayImage: "siderolabs/sbc-jetson",
Label: "Jetson Nano",
Documentation: "/talos-guides/install/single-board-computers/jetson_nano/",
},
{
Name: "libretech_all_h3_cc_h5",
BoardName: "libretech_all_h3_cc_h5",
OverlayName: "libretech_all_h3_cc_h5",
OverlayImage: "siderolabs/sbc-allwinner",
Label: "Libre Computer Board ALL-H3-CC",
Documentation: "/talos-guides/install/single-board-computers/libretech_all_h3_cc_h5/",
},
{
Name: "orangepi_r1_plus_lts",
OverlayName: "orangepi-r1-plus-lts",
OverlayImage: "siderolabs/sbc-rockchip",
Label: "Orange Pi R1 Plus LTS",
Documentation: "/talos-guides/install/single-board-computers/orangepi_r1_plus_lts/",
MinVersion: semver.MustParse("1.7.0"),
},
{
Name: "pine64",
BoardName: "pine64",
OverlayName: "pine64",
OverlayImage: "siderolabs/sbc-allwinner",
Label: "Pine64",
Documentation: "/talos-guides/install/single-board-computers/pine64/",
},
{
Name: "rock64",
BoardName: "rock64",
OverlayName: "rock64",
OverlayImage: "siderolabs/sbc-rockchip",
Label: "Pine64 Rock64",
Documentation: "/talos-guides/install/single-board-computers/rock64/",
},
{
Name: "rock4cplus",
OverlayName: "rock4cplus",
OverlayImage: "siderolabs/sbc-rockchip",
Label: "Radxa ROCK 4C Plus",
Documentation: "/talos-guides/install/single-board-computers/rock4cplus/",
MinVersion: semver.MustParse("1.7.0"),
},
{
Name: "rock4se",
OverlayName: "rock4se",
OverlayImage: "siderolabs/sbc-rockchip",
Label: "Radxa ROCK 4SE",
Documentation: "", // missing
MinVersion: semver.MustParse("1.8.0-alpha.1"),
},
{
Name: "rock5b",
OverlayName: "rock5b",
OverlayImage: "siderolabs/sbc-rockchip",
Label: "Radxa ROCK 5B",
Documentation: "/talos-guides/install/single-board-computers/rock5b/",
MinVersion: semver.MustParse("1.9.2"),
},
{
Name: "rockpi_4",
BoardName: "rockpi_4",
OverlayName: "rockpi4",
OverlayImage: "siderolabs/sbc-rockchip",
Label: "Radxa ROCK PI 4",
Documentation: "/talos-guides/install/single-board-computers/rockpi_4/",
},
{
Name: "rockpi_4c",
BoardName: "rockpi_4c",
OverlayName: "rockpi4c",
OverlayImage: "siderolabs/sbc-rockchip",
Label: "Radxa ROCK PI 4C",
Documentation: "/talos-guides/install/single-board-computers/rockpi_4c/",
},
{
Name: "helios64",
OverlayName: "helios64",
OverlayImage: "siderolabs/sbc-rockchip",
Label: "Kobol Helios64",
Documentation: "", // missing
MinVersion: semver.MustParse("1.8.0-alpha.2"),
},
{
Name: "turingrk1",
OverlayName: "turingrk1",
OverlayImage: "siderolabs/sbc-rockchip",
Label: "Turing RK1",
Documentation: "/talos-guides/install/single-board-computers/turing_rk1/",
MinVersion: semver.MustParse("1.9.0-beta.0"),
},
}
}

View File

@ -0,0 +1,49 @@
// 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 platforms_test
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/siderolabs/talos/pkg/machinery/platforms"
)
func TestSBC(t *testing.T) {
t.Parallel()
for _, test := range []struct {
name string
sbc platforms.SBC
talosVersion string
expectedDiskImagePath string
}{
{
name: "rpi_generic",
sbc: platforms.SBCs()[0],
talosVersion: "1.9.0",
expectedDiskImagePath: "metal-arm64.raw.xz",
},
{
name: "bananapi_m64",
sbc: platforms.SBCs()[0],
talosVersion: "1.4.0",
expectedDiskImagePath: "metal-rpi_generic-arm64.raw.xz",
},
} {
t.Run(test.name, func(t *testing.T) {
t.Parallel()
assert.Equal(t, test.expectedDiskImagePath, test.sbc.DiskImagePath(test.talosVersion))
})
}
}