Skip to content

Commit

Permalink
Remove the optional default storage parameter from the default Cluste…
Browse files Browse the repository at this point in the history
…rConfig

The storage override occurs only during the initial loading of the node
configuration, and can be modeled by applying the changes to the default
configuration and then merging the user-provided configuration data
into it.

Signed-off-by: Tom Wieczorek <[email protected]>
  • Loading branch information
twz123 committed Jan 20, 2025
1 parent 7ea81b6 commit e584768
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 50 deletions.
44 changes: 23 additions & 21 deletions pkg/apis/k0s/v1beta1/clusterconfig_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,21 +197,24 @@ func (s *SchedulerSpec) IsZero() bool {
return len(s.ExtraArgs) == 0
}

func ConfigFromBytes(bytes []byte, defaultStorage ...*StorageSpec) (*ClusterConfig, error) {
config := DefaultClusterConfig(defaultStorage...)
err := strictyaml.YamlUnmarshalStrictIgnoringFields(bytes, config, "interval", "podSecurityPolicy")
func ConfigFromBytes(bytes []byte) (*ClusterConfig, error) {
return DefaultClusterConfig().MergedWithYAML(bytes)
}

func (c *ClusterConfig) MergedWithYAML(bytes []byte) (*ClusterConfig, error) {
merged := c.DeepCopy()
err := strictyaml.YamlUnmarshalStrictIgnoringFields(bytes, merged, "interval", "podSecurityPolicy")
if err != nil {
return config, err
return nil, err
}
if config.Spec == nil {
config.Spec = DefaultClusterSpec(defaultStorage...)
if merged.Spec == nil {
merged.Spec = c.Spec
}
return config, nil
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 @@ -221,7 +224,7 @@ func DefaultClusterConfig(defaultStorage ...*StorageSpec) *ClusterConfig {
Name: constant.ClusterConfigObjectName,
Namespace: constant.ClusterConfigNamespace,
},
Spec: clusterSpec,
Spec: DefaultClusterSpec(),
}
}

Expand All @@ -237,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 @@ -251,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 @@ -291,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
16 changes: 8 additions & 8 deletions pkg/component/controller/workerconfig/reconciler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ func TestReconciler_Lifecycle(t *testing.T) {
t.Run("reconcile_fails", func(t *testing.T) {
underTest := createdReconciler(t, nil)

err := underTest.Reconcile(testContext(t), v1beta1.DefaultClusterConfig(nil))
err := underTest.Reconcile(testContext(t), v1beta1.DefaultClusterConfig())

require.Error(t, err)
assert.Equal(t, "cannot reconcile, not started: created", err.Error())
Expand Down Expand Up @@ -140,7 +140,7 @@ func TestReconciler_Lifecycle(t *testing.T) {
t.Run("reconcile_fails", func(t *testing.T) {
underTest := initializedReconciler(t, nil)

err := underTest.Reconcile(testContext(t), v1beta1.DefaultClusterConfig(nil))
err := underTest.Reconcile(testContext(t), v1beta1.DefaultClusterConfig())

require.Error(t, err)
assert.Equal(t, "cannot reconcile, not started: initialized", err.Error())
Expand Down Expand Up @@ -196,7 +196,7 @@ func TestReconciler_Lifecycle(t *testing.T) {
underTest, mockApplier := startedReconciler(t)
applied := mockApplier.expectApply(t, nil)

assert.NoError(t, underTest.Reconcile(testContext(t), v1beta1.DefaultClusterConfig(nil)))
assert.NoError(t, underTest.Reconcile(testContext(t), v1beta1.DefaultClusterConfig()))

assert.NotEmpty(t, applied(), "Expected some resources to be applied")
})
Expand All @@ -214,7 +214,7 @@ func TestReconciler_Lifecycle(t *testing.T) {
t.Helper()
underTest, mockApplier := startedReconciler(t)
applied := mockApplier.expectApply(t, nil)
require.NoError(t, underTest.Reconcile(testContext(t), v1beta1.DefaultClusterConfig(nil)))
require.NoError(t, underTest.Reconcile(testContext(t), v1beta1.DefaultClusterConfig()))

_ = applied() // wait until reconciliation happened
return underTest, mockApplier
Expand Down Expand Up @@ -242,7 +242,7 @@ func TestReconciler_Lifecycle(t *testing.T) {
t.Run("another_reconcile_succeeds", func(t *testing.T) {
underTest, mockApplier := reconciledReconciler(t)
applied := mockApplier.expectApply(t, nil)
clusterConfig := v1beta1.DefaultClusterConfig(nil)
clusterConfig := v1beta1.DefaultClusterConfig()
clusterConfig.Spec.WorkerProfiles = v1beta1.WorkerProfiles{
{Name: "foo", Config: &runtime.RawExtension{Raw: []byte("{}")}},
}
Expand Down Expand Up @@ -291,7 +291,7 @@ func TestReconciler_Lifecycle(t *testing.T) {
t.Run("reconcile_fails", func(t *testing.T) {
underTest := stoppedReconciler(t)

err := underTest.Reconcile(testContext(t), v1beta1.DefaultClusterConfig(nil))
err := underTest.Reconcile(testContext(t), v1beta1.DefaultClusterConfig())

require.Error(t, err)
assert.Equal(t, "cannot reconcile, not started: stopped", err.Error())
Expand Down Expand Up @@ -480,7 +480,7 @@ func TestReconciler_ResourceGeneration(t *testing.T) {
}

func TestReconciler_ReconcilesOnChangesOnly(t *testing.T) {
cluster := v1beta1.DefaultClusterConfig(nil)
cluster := v1beta1.DefaultClusterConfig()
clients := testutil.NewFakeClientFactory()
k0sVars, err := config.NewCfgVars(nil, t.TempDir())
require.NoError(t, err)
Expand Down Expand Up @@ -630,7 +630,7 @@ func TestReconciler_runReconcileLoop(t *testing.T) {

func TestReconciler_LeaderElection(t *testing.T) {
var le mockLeaderElector
cluster := v1beta1.DefaultClusterConfig(nil)
cluster := v1beta1.DefaultClusterConfig()
clients := testutil.NewFakeClientFactory()
k0sVars, err := config.NewCfgVars(nil, t.TempDir())
require.NoError(t, err)
Expand Down
38 changes: 17 additions & 21 deletions pkg/config/cfgvars.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,25 +200,22 @@ func NewCfgVars(cobraCmd command, dirs ...string) (*CfgVars, error) {
return vars, nil
}

func (c *CfgVars) defaultStorageSpec() *v1beta1.StorageSpec {
if c.DefaultStorageType == v1beta1.KineStorageType {
return &v1beta1.StorageSpec{
Type: v1beta1.KineStorageType,
Kine: v1beta1.DefaultKineConfig(c.DataDir),
}
}

return v1beta1.DefaultStorageSpec()
}

var defaultConfigPath = constant.K0sConfigPathDefault

func (c *CfgVars) NodeConfig() (*v1beta1.ClusterConfig, error) {
if c.StartupConfigPath == "" {
return nil, errors.New("config path is not set")
}

var nodeConfig *v1beta1.ClusterConfig
nodeConfig := v1beta1.DefaultClusterConfig()

// Optionally override the default storage (used for single node clusters)
if c.DefaultStorageType == v1beta1.KineStorageType {
nodeConfig.Spec.Storage = &v1beta1.StorageSpec{
Type: v1beta1.KineStorageType,
Kine: v1beta1.DefaultKineConfig(c.DataDir),
}
}

if c.StartupConfigPath == "-" {
configReader := c.stdin
Expand All @@ -232,23 +229,22 @@ func (c *CfgVars) NodeConfig() (*v1beta1.ClusterConfig, error) {
return nil, err
}

nodeConfig, err = v1beta1.ConfigFromBytes(bytes, c.defaultStorageSpec())
nodeConfig, err = nodeConfig.MergedWithYAML(bytes)
if err != nil {
return nil, err
}
} else {
cfgContent, err := os.ReadFile(c.StartupConfigPath)
if errors.Is(err, os.ErrNotExist) && c.StartupConfigPath == defaultConfigPath {
nodeConfig = v1beta1.DefaultClusterConfig(c.defaultStorageSpec())
} else if err == nil {
cfg, err := v1beta1.ConfigFromBytes(cfgContent, c.defaultStorageSpec())
if err != nil {
return nil, err
if err != nil {
if c.StartupConfigPath == defaultConfigPath && errors.Is(err, os.ErrNotExist) {
// The default configuration file doesn't exist; continue with the defaults.
return nodeConfig, nil
}
nodeConfig = cfg
} else {

return nil, err
}

return nodeConfig.MergedWithYAML(cfgContent)
}

if nodeConfig.Spec.Storage.Type == v1beta1.KineStorageType && nodeConfig.Spec.Storage.Kine == nil {
Expand Down

0 comments on commit e584768

Please sign in to comment.