Skip to content

Commit a91bb04

Browse files
committed
feat: use <platform>-installer[-secureboot] as the installer image
Make use of the change introduced in siderolabs/image-factory#210: Switch from using `factory.talos.dev/installer[-secureboot]/...` to `factory.talos.dev/<platform>-installer[-secureboot]/...`. Signed-off-by: Utku Ozdemir <[email protected]>
1 parent 77ab722 commit a91bb04

File tree

14 files changed

+435
-343
lines changed

14 files changed

+435
-343
lines changed

client/api/omni/specs/omni.pb.go

Lines changed: 303 additions & 292 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client/api/omni/specs/omni.proto

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,6 +1056,8 @@ message MachineConfigGenOptionsSpec {
10561056
bool schematic_invalid = 4;
10571057
// SecureBootStatus is the status of the SecureBoot feature.
10581058
SecureBootStatus secure_boot_status = 5;
1059+
// Platform is the machine platform to use for the install image.
1060+
string platform = 6;
10591061
}
10601062

10611063
string install_disk = 1;

client/api/omni/specs/omni_vtproto.pb.go

Lines changed: 47 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client/pkg/omni/resources/omni/cluster.go

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,6 @@
55
package omni
66

77
import (
8-
"fmt"
9-
"net/url"
10-
"path/filepath"
11-
"strings"
12-
138
"github.com/cosi-project/runtime/pkg/resource"
149
"github.com/cosi-project/runtime/pkg/resource/meta"
1510
"github.com/cosi-project/runtime/pkg/resource/protobuf"
@@ -52,22 +47,6 @@ func (ClusterExtension) ResourceDefinition() meta.ResourceDefinitionSpec {
5247
}
5348
}
5449

