Files
my-rook-config/pkg/operator/ceph/cluster/dependents_test.go
T

294 lines
12 KiB
Go

/*
Copyright 2021 The Rook Authors. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cluster
import (
"testing"
cephv1 "github.com/rook/rook/pkg/apis/ceph.rook.io/v1"
"github.com/rook/rook/pkg/clusterd"
"github.com/stretchr/testify/assert"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
)
func TestCephClusterDependents(t *testing.T) {
scheme := runtime.NewScheme()
assert.NoError(t, cephv1.AddToScheme(scheme))
ns := "test-ceph-cluster-dependents"
var c *clusterd.Context
newClusterdCtx := func(objects ...client.Object) *clusterd.Context {
return &clusterd.Context{
Client: fakeclient.NewClientBuilder().WithScheme(scheme).WithObjects(objects...).Build(),
}
}
// Create objectmeta with the given name in our test namespace
meta := func(name string) v1.ObjectMeta {
return v1.ObjectMeta{
Name: name,
Namespace: ns,
}
}
t.Run("CephBlockPools", func(t *testing.T) {
c = newClusterdCtx(
&cephv1.CephBlockPool{ObjectMeta: meta("block-pool-1")},
&cephv1.CephBlockPool{ObjectMeta: meta("block-pool-2")},
)
deps, err := CephClusterDependents(c, ns)
assert.NoError(t, err)
assert.False(t, deps.Empty())
assert.ElementsMatch(t, []string{"CephBlockPool"}, deps.PluralKinds())
assert.ElementsMatch(t, []string{"block-pool-1", "block-pool-2"}, deps.OfKind("CephBlockPool"))
})
t.Run("CephRBDMirrors", func(t *testing.T) {
c = newClusterdCtx(
&cephv1.CephRBDMirror{ObjectMeta: meta("rbdmirror")},
)
deps, err := CephClusterDependents(c, ns)
assert.NoError(t, err)
assert.False(t, deps.Empty())
assert.ElementsMatch(t, []string{"CephRBDMirror"}, deps.PluralKinds())
assert.ElementsMatch(t, []string{"rbdmirror"}, deps.OfKind("CephRBDMirror"))
})
t.Run("CephFilesystems", func(t *testing.T) {
c = newClusterdCtx(
&cephv1.CephFilesystem{ObjectMeta: meta("filesystem-1")},
&cephv1.CephFilesystem{ObjectMeta: meta("filesystem-2")},
&cephv1.CephFilesystem{ObjectMeta: meta("filesystem-3")},
)
deps, err := CephClusterDependents(c, ns)
assert.NoError(t, err)
assert.False(t, deps.Empty())
assert.ElementsMatch(t, []string{"CephFilesystem"}, deps.PluralKinds())
assert.ElementsMatch(t, []string{"filesystem-1", "filesystem-2", "filesystem-3"}, deps.OfKind("CephFilesystem"))
})
t.Run("CephFilesystemMirrors", func(t *testing.T) {
c = newClusterdCtx(
&cephv1.CephFilesystemMirror{ObjectMeta: meta("fsmirror")},
)
deps, err := CephClusterDependents(c, ns)
assert.NoError(t, err)
assert.False(t, deps.Empty())
assert.ElementsMatch(t, []string{"CephFilesystemMirror"}, deps.PluralKinds())
assert.ElementsMatch(t, []string{"fsmirror"}, deps.OfKind("CephFilesystemMirror"))
})
t.Run("CephObjectStores", func(t *testing.T) {
c = newClusterdCtx(
&cephv1.CephObjectStore{ObjectMeta: meta("objectstore-1")},
&cephv1.CephObjectStore{ObjectMeta: meta("objectstore-2")},
)
deps, err := CephClusterDependents(c, ns)
assert.NoError(t, err)
assert.False(t, deps.Empty())
assert.ElementsMatch(t, []string{"CephObjectStore"}, deps.PluralKinds())
assert.ElementsMatch(t, []string{"objectstore-1", "objectstore-2"}, deps.OfKind("CephObjectStore"))
})
t.Run("CephObjectStoreUsers", func(t *testing.T) {
c = newClusterdCtx(
&cephv1.CephObjectStoreUser{ObjectMeta: meta("u1")},
&cephv1.CephObjectStoreUser{ObjectMeta: meta("u2")},
&cephv1.CephObjectStoreUser{ObjectMeta: meta("u3")},
&cephv1.CephObjectStoreUser{ObjectMeta: meta("u4")},
&cephv1.CephObjectStoreUser{ObjectMeta: meta("u5")},
)
deps, err := CephClusterDependents(c, ns)
assert.NoError(t, err)
assert.False(t, deps.Empty())
assert.ElementsMatch(t, []string{"CephObjectStoreUser"}, deps.PluralKinds())
assert.ElementsMatch(t, []string{"u1", "u2", "u3", "u4", "u5"}, deps.OfKind("CephObjectStoreUser"))
})
t.Run("CephObjectZones", func(t *testing.T) {
c = newClusterdCtx(
&cephv1.CephObjectZone{ObjectMeta: meta("zone-1")},
&cephv1.CephObjectZone{ObjectMeta: meta("zone-2")},
)
deps, err := CephClusterDependents(c, ns)
assert.NoError(t, err)
assert.False(t, deps.Empty())
assert.ElementsMatch(t, []string{"CephObjectZone"}, deps.PluralKinds())
assert.ElementsMatch(t, []string{"zone-1", "zone-2"}, deps.OfKind("CephObjectZone"))
})
t.Run("CephObjectZoneGroups", func(t *testing.T) {
c = newClusterdCtx(
&cephv1.CephObjectZoneGroup{ObjectMeta: meta("group-1")},
&cephv1.CephObjectZoneGroup{ObjectMeta: meta("group-2")},
)
deps, err := CephClusterDependents(c, ns)
assert.NoError(t, err)
assert.False(t, deps.Empty())
assert.ElementsMatch(t, []string{"CephObjectZoneGroup"}, deps.PluralKinds())
assert.ElementsMatch(t, []string{"group-1", "group-2"}, deps.OfKind("CephObjectZoneGroup"))
})
t.Run("CephObjectRealms", func(t *testing.T) {
c = newClusterdCtx(
&cephv1.CephObjectRealm{ObjectMeta: meta("realm-1")},
&cephv1.CephObjectRealm{ObjectMeta: meta("realm-2")},
)
deps, err := CephClusterDependents(c, ns)
assert.NoError(t, err)
assert.False(t, deps.Empty())
assert.ElementsMatch(t, []string{"CephObjectRealm"}, deps.PluralKinds())
assert.ElementsMatch(t, []string{"realm-1", "realm-2"}, deps.OfKind("CephObjectRealm"))
})
t.Run("CephNFSes", func(t *testing.T) {
c = newClusterdCtx(
&cephv1.CephNFS{ObjectMeta: meta("nfs-1")},
&cephv1.CephNFS{ObjectMeta: meta("nfs-2")},
)
deps, err := CephClusterDependents(c, ns)
assert.NoError(t, err)
assert.False(t, deps.Empty())
assert.ElementsMatch(t, []string{"CephNFS"}, deps.PluralKinds())
assert.ElementsMatch(t, []string{"nfs-1", "nfs-2"}, deps.OfKind("CephNFS"))
})
t.Run("CephClients", func(t *testing.T) {
c = newClusterdCtx(
&cephv1.CephClient{ObjectMeta: meta("client-1")},
&cephv1.CephClient{ObjectMeta: meta("client-2")},
&cephv1.CephClient{ObjectMeta: meta("client-3")},
)
deps, err := CephClusterDependents(c, ns)
assert.NoError(t, err)
assert.False(t, deps.Empty())
assert.ElementsMatch(t, []string{"CephClient"}, deps.PluralKinds())
assert.ElementsMatch(t, []string{"client-1", "client-2", "client-3"}, deps.OfKind("CephClient"))
})
t.Run("CephBucketTopics", func(t *testing.T) {
c = newClusterdCtx(
&cephv1.CephBucketTopic{ObjectMeta: meta("topic-1")},
&cephv1.CephBucketTopic{ObjectMeta: meta("topic-2")},
&cephv1.CephBucketTopic{ObjectMeta: meta("topic-3")},
)
deps, err := CephClusterDependents(c, ns)
assert.NoError(t, err)
assert.False(t, deps.Empty())
assert.ElementsMatch(t, []string{"CephBucketTopic"}, deps.PluralKinds())
assert.ElementsMatch(t, []string{"topic-1", "topic-2", "topic-3"}, deps.OfKind("CephBucketTopic"))
})
t.Run("CephBucketNotifications", func(t *testing.T) {
c = newClusterdCtx(
&cephv1.CephBucketNotification{ObjectMeta: meta("notif-1")},
&cephv1.CephBucketNotification{ObjectMeta: meta("notif-2")},
&cephv1.CephBucketNotification{ObjectMeta: meta("notif-3")},
)
deps, err := CephClusterDependents(c, ns)
assert.NoError(t, err)
assert.False(t, deps.Empty())
assert.ElementsMatch(t, []string{"CephBucketNotification"}, deps.PluralKinds())
assert.ElementsMatch(t, []string{"notif-1", "notif-2", "notif-3"}, deps.OfKind("CephBucketNotification"))
})
t.Run("All", func(t *testing.T) {
c = newClusterdCtx(
&cephv1.CephBlockPool{ObjectMeta: meta("pool-1")},
&cephv1.CephRBDMirror{ObjectMeta: meta("rbdmirror-1")},
&cephv1.CephRBDMirror{ObjectMeta: meta("rbdmirror-2")},
&cephv1.CephFilesystem{ObjectMeta: meta("filesystem-1")},
&cephv1.CephFilesystemMirror{ObjectMeta: meta("fsmirror-1")},
&cephv1.CephFilesystemMirror{ObjectMeta: meta("fsmirror-2")},
&cephv1.CephObjectStore{ObjectMeta: meta("objectstore-1")},
&cephv1.CephObjectStoreUser{ObjectMeta: meta("u1")},
&cephv1.CephObjectZone{ObjectMeta: meta("zone-1")},
&cephv1.CephObjectZoneGroup{ObjectMeta: meta("group-1")},
&cephv1.CephObjectRealm{ObjectMeta: meta("realm-1")},
&cephv1.CephNFS{ObjectMeta: meta("nfs-1")},
&cephv1.CephClient{ObjectMeta: meta("client-1")},
&cephv1.CephBucketTopic{ObjectMeta: meta("topic-1")},
&cephv1.CephBucketNotification{ObjectMeta: meta("notif-1")},
)
deps, err := CephClusterDependents(c, ns)
assert.NoError(t, err)
assert.False(t, deps.Empty())
assert.ElementsMatch(t, []string{"CephBlockPool", "CephRBDMirror", "CephFilesystem",
"CephFilesystemMirror", "CephObjectStore", "CephObjectStoreUser", "CephObjectZone",
"CephObjectZoneGroup", "CephObjectRealm", "CephNFS", "CephClient", "CephBucketTopic", "CephBucketNotification"}, deps.PluralKinds())
assert.ElementsMatch(t, []string{"pool-1"}, deps.OfKind("CephBlockPool"))
assert.ElementsMatch(t, []string{"rbdmirror-1", "rbdmirror-2"}, deps.OfKind("CephRBDMirror"))
assert.ElementsMatch(t, []string{"filesystem-1"}, deps.OfKind("CephFilesystem"))
assert.ElementsMatch(t, []string{"fsmirror-1", "fsmirror-2"}, deps.OfKind("CephFilesystemMirror"))
assert.ElementsMatch(t, []string{"objectstore-1"}, deps.OfKind("CephObjectStore"))
assert.ElementsMatch(t, []string{"u1"}, deps.OfKind("CephObjectStoreUser"))
assert.ElementsMatch(t, []string{"zone-1"}, deps.OfKind("CephObjectZone"))
assert.ElementsMatch(t, []string{"group-1"}, deps.OfKind("CephObjectZoneGroup"))
assert.ElementsMatch(t, []string{"realm-1"}, deps.OfKind("CephObjectRealm"))
assert.ElementsMatch(t, []string{"nfs-1"}, deps.OfKind("CephNFS"))
assert.ElementsMatch(t, []string{"client-1"}, deps.OfKind("CephClient"))
assert.ElementsMatch(t, []string{"topic-1"}, deps.OfKind("CephBucketTopic"))
assert.ElementsMatch(t, []string{"notif-1"}, deps.OfKind("CephBucketNotification"))
t.Run("and no dependencies in another namespace", func(t *testing.T) {
deps, err := CephClusterDependents(c, "other-namespace")
assert.NoError(t, err)
assert.True(t, deps.Empty())
})
})
// TODO: how do we get this to return errors without a reactor? Do we need to add reactors
// to controller-runtime?
// Keep the below test commented-out until we can check off the above TODO. For now we will have
// to assume the errors are handled properly.
// t.Run("With errors", func(t *testing.T) {
// // // add reactor to cause failures when listing block and nfs (but not object, fs, or any others)
// // var listReactor k8stesting.ReactionFunc = func(action k8stesting.Action) (handled bool, ret runtime.Object, err error) {
// // r := action.GetResource().Resource
// // if r == "cephblockpools" || r == "cephnfses" {
// // return true, nil, errors.Errorf("fake error listing %q", r)
// // }
// // return false, nil, nil
// // }
// // dynInt.PrependReactor("list", "*", listReactor)
// client := fakeclient.NewClientBuilder().WithScheme(scheme).WithObjects(
// &cephv1.CephBlockPool{ObjectMeta: meta("pool-1")},
// &cephv1.CephFilesystem{ObjectMeta: meta("filesystem-1")},
// &cephv1.CephObjectStore{ObjectMeta: meta("objectstore-1")},
// ).Build()
// c := &clusterd.Context{
// Client: client,
// }
// deps, err := CephClusterDependents(c, ns)
// assert.Error(t, err)
// assert.Contains(t, err.Error(), "CephBlockPool")
// assert.Contains(t, err.Error(), "CephNFS")
// assert.False(t, deps.Empty())
// assert.ElementsMatch(t, []string{"CephFilesystem", "CephObjectStore"}, deps.PluralKinds())
// assert.ElementsMatch(t, []string{"filesystem-1"}, deps.OfKind("CephFilesystem"))
// assert.ElementsMatch(t, []string{"objectstore-1"}, deps.OfKind("CephObjectStore"))
// })
}