Skip to content

Commit

Permalink
Merge pull request #5514 from twz123/remove-storage-param
Browse files Browse the repository at this point in the history
Remove storage parameter from DefaultClusterConfig
  • Loading branch information
twz123 authored Feb 6, 2025
2 parents 7e5a5d1 + 775388f commit 9c30564
Show file tree
Hide file tree
Showing 12 changed files with 133 additions and 142 deletions.
19 changes: 9 additions & 10 deletions cmd/config/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,27 +35,26 @@ func NewValidateCmd() *cobra.Command {
Long: `Example:
k0s config validate --config path_to_config.yaml`,
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, _ []string) error {
var reader io.Reader
RunE: func(cmd *cobra.Command, _ []string) (err error) {
var bytes []byte

// config.CfgFile is the global value holder for --config flag, set by cobra/pflag
switch config.CfgFile {
case "-":
reader = cmd.InOrStdin()
if bytes, err = io.ReadAll(cmd.InOrStdin()); err != nil {
return fmt.Errorf("failed to read configuration from standard input: %w", err)
}
case "":
return errors.New("--config can't be empty")
default:
f, err := os.Open(config.CfgFile)
if err != nil {
return err
if bytes, err = os.ReadFile(config.CfgFile); err != nil {
return fmt.Errorf("failed to read configuration file: %w", err)
}
defer f.Close()
reader = f
}

cfg, err := v1beta1.ConfigFromReader(reader)
cfg, err := v1beta1.ConfigFromBytes(bytes)
if err != nil {
return fmt.Errorf("failed to read config: %w", err)
return fmt.Errorf("failed to parse configuration: %w", err)
}

return errors.Join(cfg.Validate()...)
Expand Down
50 changes: 21 additions & 29 deletions pkg/apis/k0s/v1beta1/clusterconfig_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
"bytes"
"encoding/json"
"fmt"
"io"
"reflect"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -198,30 +197,24 @@ func (s *SchedulerSpec) IsZero() bool {
return len(s.ExtraArgs) == 0
}

func ConfigFromString(yml string, defaultStorage ...*StorageSpec) (*ClusterConfig, error) {
config := DefaultClusterConfig(defaultStorage...)
err := strictyaml.YamlUnmarshalStrictIgnoringFields([]byte(yml), config, "interval", "podSecurityPolicy")
if err != nil {
return config, err
}
if config.Spec == nil {
config.Spec = DefaultClusterSpec(defaultStorage...)
}
return config, nil
func ConfigFromBytes(bytes []byte) (*ClusterConfig, error) {
return DefaultClusterConfig().MergedWithYAML(bytes)
}

// ConfigFromReader reads the configuration from any reader (can be stdin, file reader, etc)
func ConfigFromReader(r io.Reader, defaultStorage ...*StorageSpec) (*ClusterConfig, error) {
input, err := io.ReadAll(r)
func (c *ClusterConfig) MergedWithYAML(bytes []byte) (*ClusterConfig, error) {
merged := c.DeepCopy()
err := strictyaml.YamlUnmarshalStrictIgnoringFields(bytes, merged, "interval", "podSecurityPolicy")
if err != nil {
return nil, err
}
return ConfigFromString(string(input), defaultStorage...)
if merged.Spec == nil {
merged.Spec = c.Spec
}
return merged, nil
}

// DefaultClusterConfig sets the default ClusterConfig values, when none are given
func DefaultClusterConfig(defaultStorage ...*StorageSpec) *ClusterConfig {
clusterSpec := DefaultClusterSpec(defaultStorage...)
func DefaultClusterConfig() *ClusterConfig {
return &ClusterConfig{
TypeMeta: metav1.TypeMeta{
APIVersion: GroupVersion.String(),
Expand All @@ -231,7 +224,7 @@ func DefaultClusterConfig(defaultStorage ...*StorageSpec) *ClusterConfig {
Name: constant.ClusterConfigObjectName,
Namespace: constant.ClusterConfigNamespace,
},
Spec: clusterSpec,
Spec: DefaultClusterSpec(),
}
}

Expand All @@ -247,7 +240,10 @@ func (c *ClusterConfig) UnmarshalJSON(data []byte) error {
if c.Spec != nil && c.Spec.Storage != nil {
storage = c.Spec.Storage
}
c.Spec = DefaultClusterSpec(storage)
c.Spec = DefaultClusterSpec()
if storage != nil {
c.Spec.Storage = storage
}

type config ClusterConfig
jc := (*config)(c)
Expand All @@ -261,7 +257,10 @@ func (c *ClusterConfig) UnmarshalJSON(data []byte) error {
}

if jc.Spec == nil {
jc.Spec = DefaultClusterSpec(storage)
jc.Spec = DefaultClusterSpec()
if storage != nil {
jc.Spec.Storage = storage
}
return nil
}
if jc.Spec.Storage == nil {
Expand Down Expand Up @@ -301,17 +300,10 @@ func (c *ClusterConfig) UnmarshalJSON(data []byte) error {
}

// DefaultClusterSpec default settings
func DefaultClusterSpec(defaultStorage ...*StorageSpec) *ClusterSpec {
var storage *StorageSpec
if defaultStorage == nil || defaultStorage[0] == nil {
storage = DefaultStorageSpec()
} else {
storage = defaultStorage[0]
}

func DefaultClusterSpec() *ClusterSpec {
spec := &ClusterSpec{
Extensions: DefaultExtensions(),
Storage: storage,
Storage: DefaultStorageSpec(),
Network: DefaultNetwork(),
API: DefaultAPISpec(),
ControllerManager: DefaultControllerManagerSpec(),
Expand Down
72 changes: 36 additions & 36 deletions pkg/apis/k0s/v1beta1/clusterconfig_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,29 +30,29 @@ import (
)

func TestClusterDefaults(t *testing.T) {
c, err := ConfigFromString("apiVersion: k0s.k0sproject.io/v1beta1")
c, err := ConfigFromBytes([]byte("apiVersion: k0s.k0sproject.io/v1beta1"))
assert.NoError(t, err)
assert.Equal(t, DefaultStorageSpec(), c.Spec.Storage)
}

func TestUnknownFieldValidation(t *testing.T) {
_, err := ConfigFromString(`
_, err := ConfigFromBytes([]byte(`
apiVersion: k0s.k0sproject.io/v1beta1
kind: ClusterConfig
unknown: 1`)
unknown: 1`))

assert.Error(t, err)
}

func TestStorageDefaults(t *testing.T) {
yamlData := `
yamlData := []byte(`
apiVersion: k0s.k0sproject.io/v1beta1
kind: ClusterConfig
metadata:
name: foobar
`
`)

c, err := ConfigFromString(yamlData)
c, err := ConfigFromBytes(yamlData)
assert.NoError(t, err)
assert.Equal(t, EtcdStorageType, c.Spec.Storage.Type)
addr, err := iface.FirstPublicAddress()
Expand Down Expand Up @@ -122,17 +122,17 @@ func TestClusterSpecCustomImages(t *testing.T) {
}

func TestEtcdDefaults(t *testing.T) {
yamlData := `
yamlData := []byte(`
apiVersion: k0s.k0sproject.io/v1beta1
kind: ClusterConfig
metadata:
name: foobar
spec:
storage:
type: etcd
`
`)

c, err := ConfigFromString(yamlData)
c, err := ConfigFromBytes(yamlData)
assert.NoError(t, err)
assert.Equal(t, EtcdStorageType, c.Spec.Storage.Type)
addr, err := iface.FirstPublicAddress()
Expand All @@ -141,7 +141,7 @@ spec:
}

func TestNetworkValidation_Custom(t *testing.T) {
yamlData := `
yamlData := []byte(`
apiVersion: k0s.k0sproject.io/v1beta1
kind: ClusterConfig
metadata:
Expand All @@ -151,16 +151,16 @@ spec:
provider: custom
storage:
type: etcd
`
`)

c, err := ConfigFromString(yamlData)
c, err := ConfigFromBytes(yamlData)
assert.NoError(t, err)
errors := c.Validate()
assert.Zero(t, errors)
}

func TestNetworkValidation_Calico(t *testing.T) {
yamlData := `
yamlData := []byte(`
apiVersion: k0s.k0sproject.io/v1beta1
kind: ClusterConfig
metadata:
Expand All @@ -170,16 +170,16 @@ spec:
provider: calico
storage:
type: etcd
`
`)

c, err := ConfigFromString(yamlData)
c, err := ConfigFromBytes(yamlData)
assert.NoError(t, err)
errors := c.Validate()
assert.Zero(t, errors)
}

func TestNetworkValidation_Invalid(t *testing.T) {
yamlData := `
yamlData := []byte(`
apiVersion: k0s.k0sproject.io/v1beta1
kind: ClusterConfig
metadata:
Expand All @@ -189,9 +189,9 @@ spec:
provider: invalidProvider
storage:
type: etcd
`
`)

c, err := ConfigFromString(yamlData)
c, err := ConfigFromBytes(yamlData)
assert.NoError(t, err)
errors := c.Validate()
if assert.Len(t, errors, 1) {
Expand All @@ -200,7 +200,7 @@ spec:
}

func TestApiExternalAddress(t *testing.T) {
yamlData := `
yamlData := []byte(`
apiVersion: k0s.k0sproject.io/v1beta1
kind: ClusterConfig
metadata:
Expand All @@ -209,33 +209,33 @@ spec:
api:
externalAddress: foo.bar.com
address: 1.2.3.4
`
`)

c, err := ConfigFromString(yamlData)
c, err := ConfigFromBytes(yamlData)
assert.NoError(t, err)
assert.Equal(t, "https://foo.bar.com:6443", c.Spec.API.APIAddressURL())
assert.Equal(t, "https://foo.bar.com:9443", c.Spec.API.K0sControlPlaneAPIAddress())
}

func TestApiNoExternalAddress(t *testing.T) {
yamlData := `
yamlData := []byte(`
apiVersion: k0s.k0sproject.io/v1beta1
kind: ClusterConfig
metadata:
name: foobar
spec:
api:
address: 1.2.3.4
`
`)

c, err := ConfigFromString(yamlData)
c, err := ConfigFromBytes(yamlData)
assert.NoError(t, err)
assert.Equal(t, "https://1.2.3.4:6443", c.Spec.API.APIAddressURL())
assert.Equal(t, "https://1.2.3.4:9443", c.Spec.API.K0sControlPlaneAPIAddress())
}

func TestNullValues(t *testing.T) {
yamlData := `
yamlData := []byte(`
apiVersion: k0s.k0sproject.io/v1beta1
kind: ClusterConfig
metadata:
Expand All @@ -251,18 +251,18 @@ spec:
installConfig: null
telemetry: null
konnectivity: null
`
extensionsYamlData := `
`)
extensionsYamlData := []byte(`
apiVersion: k0s.k0sproject.io/v1beta1
kind: ClusterConfig
metadata:
name: foobar
spec:
extensions:
storage: null
`
`)

c, err := ConfigFromString(yamlData)
c, err := ConfigFromBytes(yamlData)
assert.NoError(t, err)
assert.Equal(t, DefaultClusterImages(), c.Spec.Images)
assert.Equal(t, DefaultStorageSpec(), c.Spec.Storage)
Expand All @@ -276,13 +276,13 @@ spec:
assert.Equal(t, DefaultClusterTelemetry(), c.Spec.Telemetry)
assert.Equal(t, DefaultKonnectivitySpec(), c.Spec.Konnectivity)

e, err := ConfigFromString(extensionsYamlData)
e, err := ConfigFromBytes(extensionsYamlData)
assert.NoError(t, err)
assert.Equal(t, DefaultExtensions(), e.Spec.Extensions)
}

func TestWorkerProfileConfig(t *testing.T) {
yamlData := `
yamlData := []byte(`
apiVersion: k0s.k0sproject.io/v1beta1
kind: ClusterConfig
metadata:
Expand All @@ -303,8 +303,8 @@ spec:
authentication:
anonymous:
enabled: false
`
c, err := ConfigFromString(yamlData)
`)
c, err := ConfigFromBytes(yamlData)
assert.NoError(t, err)
require.Len(t, c.Spec.WorkerProfiles, 2)
assert.Equal(t, "profile_XXX", c.Spec.WorkerProfiles[0].Name)
Expand Down Expand Up @@ -340,7 +340,7 @@ func TestDefaultClusterConfigYaml(t *testing.T) {
}

func TestFeatureGates(t *testing.T) {
yamlData := `
yamlData := []byte(`
apiVersion: k0s.k0sproject.io/v1beta1
kind: ClusterConfig
metadata:
Expand All @@ -355,8 +355,8 @@ func TestFeatureGates(t *testing.T) {
-
name: feature_ZZZ
enabled: false
`
c, err := ConfigFromString(yamlData)
`)
c, err := ConfigFromBytes(yamlData)
assert.NoError(t, err)
require.Len(t, c.Spec.FeatureGates, 3)
assert.Equal(t, "feature_XXX", c.Spec.FeatureGates[0].Name)
Expand Down
Loading

0 comments on commit 9c30564

Please sign in to comment.