constellation/internal/config/attestationversion.go
Daniel Weiße 9159b60331 Implement support for "latest" placeholders for Azure TDX
Signed-off-by: Daniel Weiße <dw@edgeless.systems>
2024-06-27 09:09:13 +02:00

90 lines
2.3 KiB
Go

/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package config
import (
"encoding/json"
"fmt"
"strings"
"github.com/edgelesssys/constellation/v2/internal/encoding"
)
type versionValue interface {
encoding.HexBytes | uint8 | uint16
}
func placeholderVersionValue[T versionValue]() T {
var placeholder T
return placeholder
}
// NewLatestPlaceholderVersion returns the latest version with a placeholder version value.
func NewLatestPlaceholderVersion[T versionValue]() AttestationVersion[T] {
return AttestationVersion[T]{
Value: placeholderVersionValue[T](),
WantLatest: true,
}
}
// AttestationVersion holds version information.
type AttestationVersion[T versionValue] struct {
Value T
WantLatest bool
}
// MarshalYAML implements a custom marshaller to write "latest" as the type's value, if set.
func (v AttestationVersion[T]) MarshalYAML() (any, error) {
if v.WantLatest {
return "latest", nil
}
return v.Value, nil
}
// UnmarshalYAML implements a custom unmarshaller to resolve "latest" values.
func (v *AttestationVersion[T]) UnmarshalYAML(unmarshal func(any) error) error {
return v.unmarshal(unmarshal)
}
// MarshalJSON implements a custom marshaller to write "latest" as the type's value, if set.
func (v AttestationVersion[T]) MarshalJSON() ([]byte, error) {
if v.WantLatest {
return json.Marshal("latest")
}
return json.Marshal(v.Value)
}
// UnmarshalJSON implements a custom unmarshaller to resolve "latest" values.
func (v *AttestationVersion[T]) UnmarshalJSON(data []byte) (err error) {
return v.unmarshal(func(a any) error {
return json.Unmarshal(data, a)
})
}
// unmarshal takes care of unmarshalling the value from YAML or JSON.
func (v *AttestationVersion[T]) unmarshal(unmarshal func(any) error) error {
// Start by trying to unmarshal to the distinct type
var distinctType T
if err := unmarshal(&distinctType); err == nil {
v.Value = distinctType
return nil
}
var unmarshalString string
if err := unmarshal(&unmarshalString); err != nil {
return fmt.Errorf("failed unmarshalling to %T or string: %w", distinctType, err)
}
if strings.ToLower(unmarshalString) == "latest" {
v.WantLatest = true
v.Value = placeholderVersionValue[T]()
return nil
}
return fmt.Errorf("failed unmarshalling to %T or string: invalid value: %s", distinctType, unmarshalString)
}