Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

StorageProfile unit tests #2288

Merged
merged 2 commits into from
Jan 29, 2024
Merged
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
259 changes: 252 additions & 7 deletions controllers/storageclassrequest/storageclassrequest_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package storageclassrequest
import (
"context"
"fmt"
"strings"
"testing"

v1 "github.com/red-hat-storage/ocs-operator/api/v4/v1"
Expand All @@ -32,26 +33,76 @@ import (
"sigs.k8s.io/controller-runtime/pkg/reconcile"
)

const (
pgAutoscaleMode = "pg_autoscale_mode"
pgNum = "pg_num"
pgpNum = "pgp_num"
namespaceName = "test-ns"
deviceClass = "ssd"
storageProfileKind = "StorageProfile"
)

var fakeStorageProfile = &v1.StorageProfile{
TypeMeta: metav1.TypeMeta{Kind: storageProfileKind},
ObjectMeta: metav1.ObjectMeta{
Name: "medium",
Namespace: "test-ns",
Namespace: namespaceName,
},
Spec: v1.StorageProfileSpec{
DeviceClass: deviceClass,
},
}

var validStorageProfile = &v1.StorageProfile{
TypeMeta: metav1.TypeMeta{Kind: storageProfileKind},
ObjectMeta: metav1.ObjectMeta{
Name: "valid",
Namespace: namespaceName,
},
Spec: v1.StorageProfileSpec{
DeviceClass: "ssd",
DeviceClass: deviceClass,
BlockPoolConfiguration: v1.BlockPoolConfigurationSpec{
Parameters: map[string]string{
pgAutoscaleMode: "on",
pgNum: "128",
pgpNum: "128",
},
},
},
Status: v1.StorageProfileStatus{Phase: ""},
}

// A rejected StorageProfile is one that is invalid due to having a blank device class field and is set to
// Rejected in its phase.
var rejectedStorageProfile = &v1.StorageProfile{
raaizik marked this conversation as resolved.
Show resolved Hide resolved
jarrpa marked this conversation as resolved.
Show resolved Hide resolved
TypeMeta: metav1.TypeMeta{Kind: storageProfileKind},
ObjectMeta: metav1.ObjectMeta{
Name: "rejected",
Namespace: namespaceName,
},
Spec: v1.StorageProfileSpec{
DeviceClass: "",
BlockPoolConfiguration: v1.BlockPoolConfigurationSpec{
Parameters: map[string]string{
pgAutoscaleMode: "on",
pgNum: "128",
pgpNum: "128",
},
},
},
Status: v1.StorageProfileStatus{Phase: ""},
}

var fakeStorageCluster = &v1.StorageCluster{
ObjectMeta: metav1.ObjectMeta{
Name: "test-storagecluster",
Namespace: "test-ns",
Namespace: namespaceName,
},
Spec: v1.StorageClusterSpec{
DefaultStorageProfile: fakeStorageProfile.Name,
StorageDeviceSets: []v1.StorageDeviceSet{
{
DeviceClass: "ssd",
DeviceClass: deviceClass,
},
},
},
Expand All @@ -63,7 +114,7 @@ var fakeStorageCluster = &v1.StorageCluster{
var fakeStorageConsumer = &v1alpha1.StorageConsumer{
ObjectMeta: metav1.ObjectMeta{
Name: "test-consumer",
Namespace: "test-ns",
Namespace: namespaceName,
},
}

Expand All @@ -76,7 +127,7 @@ var fakeCephFs = &rookCephv1.CephFilesystem{
DataPools: []rookCephv1.NamedPoolSpec{
{
PoolSpec: rookCephv1.PoolSpec{
DeviceClass: "ssd",
DeviceClass: deviceClass,
},
},
},
Expand Down Expand Up @@ -109,7 +160,7 @@ func createFakeReconciler(t *testing.T) StorageClassRequestReconciler {

fakeReconciler.Scheme = createFakeScheme(t)
fakeReconciler.log = log.Log.WithName("controller_storagecluster_test")
fakeReconciler.OperatorNamespace = "test-ns"
fakeReconciler.OperatorNamespace = namespaceName
fakeReconciler.StorageClassRequest = &v1alpha1.StorageClassRequest{}
fakeReconciler.cephResourcesByName = map[string]*v1alpha1.CephResourcesSpec{}

Expand Down Expand Up @@ -218,6 +269,200 @@ func TestProfileReconcile(t *testing.T) {
assert.NoError(t, err, caseLabel)
}

func TestStorageProfileCephBlockPool(t *testing.T) {
var err error
var caseCounter int

var primaryTestCases = []struct {
label string
expectedPoolName string
failureExpected bool
createObjects []runtime.Object
storageProfile *v1.StorageProfile
}{
{
label: "valid profile",
expectedPoolName: "test-valid-blockpool",
failureExpected: false,
storageProfile: validStorageProfile,
createObjects: []runtime.Object{
&rookCephv1.CephBlockPool{
ObjectMeta: metav1.ObjectMeta{
Name: "test-valid-blockpool",
Namespace: namespaceName,
Labels: map[string]string{
controllers.StorageConsumerNameLabel: fakeStorageConsumer.Name,
controllers.StorageProfileSpecLabel: validStorageProfile.GetSpecHash(),
},
}, Spec: rookCephv1.NamedBlockPoolSpec{
Name: "spec",
raaizik marked this conversation as resolved.
Show resolved Hide resolved
PoolSpec: rookCephv1.PoolSpec{
FailureDomain: "zone",
DeviceClass: deviceClass,
Parameters: map[string]string{},
},
},
},
},
},
{
label: "rejected profile",
expectedPoolName: "test-rejected-blockpool",
failureExpected: true,
storageProfile: rejectedStorageProfile,
createObjects: []runtime.Object{
&rookCephv1.CephBlockPool{
ObjectMeta: metav1.ObjectMeta{
Name: "test-rejected-blockpool",
Namespace: namespaceName,
Labels: map[string]string{
controllers.StorageConsumerNameLabel: fakeStorageConsumer.Name,
controllers.StorageProfileSpecLabel: rejectedStorageProfile.GetSpecHash(),
},
}, Spec: rookCephv1.NamedBlockPoolSpec{
Name: "spec",
PoolSpec: rookCephv1.PoolSpec{
FailureDomain: "zone",
raaizik marked this conversation as resolved.
Show resolved Hide resolved
DeviceClass: deviceClass,
Parameters: map[string]string{},
},
},
},
},
},
}

for _, c := range primaryTestCases {
caseCounter++
caseLabel := fmt.Sprintf("Case %d: %s", caseCounter, c.label)
fmt.Println(caseLabel)

r := createFakeReconciler(t)
r.storageCluster.Spec.DefaultStorageProfile = c.storageProfile.Name
r.StorageClassRequest.Spec.Type = "blockpool"

r.StorageClassRequest.Spec.StorageProfile = c.storageProfile.Name

c.createObjects = append(c.createObjects, c.storageProfile)
c.createObjects = append(c.createObjects, fakeStorageConsumer)

fakeClient := fake.NewClientBuilder().WithScheme(r.Scheme).WithRuntimeObjects(c.createObjects...)
r.Client = fakeClient.Build()

_, err = r.reconcilePhases()
if c.failureExpected {
assert.Error(t, err, caseLabel)
continue
}
assert.NoError(t, err, caseLabel)

assert.Equal(t, c.expectedPoolName, r.cephBlockPool.Name, caseLabel)

if strings.Contains(c.expectedPoolName, "valid") {
raaizik marked this conversation as resolved.
Show resolved Hide resolved
expectedStorageProfileParameters := validStorageProfile.Spec.BlockPoolConfiguration.Parameters
actualBlockPoolParameters := r.cephBlockPool.Spec.Parameters
assert.Equal(t, expectedStorageProfileParameters, actualBlockPoolParameters, caseLabel)
assert.NotEqual(t, v1.StorageProfilePhaseRejected, c.storageProfile.Status.Phase)
} else {
actualBlockPoolParameters := r.cephBlockPool.Spec.Parameters
assert.Equal(t, v1.StorageProfilePhaseRejected, c.storageProfile.Status.Phase)
assert.Nil(t, actualBlockPoolParameters, caseLabel)
}
}

}

func TestStorageProfileCephFsSubVolGroup(t *testing.T) {
var err error
var caseCounter int

var primaryTestCases = []struct {
label string
expectedGroupName string
failureExpected bool
createObjects []runtime.Object
cephResources []*v1alpha1.CephResourcesSpec
storageProfile *v1.StorageProfile
cephFs *rookCephv1.CephFilesystem
}{
{
label: "valid profile",
expectedGroupName: "test-subvolgroup",
raaizik marked this conversation as resolved.
Show resolved Hide resolved
storageProfile: fakeStorageProfile,
cephFs: fakeCephFs,
failureExpected: false,
cephResources: []*v1alpha1.CephResourcesSpec{
{
Name: "test-subvolgroup",
Kind: "CephFilesystemSubVolumeGroup",
},
},
createObjects: []runtime.Object{
&rookCephv1.CephFilesystemSubVolumeGroup{
ObjectMeta: metav1.ObjectMeta{
Name: "test-subvolgroup",
Namespace: namespaceName,
},
Status: &rookCephv1.CephFilesystemSubVolumeGroupStatus{},
},
},
},
{
label: "rejected profile",
expectedGroupName: "test-subvolgroup",
storageProfile: rejectedStorageProfile,
cephFs: fakeCephFs,
failureExpected: true,
cephResources: []*v1alpha1.CephResourcesSpec{
{
Name: "test-subvolgroup",
Kind: "CephFilesystemSubVolumeGroup",
},
},
createObjects: []runtime.Object{
&rookCephv1.CephFilesystemSubVolumeGroup{
ObjectMeta: metav1.ObjectMeta{
Name: "test-subvolgroup",
Namespace: namespaceName,
},
Status: &rookCephv1.CephFilesystemSubVolumeGroupStatus{},
},
},
},
}

for _, c := range primaryTestCases {
caseCounter++
caseLabel := fmt.Sprintf("Case %d: %s", caseCounter, c.label)
fmt.Println(caseLabel)

r := createFakeReconciler(t)
if strings.Contains(c.label, "rejected") {
r.storageCluster.Spec.DefaultStorageProfile = rejectedStorageProfile.Name
}

r.StorageClassRequest.Status.CephResources = c.cephResources
r.StorageClassRequest.Spec.Type = "sharedfilesystem"
r.StorageClassRequest.Spec.StorageProfile = c.storageProfile.Name

c.createObjects = append(c.createObjects, c.cephFs)
c.createObjects = append(c.createObjects, c.storageProfile)
c.createObjects = append(c.createObjects, fakeStorageConsumer)
fakeClient := fake.NewClientBuilder().WithScheme(r.Scheme).WithRuntimeObjects(c.createObjects...)

r.Client = fakeClient.Build()
r.StorageClassRequest.Status.CephResources = c.cephResources

_, err = r.reconcilePhases()
if c.failureExpected {
assert.Error(t, err, caseLabel)
continue
}
assert.NoError(t, err, caseLabel)
raaizik marked this conversation as resolved.
Show resolved Hide resolved
assert.Equal(t, c.expectedGroupName, r.cephFilesystemSubVolumeGroup.Name, caseLabel)
}
}

func TestCephBlockPool(t *testing.T) {
var err error
var caseCounter int
Expand Down
Loading
Loading