Files
my-rook-config/pkg/operator/ceph/config/store_test.go
T
Blaine Gardner 4eb4fb7aa6 ceph mds: configure completely from operator
Configure the Ceph mds daemon completely from the operator a la the
recent changes to the Ceph mon and mgr operators.

Create the mds deployments first and then
create the keyring secrets for them with their owner reference as the
corresponding deployment. This will mean that the secrets do not need to
be micromanaged. When the deployment is deleted, the secret is also
deleted. This has not been necessary for the mons or the manager since
the mons share a keyring with a lifespan of the cluster, as does the
mgr, which currently has single-mgr support only.

Signed-off-by: Blaine Gardner <blaine.gardner@suse.com>
2019-02-28 12:31:43 -07:00

221 lines
7.8 KiB
Go

/*
Copyright 2019 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 config
import (
"bufio"
"fmt"
"path"
"regexp"
"strings"
"testing"
"github.com/rook/rook/pkg/clusterd"
cephconfig "github.com/rook/rook/pkg/daemon/ceph/config"
"github.com/rook/rook/pkg/operator/k8sutil"
testop "github.com/rook/rook/pkg/operator/test"
"github.com/stretchr/testify/assert"
"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func TestStore(t *testing.T) {
clientset := testop.New(1)
ctx := &clusterd.Context{
Clientset: clientset,
}
ns := "rook-ceph"
owner := metav1.OwnerReference{}
s := GetStore(ctx, ns, &owner)
var previousConfigText = ""
var recentConfigText = ""
assertConfigStore := func(ci *cephconfig.ClusterInfo) {
c, e := clientset.CoreV1().ConfigMaps(ns).Get(storeName, metav1.GetOptions{})
assert.NoError(t, e)
previousConfigText = recentConfigText
recentConfigText = c.Data[confFileName]
assert.NotEqual(t, "", recentConfigText)
sec, e := clientset.CoreV1().Secrets(ns).Get(storeName, metav1.GetOptions{})
assert.NoError(t, e)
mh := strings.Split(sec.StringData["mon_host"], ",") // list of mon ip:port pairs in cluster
assert.Equal(t, len(ci.Monitors), len(mh))
mim := strings.Split(sec.StringData["mon_initial_members"], ",") // list of mon ids in cluster
assert.Equal(t, len(ci.Monitors), len(mim))
// make sure every mon has its id/ip:port in mon_initial_members/mon_host
for _, id := range mim {
assert.Contains(t, mh, ci.Monitors[id].Endpoint)
assert.Contains(t, mim, ci.Monitors[id].Name)
}
}
findLine := func(lineRegex, inText string) int {
scr := bufio.NewScanner(strings.NewReader(inText))
i := 1
for scr.Scan() {
m, e := regexp.Match(lineRegex, scr.Bytes())
assert.NoError(t, e)
if m {
return i
}
i++
}
return 0 // ret 0 if not found
}
i1 := testop.CreateConfigDir(1) // cluster w/ one mon
i3 := testop.CreateConfigDir(3) // same cluster w/ 3 mons
s.CreateOrUpdate(i1)
assertConfigStore(i1)
s.CreateOrUpdate(i3)
assertConfigStore(i3)
// the config should be the same regardless of how many mons there are
assert.Equal(t, previousConfigText, recentConfigText)
//
// test overrides
//
createOverrideMap(t, ctx, ns, &owner)
s.CreateOrUpdate(i3)
assertConfigStore(i3)
// configs should still be equal since the created map doesn't have data in it
assert.Equal(t, previousConfigText, recentConfigText)
updateOverrideMap(t, "", ctx, ns, &owner)
s.CreateOrUpdate(i3)
assertConfigStore(i3)
// configs should still be equal since the created map's data is blank
assert.Equal(t, previousConfigText, recentConfigText)
updateOverrideMap(t, "this is not valid ini file text", ctx, ns, &owner)
s.CreateOrUpdate(i3)
assertConfigStore(i3)
// configs should still be equal since the created map's data is invalid ini
assert.Equal(t, previousConfigText, recentConfigText)
// complicated override with overrides, new keys, new section
updateOverrideMap(t, `[global]
log_file = notreal
new_key = fake
log stderr prefix = '"debug "'
[mon]
debug_mon = makehaste
`, ctx, ns, &owner)
s.CreateOrUpdate(i3)
assertConfigStore(i3)
// Verify some simple truths about the overridden config vs the original
assert.NotEqual(t, previousConfigText, recentConfigText) // the new config has changed (finally)
l1 := findLine("log_file[[:space:]]+= ", previousConfigText) //
assert.NotZero(t, l1) // orig 'log_file = <num>' exists
l2 := findLine("log_file[[:space:]]+= notreal", recentConfigText) //
assert.Equal(t, l1, l2) // overridden debug_default still has same line num
l3 := findLine("new_key[[:space:]]+= fake", recentConfigText) //
assert.True(t, l3 > l2) // new_key should come after debug_default
l4 := findLine("log stderr prefix[[:space:]]+= \"debug \"", recentConfigText) // becomes "debug " w/o single quotes
assert.Equal(t, l3+1, l4) // ... and is 1 line after new_key
l5 := findLine("[[]mon[]]", recentConfigText) //
assert.Equal(t, l4+2, l5) // [mon] hdr comes 2 after
l6 := findLine("debug_mon[[:space:]]+= makehaste", recentConfigText) //
assert.Equal(t, l5+1, l6) // debug_mon comes 1 after
//
lg := findLine("[[]global[]]", recentConfigText) //
assert.Equal(t, 1, lg) // [global] hdr is first line
ln := findLine("[[].*[]]", strings.TrimLeft(recentConfigText, "[global]")) //
assert.Equal(t, l5, ln) // next hdr after [global] is [mon]
}
func createOverrideMap(t *testing.T,
context *clusterd.Context, namespace string, ownerRef *metav1.OwnerReference,
) {
cm := &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: k8sutil.ConfigOverrideName,
},
}
k8sutil.SetOwnerRef(context.Clientset, namespace, &cm.ObjectMeta, ownerRef)
_, err := context.Clientset.CoreV1().ConfigMaps(namespace).Create(cm)
assert.NoError(t, err)
}
func updateOverrideMap(t *testing.T, overrideText string,
context *clusterd.Context, namespace string, ownerRef *metav1.OwnerReference,
) {
cm := &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: k8sutil.ConfigOverrideName,
},
Data: map[string]string{k8sutil.ConfigOverrideVal: overrideText},
}
k8sutil.SetOwnerRef(context.Clientset, namespace, &cm.ObjectMeta, ownerRef)
_, err := context.Clientset.CoreV1().ConfigMaps(namespace).Update(cm)
assert.NoError(t, err)
}
func TestFileVolumeAndMount(t *testing.T) {
clientset := testop.New(1)
ctx := &clusterd.Context{
Clientset: clientset,
}
ns := "rook-ceph"
owner := metav1.OwnerReference{}
s := GetStore(ctx, ns, &owner)
s.CreateOrUpdate(testop.CreateConfigDir(3))
v := StoredFileVolume()
m := StoredFileVolumeMount()
// Test that the configmapped file will make it into containers with the appropriate filename at
// the location where it is expected.
assert.Equal(t, v.Name, m.Name)
assert.Equal(t, storeName, v.VolumeSource.ConfigMap.LocalObjectReference.Name)
assert.Equal(t, "/etc/ceph/ceph.conf", path.Join(m.MountPath, confFileName))
}
func TestEnvVarsAndFlags(t *testing.T) {
clientset := testop.New(1)
ctx := &clusterd.Context{
Clientset: clientset,
}
ns := "rook-ceph"
owner := metav1.OwnerReference{}
s := GetStore(ctx, ns, &owner)
s.CreateOrUpdate(testop.CreateConfigDir(3))
v := StoredMonHostEnvVars()
f := StoredMonHostEnvVarReferences().GlobalFlags()
// make sure the env var names and flags are matching pairs
mh := v[0].Name
mim := v[1].Name
assert.Contains(t, f, fmt.Sprintf("--mon-host=$(%s)", mh))
assert.Contains(t, f, fmt.Sprintf("--mon-initial-members=$(%s)", mim))
// make sure the env vars are sourced from the right place
assert.Equal(t, storeName, v[0].ValueFrom.SecretKeyRef.LocalObjectReference.Name)
assert.Equal(t, "mon_host", v[0].ValueFrom.SecretKeyRef.Key)
assert.Equal(t, storeName, v[1].ValueFrom.SecretKeyRef.LocalObjectReference.Name)
assert.Equal(t, "mon_initial_members", v[1].ValueFrom.SecretKeyRef.Key)
}