2023-05-25 12:43:44 -04:00
|
|
|
/*
|
|
|
|
Copyright (c) Edgeless Systems GmbH
|
|
|
|
|
|
|
|
SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
*/
|
|
|
|
|
2023-06-02 03:19:23 -04:00
|
|
|
package config
|
2023-05-25 12:43:44 -04:00
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"strings"
|
2024-06-12 04:24:16 -04:00
|
|
|
|
|
|
|
"github.com/edgelesssys/constellation/v2/internal/encoding"
|
2023-05-25 12:43:44 -04:00
|
|
|
)
|
|
|
|
|
2024-06-12 04:24:16 -04:00
|
|
|
type versionValue interface {
|
|
|
|
encoding.HexBytes | uint8 | uint16
|
|
|
|
}
|
|
|
|
|
|
|
|
func placeholderVersionValue[T versionValue]() T {
|
|
|
|
var placeholder T
|
|
|
|
return placeholder
|
|
|
|
}
|
2023-05-25 12:43:44 -04:00
|
|
|
|
|
|
|
// NewLatestPlaceholderVersion returns the latest version with a placeholder version value.
|
2024-06-12 04:24:16 -04:00
|
|
|
func NewLatestPlaceholderVersion[T versionValue]() AttestationVersion[T] {
|
|
|
|
return AttestationVersion[T]{
|
|
|
|
Value: placeholderVersionValue[T](),
|
2023-06-14 08:17:52 -04:00
|
|
|
WantLatest: true,
|
2023-05-25 12:43:44 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-06-12 04:24:16 -04:00
|
|
|
// AttestationVersion holds version information.
|
|
|
|
type AttestationVersion[T versionValue] struct {
|
|
|
|
Value T
|
2023-06-14 08:17:52 -04:00
|
|
|
WantLatest bool
|
2023-05-25 12:43:44 -04:00
|
|
|
}
|
|
|
|
|
2024-06-12 04:24:16 -04:00
|
|
|
// MarshalYAML implements a custom marshaller to write "latest" as the type's value, if set.
|
|
|
|
func (v AttestationVersion[T]) MarshalYAML() (any, error) {
|
2023-06-14 08:17:52 -04:00
|
|
|
if v.WantLatest {
|
2023-05-25 12:43:44 -04:00
|
|
|
return "latest", nil
|
|
|
|
}
|
2023-06-09 06:48:12 -04:00
|
|
|
return v.Value, nil
|
2023-05-25 12:43:44 -04:00
|
|
|
}
|
|
|
|
|
2024-06-12 04:24:16 -04:00
|
|
|
// UnmarshalYAML implements a custom unmarshaller to resolve "latest" values.
|
|
|
|
func (v *AttestationVersion[T]) UnmarshalYAML(unmarshal func(any) error) error {
|
|
|
|
return v.unmarshal(unmarshal)
|
2023-05-25 12:43:44 -04:00
|
|
|
}
|
|
|
|
|
2024-06-12 04:24:16 -04:00
|
|
|
// MarshalJSON implements a custom marshaller to write "latest" as the type's value, if set.
|
|
|
|
func (v AttestationVersion[T]) MarshalJSON() ([]byte, error) {
|
2023-06-14 08:17:52 -04:00
|
|
|
if v.WantLatest {
|
2023-05-25 12:43:44 -04:00
|
|
|
return json.Marshal("latest")
|
|
|
|
}
|
|
|
|
return json.Marshal(v.Value)
|
|
|
|
}
|
|
|
|
|
|
|
|
// UnmarshalJSON implements a custom unmarshaller to resolve "latest" values.
|
2024-06-12 04:24:16 -04:00
|
|
|
func (v *AttestationVersion[T]) UnmarshalJSON(data []byte) (err error) {
|
|
|
|
return v.unmarshal(func(a any) error {
|
|
|
|
return json.Unmarshal(data, a)
|
|
|
|
})
|
2023-05-25 12:43:44 -04:00
|
|
|
}
|
|
|
|
|
2024-06-12 04:24:16 -04:00
|
|
|
// 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
|
2023-08-09 05:41:04 -04:00
|
|
|
}
|
2024-06-12 04:24:16 -04:00
|
|
|
|
|
|
|
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" {
|
2023-08-09 05:41:04 -04:00
|
|
|
v.WantLatest = true
|
2024-06-12 04:24:16 -04:00
|
|
|
v.Value = placeholderVersionValue[T]()
|
|
|
|
return nil
|
2023-05-25 12:43:44 -04:00
|
|
|
}
|
2024-06-12 04:24:16 -04:00
|
|
|
|
|
|
|
return fmt.Errorf("failed unmarshalling to %T or string: invalid value: %s", distinctType, unmarshalString)
|
2023-05-25 12:43:44 -04:00
|
|
|
}
|