2016-11-05 17:09:05 -07:00
|
|
|
/*
|
|
|
|
|
Copyright 2016 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.
|
|
|
|
|
*/
|
2016-09-15 13:52:55 -07:00
|
|
|
package api
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
|
|
|
|
"net/http"
|
|
|
|
|
"net/http/httptest"
|
2016-09-20 15:20:17 -07:00
|
|
|
"strings"
|
2016-09-15 13:52:55 -07:00
|
|
|
"testing"
|
|
|
|
|
|
2016-10-26 00:38:39 +02:00
|
|
|
"github.com/rook/rook/pkg/clusterd"
|
2017-12-04 08:33:19 -08:00
|
|
|
"github.com/rook/rook/pkg/daemon/ceph/mon"
|
2017-09-20 16:42:29 -07:00
|
|
|
"github.com/rook/rook/pkg/operator/test"
|
2017-06-02 13:44:54 -07:00
|
|
|
exectest "github.com/rook/rook/pkg/util/exec/test"
|
2016-09-15 13:52:55 -07:00
|
|
|
"github.com/stretchr/testify/assert"
|
2017-10-05 10:00:19 -07:00
|
|
|
"github.com/stretchr/testify/require"
|
2016-09-15 13:52:55 -07:00
|
|
|
)
|
|
|
|
|
|
2016-10-11 21:05:33 -07:00
|
|
|
const (
|
|
|
|
|
SuccessGetPoolRBDResponse = `{"pool":"rbd","pool_id":0,"size":1}{"pool":"rbd","pool_id":0,"min_size":1}{"pool":"rbd","pool_id":0,"crash_replay_interval":0}{"pool":"rbd","pool_id":0,"pg_num":2048}{"pool":"rbd","pool_id":0,"pgp_num":2048}{"pool":"rbd","pool_id":0,"crush_ruleset":0}{"pool":"rbd","pool_id":0,"hashpspool":"true"}{"pool":"rbd","pool_id":0,"nodelete":"false"}{"pool":"rbd","pool_id":0,"nopgchange":"false"}{"pool":"rbd","pool_id":0,"nosizechange":"false"}{"pool":"rbd","pool_id":0,"write_fadvise_dontneed":"false"}{"pool":"rbd","pool_id":0,"noscrub":"false"}{"pool":"rbd","pool_id":0,"nodeep-scrub":"false"}{"pool":"rbd","pool_id":0,"use_gmt_hitset":true}{"pool":"rbd","pool_id":0,"auid":0}{"pool":"rbd","pool_id":0,"min_write_recency_for_promote":0}{"pool":"rbd","pool_id":0,"fast_read":0}{"pool":"rbd","pool_id":0}{"pool":"rbd","pool_id":0}{"pool":"rbd","pool_id":0}{"pool":"rbd","pool_id":0}{"pool":"rbd","pool_id":0}{"pool":"rbd","pool_id":0}`
|
|
|
|
|
SuccessGetPoolECPool1Response = `{"pool":"ecPool1","pool_id":1,"size":3}{"pool":"ecPool1","pool_id":1,"min_size":3}{"pool":"ecPool1","pool_id":1,"crash_replay_interval":0}{"pool":"ecPool1","pool_id":1,"pg_num":100}{"pool":"ecPool1","pool_id":1,"pgp_num":100}{"pool":"ecPool1","pool_id":1,"crush_ruleset":1}{"pool":"ecPool1","pool_id":1,"hashpspool":"true"}{"pool":"ecPool1","pool_id":1,"nodelete":"false"}{"pool":"ecPool1","pool_id":1,"nopgchange":"false"}{"pool":"ecPool1","pool_id":1,"nosizechange":"false"}{"pool":"ecPool1","pool_id":1,"write_fadvise_dontneed":"false"}{"pool":"ecPool1","pool_id":1,"noscrub":"false"}{"pool":"ecPool1","pool_id":1,"nodeep-scrub":"false"}{"pool":"ecPool1","pool_id":1,"use_gmt_hitset":true}{"pool":"ecPool1","pool_id":1,"auid":0}{"pool":"ecPool1","pool_id":1,"erasure_code_profile":"ecPool1_ecprofile"}{"pool":"ecPool1","pool_id":1,"min_write_recency_for_promote":0}{"pool":"ecPool1","pool_id":1,"fast_read":0}{"pool":"ecPool1","pool_id":1}{"pool":"ecPool1","pool_id":1}{"pool":"ecPool1","pool_id":1}{"pool":"ecPool1","pool_id":1}{"pool":"ecPool1","pool_id":1}{"pool":"ecPool1","pool_id":1}`
|
|
|
|
|
)
|
|
|
|
|
|
2017-06-02 13:44:54 -07:00
|
|
|
func newTestHandler(context *clusterd.Context) *Handler {
|
2017-10-05 10:00:19 -07:00
|
|
|
context.Clientset = test.New(3)
|
|
|
|
|
clusterInfo := &mon.ClusterInfo{Name: "default"}
|
|
|
|
|
return newHandler(context, NewConfig(context, 53390, clusterInfo, clusterInfo.Name, "myversion", false))
|
2017-02-07 08:38:05 -08:00
|
|
|
}
|
|
|
|
|
|
2017-03-10 19:00:27 -08:00
|
|
|
func TestRegisterMetrics(t *testing.T) {
|
2017-10-05 10:00:19 -07:00
|
|
|
context, _ := testContext()
|
2017-03-10 19:00:27 -08:00
|
|
|
|
|
|
|
|
// create and init a new handler. even though the first attempt fails, it should retry and return no error
|
2017-06-02 13:44:54 -07:00
|
|
|
h := newTestHandler(context)
|
2017-03-10 19:00:27 -08:00
|
|
|
err := h.RegisterMetrics(0)
|
|
|
|
|
assert.Nil(t, err)
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-15 13:52:55 -07:00
|
|
|
func TestGetNodesHandler(t *testing.T) {
|
2017-10-05 10:00:19 -07:00
|
|
|
context, _ := testContext()
|
2016-10-14 14:41:15 -07:00
|
|
|
|
2016-09-15 13:52:55 -07:00
|
|
|
req, err := http.NewRequest("GET", "http://10.0.0.100/node", nil)
|
|
|
|
|
if err != nil {
|
2016-11-11 17:37:08 -08:00
|
|
|
logger.Fatal(err)
|
2016-09-15 13:52:55 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
w := httptest.NewRecorder()
|
2017-06-02 13:44:54 -07:00
|
|
|
h := newTestHandler(context)
|
2016-09-15 13:52:55 -07:00
|
|
|
|
2017-10-05 10:00:19 -07:00
|
|
|
// one node discovered
|
2016-09-15 13:52:55 -07:00
|
|
|
h.GetNodes(w, req)
|
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
2017-10-05 10:00:19 -07:00
|
|
|
response := `[{"nodeId":"","clusterName":"","publicIp":"","privateIp":"","storage":0,"lastUpdated":0,"state":0,"location":""},{"nodeId":"","clusterName":"","publicIp":"","privateIp":"","storage":0,"lastUpdated":0,"state":0,"location":""},{"nodeId":"","clusterName":"","publicIp":"","privateIp":"","storage":0,"lastUpdated":0,"state":0,"location":""}]`
|
|
|
|
|
assert.Equal(t, response, w.Body.String())
|
2016-09-23 09:21:35 -07:00
|
|
|
}
|
|
|
|
|
|
2016-09-20 15:20:17 -07:00
|
|
|
func TestGetPoolsHandler(t *testing.T) {
|
2017-10-05 10:00:19 -07:00
|
|
|
context, executor := testContext()
|
2016-10-14 14:41:15 -07:00
|
|
|
|
2016-09-20 15:20:17 -07:00
|
|
|
req, err := http.NewRequest("GET", "http://10.0.0.100/pool", nil)
|
|
|
|
|
if err != nil {
|
2016-11-11 17:37:08 -08:00
|
|
|
logger.Fatal(err)
|
2016-09-20 15:20:17 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// first return no storage pools
|
2017-08-07 10:58:52 -07:00
|
|
|
executor.MockExecuteCommandWithOutputFile = func(debug bool, actionName string, command string, outFileArg string, args ...string) (string, error) {
|
2017-06-14 16:07:36 -07:00
|
|
|
switch {
|
|
|
|
|
case args[0] == "osd" && args[1] == "lspools":
|
|
|
|
|
return `[]`, nil
|
|
|
|
|
}
|
|
|
|
|
return "", fmt.Errorf("unexpected ceph command '%v'", args)
|
|
|
|
|
}
|
2016-09-20 15:20:17 -07:00
|
|
|
|
|
|
|
|
// no storage pools will be returned, should be empty output
|
2017-06-14 16:07:36 -07:00
|
|
|
w := httptest.NewRecorder()
|
2017-06-02 13:44:54 -07:00
|
|
|
h := newTestHandler(context)
|
2016-09-20 15:20:17 -07:00
|
|
|
h.GetPools(w, req)
|
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
|
|
|
assert.Equal(t, `[]`, w.Body.String())
|
|
|
|
|
|
|
|
|
|
// now return some storage pools from the ceph connection
|
|
|
|
|
w = httptest.NewRecorder()
|
2017-08-07 10:58:52 -07:00
|
|
|
executor.MockExecuteCommandWithOutputFile = func(debug bool, actionName string, command string, outFileArg string, args ...string) (string, error) {
|
2017-06-06 12:58:09 -07:00
|
|
|
switch {
|
|
|
|
|
case args[0] == "osd" && args[1] == "lspools":
|
|
|
|
|
return `[{"poolnum":0,"poolname":"rbd"},{"poolnum":1,"poolname":"ecPool1"}]`, nil
|
|
|
|
|
case args[0] == "osd" && args[1] == "pool" && args[2] == "get":
|
2017-06-14 16:07:36 -07:00
|
|
|
if args[3] == "rbd" {
|
2017-06-06 12:58:09 -07:00
|
|
|
return SuccessGetPoolRBDResponse, nil
|
2017-06-14 16:07:36 -07:00
|
|
|
} else if args[3] == "ecPool1" {
|
2017-06-06 12:58:09 -07:00
|
|
|
return SuccessGetPoolECPool1Response, nil
|
2016-09-20 15:20:17 -07:00
|
|
|
}
|
2017-06-06 12:58:09 -07:00
|
|
|
case args[1] == "erasure-code-profile" && args[2] == "ls":
|
|
|
|
|
return `["default","ecPool1_ecprofile"]`, nil
|
|
|
|
|
case args[1] == "erasure-code-profile" && args[2] == "get":
|
2017-06-14 16:07:36 -07:00
|
|
|
if args[3] == "default" {
|
2017-06-06 12:58:09 -07:00
|
|
|
return `{"k":"2","m":"1","plugin":"jerasure","technique":"reed_sol_van"}`, nil
|
2017-06-14 16:07:36 -07:00
|
|
|
} else if args[3] == "ecPool1_ecprofile" {
|
2017-06-06 12:58:09 -07:00
|
|
|
return `{"jerasure-per-chunk-alignment":"false","k":"2","m":"1","plugin":"jerasure","ruleset-failure-domain":"osd","ruleset-root":"default","technique":"reed_sol_van","w":"8"}`, nil
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-06-14 16:07:36 -07:00
|
|
|
return "", fmt.Errorf("unexpected ceph command '%v'", args)
|
2016-09-20 15:20:17 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// storage pools should be returned now, verify the output
|
2017-06-02 13:44:54 -07:00
|
|
|
h = newTestHandler(context)
|
2016-09-20 15:20:17 -07:00
|
|
|
h.GetPools(w, req)
|
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
2017-09-11 14:56:10 -07:00
|
|
|
assert.Equal(t, "[{\"poolName\":\"rbd\",\"poolNum\":0,\"type\":0,\"failureDomain\":\"\",\"replicatedConfig\":{\"size\":1},\"erasureCodedConfig\":{\"dataChunkCount\":0,\"codingChunkCount\":0,\"algorithm\":\"\"}},{\"poolName\":\"ecPool1\",\"poolNum\":1,\"type\":1,\"failureDomain\":\"\",\"replicatedConfig\":{\"size\":0},\"erasureCodedConfig\":{\"dataChunkCount\":2,\"codingChunkCount\":1,\"algorithm\":\"jerasure::reed_sol_van\"}}]", w.Body.String())
|
2016-09-20 15:20:17 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestGetPoolsHandlerFailure(t *testing.T) {
|
2017-10-05 10:00:19 -07:00
|
|
|
context, executor := testContext()
|
2017-09-11 14:56:10 -07:00
|
|
|
executor.MockExecuteCommandWithOutputFile = func(debug bool, actionName string, command string, outFileArg string, args ...string) (string, error) {
|
|
|
|
|
return "", fmt.Errorf("test failure")
|
|
|
|
|
}
|
2016-10-14 14:41:15 -07:00
|
|
|
|
2016-09-20 15:20:17 -07:00
|
|
|
req, err := http.NewRequest("GET", "http://10.0.0.100/pool", nil)
|
|
|
|
|
if err != nil {
|
2016-11-11 17:37:08 -08:00
|
|
|
logger.Fatal(err)
|
2016-09-20 15:20:17 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// encounter an error during GetPools
|
|
|
|
|
w := httptest.NewRecorder()
|
2017-06-02 13:44:54 -07:00
|
|
|
// TODO: Simulate failure
|
2016-09-20 15:20:17 -07:00
|
|
|
|
2017-06-02 13:44:54 -07:00
|
|
|
h := newTestHandler(context)
|
2016-09-20 15:20:17 -07:00
|
|
|
h.GetPools(w, req)
|
|
|
|
|
assert.Equal(t, http.StatusInternalServerError, w.Code)
|
|
|
|
|
assert.Equal(t, "", w.Body.String())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestCreatePoolHandler(t *testing.T) {
|
2017-10-05 10:00:19 -07:00
|
|
|
context, executor := testContext()
|
2016-10-14 14:41:15 -07:00
|
|
|
|
2016-10-11 21:05:33 -07:00
|
|
|
req, err := http.NewRequest("POST", "http://10.0.0.100/pool",
|
2017-09-11 14:56:10 -07:00
|
|
|
strings.NewReader(`{"poolName":"ecPool1","poolNum":0,"type":1,"replicatedConfig":{"size":0},"erasureCodedConfig":{"dataChunkCount":2,"codingChunkCount":1,"algorithm":""}}`))
|
2016-09-20 15:20:17 -07:00
|
|
|
if err != nil {
|
2016-11-11 17:37:08 -08:00
|
|
|
logger.Fatal(err)
|
2016-09-20 15:20:17 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
w := httptest.NewRecorder()
|
2017-08-10 18:43:45 -07:00
|
|
|
appEnabled := false
|
2017-08-07 10:58:52 -07:00
|
|
|
executor.MockExecuteCommandWithOutputFile = func(debug bool, actionName string, command string, outFileArg string, args ...string) (string, error) {
|
2017-09-11 14:56:10 -07:00
|
|
|
logger.Infof("EXECUTE: %s %v", command, args)
|
2017-06-06 12:58:09 -07:00
|
|
|
switch {
|
|
|
|
|
case args[1] == "erasure-code-profile" && args[2] == "get":
|
|
|
|
|
if args[3] == "default" {
|
|
|
|
|
return `{"k":"2","m":"1","plugin":"jerasure","technique":"reed_sol_van"}`, nil
|
2016-10-11 21:05:33 -07:00
|
|
|
}
|
2017-06-06 12:58:09 -07:00
|
|
|
case args[1] == "erasure-code-profile" && args[2] == "set":
|
|
|
|
|
return "", nil
|
|
|
|
|
case args[1] == "pool" && args[2] == "create":
|
2017-08-10 18:43:45 -07:00
|
|
|
return "", nil
|
|
|
|
|
case args[1] == "pool" && args[2] == "application" && args[3] == "enable":
|
|
|
|
|
assert.Equal(t, "ecPool1", args[4])
|
|
|
|
|
assert.Equal(t, "ecPool1", args[5])
|
|
|
|
|
appEnabled = true
|
|
|
|
|
return "", nil
|
2017-06-06 12:58:09 -07:00
|
|
|
}
|
2017-08-10 18:43:45 -07:00
|
|
|
return "", fmt.Errorf("unexpected command '%v'", args)
|
2016-09-20 15:20:17 -07:00
|
|
|
}
|
|
|
|
|
|
2017-06-02 13:44:54 -07:00
|
|
|
h := newTestHandler(context)
|
2016-09-20 15:20:17 -07:00
|
|
|
|
|
|
|
|
h.CreatePool(w, req)
|
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
2016-10-11 21:05:33 -07:00
|
|
|
assert.Equal(t, "pool 'ecPool1' created", w.Body.String())
|
2017-08-10 18:43:45 -07:00
|
|
|
assert.True(t, appEnabled)
|
2016-09-20 15:20:17 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestCreatePoolHandlerFailure(t *testing.T) {
|
2017-10-05 10:00:19 -07:00
|
|
|
context, _ := testContext()
|
2016-10-14 14:41:15 -07:00
|
|
|
|
2016-09-20 15:20:17 -07:00
|
|
|
req, err := http.NewRequest("POST", "http://10.0.0.100/pool", strings.NewReader(`{"poolname":"pool1"}`))
|
|
|
|
|
if err != nil {
|
2016-11-11 17:37:08 -08:00
|
|
|
logger.Fatal(err)
|
2016-09-20 15:20:17 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
w := httptest.NewRecorder()
|
2017-06-02 13:44:54 -07:00
|
|
|
context.Executor = &exectest.MockExecutor{
|
2017-08-07 10:58:52 -07:00
|
|
|
MockExecuteCommandWithOutputFile: func(debug bool, actionName string, command string, outFileArg string, args ...string) (string, error) {
|
2017-06-02 13:44:54 -07:00
|
|
|
return "", fmt.Errorf("mock failure to create pool1")
|
2016-09-20 15:20:17 -07:00
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-02 13:44:54 -07:00
|
|
|
h := newTestHandler(context)
|
2016-09-20 15:20:17 -07:00
|
|
|
|
|
|
|
|
h.CreatePool(w, req)
|
|
|
|
|
assert.Equal(t, http.StatusInternalServerError, w.Code)
|
|
|
|
|
assert.Equal(t, "", w.Body.String())
|
|
|
|
|
}
|
2016-09-30 12:56:56 -07:00
|
|
|
|
2016-11-28 17:38:06 -08:00
|
|
|
func TestGetClientAccessInfo(t *testing.T) {
|
2017-10-05 10:00:19 -07:00
|
|
|
context, executor := testContext()
|
2016-10-14 14:41:15 -07:00
|
|
|
|
2016-09-30 12:56:56 -07:00
|
|
|
req, err := http.NewRequest("POST", "http://10.0.0.100/image/mapinfo", nil)
|
|
|
|
|
if err != nil {
|
2017-10-05 10:00:19 -07:00
|
|
|
require.Fail(t, err.Error())
|
2016-09-30 12:56:56 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
w := httptest.NewRecorder()
|
2017-08-07 10:58:52 -07:00
|
|
|
executor.MockExecuteCommandWithOutputFile = func(debug bool, actionName string, command string, outFileArg string, args ...string) (string, error) {
|
2017-06-06 12:58:09 -07:00
|
|
|
switch {
|
|
|
|
|
case args[0] == "mon_status":
|
|
|
|
|
response := "{\"name\":\"mon0\",\"rank\":0,\"state\":\"leader\",\"election_epoch\":3,\"quorum\":[0],\"monmap\":{\"epoch\":1," +
|
|
|
|
|
"\"fsid\":\"22ae0d50-c4bc-4cfb-9cf4-341acbe35302\",\"modified\":\"2016-09-16 04:21:51.635837\",\"created\":\"2016-09-16 04:21:51.635837\"," +
|
|
|
|
|
"\"mons\":[{\"rank\":0,\"name\":\"mon0\",\"addr\":\"10.37.129.87:6790\"}]}}"
|
|
|
|
|
return response, nil
|
|
|
|
|
case args[0] == "auth" && args[1] == "get-key":
|
|
|
|
|
return `{"key":"AQBsCv1X5oD9GhAARHVU9N+kFRWDjyLA1dqzIg=="}`, nil
|
|
|
|
|
}
|
|
|
|
|
return "", nil
|
2016-09-30 12:56:56 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// get image map info and verify the response
|
2017-06-02 13:44:54 -07:00
|
|
|
h := newTestHandler(context)
|
2016-11-28 17:38:06 -08:00
|
|
|
h.GetClientAccessInfo(w, req)
|
2016-09-30 12:56:56 -07:00
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
|
|
|
assert.Equal(t, "{\"monAddresses\":[\"10.37.129.87:6790\"],\"userName\":\"admin\",\"secretKey\":\"AQBsCv1X5oD9GhAARHVU9N+kFRWDjyLA1dqzIg==\"}", w.Body.String())
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-28 17:38:06 -08:00
|
|
|
func TestGetClientAccessInfoHandlerFailure(t *testing.T) {
|
2017-10-05 10:00:19 -07:00
|
|
|
context, _ := testContext()
|
2016-10-14 14:41:15 -07:00
|
|
|
|
2016-11-28 17:38:06 -08:00
|
|
|
req, err := http.NewRequest("POST", "http://10.0.0.100/client", nil)
|
2016-09-30 12:56:56 -07:00
|
|
|
if err != nil {
|
2016-11-11 17:37:08 -08:00
|
|
|
logger.Fatal(err)
|
2016-09-30 12:56:56 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
|
|
2017-06-14 16:07:36 -07:00
|
|
|
// get image map info should fail because there's no mock response set up for auth get-key
|
2017-06-02 13:44:54 -07:00
|
|
|
h := newTestHandler(context)
|
2016-11-28 17:38:06 -08:00
|
|
|
h.GetClientAccessInfo(w, req)
|
2016-09-30 12:56:56 -07:00
|
|
|
assert.Equal(t, http.StatusInternalServerError, w.Code)
|
|
|
|
|
assert.Equal(t, "", w.Body.String())
|
|
|
|
|
}
|
2017-06-06 12:58:09 -07:00
|
|
|
|
2017-10-05 10:00:19 -07:00
|
|
|
func testContext() (*clusterd.Context, *exectest.MockExecutor) {
|
2017-06-14 16:07:36 -07:00
|
|
|
return testContextWithMons([]string{"mon0"})
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-05 10:00:19 -07:00
|
|
|
func testContextWithMons(mons []string) (*clusterd.Context, *exectest.MockExecutor) {
|
2017-06-06 12:58:09 -07:00
|
|
|
executor := &exectest.MockExecutor{}
|
|
|
|
|
return &clusterd.Context{
|
2017-10-05 10:00:19 -07:00
|
|
|
Executor: executor,
|
|
|
|
|
Clientset: test.New(1),
|
|
|
|
|
}, executor
|
2017-06-06 12:58:09 -07:00
|
|
|
}
|