Merge pull request #5067 from leseb/misc-controller-runtime

Misc controller runtime fixes
This commit is contained in:
Sébastien Han authored and GitHub committed 2020-03-25 21:31:04 +01:00
commit f7600066da
14 files changed
+176 -106

No files matched your search

+2 -2
View File
@@ -4,7 +4,7 @@ go 1.13
require (
github.com/aws/aws-sdk-go v1.16.26
github.com/banzaicloud/k8s-objectmatcher v1.2.2
github.com/banzaicloud/k8s-objectmatcher v1.1.0
github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea
github.com/coreos/prometheus-operator v0.34.0
github.com/corpix/uarand v0.1.1 // indirect
@@ -33,7 +33,7 @@ require (
k8s.io/kube-controller-manager v0.0.0
k8s.io/kubernetes v1.17.2
k8s.io/utils v0.0.0-20191114200735-6ca3b61696b6
sigs.k8s.io/controller-runtime v0.4.0
sigs.k8s.io/controller-runtime v0.5.1
sigs.k8s.io/sig-storage-lib-external-provisioner v4.1.0+incompatible
)
+17
View File
@@ -53,6 +53,12 @@ github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:l
github.com/auth0/go-jwt-middleware v0.0.0-20170425171159-5493cabe49f7/go.mod h1:LWMyo4iOLWXHGdBki7NIht1kHru/0wM179h+d3g8ATM=
github.com/aws/aws-sdk-go v1.16.26 h1:GWkl3rkRO/JGRTWoLLIqwf7AWC4/W/1hMOUZqmX0js4=
github.com/aws/aws-sdk-go v1.16.26/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/banzaicloud/k8s-objectmatcher v1.1.0 h1:KHWn9Oxh21xsaGKBHWElkaRrr4ypCDyrh15OB1zHtAw=
github.com/banzaicloud/k8s-objectmatcher v1.1.0/go.mod h1:gGaElvgkqa0Lk1khRr+jel/nsCLfzhLnD3CEWozpk9k=
github.com/banzaicloud/k8s-objectmatcher v1.1.1 h1:OWS/mUIb7HWI27pOYdxix4xu3nekNOvmS+Y3r9L5mFE=
github.com/banzaicloud/k8s-objectmatcher v1.1.1/go.mod h1:NTk6nNix5oP7/lE/5/YxFO87+241sDmTOKvoZ9E+Muw=
github.com/banzaicloud/k8s-objectmatcher v1.2.0 h1:ogya2/veg371s8jxWV2/NAtraMLnRqX+RELWJ8275JM=
github.com/banzaicloud/k8s-objectmatcher v1.2.0/go.mod h1:+kRcvF2kyA0u8k9AvTYgtt8zhv30Gi8ITKdMWqh7j+A=
github.com/banzaicloud/k8s-objectmatcher v1.2.2 h1:WekhVqrRa/wUCPuESExwRjy5R+BDTf/s7DKP99y8MvY=
github.com/banzaicloud/k8s-objectmatcher v1.2.2/go.mod h1:+kRcvF2kyA0u8k9AvTYgtt8zhv30Gi8ITKdMWqh7j+A=
github.com/bazelbuild/bazel-gazelle v0.18.2/go.mod h1:D0ehMSbS+vesFsLGiD6JXu3mVEzOlfUl8wNnq+x/9p0=
@@ -270,6 +276,7 @@ github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4er
github.com/golang/groupcache v0.0.0-20180513044358-24b0969c4cb7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20181024230925-c65c006176ff h1:kOkM9whyQYodu09SJ6W3NCsHG7crFaJILQ22Gozp3lg=
github.com/golang/groupcache v0.0.0-20181024230925-c65c006176ff/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9 h1:uHTyIjqVhYRhLbJ8nIiOJHkEZZ+5YoOsAbD3sk82NiE=
github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.0.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
@@ -501,6 +508,8 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo=
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw=
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.3.0/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
@@ -508,6 +517,8 @@ github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.8.1 h1:C5Dqfs/LeauYDX0jJXIe2SWmwCbGzx9yF8C8xy3Lh34=
github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
@@ -665,6 +676,8 @@ go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qL
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.9.1 h1:XCJQEf3W6eZaVwhRBof6ImoYGJSITeKWsyeh3HFu/5o=
@@ -691,6 +704,7 @@ golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191119213627-4f8c1d86b1ba h1:9bFeDpN3gTqNanMVqNcoR/pJQuP5uroC3t1D7eXozTE=
golang.org/x/crypto v0.0.0-20191119213627-4f8c1d86b1ba/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -780,6 +794,7 @@ golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456 h1:ng0gs1AKnRRuEMZoTLLlbOd+C17zUDepwGQBb/n+JVg=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e h1:N7DeIrjYszNmSW409R3frPPwglRwMkXSBzwVbkOjLLA=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -967,6 +982,8 @@ mvdan.cc/unparam v0.0.0-20190209190245-fbb59629db34/go.mod h1:H6SUd1XjIs+qQCyskX
sigs.k8s.io/controller-runtime v0.2.0-beta.2/go.mod h1:TSH2R0nSz4WAlUUlNnOFcOR/VUhfwBLlmtq2X6AiQCA=
sigs.k8s.io/controller-runtime v0.4.0 h1:wATM6/m+3w8lj8FXNaO6Fs/rq/vqoOjO1Q116Z9NPsg=
sigs.k8s.io/controller-runtime v0.4.0/go.mod h1:ApC79lpY3PHW9xj/w9pj+lYkLgwAAUZwfXkME1Lajns=
sigs.k8s.io/controller-runtime v0.5.1 h1:TNidCfVoU/cs2i+9xoTcL/l7yhl0bDhYXU0NCG6wmiE=
sigs.k8s.io/controller-runtime v0.5.1/go.mod h1:Uojny7gvg55YLQnEGnPzRE3dC4ik2tRlZJgOUCWXAV4=
sigs.k8s.io/controller-tools v0.2.2-0.20190919191502-76a25b63325a/go.mod h1:8SNGuj163x/sMwydREj7ld5mIMJu1cDanIfnx6xsU70=
sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU=
sigs.k8s.io/sig-storage-lib-external-provisioner v4.1.0+incompatible h1:pp7GUmQZKI57EjGnjkY88V4QbVuMpkw/ijKXqL67EsI=
@@ -24,7 +24,6 @@ import (
cephv1 "github.com/rook/rook/pkg/apis/ceph.rook.io/v1"
"github.com/rook/rook/pkg/clusterd"
cephclient "github.com/rook/rook/pkg/daemon/ceph/client"
"github.com/rook/rook/pkg/operator/k8sutil"
kerrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -44,7 +43,7 @@ var (
)
// IsReadyToReconcile determines if a controller is ready to reconcile or not
func IsReadyToReconcile(client client.Client, clustercontext *clusterd.Context, namespacedName types.NamespacedName) (cephv1.ClusterSpec, bool, bool, reconcile.Result) {
func IsReadyToReconcile(client client.Client, clustercontext *clusterd.Context, namespacedName types.NamespacedName, controllerName string) (cephv1.ClusterSpec, bool, bool, reconcile.Result) {
namespacedName.Name = namespacedName.Namespace
cephClusterExists := true
@@ -55,34 +54,36 @@ func IsReadyToReconcile(client client.Client, clustercontext *clusterd.Context,
if err != nil {
if kerrors.IsNotFound(err) {
cephClusterExists = false
logger.Errorf("CephCluster resource %q not found in namespace %q", namespacedName.Name, namespacedName.Namespace)
return cephv1.ClusterSpec{}, false, cephClusterExists, ImmediateRetryResult
logger.Errorf("%q: CephCluster resource %q not found in namespace %q", controllerName, namespacedName.Name, namespacedName.Namespace)
return cephv1.ClusterSpec{}, false, cephClusterExists, WaitForRequeueIfCephClusterNotReady
} else if err != nil {
logger.Errorf("failed to fetch CephCluster %v", err)
logger.Errorf("%q:failed to fetch CephCluster %v", controllerName, err)
return cephv1.ClusterSpec{}, false, cephClusterExists, ImmediateRetryResult
}
}
logger.Debugf("CephCluster resource %q found in namespace %q", namespacedName.Name, namespacedName.Namespace)
logger.Debugf("%q: CephCluster resource %q found in namespace %q", controllerName, namespacedName.Name, namespacedName.Namespace)
// If the cluster is ready
if cephCluster.Status.Phase == k8sutil.ReadyStatus {
// Test a Ceph command to verify the Operator is ready
// This is done to silence errors when the operator just started and cannot reconcile yet
_, err = cephclient.Status(clustercontext, namespacedName.Namespace)
if err != nil {
if strings.Contains(err.Error(), "error calling conf_read_file") {
logger.Info("operator is not ready to run ceph command, cannot reconcile yet.")
return cephCluster.Spec, false, cephClusterExists, WaitForRequeueIfCephClusterNotReady
}
// We should not arrive there
logger.Errorf("ceph command error %v", err)
return cephCluster.Spec, false, cephClusterExists, ImmediateRetryResult
// If the cluster is healthy
// Test a Ceph command to verify the Operator is ready
// This is done to silence errors when the operator just started and cannot reconcile yet
status, err := cephclient.Status(clustercontext, namespacedName.Namespace)
if err != nil {
if strings.Contains(err.Error(), "error calling conf_read_file") {
logger.Infof("%q: operator is not ready to run ceph command, cannot reconcile yet.", controllerName)
return cephCluster.Spec, false, cephClusterExists, WaitForRequeueIfCephClusterNotReady
}
logger.Debugf("operator is ready to run ceph command, reconciling")
// We should not arrive there
logger.Errorf("%q: ceph command error %v", controllerName, err)
return cephCluster.Spec, false, cephClusterExists, ImmediateRetryResult
}
// If Ceph status is ok we can reconcile
if status.Health.Status == "HEALTH_OK" || status.Health.Status == "HEALTH_WARN" {
logger.Debugf("%q: ceph status is %q, operator is ready to run ceph command, reconciling", controllerName, status.Health.Status)
return cephCluster.Spec, true, cephClusterExists, reconcile.Result{}
}
logger.Debugf("CephCluster resource %q found in namespace %q but not ready yet", namespacedName.Name, namespacedName.Namespace)
return cephCluster.Spec, false, cephClusterExists, ImmediateRetryResult
logger.Debugf("%q: CephCluster resource %q found in namespace %q but cluster state is not appropriate %q", controllerName, namespacedName.Name, namespacedName.Namespace, status.Health.Status)
return cephCluster.Spec, false, cephClusterExists, WaitForRequeueIfCephClusterNotReady
}
+3 -5
View File
@@ -36,6 +36,7 @@ import (
kerrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
appsv1 "k8s.io/api/apps/v1"
"k8s.io/apimachinery/pkg/runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller"
@@ -54,8 +55,7 @@ var logger = capnslog.NewPackageLogger("github.com/rook/rook", controllerName)
// List of object resources to watch by the controller
var objectsToWatch = []runtime.Object{
&corev1.Secret{TypeMeta: metav1.TypeMeta{Kind: "Secret", APIVersion: corev1.SchemeGroupVersion.String()}},
// Stop watching for Deployment object until https://github.com/rook/rook/issues/5047 is fully resolved
// &appsv1.Deployment{TypeMeta: metav1.TypeMeta{Kind: "Deployment", APIVersion: appsv1.SchemeGroupVersion.String()}},
&appsv1.Deployment{TypeMeta: metav1.TypeMeta{Kind: "Deployment", APIVersion: appsv1.SchemeGroupVersion.String()}},
}
var cephFilesystemKind = reflect.TypeOf(cephv1.CephFilesystem{}).Name()
@@ -159,7 +159,7 @@ func (r *ReconcileCephFilesystem) reconcile(request reconcile.Request) (reconcil
}
// Make sure a CephCluster is present otherwise do nothing
cephClusterSpec, isReadyToReconcile, cephClusterExists, reconcileResponse := opcontroller.IsReadyToReconcile(r.client, r.context, request.NamespacedName)
cephClusterSpec, isReadyToReconcile, cephClusterExists, reconcileResponse := opcontroller.IsReadyToReconcile(r.client, r.context, request.NamespacedName, controllerName)
if !isReadyToReconcile {
// This handles the case where the Ceph Cluster is gone and we want to delete that CR
// We skip the deleteFilesystem() function since everything is gone already
@@ -177,8 +177,6 @@ func (r *ReconcileCephFilesystem) reconcile(request reconcile.Request) (reconcil
// Return and do not requeue. Successful deletion.
return reconcile.Result{}, nil
}
logger.Debugf("CephCluster resource not ready in namespace %q, retrying in %q.", request.NamespacedName.Namespace, opcontroller.WaitForRequeueIfCephClusterNotReadyAfter.String())
return reconcileResponse, nil
}
r.cephClusterSpec = &cephClusterSpec
+21 -7
View File
@@ -179,13 +179,7 @@ func TestCephObjectStoreController(t *testing.T) {
executor := &exectest.MockExecutor{
MockExecuteCommandWithOutputFile: func(command, outfile string, args ...string) (string, error) {
if args[0] == "status" {
return `{"pgmap":{"num_pgs":100,"pgs_by_state":[{"state_name":"active+clean","count":100}]}}`, nil
}
if args[0] == "fs" && args[1] == "get" {
return fsGet, nil
}
if args[0] == "auth" && args[1] == "get-or-create-key" {
return mdsCephAuthGetOrCreateKey, nil
return `{"fsid":"c47cac40-9bee-4d52-823b-ccd803ba5bfe","health":{"checks":{},"status":"HEALTH_ERR"},"pgmap":{"num_pgs":100,"pgs_by_state":[{"state_name":"active+clean","count":100}]}}`, nil
}
if args[0] == "versions" {
return dummyVersionsRaw, nil
@@ -193,6 +187,7 @@ func TestCephObjectStoreController(t *testing.T) {
return "", nil
},
}
clientset := test.New(t, 3)
c := &clusterd.Context{
Executor: executor,
@@ -279,6 +274,25 @@ func TestCephObjectStoreController(t *testing.T) {
// Create a fake client to mock API calls.
cl = fake.NewFakeClientWithScheme(s, object...)
executor = &exectest.MockExecutor{
MockExecuteCommandWithOutputFile: func(command, outfile string, args ...string) (string, error) {
if args[0] == "status" {
return `{"fsid":"c47cac40-9bee-4d52-823b-ccd803ba5bfe","health":{"checks":{},"status":"HEALTH_OK"},"pgmap":{"num_pgs":100,"pgs_by_state":[{"state_name":"active+clean","count":100}]}}`, nil
}
if args[0] == "fs" && args[1] == "get" {
return fsGet, nil
}
if args[0] == "auth" && args[1] == "get-or-create-key" {
return mdsCephAuthGetOrCreateKey, nil
}
if args[0] == "versions" {
return dummyVersionsRaw, nil
}
return "", nil
},
}
c.Executor = executor
// Create a ReconcileCephFilesystem object with the scheme and fake client.
r = &ReconcileCephFilesystem{client: cl, scheme: s, context: c}
+3 -5
View File
@@ -31,6 +31,7 @@ import (
opconfig "github.com/rook/rook/pkg/operator/ceph/config"
opcontroller "github.com/rook/rook/pkg/operator/ceph/controller"
"github.com/rook/rook/pkg/operator/k8sutil"
appsv1 "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
kerrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -53,8 +54,7 @@ var logger = capnslog.NewPackageLogger("github.com/rook/rook", controllerName)
var objectsToWatch = []runtime.Object{
&v1.Service{TypeMeta: metav1.TypeMeta{Kind: "Service", APIVersion: v1.SchemeGroupVersion.String()}},
&v1.ConfigMap{TypeMeta: metav1.TypeMeta{Kind: "ConfigMap", APIVersion: v1.SchemeGroupVersion.String()}},
// Stop watching Deployments until this is resolved: https://github.com/rook/rook/issues/5047
// &appsv1.Deployment{TypeMeta: metav1.TypeMeta{Kind: "Deployment", APIVersion: appsv1.SchemeGroupVersion.String()}},
&appsv1.Deployment{TypeMeta: metav1.TypeMeta{Kind: "Deployment", APIVersion: appsv1.SchemeGroupVersion.String()}},
}
var cephNFSKind = reflect.TypeOf(cephv1.CephNFS{}).Name()
@@ -158,7 +158,7 @@ func (r *ReconcileCephNFS) reconcile(request reconcile.Request) (reconcile.Resul
}
// Make sure a CephCluster is present otherwise do nothing
cephClusterSpec, isReadyToReconcile, cephClusterExists, reconcileResponse := opcontroller.IsReadyToReconcile(r.client, r.context, request.NamespacedName)
cephClusterSpec, isReadyToReconcile, cephClusterExists, reconcileResponse := opcontroller.IsReadyToReconcile(r.client, r.context, request.NamespacedName, controllerName)
if !isReadyToReconcile {
// This handles the case where the Ceph Cluster is gone and we want to delete that CR
// We skip the deleteStore() function since everything is gone already
@@ -176,8 +176,6 @@ func (r *ReconcileCephNFS) reconcile(request reconcile.Request) (reconcile.Resul
// Return and do not requeue. Successful deletion.
return reconcile.Result{}, nil
}
logger.Debugf("CephCluster resource not ready in namespace %q, retrying in %q.", request.NamespacedName.Namespace, opcontroller.WaitForRequeueIfCephClusterNotReadyAfter.String())
return reconcileResponse, nil
}
r.cephClusterSpec = &cephClusterSpec
+35 -22
View File
@@ -107,32 +107,12 @@ func TestCephNFSController(t *testing.T) {
executor := &exectest.MockExecutor{
MockExecuteCommandWithOutputFile: func(command, outfile string, args ...string) (string, error) {
if args[0] == "status" {
return `{"pgmap":{"num_pgs":100,"pgs_by_state":[{"state_name":"active+clean","count":100}]}}`, nil
return `{"fsid":"c47cac40-9bee-4d52-823b-ccd803ba5bfe","health":{"checks":{},"status":"HEALTH_ERR"},"pgmap":{"num_pgs":100,"pgs_by_state":[{"state_name":"active+clean","count":100}]}}`, nil
}
if args[0] == "versions" {
return dummyVersionsRaw, nil
}
if args[0] == "osd" && args[1] == "pool" && args[2] == "get" {
return poolDetails, nil
}
return "", errors.New("unknown command")
},
MockExecuteCommand: func(command string, args ...string) error {
if command == "rados" {
logger.Infof("mock execute. %s. %s", command, args)
assert.Equal(t, "stat", args[6])
return nil
}
return errors.New("unknown command")
},
MockExecuteCommandWithEnv: func(env []string, command string, args ...string) error {
if command == "ganesha-rados-grace" {
logger.Infof("mock execute. %s. %s", command, args)
assert.Equal(t, "add", args[4])
assert.Len(t, env, 1)
return nil
}
return errors.New("unknown command")
return "", nil
},
}
clientset := test.New(t, 3)
@@ -221,6 +201,39 @@ func TestCephNFSController(t *testing.T) {
// Create a fake client to mock API calls.
cl = fake.NewFakeClientWithScheme(s, object...)
executor = &exectest.MockExecutor{
MockExecuteCommandWithOutputFile: func(command, outfile string, args ...string) (string, error) {
if args[0] == "status" {
return `{"fsid":"c47cac40-9bee-4d52-823b-ccd803ba5bfe","health":{"checks":{},"status":"HEALTH_OK"},"pgmap":{"num_pgs":100,"pgs_by_state":[{"state_name":"active+clean","count":100}]}}`, nil
}
if args[0] == "versions" {
return dummyVersionsRaw, nil
}
if args[0] == "osd" && args[1] == "pool" && args[2] == "get" {
return poolDetails, nil
}
return "", errors.New("unknown command")
},
MockExecuteCommand: func(command string, args ...string) error {
if command == "rados" {
logger.Infof("mock execute. %s. %s", command, args)
assert.Equal(t, "stat", args[6])
return nil
}
return errors.New("unknown command")
},
MockExecuteCommandWithEnv: func(env []string, command string, args ...string) error {
if command == "ganesha-rados-grace" {
logger.Infof("mock execute. %s. %s", command, args)
assert.Equal(t, "add", args[4])
assert.Len(t, env, 1)
return nil
}
return errors.New("unknown command")
},
}
c.Executor = executor
// Create a ReconcileCephNFS object with the scheme and fake client.
r = &ReconcileCephNFS{client: cl, scheme: s, context: c}
+3 -4
View File
@@ -31,6 +31,7 @@ import (
opconfig "github.com/rook/rook/pkg/operator/ceph/config"
opcontroller "github.com/rook/rook/pkg/operator/ceph/controller"
"github.com/rook/rook/pkg/operator/k8sutil"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
kerrors "k8s.io/apimachinery/pkg/api/errors"
@@ -54,8 +55,7 @@ var logger = capnslog.NewPackageLogger("github.com/rook/rook", controllerName)
var objectsToWatch = []runtime.Object{
&corev1.Secret{TypeMeta: metav1.TypeMeta{Kind: "Secret", APIVersion: corev1.SchemeGroupVersion.String()}},
&v1.Service{TypeMeta: metav1.TypeMeta{Kind: "Service", APIVersion: v1.SchemeGroupVersion.String()}},
// Stop watching for Deployment object until https://github.com/rook/rook/issues/5047 is fully resolved
// &appsv1.Deployment{TypeMeta: metav1.TypeMeta{Kind: "Deployment", APIVersion: appsv1.SchemeGroupVersion.String()}},
&appsv1.Deployment{TypeMeta: metav1.TypeMeta{Kind: "Deployment", APIVersion: appsv1.SchemeGroupVersion.String()}},
}
var cephObjectStoreKind = reflect.TypeOf(cephv1.CephObjectStore{}).Name()
@@ -159,7 +159,7 @@ func (r *ReconcileCephObjectStore) reconcile(request reconcile.Request) (reconci
}
// Make sure a CephCluster is present otherwise do nothing
cephClusterSpec, isReadyToReconcile, cephClusterExists, reconcileResponse := opcontroller.IsReadyToReconcile(r.client, r.context, request.NamespacedName)
cephClusterSpec, isReadyToReconcile, cephClusterExists, reconcileResponse := opcontroller.IsReadyToReconcile(r.client, r.context, request.NamespacedName, controllerName)
if !isReadyToReconcile {
// This handles the case where the Ceph Cluster is gone and we want to delete that CR
// We skip the deleteStore() function since everything is gone already
@@ -178,7 +178,6 @@ func (r *ReconcileCephObjectStore) reconcile(request reconcile.Request) (reconci
return reconcile.Result{}, nil
}
logger.Debugf("CephCluster resource not ready in namespace %q, retrying in %q.", request.NamespacedName.Namespace, opcontroller.WaitForRequeueIfCephClusterNotReadyAfter.String())
return reconcileResponse, nil
}
r.cephClusterSpec = &cephClusterSpec
+33 -22
View File
@@ -174,31 +174,13 @@ func TestCephObjectStoreController(t *testing.T) {
executor := &exectest.MockExecutor{
MockExecuteCommandWithOutputFile: func(command, outfile string, args ...string) (string, error) {
if args[0] == "status" {
return `{"pgmap":{"num_pgs":100,"pgs_by_state":[{"state_name":"active+clean","count":100}]}}`, nil
}
if args[0] == "auth" && args[1] == "get-or-create-key" {
return rgwCephAuthGetOrCreateKey, nil
return `{"fsid":"c47cac40-9bee-4d52-823b-ccd803ba5bfe","health":{"checks":{},"status":"HEALTH_ERR"},"pgmap":{"num_pgs":100,"pgs_by_state":[{"state_name":"active+clean","count":100}]}}`, nil
}
if args[0] == "versions" {
return dummyVersionsRaw, nil
}
return "", nil
},
MockExecuteCommandWithOutput: func(command string, args ...string) (string, error) {
if args[0] == "realm" && args[1] == "list" {
return realmListJSON, nil
}
if args[0] == "realm" && args[1] == "get" {
return realmGetJSON, nil
}
if args[0] == "zonegroup" && args[1] == "get" {
return zoneGroupGetJSON, nil
}
if args[0] == "zone" && args[1] == "get" {
return zoneGetJSON, nil
}
return "", nil
},
}
clientset := test.New(t, 3)
c := &clusterd.Context{
@@ -280,12 +262,41 @@ func TestCephObjectStoreController(t *testing.T) {
_, err = c.Clientset.CoreV1().Secrets(namespace).Create(secret)
assert.NoError(t, err)
// Add ready status to the CephCluster
cephCluster.Status.Phase = k8sutil.ReadyStatus
// Create a fake client to mock API calls.
cl = fake.NewFakeClientWithScheme(s, object...)
// Override executor with the new ceph status and more content
executor = &exectest.MockExecutor{
MockExecuteCommandWithOutputFile: func(command, outfile string, args ...string) (string, error) {
if args[0] == "status" {
return `{"fsid":"c47cac40-9bee-4d52-823b-ccd803ba5bfe","health":{"checks":{},"status":"HEALTH_OK"},"pgmap":{"num_pgs":100,"pgs_by_state":[{"state_name":"active+clean","count":100}]}}`, nil
}
if args[0] == "auth" && args[1] == "get-or-create-key" {
return rgwCephAuthGetOrCreateKey, nil
}
if args[0] == "versions" {
return dummyVersionsRaw, nil
}
return "", nil
},
MockExecuteCommandWithOutput: func(command string, args ...string) (string, error) {
if args[0] == "realm" && args[1] == "list" {
return realmListJSON, nil
}
if args[0] == "realm" && args[1] == "get" {
return realmGetJSON, nil
}
if args[0] == "zonegroup" && args[1] == "get" {
return zoneGroupGetJSON, nil
}
if args[0] == "zone" && args[1] == "get" {
return zoneGetJSON, nil
}
return "", nil
},
}
c.Executor = executor
// Create a ReconcileCephObjectStore object with the scheme and fake client.
r = &ReconcileCephObjectStore{client: cl, scheme: s, context: c}
+1 -3
View File
@@ -151,7 +151,7 @@ func (r *ReconcileObjectStoreUser) reconcile(request reconcile.Request) (reconci
}
// Make sure a CephCluster is present otherwise do nothing
_, isReadyToReconcile, cephClusterExists, reconcileResponse := opcontroller.IsReadyToReconcile(r.client, r.context, request.NamespacedName)
_, isReadyToReconcile, cephClusterExists, reconcileResponse := opcontroller.IsReadyToReconcile(r.client, r.context, request.NamespacedName, controllerName)
if !isReadyToReconcile {
// This handles the case where the Ceph Cluster is gone and we want to delete that CR
// We skip the deleteUser() function since everything is gone already
@@ -169,8 +169,6 @@ func (r *ReconcileObjectStoreUser) reconcile(request reconcile.Request) (reconci
// Return and do not requeue. Successful deletion.
return reconcile.Result{}, nil
}
logger.Debugf("CephCluster resource not ready in namespace %q, retrying in %q.", request.NamespacedName.Namespace, opcontroller.WaitForRequeueIfCephClusterNotReadyAfter.String())
return reconcileResponse, nil
}
@@ -118,13 +118,7 @@ func TestCephObjectStoreUserController(t *testing.T) {
executor := &exectest.MockExecutor{
MockExecuteCommandWithOutputFile: func(command, outfile string, args ...string) (string, error) {
if args[0] == "status" {
return `{"pgmap":{"num_pgs":100,"pgs_by_state":[{"state_name":"active+clean","count":100}]}}`, nil
}
return "", nil
},
MockExecuteCommandWithOutput: func(command string, args ...string) (string, error) {
if args[0] == "user" {
return userCreateJSON, nil
return `{"fsid":"c47cac40-9bee-4d52-823b-ccd803ba5bfe","health":{"checks":{},"status":"HEALTH_ERR"},"pgmap":{"num_pgs":100,"pgs_by_state":[{"state_name":"active+clean","count":100}]}}`, nil
}
return "", nil
},
@@ -190,6 +184,23 @@ func TestCephObjectStoreUserController(t *testing.T) {
cephCluster.Status.Phase = k8sutil.ReadyStatus
// Create a fake client to mock API calls.
cl = fake.NewFakeClientWithScheme(s, object...)
executor = &exectest.MockExecutor{
MockExecuteCommandWithOutputFile: func(command, outfile string, args ...string) (string, error) {
if args[0] == "status" {
return `{"fsid":"c47cac40-9bee-4d52-823b-ccd803ba5bfe","health":{"checks":{},"status":"HEALTH_OK"},"pgmap":{"num_pgs":100,"pgs_by_state":[{"state_name":"active+clean","count":100}]}}`, nil
}
return "", nil
},
MockExecuteCommandWithOutput: func(command string, args ...string) (string, error) {
if args[0] == "user" {
return userCreateJSON, nil
}
return "", nil
},
}
c.Executor = executor
// Create a ReconcileObjectStoreUser object with the scheme and fake client.
r = &ReconcileObjectStoreUser{client: cl, scheme: s, context: c}
+1 -3
View File
@@ -141,7 +141,7 @@ func (r *ReconcileCephBlockPool) reconcile(request reconcile.Request) (reconcile
}
// Make sure a CephCluster is present otherwise do nothing
_, isReadyToReconcile, cephClusterExists, reconcileResponse := opcontroller.IsReadyToReconcile(r.client, r.context, request.NamespacedName)
_, isReadyToReconcile, cephClusterExists, reconcileResponse := opcontroller.IsReadyToReconcile(r.client, r.context, request.NamespacedName, controllerName)
if !isReadyToReconcile {
// This handles the case where the Ceph Cluster is gone and we want to delete that CR
// We skip the deletePool() function since everything is gone already
@@ -159,8 +159,6 @@ func (r *ReconcileCephBlockPool) reconcile(request reconcile.Request) (reconcile
// Return and do not requeue. Successful deletion.
return reconcile.Result{}, nil
}
logger.Debugf("CephCluster resource not ready in namespace %q, retrying in %q.", request.NamespacedName.Namespace, opcontroller.WaitForRequeueIfCephClusterNotReadyAfter.String())
return reconcileResponse, nil
}
+13 -1
View File
@@ -238,7 +238,7 @@ func TestCephBlockPoolController(t *testing.T) {
executor := &exectest.MockExecutor{
MockExecuteCommandWithOutputFile: func(command, outfile string, args ...string) (string, error) {
if args[0] == "status" {
return `{"pgmap":{"num_pgs":100,"pgs_by_state":[{"state_name":"active+clean","count":100}]}}`, nil
return `{"fsid":"c47cac40-9bee-4d52-823b-ccd803ba5bfe","health":{"checks":{},"status":"HEALTH_ERR"},"pgmap":{"num_pgs":100,"pgs_by_state":[{"state_name":"active+clean","count":100}]}}`, nil
}
return "", nil
@@ -313,6 +313,18 @@ func TestCephBlockPoolController(t *testing.T) {
}
// Create a fake client to mock API calls.
cl = fake.NewFakeClient(objects...)
executor = &exectest.MockExecutor{
MockExecuteCommandWithOutputFile: func(command, outfile string, args ...string) (string, error) {
if args[0] == "status" {
return `{"fsid":"c47cac40-9bee-4d52-823b-ccd803ba5bfe","health":{"checks":{},"status":"HEALTH_OK"},"pgmap":{"num_pgs":100,"pgs_by_state":[{"state_name":"active+clean","count":100}]}}`, nil
}
return "", nil
},
}
c.Executor = executor
// Create a ReconcileCephBlockPool object with the scheme and fake client.
r = &ReconcileCephBlockPool{client: cl, scheme: s, context: c}
+3 -3
View File
@@ -96,7 +96,7 @@ var rawContext = `{
func TestLoadMinikubeContext(t *testing.T) {
executor := &exectest.MockExecutor{
MockExecuteCommandWithOutput: func(command string, subcommand string, args ...string) (string, error) {
MockExecuteCommandWithOutput: func(command string, args ...string) (string, error) {
return fmt.Sprintf(rawContext, "minikube"), nil
}}
config, err := getKubeConfig(executor)
@@ -111,7 +111,7 @@ func TestLoadMinikubeContext(t *testing.T) {
func TestLoadDindContext(t *testing.T) {
executor := &exectest.MockExecutor{
MockExecuteCommandWithOutput: func(command string, subcommand string, args ...string) (string, error) {
MockExecuteCommandWithOutput: func(command string, args ...string) (string, error) {
return fmt.Sprintf(rawContext, "dind"), nil
}}
config, err := getKubeConfig(executor)
@@ -126,7 +126,7 @@ func TestLoadDindContext(t *testing.T) {
func TestLoadVagrantContext(t *testing.T) {
executor := &exectest.MockExecutor{
MockExecuteCommandWithOutput: func(command string, subcommand string, args ...string) (string, error) {
MockExecuteCommandWithOutput: func(command string, args ...string) (string, error) {
return fmt.Sprintf(rawContext, "vagrant-single"), nil
}}
config, err := getKubeConfig(executor)