From 6501f4ec3f9078ff9d9b084304df3f3354a87b5c Mon Sep 17 00:00:00 2001 From: Etienne Audet-Cobello Date: Thu, 12 Dec 2024 18:51:44 -0500 Subject: [PATCH] use ready wg, create configmap if not found --- src/k8s/pkg/k8sd/app/app.go | 6 +- .../node_configuration_reconciler.go | 28 +++++++- .../node_configuration_reconciler_test.go | 66 ++++++++++++------- 3 files changed, 70 insertions(+), 30 deletions(-) diff --git a/src/k8s/pkg/k8sd/app/app.go b/src/k8s/pkg/k8sd/app/app.go index 642d3a12d..c24bc76c7 100644 --- a/src/k8s/pkg/k8sd/app/app.go +++ b/src/k8s/pkg/k8sd/app/app.go @@ -132,7 +132,7 @@ func New(cfg Config) (*App, error) { if err != nil { return nil, fmt.Errorf("failed to setup manager: %w", err) } - ctrller, err := setupControllers(mgr, cfg) + ctrller, err := setupControllers(app, mgr, cfg) if err != nil { return nil, fmt.Errorf("failed to setup controllers: %w", err) } @@ -294,7 +294,7 @@ func setupManager(cfg Config) (manager.Manager, error) { return mgr, nil } -func setupControllers(mgr manager.Manager, cfg Config) (*controllers.NodeConfigurationReconciler, error) { +func setupControllers(app *App, mgr manager.Manager, cfg Config) (*controllers.NodeConfigurationReconciler, error) { scheme := mgr.GetScheme() if !cfg.DisableUpdateNodeConfigController { @@ -302,7 +302,7 @@ func setupControllers(mgr manager.Manager, cfg Config) (*controllers.NodeConfigu mgr.GetClient(), scheme, cfg.Snap, - func() {}, + app.readyWg.Wait, ) if err := controller.SetupWithManager(mgr); err != nil { diff --git a/src/k8s/pkg/k8sd/controllers/node_configuration_reconciler.go b/src/k8s/pkg/k8sd/controllers/node_configuration_reconciler.go index cb5d4e6ee..558928f7d 100644 --- a/src/k8s/pkg/k8sd/controllers/node_configuration_reconciler.go +++ b/src/k8s/pkg/k8sd/controllers/node_configuration_reconciler.go @@ -11,6 +11,7 @@ import ( snaputil "github.com/canonical/k8s/pkg/snap/util" pkiutil "github.com/canonical/k8s/pkg/utils/pki" corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" @@ -106,8 +107,23 @@ func (c *NodeConfigurationReconciler) Reconcile(ctx context.Context, req ctrl.Re // Get existing ConfigMap cm := &corev1.ConfigMap{} if err := c.Get(ctx, req.NamespacedName, cm); err != nil { - logger.Error(err, "Failed to get ConfigMap") - return reconcile.Result{}, err + if !apierrors.IsNotFound(err) { + logger.Error(err, "Failed to get ConfigMap") + return reconcile.Result{}, err + } else { + cm = &corev1.ConfigMap{ + ObjectMeta: ctrl.ObjectMeta{ + Name: req.Name, + Namespace: req.Namespace, + }, + Data: cmData, + } + if err := c.Create(ctx, cm); err != nil { + logger.Error(err, "Failed to create ConfigMap") + return reconcile.Result{}, err + } + return reconcile.Result{}, nil + } } // Update ConfigMap @@ -134,3 +150,11 @@ func (c *NodeConfigurationReconciler) ReconciledCh() <-chan struct{} { func (r *NodeConfigurationReconciler) SetConfigGetter(getter func(context.Context) (types.ClusterConfig, error)) { r.getClusterConfig = getter } + +func (c *NodeConfigurationReconciler) Start(ctx context.Context) error { + logger := log.FromContext(ctx) + logger.V(1).Info("Waiting for node to be ready") + c.waitReady() + logger.V(1).Info("Starting update node configuration controller") + return nil +} diff --git a/src/k8s/pkg/k8sd/controllers/node_configuration_reconciler_test.go b/src/k8s/pkg/k8sd/controllers/node_configuration_reconciler_test.go index ce7bed7bb..1adcaf4ea 100644 --- a/src/k8s/pkg/k8sd/controllers/node_configuration_reconciler_test.go +++ b/src/k8s/pkg/k8sd/controllers/node_configuration_reconciler_test.go @@ -11,6 +11,7 @@ import ( "github.com/canonical/k8s/pkg/utils" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "sigs.k8s.io/controller-runtime/pkg/client" @@ -20,20 +21,27 @@ import ( func TestNodeConfigurationReconciler(t *testing.T) { testCases := []struct { - name string - initialConfig types.ClusterConfig - expectedConfig types.ClusterConfig - expectedFailure bool + name string + existingMap bool + expectedConfig types.ClusterConfig }{ { - name: "ControlPlane_DefaultConfig", - initialConfig: types.ClusterConfig{}, + name: "ControlPlane_NotExist", + existingMap: false, + expectedConfig: types.ClusterConfig{ + Kubelet: types.Kubelet{ + ClusterDomain: utils.Pointer("cluster.local"), + }, + }, + }, + { + name: "ControlPlane_ExistingConfig", + existingMap: true, expectedConfig: types.ClusterConfig{ Kubelet: types.Kubelet{ ClusterDomain: utils.Pointer("cluster.local"), }, }, - expectedFailure: false, }, } @@ -46,22 +54,24 @@ func TestNodeConfigurationReconciler(t *testing.T) { scheme := runtime.NewScheme() g.Expect(corev1.AddToScheme(scheme)).To(Succeed()) - // Create initial ConfigMap - kubeletConfigMap, err := tc.initialConfig.Kubelet.ToConfigMap(nil) - g.Expect(err).ToNot(HaveOccurred()) - - configMap := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: "k8sd-config", - Namespace: "kube-systems", - }, - Data: kubeletConfigMap, + // Setup objects for fake client + objects := []client.Object{} + if tc.existingMap { + // Only create initial ConfigMap if test case requires it + initialMap := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "k8sd-config", + Namespace: "kube-system", + }, + Data: map[string]string{"initial": "data"}, + } + objects = append(objects, initialMap) } // Create fake client k8sClient := fake.NewClientBuilder(). WithScheme(scheme). - WithObjects(configMap). + WithObjects(objects...). Build() // Setup mock snap @@ -85,11 +95,22 @@ func TestNodeConfigurationReconciler(t *testing.T) { return tc.expectedConfig, nil }) + // Verify ConfigMap doesn't exist if it shouldn't + if !tc.existingMap { + var cm corev1.ConfigMap + err := k8sClient.Get(ctx, client.ObjectKey{ + Name: "k8sd-config", + Namespace: "kube-system", + }, &cm) + g.Expect(err).To(HaveOccurred()) + g.Expect(apierrors.IsNotFound(err)).To(BeTrue(), "Expected ConfigMap not to exist") + } + // Trigger reconciliation req := reconcile.Request{ NamespacedName: client.ObjectKey{ Name: "k8sd-config", - Namespace: "kube-systems", + Namespace: "kube-system", }, } @@ -106,12 +127,7 @@ func TestNodeConfigurationReconciler(t *testing.T) { expectedConfigMap, err := tc.expectedConfig.Kubelet.ToConfigMap(nil) g.Expect(err).ToNot(HaveOccurred()) - - if tc.expectedFailure { - g.Expect(getResult.Data).ToNot(Equal(expectedConfigMap)) - } else { - g.Expect(getResult.Data).To(Equal(expectedConfigMap)) - } + g.Expect(getResult.Data).To(Equal(expectedConfigMap)) }) } }