55-
// GetInstallImage extracts Talos version from the cluster resource and adds the installer image url.
56-
func GetInstallImage(vanillaInstallerBaseURL, factoryBaseURL, schematic, version string) (string, error) {
57-
version = strings.TrimLeft(version, "v")
58-
59-
if schematic == "" {
60-
return fmt.Sprintf("%s:v%s", vanillaInstallerBaseURL, version), nil
61-
}
62-
63-
u, err := url.Parse(factoryBaseURL)
64-
if err != nil {
65-
return "", fmt.Errorf("failed to parse image factory url %w", err)
66-
}
67-
68-
return filepath.Join(u.Host, "installer", fmt.Sprintf("%s:v%s", schematic, version)), nil
69-
}
70-
7150
// GetEncryptionEnabled returns cluster disk encryption feature flag state.
7251
func GetEncryptionEnabled(cluster *Cluster) bool {
7352
return cluster.TypedSpec().Value.Features != nil && cluster.TypedSpec().Value.Features.DiskEncryption

frontend/src/api/omni/specs/omni.pb.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,7 @@ export type MachineConfigGenOptionsSpecInstallImage = {
694694
schematic_initialized?: boolean
695695
schematic_invalid?: boolean
696696
secure_boot_status?: SecureBootStatus
697+
platform?: string
697698
}
698699

699700
export type MachineConfigGenOptionsSpec = {

frontend/src/methods/machine.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { MachineService } from "@/api/talos/machine/machine.pb";
1414
import { destroyResources, getMachineConfigPatchesToDelete } from "@/methods/cluster";
1515
import { parseLabels } from "@/methods/labels";
1616
import { getImageFactoryBaseURL } from "@/methods/features";
17+
import * as semver from "semver";
1718

1819
export const addMachineLabels = async (machineID: string, ...labels: string[]) => {
1920
let resource: Resource = {
@@ -151,14 +152,25 @@ const copyUserLabels = (src: Resource, dst: Resource) => {
151152
}
152153
}
153154

154-
export const updateTalosMaintenance = async (machine: string, talosVersion: string, schematic?: string) => {
155+
export const updateTalosMaintenance = async (machine: string, talosVersion: string, platform?: string, schematic?: string) => {
155156
const imageFactoryBaseURL = await getImageFactoryBaseURL();
156157

157158
const host = new URL(imageFactoryBaseURL).host;
158159

159-
const image = schematic ?
160-
`${host}/installer/${schematic}:v${talosVersion}` :
161-
`ghcr.io/siderolabs/installer:v${talosVersion}`;
160+
let image = `ghcr.io/siderolabs/installer:v${talosVersion}`;
161+
162+
if (schematic) {
163+
if (!platform) {
164+
throw new Error("Platform is required when schematic is specified");
165+
}
166+
167+
// prepend platform for Talos 1.10.0 and later
168+
const major = semver.major(talosVersion)
169+
const minor = semver.minor(talosVersion)
170+
const installerName = major >= 1 && minor >= 10 ? `${platform}-installer` : "installer";
171+
172+
image = `${host}/${installerName}/${schematic}:v${talosVersion}`;
173+
}
162174

163175
await MachineService.Upgrade({image}, withRuntime(Runtime.Talos), withContext({
164176
nodes: [machine]

frontend/src/views/omni/Modals/MaintenanceUpdate.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,10 +141,12 @@ const upgradeClick = async () => {
141141
return;
142142
}
143143
144+
const platform = machine.value?.spec?.platform_metadata?.platform;
145+
144146
updating.value = true;
145147
146148
try {
147-
await updateTalosMaintenance(route.query.machine as string, selectedVersion.value, machine.value?.spec.schematic?.id);
149+
await updateTalosMaintenance(route.query.machine as string, selectedVersion.value, platform, machine.value?.spec.schematic?.id);
148150
} catch (e) {
149151
showError("Failed to Do Maintenance Update", e.message)
150152

internal/backend/runtime/omni/controllers/omni/cluster_machine_config.go

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"text/template"
1616
"time"
1717

18+
"github.com/blang/semver"
1819
"github.com/cosi-project/runtime/pkg/controller"
1920
"github.com/cosi-project/runtime/pkg/controller/generic/qtransform"
2021
"github.com/cosi-project/runtime/pkg/resource"
@@ -271,13 +272,15 @@ type clusterMachineConfigControllerHelper struct {
271272
imageFactoryHost string
272273
}
273274

275+
const talosVersionLatest = "latest"
276+
274277
func (helper clusterMachineConfigControllerHelper) generateConfig(clusterMachine *omni.ClusterMachine, clusterMachineConfigPatches *omni.ClusterMachineConfigPatches, secrets *omni.ClusterSecrets,
275278
loadbalancer *omni.LoadBalancerConfig, cluster *omni.Cluster, clusterConfigVersion *omni.ClusterConfigVersion, configGenOptions *omni.MachineConfigGenOptions, extraGenOptions []generate.Option,
276279
connectionParams *siderolink.ConnectionParams, link *siderolink.Link, eventSinkPort int,
277280
) ([]byte, error) {
278281
clusterName := cluster.Metadata().ID()
279282

280-
talosVersion := clusterConfigVersion.TypedSpec().Value.Version
283+
talosVersion := cluster.TypedSpec().Value.TalosVersion
281284
kubernetesVersion := clusterMachine.TypedSpec().Value.KubernetesVersion
282285

283286
if talosVersion == "" {
@@ -299,7 +302,7 @@ func (helper clusterMachineConfigControllerHelper) generateConfig(clusterMachine
299302
genOptions = append(genOptions, generate.WithInstallDisk(configGenOptions.TypedSpec().Value.InstallDisk))
300303
}
301304

302-
if talosVersion != "latest" {
305+
if talosVersion != talosVersionLatest {
303306
versionContract, parseErr := config.ParseContractFromVersion(talosVersion)
304307
if parseErr != nil {
305308
return nil, parseErr
@@ -464,7 +467,7 @@ func buildInstallImage(imageFactoryHost string, resID resource.ID, installImage
464467
installerName = "installer-secureboot"
465468
}
466469

467-
if talosVersion == "latest" && schematicID != "" {
470+
if talosVersion == talosVersionLatest && schematicID != "" {
468471
return "", fmt.Errorf("machine %q has a schematic but using Talos version %q", resID, talosVersion)
469472
}
470473

@@ -480,6 +483,21 @@ func buildInstallImage(imageFactoryHost string, resID resource.ID, installImage
480483
talosVersion = installImage.TalosVersion
481484
}
482485

486+
if talosVersion != talosVersionLatest {
487+
version, err := semver.ParseTolerant(talosVersion)
488+
if err != nil {
489+
return "", fmt.Errorf("failed to parse Talos version %q: %w", talosVersion, err)
490+
}
491+
492+
if version.Major >= 1 && version.Minor >= 10 { // prepend the platform to the installer name for Talos 1.10+
493+
if installImage.Platform == "" {
494+
return "", fmt.Errorf("machine %q has no platform set", resID)
495+
}
496+
497+
installerName = installImage.Platform + "-" + installerName
498+
}
499+
}
500+
483501
if !strings.HasPrefix(talosVersion, "v") {
484502
talosVersion = "v" + talosVersion
485503
}

internal/backend/runtime/omni/controllers/omni/cluster_machine_config_status_test.go

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"github.com/siderolabs/gen/xslices"
2020
"github.com/siderolabs/go-retry/retry"
2121
"github.com/siderolabs/talos/pkg/machinery/api/machine"
22+
talosconstants "github.com/siderolabs/talos/pkg/machinery/constants"
2223
"github.com/siderolabs/talos/pkg/machinery/resources/runtime"
2324
"github.com/stretchr/testify/assert"
2425
"github.com/stretchr/testify/require"
@@ -216,6 +217,9 @@ func (suite *ClusterMachineConfigStatusSuite) prepareMachines(machines []*omni.C
216217
res.TypedSpec().Value.SecureBootStatus = &specs.SecureBootStatus{
217218
Enabled: false,
218219
}
220+
res.TypedSpec().Value.PlatformMetadata = &specs.MachineStatusSpec_PlatformMetadata{
221+
Platform: talosconstants.PlatformMetal,
222+
}
219223

220224
return nil
221225
},
@@ -284,6 +288,9 @@ func (suite *ClusterMachineConfigStatusSuite) TestResetUngraceful() {
284288
res.TypedSpec().Value.SecureBootStatus = &specs.SecureBootStatus{
285289
Enabled: false,
286290
}
291+
res.TypedSpec().Value.PlatformMetadata = &specs.MachineStatusSpec_PlatformMetadata{
292+
Platform: talosconstants.PlatformMetal,
293+
}
287294

288295
return nil
289296
},
@@ -423,6 +430,9 @@ func (suite *ClusterMachineConfigStatusSuite) TestUpgrades() {
423430
res.TypedSpec().Value.SecureBootStatus = &specs.SecureBootStatus{
424431
Enabled: false,
425432
}
433+
res.TypedSpec().Value.PlatformMetadata = &specs.MachineStatusSpec_PlatformMetadata{
434+
Platform: talosconstants.PlatformMetal,
435+
}
426436

427437
return nil
428438
},
@@ -432,7 +442,7 @@ func (suite *ClusterMachineConfigStatusSuite) TestUpgrades() {
432442
}
433443

434444
const (
435-
expectedTalosVersion = "1.6.1"
445+
expectedTalosVersion = "1.10.1"
436446
expectedSchematicID = "cccc"
437447
)
438448

@@ -453,7 +463,7 @@ func (suite *ClusterMachineConfigStatusSuite) TestUpgrades() {
453463
return retry.ExpectedErrorf("no upgrade requests received")
454464
}
455465

456-
expectedImage := fmt.Sprintf("factory-test.talos.dev/installer/%s:v%s", expectedSchematicID, expectedTalosVersion)
466+
expectedImage := fmt.Sprintf("factory-test.talos.dev/metal-installer/%s:v%s", expectedSchematicID, expectedTalosVersion)
457467
for i, r := range requests {
458468
if r.Image != expectedImage {
459469
return fmt.Errorf("%d request image is invalid: expected %q got %q", i, expectedImage, r.Image)
@@ -556,6 +566,9 @@ func (suite *ClusterMachineConfigStatusSuite) TestStagedUpgrade() {
556566
res.TypedSpec().Value.SecureBootStatus = &specs.SecureBootStatus{
557567
Enabled: false,
558568
}
569+
res.TypedSpec().Value.PlatformMetadata = &specs.MachineStatusSpec_PlatformMetadata{
570+
Platform: talosconstants.PlatformMetal,
571+
}
559572

560573
return nil
561574
},
@@ -601,7 +614,7 @@ func (suite *ClusterMachineConfigStatusSuite) TestSchematicChanges() {
601614

602615
clusterName := "test-upgrades"
603616

604-
cluster, machines := suite.createCluster(clusterName, 1, 0)
617+
cluster, machines := suite.createClusterWithTalosVersion(clusterName, 1, 0, "1.10.0")
605618

606619
for _, m := range machines {
607620
talosVersion := omni.NewClusterMachineTalosVersion(resources.DefaultNamespace, m.Metadata().ID())
@@ -636,6 +649,9 @@ func (suite *ClusterMachineConfigStatusSuite) TestSchematicChanges() {
636649
res.TypedSpec().Value.SecureBootStatus = &specs.SecureBootStatus{
637650
Enabled: false,
638651
}
652+
res.TypedSpec().Value.PlatformMetadata = &specs.MachineStatusSpec_PlatformMetadata{
653+
Platform: talosconstants.PlatformMetal,
654+
}
639655

640656
return nil
641657
},
@@ -656,7 +672,7 @@ func (suite *ClusterMachineConfigStatusSuite) TestSchematicChanges() {
656672
suite.Require().NoError(err)
657673
}
658674

659-
expectedFactoryImage := imageFactoryHost + "/installer/bbbb:v1.3.0"
675+
expectedFactoryImage := imageFactoryHost + "/metal-installer/bbbb:v1.10.0" // expected image has the platform prefixed, as the Talos version is >= 1.10.0
660676

661677
suite.Require().NoError(retry.Constant(time.Second * 5).Retry(func() error {
662678
requests := suite.machineService.getUpgradeRequests()
@@ -705,7 +721,7 @@ func (suite *ClusterMachineConfigStatusSuite) TestSchematicChanges() {
705721
return retry.ExpectedErrorf("no new upgrade requests received")
706722
}
707723

708-
expectedImage := "ghcr.io/siderolabs/installer:v1.3.0"
724+
expectedImage := "ghcr.io/siderolabs/installer:v1.10.0"
709725
for i, image := range trimmedImages {
710726
if image != expectedImage {
711727
return fmt.Errorf("%d request image is invalid: expected %q got %q", i, expectedImage, image)
@@ -772,6 +788,9 @@ func (suite *ClusterMachineConfigStatusSuite) TestSecureBootInstallImage() {
772788
res.TypedSpec().Value.SecureBootStatus = &specs.SecureBootStatus{
773789
Enabled: true,
774790
}
791+
res.TypedSpec().Value.PlatformMetadata = &specs.MachineStatusSpec_PlatformMetadata{
792+
Platform: talosconstants.PlatformMetal,
793+
}
775794
res.TypedSpec().Value.Schematic = &specs.MachineStatusSpec_Schematic{
776795
FullId: "abcd",
777796
}
@@ -789,7 +808,7 @@ func (suite *ClusterMachineConfigStatusSuite) TestSecureBootInstallImage() {
789808
return retry.ExpectedErrorf("no upgrade requests received")
790809
}
791810

792-
expectedImage := imageFactoryHost + "/installer-secureboot/abcd:v1.3.0"
811+
expectedImage := imageFactoryHost + "/installer-secureboot/abcd:v1.3.0" // expected installer image without the platform prepended to it, as the Talos version is < 1.10.0
793812
for i, r := range requests {
794813
if r.Image != expectedImage {
795814
return fmt.Errorf("%d request image is invalid: expected %q got %q", i, expectedImage, r.Image)

0 commit comments

Comments
 (0)