From 5e8aa74168a7b98c3ea36bfeb705888642d48151 Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Fri, 11 Aug 2023 11:05:44 +0200 Subject: [PATCH] Not fail csi-init on network problems (#2042) --- src/cmd/csi/init/builder.go | 9 ++++-- src/cmd/csi/init/config.go | 5 ++++ src/controllers/csi/metadata/correctness.go | 30 ++++++++++++------- .../csi/metadata/correctness_test.go | 29 ++++++++++++++++++ test/testdata/sample-app/restricted-csi.yaml | 4 ++- 5 files changed, 63 insertions(+), 14 deletions(-) create mode 100644 src/cmd/csi/init/config.go diff --git a/src/cmd/csi/init/builder.go b/src/cmd/csi/init/builder.go index cbafe13d22..41dd38aab7 100644 --- a/src/cmd/csi/init/builder.go +++ b/src/cmd/csi/init/builder.go @@ -10,6 +10,7 @@ import ( "github.com/spf13/cobra" "golang.org/x/sys/unix" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" ) const use = "csi-init" @@ -56,7 +57,7 @@ func (builder CommandBuilder) buildRun() func(*cobra.Command, []string) error { csiManager, err := createManager(builder.namespace, kubeConfig) if err != nil { - return err + log.Info("failed to create/configure kubernetes client, will only run non-network related corrections and checks", "err", err.Error()) } err = createCsiDataPath(afero.NewOsFs()) @@ -76,7 +77,11 @@ func (builder CommandBuilder) buildRun() func(*cobra.Command, []string) error { RootDir: dtcsi.DataPath, } - err = metadata.NewCorrectnessChecker(csiManager.GetClient(), access, csiOptions).CorrectCSI(signalHandler) + var apiReader client.Reader + if csiManager != nil { + apiReader = csiManager.GetAPIReader() + } + err = metadata.NewCorrectnessChecker(apiReader, access, csiOptions).CorrectCSI(signalHandler) if err != nil { return err } diff --git a/src/cmd/csi/init/config.go b/src/cmd/csi/init/config.go new file mode 100644 index 0000000000..533c405aa5 --- /dev/null +++ b/src/cmd/csi/init/config.go @@ -0,0 +1,5 @@ +package init + +import "github.com/Dynatrace/dynatrace-operator/src/logger" + +var log = logger.Factory.GetLogger("csi-init") diff --git a/src/controllers/csi/metadata/correctness.go b/src/controllers/csi/metadata/correctness.go index 418578a8da..a5dde64c08 100644 --- a/src/controllers/csi/metadata/correctness.go +++ b/src/controllers/csi/metadata/correctness.go @@ -15,18 +15,18 @@ import ( ) type CorrectnessChecker struct { - cl client.Client - fs afero.Fs - path PathResolver - access Access + apiReader client.Reader + fs afero.Fs + path PathResolver + access Access } -func NewCorrectnessChecker(cl client.Client, access Access, opts dtcsi.CSIOptions) *CorrectnessChecker { +func NewCorrectnessChecker(cl client.Reader, access Access, opts dtcsi.CSIOptions) *CorrectnessChecker { return &CorrectnessChecker{ - cl: cl, - fs: afero.NewOsFs(), - path: PathResolver{RootDir: opts.RootDir}, - access: access, + apiReader: cl, + fs: afero.NewOsFs(), + path: PathResolver{RootDir: opts.RootDir}, + access: access, } } @@ -49,6 +49,10 @@ func (checker *CorrectnessChecker) CorrectCSI(ctx context.Context) error { // Removes volume entries if their pod is no longer exists func (checker *CorrectnessChecker) removeVolumesForMissingPods(ctx context.Context) error { + if checker.apiReader == nil { + log.Info("no kubernetes client configured, skipping orphaned volume metadata cleanup") + return nil + } podNames, err := checker.access.GetPodNames(ctx) if err != nil { return err @@ -56,7 +60,7 @@ func (checker *CorrectnessChecker) removeVolumesForMissingPods(ctx context.Conte pruned := []string{} for podName := range podNames { var pod corev1.Pod - if err := checker.cl.Get(context.TODO(), client.ObjectKey{Name: podName}, &pod); !k8serrors.IsNotFound(err) { + if err := checker.apiReader.Get(ctx, client.ObjectKey{Name: podName}, &pod); !k8serrors.IsNotFound(err) { continue } volumeID := podNames[podName] @@ -71,6 +75,10 @@ func (checker *CorrectnessChecker) removeVolumesForMissingPods(ctx context.Conte // Removes dynakube entries if their Dynakube instance no longer exists in the cluster func (checker *CorrectnessChecker) removeMissingDynakubes(ctx context.Context) error { + if checker.apiReader == nil { + log.Info("no kubernetes client configured, skipping orphaned dynakube metadata cleanup") + return nil + } dynakubes, err := checker.access.GetTenantsToDynakubes(ctx) if err != nil { return err @@ -78,7 +86,7 @@ func (checker *CorrectnessChecker) removeMissingDynakubes(ctx context.Context) e pruned := []string{} for dynakubeName := range dynakubes { var dynakube dynatracev1beta1.DynaKube - if err := checker.cl.Get(context.TODO(), client.ObjectKey{Name: dynakubeName}, &dynakube); !k8serrors.IsNotFound(err) { + if err := checker.apiReader.Get(ctx, client.ObjectKey{Name: dynakubeName}, &dynakube); !k8serrors.IsNotFound(err) { continue } if err := checker.access.DeleteDynakube(ctx, dynakubeName); err != nil { diff --git a/src/controllers/csi/metadata/correctness_test.go b/src/controllers/csi/metadata/correctness_test.go index 06a15d0ce7..67e97b138b 100644 --- a/src/controllers/csi/metadata/correctness_test.go +++ b/src/controllers/csi/metadata/correctness_test.go @@ -54,12 +54,36 @@ func TestCorrectCSI(t *testing.T) { assert.NoError(t, err) }) + t.Run("no error on nil apiReader, database is not cleaned", func(t *testing.T) { + ctx := context.TODO() + testVolume1 := createTestVolume(1) + testDynakube1 := createTestDynakube(1) + db := FakeMemoryDB() + db.InsertVolume(ctx, &testVolume1) + db.InsertDynakube(ctx, &testDynakube1) + + checker := NewCorrectnessChecker(nil, db, dtcsi.CSIOptions{}) + + err := checker.CorrectCSI(context.TODO()) + + assert.NoError(t, err) + vol, err := db.GetVolume(ctx, testVolume1.VolumeID) + assert.NoError(t, err) + assert.Equal(t, &testVolume1, vol) + + assert.NoError(t, err) + dk, err := db.GetDynakube(ctx, testDynakube1.Name) + assert.NoError(t, err) + assert.Equal(t, &testDynakube1, dk) + }) + t.Run("nothing to remove, everything is still correct", func(t *testing.T) { ctx := context.TODO() testVolume1 := createTestVolume(1) testDynakube1 := createTestDynakube(1) db := FakeMemoryDB() db.InsertVolume(ctx, &testVolume1) + db.InsertDynakube(ctx, &testDynakube1) client := fake.NewClient( &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: testVolume1.PodName}}, &dynatracev1beta1.DynaKube{ObjectMeta: metav1.ObjectMeta{Name: testDynakube1.Name}}, @@ -73,6 +97,11 @@ func TestCorrectCSI(t *testing.T) { vol, err := db.GetVolume(ctx, testVolume1.VolumeID) assert.NoError(t, err) assert.Equal(t, &testVolume1, vol) + + assert.NoError(t, err) + dk, err := db.GetDynakube(ctx, testDynakube1.Name) + assert.NoError(t, err) + assert.Equal(t, &testDynakube1, dk) }) t.Run("remove unnecessary entries in the filesystem", func(t *testing.T) { ctx := context.TODO() diff --git a/test/testdata/sample-app/restricted-csi.yaml b/test/testdata/sample-app/restricted-csi.yaml index 254a28949e..cf88725622 100644 --- a/test/testdata/sample-app/restricted-csi.yaml +++ b/test/testdata/sample-app/restricted-csi.yaml @@ -1,7 +1,7 @@ apiVersion: security.openshift.io/v1 kind: SecurityContextConstraints metadata: - name: restricted-csi + name: operator-e2e-restricted-csi runAsUser: type: RunAsAny seLinuxContext: @@ -30,3 +30,5 @@ volumes: - emptyDir - secret - csi +- projected +- downwardAPI