Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 24 additions & 20 deletions internal/controller/controlplane/k0s_controlplane_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,21 +193,6 @@ func (c *K0sController) Reconcile(ctx context.Context, req ctrl.Request) (res ct

log = log.WithValues("cluster", cluster.Name)

if err := c.ensureCertificates(ctx, cluster, kcp); err != nil {
log.Error(err, "Failed to ensure certificates")
return ctrl.Result{}, err
}

if err := c.reconcileTunneling(ctx, cluster, kcp); err != nil {
log.Error(err, "Failed to reconcile tunneling")
return ctrl.Result{}, err
}

if err := c.reconcileConfig(ctx, cluster, kcp); err != nil {
log.Error(err, "Failed to reconcile config")
return ctrl.Result{}, err
}

err = c.reconcile(ctx, cluster, kcp)
if err != nil {
if errors.Is(err, ErrNotReady) {
Expand Down Expand Up @@ -317,6 +302,18 @@ func (c *K0sController) reconcileKubeconfig(ctx context.Context, cluster *cluste
}

func (c *K0sController) reconcile(ctx context.Context, cluster *clusterv1.Cluster, kcp *cpv1beta1.K0sControlPlane) error {
if err := c.ensureCertificates(ctx, cluster, kcp); err != nil {
return fmt.Errorf("failed to ensure certificates: %w", err)
}

if err := c.reconcileTunneling(ctx, cluster, kcp); err != nil {
return fmt.Errorf("failed to reconcile tunneling: %w", err)
}

if err := c.reconcileConfig(ctx, cluster, kcp); err != nil {
return fmt.Errorf("failed to reconcile config: %w", err)
}

var err error
kcp.Spec.K0sConfigSpec.K0s, err = enrichK0sConfigWithClusterData(cluster, kcp.Spec.K0sConfigSpec.K0s)
if err != nil {
Expand Down Expand Up @@ -671,11 +668,18 @@ func (c *K0sController) reconcileConfig(ctx context.Context, cluster *clusterv1.
}
}

// Reconcile the dynamic config
dErr := kutil.ReconcileDynamicConfig(ctx, cluster, c.Client, *kcp.Spec.K0sConfigSpec.K0s.DeepCopy())
if dErr != nil {
// Don't return error from dynamic config reconciliation, as it may not be created yet
log.Error(fmt.Errorf("failed to reconcile dynamic config, kubeconfig may not be available yet: %w", dErr), "Failed to reconcile dynamic config")
// Reconcile the dynamic config. The status must be Ready, denoting that the workload cluster API is available to modify
// the configuration dynamically.
if kcp.Status.Ready {
err := kutil.ReconcileDynamicConfig(ctx, cluster, c.Client, *kcp.Spec.K0sConfigSpec.K0s.DeepCopy())
if err != nil {
if errors.Is(err, kutil.ErrClusterConfigNotFound) {
log.Info("ClusterConfig is not available yet")
return fmt.Errorf("%v: %w", err, ErrNotReady)
}

return err
}
}
}

Expand Down
7 changes: 7 additions & 0 deletions internal/util/dynamic_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ package util

import (
"context"
"errors"
"fmt"
"time"

apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/util/wait"
Expand All @@ -14,6 +16,8 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
)

var ErrClusterConfigNotFound = errors.New("ClusterConfig not available yet")

func ReconcileDynamicConfig(ctx context.Context, cluster metav1.Object, cli client.Client, u unstructured.Unstructured) error {
u.SetName("k0s")
u.SetNamespace("kube-system")
Expand Down Expand Up @@ -45,6 +49,9 @@ func ReconcileDynamicConfig(ctx context.Context, cluster metav1.Object, cli clie
return chCS.Patch(ctx, &u, client.RawPatch(client.Merge.Type(), b), []client.PatchOption{}...)
})
if err != nil {
if apierrors.IsNotFound(err) {
return fmt.Errorf("failed to patch k0s config: %w", ErrClusterConfigNotFound)
}
return fmt.Errorf("failed to patch k0s config: %w", err)
}

Expand Down
Loading