Skip to content

Commit

Permalink
fix: use imager incoming version for extension validation
Browse files Browse the repository at this point in the history
Use the version coming from imager to validate extension constraints.

Part of : #9694

Signed-off-by: Noel Georgi <git@frezbo.dev>
  • Loading branch information
frezbo committed Nov 12, 2024
1 parent 9a02ecc commit 682718d
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 32 deletions.
11 changes: 6 additions & 5 deletions cmd/installer/pkg/install/extensions.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ import (

func (i *Installer) installExtensions() error {
builder := extensions.Builder{
InitramfsPath: fmt.Sprintf(constants.InitramfsAssetPath, i.options.Arch),
Arch: i.options.Arch,
ExtensionTreePath: constants.SystemExtensionsPath,
Printf: log.Printf,
Quirks: quirks.New(i.options.Version),
InitramfsPath: fmt.Sprintf(constants.InitramfsAssetPath, i.options.Arch),
Arch: i.options.Arch,
ExtensionTreePath: constants.SystemExtensionsPath,
ExtensionValidateContents: true,
Printf: log.Printf,
Quirks: quirks.New(i.options.Version),
}

return builder.Build()
Expand Down
13 changes: 12 additions & 1 deletion pkg/imager/extensions/extensions.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ type Builder struct {
Arch string
// ExtensionTreePath is a path to the extracted extension tree.
ExtensionTreePath string
// ExtensionValidateContents enables validation of the extension contents.
ExtensionValidateContents bool
// Printf is used for logging.
Printf func(format string, v ...any)
// Quirks for the Talos version being used.
Expand Down Expand Up @@ -95,8 +97,17 @@ func (builder *Builder) Build() error {
func (builder *Builder) validateExtensions(extensions []*extensions.Extension) error {
builder.Printf("validating system extensions")

opts := []extinterface.ValidationOption{
extinterface.WithValidateConstraints(),
extinterface.WithTalosVersion(builder.Quirks.Version()),
}

if builder.ExtensionValidateContents {
opts = append(opts, extinterface.WithValidateContents())
}

for _, ext := range extensions {
if err := ext.Validate(); err != nil {
if err := ext.Validate(opts...); err != nil {
return fmt.Errorf("error validating extension %q: %w", ext.Manifest.Metadata.Name, err)
}
}
Expand Down
33 changes: 16 additions & 17 deletions pkg/machinery/extensions/extensions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import (
"path/filepath"
"testing"

"github.com/blang/semver/v4"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/siderolabs/talos/pkg/machinery/extensions"
"github.com/siderolabs/talos/pkg/machinery/version"
)

func TestLoadValidate(t *testing.T) {
Expand All @@ -21,25 +21,19 @@ func TestLoadValidate(t *testing.T) {

assert.Equal(t, "gvisor", ext.Manifest.Metadata.Name)

// override Talos version to make it predictable
oldVersion := version.Tag
version.Tag = "v1.0.0"

t.Cleanup(func() {
version.Tag = oldVersion
})
version, err := semver.Parse("1.0.0")
require.NoError(t, err)

assert.NoError(t, ext.Validate())
assert.NoError(t, ext.Validate(
extensions.WithValidateConstraints(),
extensions.WithValidateContents(),
extensions.WithTalosVersion(version),
))
}

func TestValidateFailures(t *testing.T) {
// override Talos version to make it predictable
oldVersion := version.Tag
version.Tag = "v1.0.0"

t.Cleanup(func() {
version.Tag = oldVersion
})
version, err := semver.Parse("1.0.0")
require.NoError(t, err)

for _, tt := range []struct {
name string
Expand Down Expand Up @@ -73,7 +67,12 @@ func TestValidateFailures(t *testing.T) {
}

if err == nil {
err = ext.Validate()
err = ext.Validate(
extensions.WithValidateConstraints(),
extensions.WithValidateContents(),
extensions.WithTalosVersion(version),
)

assert.EqualError(t, err, tt.validateError)
}
})
Expand Down
77 changes: 68 additions & 9 deletions pkg/machinery/extensions/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,83 @@ import (
"github.com/siderolabs/talos/pkg/machinery/version"
)

// Validate the extension: compatibility, contents, etc.
func (ext *Extension) Validate() error {
if err := ext.validateConstraints(); err != nil {
return err
// ValidationOptions are used to configure the validation process.
type ValidationOptions struct {
// ValidateContstraints enables validation of the extension constraints.
ValidateContstraints bool
// ValidateContents enables validation of the extension contents.
ValidateContents bool

// TalosVersion is the version of Talos to validate against.
TalosVersion *semver.Version
}

// WithValidateConstraints enables validation of the extension constraints.
func WithValidateConstraints() ValidationOption {
return func(o *ValidationOptions) error {
o.ValidateContstraints = true

return nil
}
}

// WithValidateContents enables validation of the extension contents.
func WithValidateContents() ValidationOption {
return func(o *ValidationOptions) error {
o.ValidateContents = true

return nil
}
}

// WithTalosVersion sets the Talos version to validate against.
func WithTalosVersion(version semver.Version) ValidationOption {
return func(o *ValidationOptions) error {
o.TalosVersion = &version

return ext.validateContents()
return nil
}
}

func (ext *Extension) validateConstraints() error {
constraint := ext.Manifest.Metadata.Compatibility.Talos.Version
// ValidationOption is a function that configures the validation options.
type ValidationOption func(*ValidationOptions) error

if constraint != "" {
talosVersion, err := semver.ParseTolerant(version.Tag)
// Validate the extension: compatibility, contents, etc.
func (ext *Extension) Validate(opts ...ValidationOption) error {
validationOptions := &ValidationOptions{}

for _, opt := range opts {
if err := opt(validationOptions); err != nil {
panic(err)
}
}

if validationOptions.TalosVersion == nil {
version, err := semver.ParseTolerant(version.Tag)
if err != nil {
return err
}

validationOptions.TalosVersion = &version
}

if validationOptions.ValidateContstraints {
if err := ext.validateConstraints(*validationOptions.TalosVersion); err != nil {
return err
}
}

if validationOptions.ValidateContents {
return ext.validateContents()
}

return nil
}

func (ext *Extension) validateConstraints(talosVersion semver.Version) error {
constraint := ext.Manifest.Metadata.Compatibility.Talos.Version

if constraint != "" {
versionConstraint, err := semver.ParseRange(trim(constraint))
if err != nil {
return fmt.Errorf("error parsing Talos version constraint: %w", err)
Expand Down
5 changes: 5 additions & 0 deletions pkg/machinery/imager/quirks/quirks.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ func New(talosVersion string) Quirks {

var minVersionResetOption = semver.MustParse("1.4.0")

// Version returns the Talos version.
func (q Quirks) Version() semver.Version {
return *q.v
}

// SupportsResetGRUBOption returns true if the Talos version supports the reset option in GRUB menu (image and ISO).
func (q Quirks) SupportsResetGRUBOption() bool {
// if the version doesn't parse, we assume it's latest Talos
Expand Down

0 comments on commit 682718d

Please sign in to comment.