Merge pull request #5707 from endocode/kbeecher/etcd_prefix

Adds ability to define a prefix for etcd paths
pull/6/head
Daniel Smith 2015-04-27 13:37:43 -07:00
commit 83093af8b0
45 changed files with 562 additions and 227 deletions

View File

@ -51,6 +51,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/master" "github.com/GoogleCloudPlatform/kubernetes/pkg/master"
"github.com/GoogleCloudPlatform/kubernetes/pkg/probe" "github.com/GoogleCloudPlatform/kubernetes/pkg/probe"
"github.com/GoogleCloudPlatform/kubernetes/pkg/service" "github.com/GoogleCloudPlatform/kubernetes/pkg/service"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools/etcdtest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util/wait" "github.com/GoogleCloudPlatform/kubernetes/pkg/util/wait"
"github.com/GoogleCloudPlatform/kubernetes/pkg/volume/empty_dir" "github.com/GoogleCloudPlatform/kubernetes/pkg/volume/empty_dir"
@ -160,7 +161,7 @@ func startComponents(firstManifestURL, secondManifestURL, apiVersion string) (st
cl := client.NewOrDie(&client.Config{Host: apiServer.URL, Version: apiVersion}) cl := client.NewOrDie(&client.Config{Host: apiServer.URL, Version: apiVersion})
helper, err := master.NewEtcdHelper(etcdClient, "") helper, err := master.NewEtcdHelper(etcdClient, "", etcdtest.PathPrefix())
if err != nil { if err != nil {
glog.Fatalf("Unable to get etcd helper: %v", err) glog.Fatalf("Unable to get etcd helper: %v", err)
} }

View File

@ -71,6 +71,7 @@ type APIServer struct {
AdmissionControlConfigFile string AdmissionControlConfigFile string
EtcdServerList util.StringList EtcdServerList util.StringList
EtcdConfigFile string EtcdConfigFile string
EtcdPathPrefix string
CorsAllowedOriginList util.StringList CorsAllowedOriginList util.StringList
AllowPrivileged bool AllowPrivileged bool
PortalNet util.IPNet // TODO: make this a list PortalNet util.IPNet // TODO: make this a list
@ -98,6 +99,7 @@ func NewAPIServer() *APIServer {
EventTTL: 1 * time.Hour, EventTTL: 1 * time.Hour,
AuthorizationMode: "AlwaysAllow", AuthorizationMode: "AlwaysAllow",
AdmissionControl: "AlwaysAdmit", AdmissionControl: "AlwaysAdmit",
EtcdPathPrefix: master.DefaultEtcdPathPrefix,
EnableLogsSupport: true, EnableLogsSupport: true,
MasterServiceNamespace: api.NamespaceDefault, MasterServiceNamespace: api.NamespaceDefault,
ClusterName: "kubernetes", ClusterName: "kubernetes",
@ -161,6 +163,7 @@ func (s *APIServer) AddFlags(fs *pflag.FlagSet) {
fs.StringVar(&s.AdmissionControlConfigFile, "admission_control_config_file", s.AdmissionControlConfigFile, "File with admission control configuration.") fs.StringVar(&s.AdmissionControlConfigFile, "admission_control_config_file", s.AdmissionControlConfigFile, "File with admission control configuration.")
fs.Var(&s.EtcdServerList, "etcd_servers", "List of etcd servers to watch (http://ip:port), comma separated. Mutually exclusive with -etcd_config") fs.Var(&s.EtcdServerList, "etcd_servers", "List of etcd servers to watch (http://ip:port), comma separated. Mutually exclusive with -etcd_config")
fs.StringVar(&s.EtcdConfigFile, "etcd_config", s.EtcdConfigFile, "The config file for the etcd client. Mutually exclusive with -etcd_servers.") fs.StringVar(&s.EtcdConfigFile, "etcd_config", s.EtcdConfigFile, "The config file for the etcd client. Mutually exclusive with -etcd_servers.")
fs.StringVar(&s.EtcdPathPrefix, "etcd_prefix", s.EtcdPathPrefix, "The prefix for all resource paths in etcd.")
fs.Var(&s.CorsAllowedOriginList, "cors_allowed_origins", "List of allowed origins for CORS, comma separated. An allowed origin can be a regular expression to support subdomain matching. If this list is empty CORS will not be enabled.") fs.Var(&s.CorsAllowedOriginList, "cors_allowed_origins", "List of allowed origins for CORS, comma separated. An allowed origin can be a regular expression to support subdomain matching. If this list is empty CORS will not be enabled.")
fs.BoolVar(&s.AllowPrivileged, "allow_privileged", s.AllowPrivileged, "If true, allow privileged containers.") fs.BoolVar(&s.AllowPrivileged, "allow_privileged", s.AllowPrivileged, "If true, allow privileged containers.")
fs.Var(&s.PortalNet, "portal_net", "A CIDR notation IP range from which to assign portal IPs. This must not overlap with any IP ranges assigned to nodes for pods.") fs.Var(&s.PortalNet, "portal_net", "A CIDR notation IP range from which to assign portal IPs. This must not overlap with any IP ranges assigned to nodes for pods.")
@ -181,7 +184,7 @@ func (s *APIServer) verifyPortalFlags() {
} }
} }
func newEtcd(etcdConfigFile string, etcdServerList util.StringList, storageVersion string) (helper tools.EtcdHelper, err error) { func newEtcd(etcdConfigFile string, etcdServerList util.StringList, storageVersion string, pathPrefix string) (helper tools.EtcdHelper, err error) {
var client tools.EtcdGetSet var client tools.EtcdGetSet
if etcdConfigFile != "" { if etcdConfigFile != "" {
client, err = etcd.NewClientFromFile(etcdConfigFile) client, err = etcd.NewClientFromFile(etcdConfigFile)
@ -192,7 +195,7 @@ func newEtcd(etcdConfigFile string, etcdServerList util.StringList, storageVersi
client = etcd.NewClient(etcdServerList) client = etcd.NewClient(etcdServerList)
} }
return master.NewEtcdHelper(client, storageVersion) return master.NewEtcdHelper(client, storageVersion, pathPrefix)
} }
// Run runs the specified APIServer. This should never exit. // Run runs the specified APIServer. This should never exit.
@ -232,7 +235,7 @@ func (s *APIServer) Run(_ []string) error {
glog.Fatalf("Invalid server address: %v", err) glog.Fatalf("Invalid server address: %v", err)
} }
helper, err := newEtcd(s.EtcdConfigFile, s.EtcdServerList, s.StorageVersion) helper, err := newEtcd(s.EtcdConfigFile, s.EtcdServerList, s.StorageVersion, s.EtcdPathPrefix)
if err != nil { if err != nil {
glog.Fatalf("Invalid storage version or misconfigured etcd: %v", err) glog.Fatalf("Invalid storage version or misconfigured etcd: %v", err)
} }

View File

@ -82,7 +82,7 @@ func (h *delegateHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
func runApiServer(etcdClient tools.EtcdClient, addr net.IP, port int, masterServiceNamespace string) { func runApiServer(etcdClient tools.EtcdClient, addr net.IP, port int, masterServiceNamespace string) {
handler := delegateHandler{} handler := delegateHandler{}
helper, err := master.NewEtcdHelper(etcdClient, "") helper, err := master.NewEtcdHelper(etcdClient, "", master.DefaultEtcdPathPrefix)
if err != nil { if err != nil {
glog.Fatalf("Unable to get etcd helper: %v", err) glog.Fatalf("Unable to get etcd helper: %v", err)
} }

View File

@ -53,6 +53,9 @@ KUBE_RACE=${KUBE_RACE:-} # use KUBE_RACE="-race" to enable race testing
KUBE_GOVERALLS_BIN=${KUBE_GOVERALLS_BIN:-} KUBE_GOVERALLS_BIN=${KUBE_GOVERALLS_BIN:-}
# Comma separated list of API Versions that should be tested. # Comma separated list of API Versions that should be tested.
KUBE_TEST_API_VERSIONS=${KUBE_TEST_API_VERSIONS:-"v1beta1,v1beta3"} KUBE_TEST_API_VERSIONS=${KUBE_TEST_API_VERSIONS:-"v1beta1,v1beta3"}
# Prefixes for etcd paths (standard and customized)
ETCD_STANDARD_PREFIX="registry"
ETCD_CUSTOM_PREFIX="kubernetes.io/registry"
kube::test::usage() { kube::test::usage() {
kube::log::usage_from_stdin <<EOF kube::log::usage_from_stdin <<EOF
@ -203,10 +206,13 @@ reportCoverageToCoveralls() {
# Convert the CSV to an array of API versions to test # Convert the CSV to an array of API versions to test
IFS=',' read -a apiVersions <<< "${KUBE_TEST_API_VERSIONS}" IFS=',' read -a apiVersions <<< "${KUBE_TEST_API_VERSIONS}"
ETCD_PREFIX=${ETCD_STANDARD_PREFIX}
for apiVersion in "${apiVersions[@]}"; do for apiVersion in "${apiVersions[@]}"; do
echo "Running tests for APIVersion: $apiVersion" echo "Running tests for APIVersion: $apiVersion"
KUBE_API_VERSION="${apiVersion}" runTests "$@" KUBE_API_VERSION="${apiVersion}" ETCD_PREFIX=${ETCD_STANDARD_PREFIX} runTests "$@"
done done
echo "Using custom etcd path prefix: ${ETCD_CUSTOM_PREFIX}"
KUBE_API_VERSION="${apiVersions[-1]}" ETCD_PREFIX=${ETCD_CUSTOM_PREFIX} runTests "$@"
# We might run the tests for multiple versions, but we want to report only # We might run the tests for multiple versions, but we want to report only
# one of them to coveralls. Here we report coverage from the last run. # one of them to coveralls. Here we report coverage from the last run.

View File

@ -271,7 +271,6 @@ func (t *Tester) TestDeleteNoGraceful(createFn func() runtime.Object, wasGracefu
if err != nil { if err != nil {
t.Fatalf("object does not have ObjectMeta: %v\n%#v", err, existing) t.Fatalf("object does not have ObjectMeta: %v\n%#v", err, existing)
} }
ctx := api.WithNamespace(api.NewContext(), objectMeta.Namespace) ctx := api.WithNamespace(api.NewContext(), objectMeta.Namespace)
_, err = t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, api.NewDeleteOptions(10)) _, err = t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, api.NewDeleteOptions(10))
if err != nil { if err != nil {

View File

@ -71,6 +71,10 @@ import (
"github.com/golang/glog" "github.com/golang/glog"
) )
const (
DefaultEtcdPathPrefix = "/registry"
)
// Config is a structure used to configure a Master. // Config is a structure used to configure a Master.
type Config struct { type Config struct {
EtcdHelper tools.EtcdHelper EtcdHelper tools.EtcdHelper
@ -178,7 +182,7 @@ type Master struct {
// NewEtcdHelper returns an EtcdHelper for the provided arguments or an error if the version // NewEtcdHelper returns an EtcdHelper for the provided arguments or an error if the version
// is incorrect. // is incorrect.
func NewEtcdHelper(client tools.EtcdGetSet, version string) (helper tools.EtcdHelper, err error) { func NewEtcdHelper(client tools.EtcdGetSet, version string, prefix string) (helper tools.EtcdHelper, err error) {
if version == "" { if version == "" {
version = latest.Version version = latest.Version
} }
@ -186,7 +190,7 @@ func NewEtcdHelper(client tools.EtcdGetSet, version string) (helper tools.EtcdHe
if err != nil { if err != nil {
return helper, err return helper, err
} }
return tools.NewEtcdHelper(client, versionInterfaces.Codec), nil return tools.NewEtcdHelper(client, versionInterfaces.Codec, prefix), nil
} }
// setDefaults fills in any fields not set that are required to have valid data. // setDefaults fills in any fields not set that are required to have valid data.
@ -363,7 +367,7 @@ func logStackOnRecover(panicReason interface{}, httpWriter http.ResponseWriter)
func (m *Master) init(c *Config) { func (m *Master) init(c *Config) {
// TODO: make initialization of the helper part of the Master, and allow some storage // TODO: make initialization of the helper part of the Master, and allow some storage
// objects to have a newer storage version than the user's default. // objects to have a newer storage version than the user's default.
newerHelper, err := NewEtcdHelper(c.EtcdHelper.Client, "v1beta3") newerHelper, err := NewEtcdHelper(c.EtcdHelper.Client, "v1beta3", DefaultEtcdPathPrefix)
if err != nil { if err != nil {
glog.Fatalf("Unable to setup storage for v1beta3: %v", err) glog.Fatalf("Unable to setup storage for v1beta3: %v", err)
} }

View File

@ -23,6 +23,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/registrytest" "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/registrytest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools" "github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools/etcdtest"
) )
func TestGetServersToValidate(t *testing.T) { func TestGetServersToValidate(t *testing.T) {
@ -30,7 +31,7 @@ func TestGetServersToValidate(t *testing.T) {
config := Config{} config := Config{}
fakeClient := tools.NewFakeEtcdClient(t) fakeClient := tools.NewFakeEtcdClient(t)
fakeClient.Machines = []string{"http://machine1:4001", "http://machine2", "http://machine3:4003"} fakeClient.Machines = []string{"http://machine1:4001", "http://machine2", "http://machine3:4003"}
config.EtcdHelper = tools.EtcdHelper{fakeClient, latest.Codec, nil} config.EtcdHelper = tools.EtcdHelper{fakeClient, latest.Codec, nil, etcdtest.PathPrefix()}
master.nodeRegistry = registrytest.NewMinionRegistry([]string{"node1", "node2"}, api.NodeResources{}) master.nodeRegistry = registrytest.NewMinionRegistry([]string{"node1", "node2"}, api.NodeResources{})

View File

@ -34,7 +34,7 @@ type REST struct {
// controllerPrefix is the location for controllers in etcd, only exposed // controllerPrefix is the location for controllers in etcd, only exposed
// for testing // for testing
var controllerPrefix = "/registry/controllers" var controllerPrefix = "/controllers"
// NewREST returns a RESTStorage object that will work against replication controllers. // NewREST returns a RESTStorage object that will work against replication controllers.
func NewREST(h tools.EtcdHelper) *REST { func NewREST(h tools.EtcdHelper) *REST {

View File

@ -31,6 +31,7 @@ import (
etcdgeneric "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic/etcd" etcdgeneric "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic/etcd"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools" "github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools/etcdtest"
"github.com/coreos/go-etcd/etcd" "github.com/coreos/go-etcd/etcd"
) )
@ -39,11 +40,16 @@ const (
FAIL FAIL
) )
// newStorage creates a REST storage backed by etcd helpers func newHelper(t *testing.T) (*tools.FakeEtcdClient, tools.EtcdHelper) {
func newStorage(t *testing.T) (*REST, *tools.FakeEtcdClient) {
fakeEtcdClient := tools.NewFakeEtcdClient(t) fakeEtcdClient := tools.NewFakeEtcdClient(t)
fakeEtcdClient.TestIndex = true fakeEtcdClient.TestIndex = true
h := tools.NewEtcdHelper(fakeEtcdClient, latest.Codec) helper := tools.NewEtcdHelper(fakeEtcdClient, latest.Codec, etcdtest.PathPrefix())
return fakeEtcdClient, helper
}
// newStorage creates a REST storage backed by etcd helpers
func newStorage(t *testing.T) (*REST, *tools.FakeEtcdClient) {
fakeEtcdClient, h := newHelper(t)
storage := NewREST(h) storage := NewREST(h)
return storage, fakeEtcdClient return storage, fakeEtcdClient
} }
@ -107,6 +113,7 @@ func TestEtcdCreateController(t *testing.T) {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
} }
key, _ := makeControllerKey(ctx, validController.Name) key, _ := makeControllerKey(ctx, validController.Name)
key = etcdtest.AddPrefix(key)
resp, err := fakeClient.Get(key, false, false) resp, err := fakeClient.Get(key, false, false)
if err != nil { if err != nil {
t.Fatalf("Unexpected error %v", err) t.Fatalf("Unexpected error %v", err)
@ -126,6 +133,7 @@ func TestEtcdCreateControllerAlreadyExisting(t *testing.T) {
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
storage, fakeClient := newStorage(t) storage, fakeClient := newStorage(t)
key, _ := makeControllerKey(ctx, validController.Name) key, _ := makeControllerKey(ctx, validController.Name)
key = etcdtest.AddPrefix(key)
fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &validController), 0) fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &validController), 0)
_, err := storage.Create(ctx, &validController) _, err := storage.Create(ctx, &validController)
@ -199,6 +207,7 @@ func TestEtcdGetController(t *testing.T) {
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
storage, fakeClient := newStorage(t) storage, fakeClient := newStorage(t)
key, _ := makeControllerKey(ctx, validController.Name) key, _ := makeControllerKey(ctx, validController.Name)
key = etcdtest.AddPrefix(key)
fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &validController), 0) fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &validController), 0)
ctrl, err := storage.Get(ctx, validController.Name) ctrl, err := storage.Get(ctx, validController.Name)
if err != nil { if err != nil {
@ -282,6 +291,9 @@ func TestEtcdGetControllerDifferentNamespace(t *testing.T) {
key1, _ := makeControllerKey(ctx1, validController.Name) key1, _ := makeControllerKey(ctx1, validController.Name)
key2, _ := makeControllerKey(ctx2, validController.Name) key2, _ := makeControllerKey(ctx2, validController.Name)
key1 = etcdtest.AddPrefix(key1)
key2 = etcdtest.AddPrefix(key2)
fakeClient.Set(key1, runtime.EncodeOrDie(latest.Codec, &validController), 0) fakeClient.Set(key1, runtime.EncodeOrDie(latest.Codec, &validController), 0)
otherNsController := validController otherNsController := validController
otherNsController.Namespace = otherNs otherNsController.Namespace = otherNs
@ -317,6 +329,8 @@ func TestEtcdGetControllerNotFound(t *testing.T) {
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
storage, fakeClient := newStorage(t) storage, fakeClient := newStorage(t)
key, _ := makeControllerKey(ctx, validController.Name) key, _ := makeControllerKey(ctx, validController.Name)
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: nil, Node: nil,
@ -336,6 +350,7 @@ func TestEtcdUpdateController(t *testing.T) {
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
storage, fakeClient := newStorage(t) storage, fakeClient := newStorage(t)
key, _ := makeControllerKey(ctx, validController.Name) key, _ := makeControllerKey(ctx, validController.Name)
key = etcdtest.AddPrefix(key)
// set a key, then retrieve the current resource version and try updating it // set a key, then retrieve the current resource version and try updating it
resp, _ := fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &validController), 0) resp, _ := fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &validController), 0)
@ -360,6 +375,8 @@ func TestEtcdDeleteController(t *testing.T) {
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
storage, fakeClient := newStorage(t) storage, fakeClient := newStorage(t)
key, _ := makeControllerKey(ctx, validController.Name) key, _ := makeControllerKey(ctx, validController.Name)
key = etcdtest.AddPrefix(key)
fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &validController), 0) fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &validController), 0)
obj, err := storage.Delete(ctx, validController.Name, nil) obj, err := storage.Delete(ctx, validController.Name, nil)
if err != nil { if err != nil {
@ -382,6 +399,7 @@ func TestEtcdListControllers(t *testing.T) {
storage, fakeClient := newStorage(t) storage, fakeClient := newStorage(t)
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
key := makeControllerListKey(ctx) key := makeControllerListKey(ctx)
key = etcdtest.AddPrefix(key)
controller := validController controller := validController
controller.Name = "bar" controller.Name = "bar"
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
@ -413,6 +431,8 @@ func TestEtcdListControllersNotFound(t *testing.T) {
storage, fakeClient := newStorage(t) storage, fakeClient := newStorage(t)
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
key := makeControllerListKey(ctx) key := makeControllerListKey(ctx)
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{}, R: &etcd.Response{},
E: tools.EtcdErrorNotFound, E: tools.EtcdErrorNotFound,
@ -431,6 +451,7 @@ func TestEtcdListControllersLabelsMatch(t *testing.T) {
storage, fakeClient := newStorage(t) storage, fakeClient := newStorage(t)
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
key := makeControllerListKey(ctx) key := makeControllerListKey(ctx)
key = etcdtest.AddPrefix(key)
controller := validController controller := validController
controller.Labels = map[string]string{"k": "v"} controller.Labels = map[string]string{"k": "v"}
@ -678,13 +699,16 @@ func TestCreate(t *testing.T) {
} }
func TestDelete(t *testing.T) { func TestDelete(t *testing.T) {
ctx := api.NewDefaultContext()
storage, fakeClient := newStorage(t) storage, fakeClient := newStorage(t)
test := resttest.New(t, storage, fakeClient.SetError) test := resttest.New(t, storage, fakeClient.SetError)
key, _ := makeControllerKey(ctx, validController.Name)
key = etcdtest.AddPrefix(key)
createFn := func() runtime.Object { createFn := func() runtime.Object {
rc := validController rc := validController
rc.ResourceVersion = "1" rc.ResourceVersion = "1"
fakeClient.Data["/registry/controllers/default/foo"] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
Value: runtime.EncodeOrDie(latest.Codec, &rc), Value: runtime.EncodeOrDie(latest.Codec, &rc),
@ -697,7 +721,7 @@ func TestDelete(t *testing.T) {
gracefulSetFn := func() bool { gracefulSetFn := func() bool {
// If the controller is still around after trying to delete either the delete // If the controller is still around after trying to delete either the delete
// failed, or we're deleting it gracefully. // failed, or we're deleting it gracefully.
if fakeClient.Data["/registry/controllers/default/foo"].R.Node != nil { if fakeClient.Data[key].R.Node != nil {
return true return true
} }
return false return false

View File

@ -34,7 +34,7 @@ type REST struct {
// NewStorage returns a RESTStorage object that will work against endpoints. // NewStorage returns a RESTStorage object that will work against endpoints.
func NewStorage(h tools.EtcdHelper) *REST { func NewStorage(h tools.EtcdHelper) *REST {
prefix := "/registry/services/endpoints" prefix := "/services/endpoints"
return &REST{ return &REST{
&etcdgeneric.Etcd{ &etcdgeneric.Etcd{
NewFunc: func() runtime.Object { return &api.Endpoints{} }, NewFunc: func() runtime.Object { return &api.Endpoints{} },

View File

@ -26,6 +26,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools" "github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools/etcdtest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/coreos/go-etcd/etcd" "github.com/coreos/go-etcd/etcd"
@ -34,7 +35,7 @@ import (
func newHelper(t *testing.T) (*tools.FakeEtcdClient, tools.EtcdHelper) { func newHelper(t *testing.T) (*tools.FakeEtcdClient, tools.EtcdHelper) {
fakeEtcdClient := tools.NewFakeEtcdClient(t) fakeEtcdClient := tools.NewFakeEtcdClient(t)
fakeEtcdClient.TestIndex = true fakeEtcdClient.TestIndex = true
helper := tools.NewEtcdHelper(fakeEtcdClient, latest.Codec) helper := tools.NewEtcdHelper(fakeEtcdClient, latest.Codec, etcdtest.PathPrefix())
return fakeEtcdClient, helper return fakeEtcdClient, helper
} }
@ -89,6 +90,7 @@ func TestDelete(t *testing.T) {
endpoints := validChangedEndpoints() endpoints := validChangedEndpoints()
key, _ := storage.KeyFunc(ctx, endpoints.Name) key, _ := storage.KeyFunc(ctx, endpoints.Name)
key = etcdtest.AddPrefix(key)
createFn := func() runtime.Object { createFn := func() runtime.Object {
fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{ fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
@ -113,6 +115,7 @@ func TestEtcdListEndpoints(t *testing.T) {
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
storage, fakeClient := newStorage(t) storage, fakeClient := newStorage(t)
key := storage.KeyRootFunc(ctx) key := storage.KeyRootFunc(ctx)
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
@ -154,6 +157,7 @@ func TestEtcdGetEndpoints(t *testing.T) {
endpoints := validNewEndpoints() endpoints := validNewEndpoints()
name := endpoints.Name name := endpoints.Name
key, _ := storage.KeyFunc(ctx, name) key, _ := storage.KeyFunc(ctx, name)
key = etcdtest.AddPrefix(key)
fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, endpoints), 0) fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, endpoints), 0)
response, err := fakeClient.Get(key, false, false) response, err := fakeClient.Get(key, false, false)
@ -183,6 +187,7 @@ func TestListEmptyEndpointsList(t *testing.T) {
storage, fakeClient := newStorage(t) storage, fakeClient := newStorage(t)
fakeClient.ChangeIndex = 1 fakeClient.ChangeIndex = 1
key := storage.KeyRootFunc(ctx) key := storage.KeyRootFunc(ctx)
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{}, R: &etcd.Response{},
E: fakeClient.NewError(tools.EtcdErrorCodeNotFound), E: fakeClient.NewError(tools.EtcdErrorCodeNotFound),
@ -206,6 +211,7 @@ func TestListEndpointsList(t *testing.T) {
storage, fakeClient := newStorage(t) storage, fakeClient := newStorage(t)
fakeClient.ChangeIndex = 1 fakeClient.ChangeIndex = 1
key := storage.KeyRootFunc(ctx) key := storage.KeyRootFunc(ctx)
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
@ -266,6 +272,7 @@ func TestEtcdUpdateEndpoints(t *testing.T) {
endpoints := validChangedEndpoints() endpoints := validChangedEndpoints()
key, _ := storage.KeyFunc(ctx, "foo") key, _ := storage.KeyFunc(ctx, "foo")
key = etcdtest.AddPrefix(key)
fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, validNewEndpoints()), 0) fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, validNewEndpoints()), 0)
_, _, err := storage.Update(ctx, endpoints) _, _, err := storage.Update(ctx, endpoints)
@ -295,6 +302,7 @@ func TestDeleteEndpoints(t *testing.T) {
endpoints := validNewEndpoints() endpoints := validNewEndpoints()
name := endpoints.Name name := endpoints.Name
key, _ := storage.KeyFunc(ctx, name) key, _ := storage.KeyFunc(ctx, name)
key = etcdtest.AddPrefix(key)
fakeClient.ChangeIndex = 1 fakeClient.ChangeIndex = 1
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{

View File

@ -35,9 +35,9 @@ import (
const ( const (
// ControllerPath is the path to controller resources in etcd // ControllerPath is the path to controller resources in etcd
ControllerPath string = "/registry/controllers" ControllerPath string = "/controllers"
// ServicePath is the path to service resources in etcd // ServicePath is the path to service resources in etcd
ServicePath string = "/registry/services/specs" ServicePath string = "/services/specs"
) )
// TODO: Need to add a reconciler loop that makes sure that things in pods are reflected into // TODO: Need to add a reconciler loop that makes sure that things in pods are reflected into

View File

@ -33,17 +33,19 @@ import (
podetcd "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/pod/etcd" podetcd "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/pod/etcd"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools" "github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools/etcdtest"
"github.com/coreos/go-etcd/etcd" "github.com/coreos/go-etcd/etcd"
) )
func NewTestEtcdRegistry(client tools.EtcdClient) *Registry { func NewTestEtcdRegistry(client tools.EtcdClient) *Registry {
registry := NewRegistry(tools.NewEtcdHelper(client, latest.Codec), nil, nil) helper := tools.NewEtcdHelper(client, latest.Codec, etcdtest.PathPrefix())
registry := NewRegistry(helper, nil, nil)
return registry return registry
} }
func NewTestEtcdRegistryWithPods(client tools.EtcdClient) *Registry { func NewTestEtcdRegistryWithPods(client tools.EtcdClient) *Registry {
helper := tools.NewEtcdHelper(client, latest.Codec) helper := tools.NewEtcdHelper(client, latest.Codec, etcdtest.PathPrefix())
podStorage := podetcd.NewStorage(helper, nil) podStorage := podetcd.NewStorage(helper, nil)
endpointStorage := endpointetcd.NewStorage(helper) endpointStorage := endpointetcd.NewStorage(helper)
registry := NewRegistry(helper, pod.NewRegistry(podStorage.Pod), endpoint.NewRegistry(endpointStorage)) registry := NewRegistry(helper, pod.NewRegistry(podStorage.Pod), endpoint.NewRegistry(endpointStorage))
@ -54,6 +56,7 @@ func TestEtcdListControllersNotFound(t *testing.T) {
fakeClient := tools.NewFakeEtcdClient(t) fakeClient := tools.NewFakeEtcdClient(t)
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
key := makeControllerListKey(ctx) key := makeControllerListKey(ctx)
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{}, R: &etcd.Response{},
E: tools.EtcdErrorNotFound, E: tools.EtcdErrorNotFound,
@ -71,13 +74,14 @@ func TestEtcdListControllersNotFound(t *testing.T) {
func TestEtcdListServicesNotFound(t *testing.T) { func TestEtcdListServicesNotFound(t *testing.T) {
fakeClient := tools.NewFakeEtcdClient(t) fakeClient := tools.NewFakeEtcdClient(t)
registry := NewTestEtcdRegistry(fakeClient)
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
key := makeServiceListKey(ctx) key := makeServiceListKey(ctx)
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{}, R: &etcd.Response{},
E: tools.EtcdErrorNotFound, E: tools.EtcdErrorNotFound,
} }
registry := NewTestEtcdRegistry(fakeClient)
services, err := registry.ListServices(ctx) services, err := registry.ListServices(ctx)
if err != nil { if err != nil {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
@ -90,8 +94,10 @@ func TestEtcdListServicesNotFound(t *testing.T) {
func TestEtcdListControllers(t *testing.T) { func TestEtcdListControllers(t *testing.T) {
fakeClient := tools.NewFakeEtcdClient(t) fakeClient := tools.NewFakeEtcdClient(t)
registry := NewTestEtcdRegistry(fakeClient)
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
key := makeControllerListKey(ctx) key := makeControllerListKey(ctx)
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
@ -107,7 +113,6 @@ func TestEtcdListControllers(t *testing.T) {
}, },
E: nil, E: nil,
} }
registry := NewTestEtcdRegistry(fakeClient)
controllers, err := registry.ListControllers(ctx) controllers, err := registry.ListControllers(ctx)
if err != nil { if err != nil {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
@ -121,6 +126,7 @@ func TestEtcdListControllers(t *testing.T) {
// TestEtcdGetControllerDifferentNamespace ensures same-name controllers in different namespaces do not clash // TestEtcdGetControllerDifferentNamespace ensures same-name controllers in different namespaces do not clash
func TestEtcdGetControllerDifferentNamespace(t *testing.T) { func TestEtcdGetControllerDifferentNamespace(t *testing.T) {
fakeClient := tools.NewFakeEtcdClient(t) fakeClient := tools.NewFakeEtcdClient(t)
registry := NewTestEtcdRegistry(fakeClient)
ctx1 := api.NewDefaultContext() ctx1 := api.NewDefaultContext()
ctx2 := api.WithNamespace(api.NewContext(), "other") ctx2 := api.WithNamespace(api.NewContext(), "other")
@ -128,11 +134,12 @@ func TestEtcdGetControllerDifferentNamespace(t *testing.T) {
key1, _ := makeControllerKey(ctx1, "foo") key1, _ := makeControllerKey(ctx1, "foo")
key2, _ := makeControllerKey(ctx2, "foo") key2, _ := makeControllerKey(ctx2, "foo")
key1 = etcdtest.AddPrefix(key1)
key2 = etcdtest.AddPrefix(key2)
fakeClient.Set(key1, runtime.EncodeOrDie(latest.Codec, &api.ReplicationController{ObjectMeta: api.ObjectMeta{Namespace: "default", Name: "foo"}}), 0) fakeClient.Set(key1, runtime.EncodeOrDie(latest.Codec, &api.ReplicationController{ObjectMeta: api.ObjectMeta{Namespace: "default", Name: "foo"}}), 0)
fakeClient.Set(key2, runtime.EncodeOrDie(latest.Codec, &api.ReplicationController{ObjectMeta: api.ObjectMeta{Namespace: "other", Name: "foo"}}), 0) fakeClient.Set(key2, runtime.EncodeOrDie(latest.Codec, &api.ReplicationController{ObjectMeta: api.ObjectMeta{Namespace: "other", Name: "foo"}}), 0)
registry := NewTestEtcdRegistry(fakeClient)
ctrl1, err := registry.GetController(ctx1, "foo") ctrl1, err := registry.GetController(ctx1, "foo")
if err != nil { if err != nil {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
@ -154,15 +161,15 @@ func TestEtcdGetControllerDifferentNamespace(t *testing.T) {
if ctrl2.Namespace != "other" { if ctrl2.Namespace != "other" {
t.Errorf("Unexpected controller: %#v", ctrl2) t.Errorf("Unexpected controller: %#v", ctrl2)
} }
} }
func TestEtcdGetController(t *testing.T) { func TestEtcdGetController(t *testing.T) {
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
fakeClient := tools.NewFakeEtcdClient(t) fakeClient := tools.NewFakeEtcdClient(t)
key, _ := makeControllerKey(ctx, "foo")
fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &api.ReplicationController{ObjectMeta: api.ObjectMeta{Name: "foo"}}), 0)
registry := NewTestEtcdRegistry(fakeClient) registry := NewTestEtcdRegistry(fakeClient)
key, _ := makeControllerKey(ctx, "foo")
key = etcdtest.AddPrefix(key)
fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &api.ReplicationController{ObjectMeta: api.ObjectMeta{Name: "foo"}}), 0)
ctrl, err := registry.GetController(ctx, "foo") ctrl, err := registry.GetController(ctx, "foo")
if err != nil { if err != nil {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
@ -176,14 +183,15 @@ func TestEtcdGetController(t *testing.T) {
func TestEtcdGetControllerNotFound(t *testing.T) { func TestEtcdGetControllerNotFound(t *testing.T) {
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
fakeClient := tools.NewFakeEtcdClient(t) fakeClient := tools.NewFakeEtcdClient(t)
registry := NewTestEtcdRegistry(fakeClient)
key, _ := makeControllerKey(ctx, "foo") key, _ := makeControllerKey(ctx, "foo")
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: nil, Node: nil,
}, },
E: tools.EtcdErrorNotFound, E: tools.EtcdErrorNotFound,
} }
registry := NewTestEtcdRegistry(fakeClient)
ctrl, err := registry.GetController(ctx, "foo") ctrl, err := registry.GetController(ctx, "foo")
if ctrl != nil { if ctrl != nil {
t.Errorf("Unexpected non-nil controller: %#v", ctrl) t.Errorf("Unexpected non-nil controller: %#v", ctrl)
@ -198,6 +206,7 @@ func TestEtcdDeleteController(t *testing.T) {
fakeClient := tools.NewFakeEtcdClient(t) fakeClient := tools.NewFakeEtcdClient(t)
registry := NewTestEtcdRegistry(fakeClient) registry := NewTestEtcdRegistry(fakeClient)
key, _ := makeControllerKey(ctx, "foo") key, _ := makeControllerKey(ctx, "foo")
key = etcdtest.AddPrefix(key)
fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &api.ReplicationController{ObjectMeta: api.ObjectMeta{Name: "foo"}}), 0) fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &api.ReplicationController{ObjectMeta: api.ObjectMeta{Name: "foo"}}), 0)
err := registry.DeleteController(ctx, "foo") err := registry.DeleteController(ctx, "foo")
if err != nil { if err != nil {
@ -217,6 +226,7 @@ func TestEtcdCreateController(t *testing.T) {
fakeClient := tools.NewFakeEtcdClient(t) fakeClient := tools.NewFakeEtcdClient(t)
registry := NewTestEtcdRegistry(fakeClient) registry := NewTestEtcdRegistry(fakeClient)
key, _ := makeControllerKey(ctx, "foo") key, _ := makeControllerKey(ctx, "foo")
key = etcdtest.AddPrefix(key)
_, err := registry.CreateController(ctx, &api.ReplicationController{ _, err := registry.CreateController(ctx, &api.ReplicationController{
ObjectMeta: api.ObjectMeta{ ObjectMeta: api.ObjectMeta{
Name: "foo", Name: "foo",
@ -243,10 +253,11 @@ func TestEtcdCreateController(t *testing.T) {
func TestEtcdCreateControllerAlreadyExisting(t *testing.T) { func TestEtcdCreateControllerAlreadyExisting(t *testing.T) {
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
fakeClient := tools.NewFakeEtcdClient(t) fakeClient := tools.NewFakeEtcdClient(t)
registry := NewTestEtcdRegistry(fakeClient)
key, _ := makeControllerKey(ctx, "foo") key, _ := makeControllerKey(ctx, "foo")
key = etcdtest.AddPrefix(key)
fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &api.ReplicationController{ObjectMeta: api.ObjectMeta{Name: "foo"}}), 0) fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &api.ReplicationController{ObjectMeta: api.ObjectMeta{Name: "foo"}}), 0)
registry := NewTestEtcdRegistry(fakeClient)
_, err := registry.CreateController(ctx, &api.ReplicationController{ _, err := registry.CreateController(ctx, &api.ReplicationController{
ObjectMeta: api.ObjectMeta{ ObjectMeta: api.ObjectMeta{
Name: "foo", Name: "foo",
@ -260,10 +271,11 @@ func TestEtcdCreateControllerAlreadyExisting(t *testing.T) {
func TestEtcdUpdateController(t *testing.T) { func TestEtcdUpdateController(t *testing.T) {
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
fakeClient := tools.NewFakeEtcdClient(t) fakeClient := tools.NewFakeEtcdClient(t)
registry := NewTestEtcdRegistry(fakeClient)
fakeClient.TestIndex = true fakeClient.TestIndex = true
key, _ := makeControllerKey(ctx, "foo") key, _ := makeControllerKey(ctx, "foo")
key = etcdtest.AddPrefix(key)
resp, _ := fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &api.ReplicationController{ObjectMeta: api.ObjectMeta{Name: "foo"}}), 0) resp, _ := fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &api.ReplicationController{ObjectMeta: api.ObjectMeta{Name: "foo"}}), 0)
registry := NewTestEtcdRegistry(fakeClient)
_, err := registry.UpdateController(ctx, &api.ReplicationController{ _, err := registry.UpdateController(ctx, &api.ReplicationController{
ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: strconv.FormatUint(resp.Node.ModifiedIndex, 10)}, ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: strconv.FormatUint(resp.Node.ModifiedIndex, 10)},
Spec: api.ReplicationControllerSpec{ Spec: api.ReplicationControllerSpec{
@ -311,8 +323,10 @@ func TestEtcdWatchController(t *testing.T) {
func TestEtcdWatchControllersMatch(t *testing.T) { func TestEtcdWatchControllersMatch(t *testing.T) {
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
fakeClient := tools.NewFakeEtcdClient(t) fakeClient := tools.NewFakeEtcdClient(t)
fakeClient.ExpectNotFoundGet(etcdgeneric.NamespaceKeyRootFunc(ctx, "/registry/pods"))
registry := NewTestEtcdRegistryWithPods(fakeClient) registry := NewTestEtcdRegistryWithPods(fakeClient)
path := etcdgeneric.NamespaceKeyRootFunc(ctx, "/pods")
path = etcdtest.AddPrefix(path)
fakeClient.ExpectNotFoundGet(path)
watching, err := registry.WatchControllers(ctx, watching, err := registry.WatchControllers(ctx,
labels.SelectorFromSet(labels.Set{"name": "foo"}), labels.SelectorFromSet(labels.Set{"name": "foo"}),
fields.Everything(), fields.Everything(),
@ -391,7 +405,9 @@ func TestEtcdWatchControllersNotMatch(t *testing.T) {
func TestEtcdListServices(t *testing.T) { func TestEtcdListServices(t *testing.T) {
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
fakeClient := tools.NewFakeEtcdClient(t) fakeClient := tools.NewFakeEtcdClient(t)
registry := NewTestEtcdRegistry(fakeClient)
key := makeServiceListKey(ctx) key := makeServiceListKey(ctx)
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
@ -407,7 +423,6 @@ func TestEtcdListServices(t *testing.T) {
}, },
E: nil, E: nil,
} }
registry := NewTestEtcdRegistry(fakeClient)
services, err := registry.ListServices(ctx) services, err := registry.ListServices(ctx)
if err != nil { if err != nil {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
@ -430,6 +445,7 @@ func TestEtcdCreateService(t *testing.T) {
} }
key, _ := makeServiceKey(ctx, "foo") key, _ := makeServiceKey(ctx, "foo")
key = etcdtest.AddPrefix(key)
resp, err := fakeClient.Get(key, false, false) resp, err := fakeClient.Get(key, false, false)
if err != nil { if err != nil {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
@ -449,9 +465,10 @@ func TestEtcdCreateService(t *testing.T) {
func TestEtcdCreateServiceAlreadyExisting(t *testing.T) { func TestEtcdCreateServiceAlreadyExisting(t *testing.T) {
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
fakeClient := tools.NewFakeEtcdClient(t) fakeClient := tools.NewFakeEtcdClient(t)
key, _ := makeServiceKey(ctx, "foo")
fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &api.Service{ObjectMeta: api.ObjectMeta{Name: "foo"}}), 0)
registry := NewTestEtcdRegistry(fakeClient) registry := NewTestEtcdRegistry(fakeClient)
key, _ := makeServiceKey(ctx, "foo")
key = etcdtest.AddPrefix(key)
fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &api.Service{ObjectMeta: api.ObjectMeta{Name: "foo"}}), 0)
_, err := registry.CreateService(ctx, &api.Service{ _, err := registry.CreateService(ctx, &api.Service{
ObjectMeta: api.ObjectMeta{Name: "foo"}, ObjectMeta: api.ObjectMeta{Name: "foo"},
}) })
@ -463,6 +480,7 @@ func TestEtcdCreateServiceAlreadyExisting(t *testing.T) {
// TestEtcdGetServiceDifferentNamespace ensures same-name services in different namespaces do not clash // TestEtcdGetServiceDifferentNamespace ensures same-name services in different namespaces do not clash
func TestEtcdGetServiceDifferentNamespace(t *testing.T) { func TestEtcdGetServiceDifferentNamespace(t *testing.T) {
fakeClient := tools.NewFakeEtcdClient(t) fakeClient := tools.NewFakeEtcdClient(t)
registry := NewTestEtcdRegistry(fakeClient)
ctx1 := api.NewDefaultContext() ctx1 := api.NewDefaultContext()
ctx2 := api.WithNamespace(api.NewContext(), "other") ctx2 := api.WithNamespace(api.NewContext(), "other")
@ -470,11 +488,12 @@ func TestEtcdGetServiceDifferentNamespace(t *testing.T) {
key1, _ := makeServiceKey(ctx1, "foo") key1, _ := makeServiceKey(ctx1, "foo")
key2, _ := makeServiceKey(ctx2, "foo") key2, _ := makeServiceKey(ctx2, "foo")
key1 = etcdtest.AddPrefix(key1)
key2 = etcdtest.AddPrefix(key2)
fakeClient.Set(key1, runtime.EncodeOrDie(latest.Codec, &api.Service{ObjectMeta: api.ObjectMeta{Namespace: "default", Name: "foo"}}), 0) fakeClient.Set(key1, runtime.EncodeOrDie(latest.Codec, &api.Service{ObjectMeta: api.ObjectMeta{Namespace: "default", Name: "foo"}}), 0)
fakeClient.Set(key2, runtime.EncodeOrDie(latest.Codec, &api.Service{ObjectMeta: api.ObjectMeta{Namespace: "other", Name: "foo"}}), 0) fakeClient.Set(key2, runtime.EncodeOrDie(latest.Codec, &api.Service{ObjectMeta: api.ObjectMeta{Namespace: "other", Name: "foo"}}), 0)
registry := NewTestEtcdRegistry(fakeClient)
service1, err := registry.GetService(ctx1, "foo") service1, err := registry.GetService(ctx1, "foo")
if err != nil { if err != nil {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
@ -502,9 +521,10 @@ func TestEtcdGetServiceDifferentNamespace(t *testing.T) {
func TestEtcdGetService(t *testing.T) { func TestEtcdGetService(t *testing.T) {
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
fakeClient := tools.NewFakeEtcdClient(t) fakeClient := tools.NewFakeEtcdClient(t)
key, _ := makeServiceKey(ctx, "foo")
fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &api.Service{ObjectMeta: api.ObjectMeta{Name: "foo"}}), 0)
registry := NewTestEtcdRegistry(fakeClient) registry := NewTestEtcdRegistry(fakeClient)
key, _ := makeServiceKey(ctx, "foo")
key = etcdtest.AddPrefix(key)
fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &api.Service{ObjectMeta: api.ObjectMeta{Name: "foo"}}), 0)
service, err := registry.GetService(ctx, "foo") service, err := registry.GetService(ctx, "foo")
if err != nil { if err != nil {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
@ -518,14 +538,15 @@ func TestEtcdGetService(t *testing.T) {
func TestEtcdGetServiceNotFound(t *testing.T) { func TestEtcdGetServiceNotFound(t *testing.T) {
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
fakeClient := tools.NewFakeEtcdClient(t) fakeClient := tools.NewFakeEtcdClient(t)
registry := NewTestEtcdRegistry(fakeClient)
key, _ := makeServiceKey(ctx, "foo") key, _ := makeServiceKey(ctx, "foo")
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: nil, Node: nil,
}, },
E: tools.EtcdErrorNotFound, E: tools.EtcdErrorNotFound,
} }
registry := NewTestEtcdRegistry(fakeClient)
_, err := registry.GetService(ctx, "foo") _, err := registry.GetService(ctx, "foo")
if !errors.IsNotFound(err) { if !errors.IsNotFound(err) {
t.Errorf("Unexpected error returned: %#v", err) t.Errorf("Unexpected error returned: %#v", err)
@ -536,9 +557,11 @@ func TestEtcdDeleteService(t *testing.T) {
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
fakeClient := tools.NewFakeEtcdClient(t) fakeClient := tools.NewFakeEtcdClient(t)
registry := NewTestEtcdRegistryWithPods(fakeClient) registry := NewTestEtcdRegistryWithPods(fakeClient)
key, _ := makeServiceKey(ctx, "foo") key, _ := etcdgeneric.NamespaceKeyFunc(ctx, "/services/specs", "foo")
key = etcdtest.AddPrefix(key)
fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &api.Service{ObjectMeta: api.ObjectMeta{Name: "foo"}}), 0) fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &api.Service{ObjectMeta: api.ObjectMeta{Name: "foo"}}), 0)
endpointsKey, _ := etcdgeneric.NamespaceKeyFunc(ctx, "/registry/services/endpoints", "foo") path, _ := etcdgeneric.NamespaceKeyFunc(ctx, "/services/endpoints", "foo")
endpointsKey := etcdtest.AddPrefix(path)
fakeClient.Set(endpointsKey, runtime.EncodeOrDie(latest.Codec, &api.Endpoints{ObjectMeta: api.ObjectMeta{Name: "foo"}}), 0) fakeClient.Set(endpointsKey, runtime.EncodeOrDie(latest.Codec, &api.Endpoints{ObjectMeta: api.ObjectMeta{Name: "foo"}}), 0)
err := registry.DeleteService(ctx, "foo") err := registry.DeleteService(ctx, "foo")
@ -561,9 +584,10 @@ func TestEtcdUpdateService(t *testing.T) {
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
fakeClient := tools.NewFakeEtcdClient(t) fakeClient := tools.NewFakeEtcdClient(t)
fakeClient.TestIndex = true fakeClient.TestIndex = true
key, _ := makeServiceKey(ctx, "uniquefoo")
resp, _ := fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &api.Service{ObjectMeta: api.ObjectMeta{Name: "uniquefoo"}}), 0)
registry := NewTestEtcdRegistry(fakeClient) registry := NewTestEtcdRegistry(fakeClient)
key, _ := makeServiceKey(ctx, "uniquefoo")
key = etcdtest.AddPrefix(key)
resp, _ := fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &api.Service{ObjectMeta: api.ObjectMeta{Name: "uniquefoo"}}), 0)
testService := api.Service{ testService := api.Service{
ObjectMeta: api.ObjectMeta{ ObjectMeta: api.ObjectMeta{
Name: "uniquefoo", Name: "uniquefoo",

View File

@ -32,16 +32,17 @@ type registry struct {
// NewEtcdRegistry returns a registry which will store Events in the given // NewEtcdRegistry returns a registry which will store Events in the given
// EtcdHelper. ttl is the time that Events will be retained by the system. // EtcdHelper. ttl is the time that Events will be retained by the system.
func NewEtcdRegistry(h tools.EtcdHelper, ttl uint64) generic.Registry { func NewEtcdRegistry(h tools.EtcdHelper, ttl uint64) generic.Registry {
prefix := "/events"
return registry{ return registry{
Etcd: &etcdgeneric.Etcd{ Etcd: &etcdgeneric.Etcd{
NewFunc: func() runtime.Object { return &api.Event{} }, NewFunc: func() runtime.Object { return &api.Event{} },
NewListFunc: func() runtime.Object { return &api.EventList{} }, NewListFunc: func() runtime.Object { return &api.EventList{} },
EndpointName: "events", EndpointName: "events",
KeyRootFunc: func(ctx api.Context) string { KeyRootFunc: func(ctx api.Context) string {
return etcdgeneric.NamespaceKeyRootFunc(ctx, "/registry/events") return etcdgeneric.NamespaceKeyRootFunc(ctx, prefix)
}, },
KeyFunc: func(ctx api.Context, id string) (string, error) { KeyFunc: func(ctx api.Context, id string) (string, error) {
return etcdgeneric.NamespaceKeyFunc(ctx, "/registry/events", id) return etcdgeneric.NamespaceKeyFunc(ctx, prefix, id)
}, },
TTLFunc: func(runtime.Object, bool) (uint64, error) { TTLFunc: func(runtime.Object, bool) (uint64, error) {
return ttl, nil return ttl, nil

View File

@ -27,6 +27,7 @@ import (
etcdgeneric "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic/etcd" etcdgeneric "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic/etcd"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools" "github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools/etcdtest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/coreos/go-etcd/etcd" "github.com/coreos/go-etcd/etcd"
@ -37,7 +38,8 @@ var testTTL uint64 = 60
func NewTestEventEtcdRegistry(t *testing.T) (*tools.FakeEtcdClient, generic.Registry) { func NewTestEventEtcdRegistry(t *testing.T) (*tools.FakeEtcdClient, generic.Registry) {
f := tools.NewFakeEtcdClient(t) f := tools.NewFakeEtcdClient(t)
f.TestIndex = true f.TestIndex = true
h := tools.NewEtcdHelper(f, testapi.Codec())
h := tools.NewEtcdHelper(f, testapi.Codec(), etcdtest.PathPrefix())
return f, NewEtcdRegistry(h, testTTL) return f, NewEtcdRegistry(h, testTTL)
} }
@ -70,7 +72,8 @@ func TestEventCreate(t *testing.T) {
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
key := "foo" key := "foo"
path, err := etcdgeneric.NamespaceKeyFunc(ctx, "/registry/events", key) path, err := etcdgeneric.NamespaceKeyFunc(ctx, "/events", key)
path = etcdtest.AddPrefix(path)
if err != nil { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error: %v", err)
} }
@ -166,7 +169,8 @@ func TestEventUpdate(t *testing.T) {
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
key := "foo" key := "foo"
path, err := etcdgeneric.NamespaceKeyFunc(ctx, "/registry/events", key) path, err := etcdgeneric.NamespaceKeyFunc(ctx, "/events", key)
path = etcdtest.AddPrefix(path)
if err != nil { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error: %v", err)
} }

View File

@ -27,6 +27,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic" "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools" "github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools/etcdtest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util/fielderrors" "github.com/GoogleCloudPlatform/kubernetes/pkg/util/fielderrors"
@ -66,17 +67,20 @@ func hasCreated(t *testing.T, pod *api.Pod) func(runtime.Object) bool {
func NewTestGenericEtcdRegistry(t *testing.T) (*tools.FakeEtcdClient, *Etcd) { func NewTestGenericEtcdRegistry(t *testing.T) (*tools.FakeEtcdClient, *Etcd) {
f := tools.NewFakeEtcdClient(t) f := tools.NewFakeEtcdClient(t)
f.TestIndex = true f.TestIndex = true
h := tools.NewEtcdHelper(f, testapi.Codec()) h := tools.NewEtcdHelper(f, testapi.Codec(), etcdtest.PathPrefix())
strategy := &testRESTStrategy{api.Scheme, api.SimpleNameGenerator, true, false} strategy := &testRESTStrategy{api.Scheme, api.SimpleNameGenerator, true, false}
podPrefix := "/pods"
return f, &Etcd{ return f, &Etcd{
NewFunc: func() runtime.Object { return &api.Pod{} }, NewFunc: func() runtime.Object { return &api.Pod{} },
NewListFunc: func() runtime.Object { return &api.PodList{} }, NewListFunc: func() runtime.Object { return &api.PodList{} },
EndpointName: "pods", EndpointName: "pods",
CreateStrategy: strategy, CreateStrategy: strategy,
UpdateStrategy: strategy, UpdateStrategy: strategy,
KeyRootFunc: func(ctx api.Context) string { return "/registry/pods" }, KeyRootFunc: func(ctx api.Context) string {
return podPrefix
},
KeyFunc: func(ctx api.Context, id string) (string, error) { KeyFunc: func(ctx api.Context, id string) (string, error) {
return path.Join("/registry/pods", id), nil return path.Join(podPrefix, id), nil
}, },
ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*api.Pod).Name, nil }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*api.Pod).Name, nil },
Helper: h, Helper: h,
@ -205,16 +209,18 @@ func TestEtcdList(t *testing.T) {
t.Errorf("Couldn't create key for %v", name) t.Errorf("Couldn't create key for %v", name)
continue continue
} }
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = item.in fakeClient.Data[key] = item.in
} else { } else {
fakeClient.Data[registry.KeyRootFunc(api.NewContext())] = item.in key, _ := registry.KeyFunc(api.NewContext(), name)
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = item.in
} }
list, err := registry.ListPredicate(api.NewContext(), item.m) list, err := registry.ListPredicate(api.NewContext(), item.m)
if e, a := item.succeed, err == nil; e != a { if e, a := item.succeed, err == nil; e != a {
t.Errorf("%v: expected %v, got %v", name, e, a) t.Errorf("%v: expected %v, got %v", name, e, a)
continue continue
} }
if e, a := item.out, list; !api.Semantic.DeepDerivative(e, a) { if e, a := item.out, list; !api.Semantic.DeepDerivative(e, a) {
t.Errorf("%v: Expected %#v, got %#v", name, e, a) t.Errorf("%v: Expected %#v, got %#v", name, e, a)
} }
@ -247,8 +253,6 @@ func TestEtcdCreate(t *testing.T) {
E: tools.EtcdErrorNotFound, E: tools.EtcdErrorNotFound,
} }
path := "/registry/pods/foo"
table := map[string]struct { table := map[string]struct {
existing tools.EtcdResponseWithError existing tools.EtcdResponseWithError
expect tools.EtcdResponseWithError expect tools.EtcdResponseWithError
@ -272,6 +276,7 @@ func TestEtcdCreate(t *testing.T) {
for name, item := range table { for name, item := range table {
fakeClient, registry := NewTestGenericEtcdRegistry(t) fakeClient, registry := NewTestGenericEtcdRegistry(t)
path := etcdtest.AddPrefix("pods/foo")
fakeClient.Data[path] = item.existing fakeClient.Data[path] = item.existing
obj, err := registry.Create(api.NewDefaultContext(), item.toCreate) obj, err := registry.Create(api.NewDefaultContext(), item.toCreate)
if !item.errOK(err) { if !item.errOK(err) {
@ -326,7 +331,6 @@ func TestEtcdCreateWithName(t *testing.T) {
E: tools.EtcdErrorNotFound, E: tools.EtcdErrorNotFound,
} }
path := "/registry/pods/foo"
key := "foo" key := "foo"
table := map[string]struct { table := map[string]struct {
@ -352,6 +356,7 @@ func TestEtcdCreateWithName(t *testing.T) {
for name, item := range table { for name, item := range table {
fakeClient, registry := NewTestGenericEtcdRegistry(t) fakeClient, registry := NewTestGenericEtcdRegistry(t)
path := etcdtest.AddPrefix("pods/foo")
fakeClient.Data[path] = item.existing fakeClient.Data[path] = item.existing
err := registry.CreateWithName(api.NewDefaultContext(), key, item.toCreate) err := registry.CreateWithName(api.NewDefaultContext(), key, item.toCreate)
if !item.errOK(err) { if !item.errOK(err) {
@ -424,8 +429,6 @@ func TestEtcdUpdate(t *testing.T) {
E: tools.EtcdErrorNotFound, E: tools.EtcdErrorNotFound,
} }
path := "/registry/pods/foo"
table := map[string]struct { table := map[string]struct {
existing tools.EtcdResponseWithError existing tools.EtcdResponseWithError
expect tools.EtcdResponseWithError expect tools.EtcdResponseWithError
@ -464,6 +467,7 @@ func TestEtcdUpdate(t *testing.T) {
for name, item := range table { for name, item := range table {
fakeClient, registry := NewTestGenericEtcdRegistry(t) fakeClient, registry := NewTestGenericEtcdRegistry(t)
registry.UpdateStrategy.(*testRESTStrategy).allowCreateOnUpdate = item.allowCreate registry.UpdateStrategy.(*testRESTStrategy).allowCreateOnUpdate = item.allowCreate
path := etcdtest.AddPrefix("pods/foo")
fakeClient.Data[path] = item.existing fakeClient.Data[path] = item.existing
obj, _, err := registry.Update(api.NewDefaultContext(), item.toUpdate) obj, _, err := registry.Update(api.NewDefaultContext(), item.toUpdate)
if !item.errOK(err) { if !item.errOK(err) {
@ -529,7 +533,6 @@ func TestEtcdUpdateWithName(t *testing.T) {
E: tools.EtcdErrorNotFound, E: tools.EtcdErrorNotFound,
} }
path := "/registry/pods/foo"
key := "foo" key := "foo"
table := map[string]struct { table := map[string]struct {
@ -555,6 +558,7 @@ func TestEtcdUpdateWithName(t *testing.T) {
for name, item := range table { for name, item := range table {
fakeClient, registry := NewTestGenericEtcdRegistry(t) fakeClient, registry := NewTestGenericEtcdRegistry(t)
path := etcdtest.AddPrefix("pods/foo")
fakeClient.Data[path] = item.existing fakeClient.Data[path] = item.existing
err := registry.UpdateWithName(api.NewContext(), key, item.toUpdate) err := registry.UpdateWithName(api.NewContext(), key, item.toUpdate)
if !item.errOK(err) { if !item.errOK(err) {
@ -589,7 +593,6 @@ func TestEtcdGet(t *testing.T) {
E: tools.EtcdErrorNotFound, E: tools.EtcdErrorNotFound,
} }
path := "/registry/pods/foo"
key := "foo" key := "foo"
table := map[string]struct { table := map[string]struct {
@ -611,6 +614,7 @@ func TestEtcdGet(t *testing.T) {
for name, item := range table { for name, item := range table {
fakeClient, registry := NewTestGenericEtcdRegistry(t) fakeClient, registry := NewTestGenericEtcdRegistry(t)
path := etcdtest.AddPrefix("pods/foo")
fakeClient.Data[path] = item.existing fakeClient.Data[path] = item.existing
got, err := registry.Get(api.NewContext(), key) got, err := registry.Get(api.NewContext(), key)
if !item.errOK(err) { if !item.errOK(err) {
@ -645,7 +649,6 @@ func TestEtcdDelete(t *testing.T) {
E: tools.EtcdErrorNotFound, E: tools.EtcdErrorNotFound,
} }
path := "/registry/pods/foo"
key := "foo" key := "foo"
table := map[string]struct { table := map[string]struct {
@ -667,6 +670,7 @@ func TestEtcdDelete(t *testing.T) {
for name, item := range table { for name, item := range table {
fakeClient, registry := NewTestGenericEtcdRegistry(t) fakeClient, registry := NewTestGenericEtcdRegistry(t)
path := etcdtest.AddPrefix("pods/foo")
fakeClient.Data[path] = item.existing fakeClient.Data[path] = item.existing
obj, err := registry.Delete(api.NewContext(), key, nil) obj, err := registry.Delete(api.NewContext(), key, nil)
if !item.errOK(err) { if !item.errOK(err) {

View File

@ -31,16 +31,17 @@ type registry struct {
// NewEtcdRegistry returns a registry which will store LimitRange in the given helper // NewEtcdRegistry returns a registry which will store LimitRange in the given helper
func NewEtcdRegistry(h tools.EtcdHelper) generic.Registry { func NewEtcdRegistry(h tools.EtcdHelper) generic.Registry {
prefix := "/limitranges"
return registry{ return registry{
Etcd: &etcdgeneric.Etcd{ Etcd: &etcdgeneric.Etcd{
NewFunc: func() runtime.Object { return &api.LimitRange{} }, NewFunc: func() runtime.Object { return &api.LimitRange{} },
NewListFunc: func() runtime.Object { return &api.LimitRangeList{} }, NewListFunc: func() runtime.Object { return &api.LimitRangeList{} },
EndpointName: "limitranges", EndpointName: "limitranges",
KeyRootFunc: func(ctx api.Context) string { KeyRootFunc: func(ctx api.Context) string {
return etcdgeneric.NamespaceKeyRootFunc(ctx, "/registry/limitranges") return etcdgeneric.NamespaceKeyRootFunc(ctx, prefix)
}, },
KeyFunc: func(ctx api.Context, id string) (string, error) { KeyFunc: func(ctx api.Context, id string) (string, error) {
return etcdgeneric.NamespaceKeyFunc(ctx, "/registry/limitranges", id) return etcdgeneric.NamespaceKeyFunc(ctx, prefix, id)
}, },
Helper: h, Helper: h,
}, },

View File

@ -28,6 +28,7 @@ import (
etcdgeneric "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic/etcd" etcdgeneric "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic/etcd"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools" "github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools/etcdtest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/coreos/go-etcd/etcd" "github.com/coreos/go-etcd/etcd"
@ -36,7 +37,7 @@ import (
func NewTestLimitRangeEtcdRegistry(t *testing.T) (*tools.FakeEtcdClient, generic.Registry) { func NewTestLimitRangeEtcdRegistry(t *testing.T) (*tools.FakeEtcdClient, generic.Registry) {
f := tools.NewFakeEtcdClient(t) f := tools.NewFakeEtcdClient(t)
f.TestIndex = true f.TestIndex = true
h := tools.NewEtcdHelper(f, testapi.Codec()) h := tools.NewEtcdHelper(f, testapi.Codec(), etcdtest.PathPrefix())
return f, NewEtcdRegistry(h) return f, NewEtcdRegistry(h)
} }
@ -81,7 +82,9 @@ func TestLimitRangeCreate(t *testing.T) {
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
key := "foo" key := "foo"
path, err := etcdgeneric.NamespaceKeyFunc(ctx, "/registry/limitranges", key) prefix := etcdtest.AddPrefix("limitranges")
path, err := etcdgeneric.NamespaceKeyFunc(ctx, prefix, key)
if err != nil { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error: %v", err)
} }

View File

@ -50,7 +50,7 @@ func (r *StatusREST) Update(ctx api.Context, obj runtime.Object) (runtime.Object
// NewStorage returns a RESTStorage object that will work against nodes. // NewStorage returns a RESTStorage object that will work against nodes.
func NewStorage(h tools.EtcdHelper, connection client.ConnectionInfoGetter) (*REST, *StatusREST) { func NewStorage(h tools.EtcdHelper, connection client.ConnectionInfoGetter) (*REST, *StatusREST) {
prefix := "/registry/minions" prefix := "/minions"
store := &etcdgeneric.Etcd{ store := &etcdgeneric.Etcd{
NewFunc: func() runtime.Object { return &api.Node{} }, NewFunc: func() runtime.Object { return &api.Node{} },
NewListFunc: func() runtime.Object { return &api.NodeList{} }, NewListFunc: func() runtime.Object { return &api.NodeList{} },

View File

@ -30,6 +30,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools" "github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools/etcdtest"
"github.com/coreos/go-etcd/etcd" "github.com/coreos/go-etcd/etcd"
) )
@ -49,7 +50,7 @@ func (fakeConnectionInfoGetter) GetConnectionInfo(host string) (string, uint, ht
func newHelper(t *testing.T) (*tools.FakeEtcdClient, tools.EtcdHelper) { func newHelper(t *testing.T) (*tools.FakeEtcdClient, tools.EtcdHelper) {
fakeEtcdClient := tools.NewFakeEtcdClient(t) fakeEtcdClient := tools.NewFakeEtcdClient(t)
fakeEtcdClient.TestIndex = true fakeEtcdClient.TestIndex = true
helper := tools.NewEtcdHelper(fakeEtcdClient, latest.Codec) helper := tools.NewEtcdHelper(fakeEtcdClient, latest.Codec, etcdtest.PathPrefix())
return fakeEtcdClient, helper return fakeEtcdClient, helper
} }
@ -107,6 +108,7 @@ func TestDelete(t *testing.T) {
node := validChangedNode() node := validChangedNode()
key, _ := storage.KeyFunc(ctx, node.Name) key, _ := storage.KeyFunc(ctx, node.Name)
key = etcdtest.AddPrefix(key)
createFn := func() runtime.Object { createFn := func() runtime.Object {
fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{ fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
@ -131,6 +133,7 @@ func TestEtcdListNodes(t *testing.T) {
ctx := api.NewContext() ctx := api.NewContext()
storage, fakeClient := newStorage(t) storage, fakeClient := newStorage(t)
key := storage.KeyRootFunc(ctx) key := storage.KeyRootFunc(ctx)
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
@ -165,6 +168,7 @@ func TestEtcdListNodesMatch(t *testing.T) {
ctx := api.NewContext() ctx := api.NewContext()
storage, fakeClient := newStorage(t) storage, fakeClient := newStorage(t)
key := storage.KeyRootFunc(ctx) key := storage.KeyRootFunc(ctx)
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
@ -209,6 +213,7 @@ func TestEtcdGetNode(t *testing.T) {
storage, fakeClient := newStorage(t) storage, fakeClient := newStorage(t)
node := validNewNode() node := validNewNode()
key, _ := storage.KeyFunc(ctx, node.Name) key, _ := storage.KeyFunc(ctx, node.Name)
key = etcdtest.AddPrefix(key)
fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, node), 0) fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, node), 0)
nodeObj, err := storage.Get(ctx, node.Name) nodeObj, err := storage.Get(ctx, node.Name)
@ -229,6 +234,7 @@ func TestEtcdUpdateEndpoints(t *testing.T) {
node := validChangedNode() node := validChangedNode()
key, _ := storage.KeyFunc(ctx, node.Name) key, _ := storage.KeyFunc(ctx, node.Name)
key = etcdtest.AddPrefix(key)
fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, validNewNode()), 0) fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, validNewNode()), 0)
_, _, err := storage.Update(ctx, node) _, _, err := storage.Update(ctx, node)
@ -255,7 +261,8 @@ func TestEtcdUpdateEndpoints(t *testing.T) {
func TestEtcdGetNodeNotFound(t *testing.T) { func TestEtcdGetNodeNotFound(t *testing.T) {
ctx := api.NewContext() ctx := api.NewContext()
storage, fakeClient := newStorage(t) storage, fakeClient := newStorage(t)
fakeClient.Data["/registry/minions/foo"] = tools.EtcdResponseWithError{ key := etcdtest.AddPrefix("minions/foo")
fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: nil, Node: nil,
}, },
@ -273,6 +280,7 @@ func TestEtcdDeleteNode(t *testing.T) {
storage, fakeClient := newStorage(t) storage, fakeClient := newStorage(t)
node := validNewNode() node := validNewNode()
key, _ := storage.KeyFunc(ctx, node.Name) key, _ := storage.KeyFunc(ctx, node.Name)
key = etcdtest.AddPrefix(key)
fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, node), 0) fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, node), 0)
_, err := storage.Delete(ctx, node.Name, nil) _, err := storage.Delete(ctx, node.Name, nil)
if err != nil { if err != nil {

View File

@ -18,6 +18,7 @@ package etcd
import ( import (
"fmt" "fmt"
"path"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/fields" "github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
@ -48,14 +49,15 @@ type FinalizeREST struct {
// NewStorage returns a RESTStorage object that will work against namespaces // NewStorage returns a RESTStorage object that will work against namespaces
func NewStorage(h tools.EtcdHelper) (*REST, *StatusREST, *FinalizeREST) { func NewStorage(h tools.EtcdHelper) (*REST, *StatusREST, *FinalizeREST) {
prefix := "/namespaces"
store := &etcdgeneric.Etcd{ store := &etcdgeneric.Etcd{
NewFunc: func() runtime.Object { return &api.Namespace{} }, NewFunc: func() runtime.Object { return &api.Namespace{} },
NewListFunc: func() runtime.Object { return &api.NamespaceList{} }, NewListFunc: func() runtime.Object { return &api.NamespaceList{} },
KeyRootFunc: func(ctx api.Context) string { KeyRootFunc: func(ctx api.Context) string {
return "/registry/namespaces" return prefix
}, },
KeyFunc: func(ctx api.Context, name string) (string, error) { KeyFunc: func(ctx api.Context, name string) (string, error) {
return "/registry/namespaces/" + name, nil return path.Join(prefix, name), nil
}, },
ObjectNameFunc: func(obj runtime.Object) (string, error) { ObjectNameFunc: func(obj runtime.Object) (string, error) {
return obj.(*api.Namespace).Name, nil return obj.(*api.Namespace).Name, nil

View File

@ -27,6 +27,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/namespace" "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/namespace"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools" "github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools/etcdtest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/coreos/go-etcd/etcd" "github.com/coreos/go-etcd/etcd"
@ -35,7 +36,7 @@ import (
func newHelper(t *testing.T) (*tools.FakeEtcdClient, tools.EtcdHelper) { func newHelper(t *testing.T) (*tools.FakeEtcdClient, tools.EtcdHelper) {
fakeEtcdClient := tools.NewFakeEtcdClient(t) fakeEtcdClient := tools.NewFakeEtcdClient(t)
fakeEtcdClient.TestIndex = true fakeEtcdClient.TestIndex = true
helper := tools.NewEtcdHelper(fakeEtcdClient, latest.Codec) helper := tools.NewEtcdHelper(fakeEtcdClient, latest.Codec, etcdtest.PathPrefix())
return fakeEtcdClient, helper return fakeEtcdClient, helper
} }
@ -102,7 +103,12 @@ func TestCreateSetsFields(t *testing.T) {
} }
actual := &api.Namespace{} actual := &api.Namespace{}
if err := helper.ExtractObj("/registry/namespaces/foo", actual, false); err != nil { ctx := api.NewDefaultContext()
key, err := storage.Etcd.KeyFunc(ctx, "foo")
if err != nil {
t.Fatalf("unexpected key error: %v", err)
}
if err := helper.ExtractObj(key, actual, false); err != nil {
t.Fatalf("unexpected extraction error: %v", err) t.Fatalf("unexpected extraction error: %v", err)
} }
if actual.Name != namespace.Name { if actual.Name != namespace.Name {
@ -119,7 +125,8 @@ func TestCreateSetsFields(t *testing.T) {
func TestListEmptyNamespaceList(t *testing.T) { func TestListEmptyNamespaceList(t *testing.T) {
fakeEtcdClient, helper := newHelper(t) fakeEtcdClient, helper := newHelper(t)
fakeEtcdClient.ChangeIndex = 1 fakeEtcdClient.ChangeIndex = 1
fakeEtcdClient.Data["/registry/namespaces"] = tools.EtcdResponseWithError{ key := etcdtest.AddPrefix("/namespaces")
fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{}, R: &etcd.Response{},
E: fakeEtcdClient.NewError(tools.EtcdErrorCodeNotFound), E: fakeEtcdClient.NewError(tools.EtcdErrorCodeNotFound),
} }
@ -139,7 +146,8 @@ func TestListEmptyNamespaceList(t *testing.T) {
func TestListNamespaceList(t *testing.T) { func TestListNamespaceList(t *testing.T) {
fakeEtcdClient, helper := newHelper(t) fakeEtcdClient, helper := newHelper(t)
fakeEtcdClient.Data["/registry/namespaces"] = tools.EtcdResponseWithError{ key := etcdtest.AddPrefix("/namespaces")
fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
Nodes: []*etcd.Node{ Nodes: []*etcd.Node{
@ -177,7 +185,8 @@ func TestListNamespaceList(t *testing.T) {
func TestListNamespaceListSelection(t *testing.T) { func TestListNamespaceListSelection(t *testing.T) {
fakeEtcdClient, helper := newHelper(t) fakeEtcdClient, helper := newHelper(t)
fakeEtcdClient.Data["/registry/namespaces"] = tools.EtcdResponseWithError{ key := etcdtest.AddPrefix("/namespaces")
fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
Nodes: []*etcd.Node{ Nodes: []*etcd.Node{
@ -275,15 +284,20 @@ func TestNamespaceDecode(t *testing.T) {
func TestGet(t *testing.T) { func TestGet(t *testing.T) {
expect := validNewNamespace() expect := validNewNamespace()
expect.Status.Phase = api.NamespaceActive expect.Status.Phase = api.NamespaceActive
fakeEtcdClient, helper := newHelper(t) storage, fakeEtcdClient, _ := newStorage(t)
fakeEtcdClient.Data["/registry/namespaces/foo"] = tools.EtcdResponseWithError{ ctx := api.NewDefaultContext()
key, err := storage.Etcd.KeyFunc(ctx, "foo")
key = etcdtest.AddPrefix(key)
if err != nil {
t.Fatalf("unexpected key error: %v", err)
}
fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
Value: runtime.EncodeOrDie(latest.Codec, expect), Value: runtime.EncodeOrDie(latest.Codec, expect),
}, },
}, },
} }
storage, _, _ := NewStorage(helper)
obj, err := storage.Get(api.NewContext(), "foo") obj, err := storage.Get(api.NewContext(), "foo")
namespace := obj.(*api.Namespace) namespace := obj.(*api.Namespace)
if err != nil { if err != nil {
@ -299,7 +313,11 @@ func TestGet(t *testing.T) {
func TestDeleteNamespace(t *testing.T) { func TestDeleteNamespace(t *testing.T) {
fakeEtcdClient, helper := newHelper(t) fakeEtcdClient, helper := newHelper(t)
fakeEtcdClient.ChangeIndex = 1 fakeEtcdClient.ChangeIndex = 1
fakeEtcdClient.Data["/registry/namespaces/foo"] = tools.EtcdResponseWithError{ storage, _, _ := NewStorage(helper)
ctx := api.NewDefaultContext()
key, err := storage.Etcd.KeyFunc(ctx, "foo")
key = etcdtest.AddPrefix(key)
fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
Value: runtime.EncodeOrDie(latest.Codec, &api.Namespace{ Value: runtime.EncodeOrDie(latest.Codec, &api.Namespace{
@ -313,8 +331,7 @@ func TestDeleteNamespace(t *testing.T) {
}, },
}, },
} }
storage, _, _ := NewStorage(helper) _, err = storage.Delete(api.NewDefaultContext(), "foo", nil)
_, err := storage.Delete(api.NewDefaultContext(), "foo", nil)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
@ -325,7 +342,8 @@ func TestDeleteNamespaceWithIncompleteFinalizers(t *testing.T) {
now := util.Now() now := util.Now()
fakeEtcdClient, helper := newHelper(t) fakeEtcdClient, helper := newHelper(t)
fakeEtcdClient.ChangeIndex = 1 fakeEtcdClient.ChangeIndex = 1
fakeEtcdClient.Data["/registry/namespaces/foo"] = tools.EtcdResponseWithError{ key := etcdtest.AddPrefix("/namespaces/foo")
fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
Value: runtime.EncodeOrDie(latest.Codec, &api.Namespace{ Value: runtime.EncodeOrDie(latest.Codec, &api.Namespace{
@ -354,7 +372,8 @@ func TestDeleteNamespaceWithCompleteFinalizers(t *testing.T) {
now := util.Now() now := util.Now()
fakeEtcdClient, helper := newHelper(t) fakeEtcdClient, helper := newHelper(t)
fakeEtcdClient.ChangeIndex = 1 fakeEtcdClient.ChangeIndex = 1
fakeEtcdClient.Data["/registry/namespaces/foo"] = tools.EtcdResponseWithError{ key := etcdtest.AddPrefix("/namespaces/foo")
fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
Value: runtime.EncodeOrDie(latest.Codec, &api.Namespace{ Value: runtime.EncodeOrDie(latest.Codec, &api.Namespace{

View File

@ -17,6 +17,8 @@ limitations under the License.
package etcd package etcd
import ( import (
"path"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/fields" "github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
@ -34,7 +36,7 @@ type REST struct {
// NewREST returns a RESTStorage object that will work against PersistentVolume objects. // NewREST returns a RESTStorage object that will work against PersistentVolume objects.
func NewStorage(h tools.EtcdHelper) (*REST, *StatusREST) { func NewStorage(h tools.EtcdHelper) (*REST, *StatusREST) {
prefix := "/registry/persistentvolumes" prefix := "/persistentvolumes"
store := &etcdgeneric.Etcd{ store := &etcdgeneric.Etcd{
NewFunc: func() runtime.Object { return &api.PersistentVolume{} }, NewFunc: func() runtime.Object { return &api.PersistentVolume{} },
NewListFunc: func() runtime.Object { return &api.PersistentVolumeList{} }, NewListFunc: func() runtime.Object { return &api.PersistentVolumeList{} },
@ -42,7 +44,7 @@ func NewStorage(h tools.EtcdHelper) (*REST, *StatusREST) {
return prefix return prefix
}, },
KeyFunc: func(ctx api.Context, name string) (string, error) { KeyFunc: func(ctx api.Context, name string) (string, error) {
return prefix + "/" + name, nil return path.Join(prefix, name), nil
}, },
ObjectNameFunc: func(obj runtime.Object) (string, error) { ObjectNameFunc: func(obj runtime.Object) (string, error) {
return obj.(*api.PersistentVolume).Name, nil return obj.(*api.PersistentVolume).Name, nil

View File

@ -28,6 +28,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/registrytest" "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/registrytest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools" "github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools/etcdtest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/coreos/go-etcd/etcd" "github.com/coreos/go-etcd/etcd"
@ -40,7 +41,7 @@ type testRegistry struct {
func newStorage(t *testing.T) (*REST, *StatusREST, *tools.FakeEtcdClient, tools.EtcdHelper) { func newStorage(t *testing.T) (*REST, *StatusREST, *tools.FakeEtcdClient, tools.EtcdHelper) {
fakeEtcdClient := tools.NewFakeEtcdClient(t) fakeEtcdClient := tools.NewFakeEtcdClient(t)
fakeEtcdClient.TestIndex = true fakeEtcdClient.TestIndex = true
helper := tools.NewEtcdHelper(fakeEtcdClient, latest.Codec) helper := tools.NewEtcdHelper(fakeEtcdClient, latest.Codec, etcdtest.PathPrefix())
storage, statusStorage := NewStorage(helper) storage, statusStorage := NewStorage(helper)
return storage, statusStorage, fakeEtcdClient, helper return storage, statusStorage, fakeEtcdClient, helper
} }
@ -93,6 +94,7 @@ func TestDelete(t *testing.T) {
pv := validChangedPersistentVolume() pv := validChangedPersistentVolume()
key, _ := storage.KeyFunc(ctx, pv.Name) key, _ := storage.KeyFunc(ctx, pv.Name)
key = etcdtest.AddPrefix(key)
createFn := func() runtime.Object { createFn := func() runtime.Object {
fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{ fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
@ -117,6 +119,7 @@ func TestEtcdListPersistentVolumes(t *testing.T) {
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
storage, _, fakeClient, _ := newStorage(t) storage, _, fakeClient, _ := newStorage(t)
key := storage.KeyRootFunc(ctx) key := storage.KeyRootFunc(ctx)
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
@ -150,6 +153,7 @@ func TestEtcdGetPersistentVolumes(t *testing.T) {
persistentVolume := validNewPersistentVolume("foo") persistentVolume := validNewPersistentVolume("foo")
name := persistentVolume.Name name := persistentVolume.Name
key, _ := storage.KeyFunc(ctx, name) key, _ := storage.KeyFunc(ctx, name)
key = etcdtest.AddPrefix(key)
fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, persistentVolume), 0) fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, persistentVolume), 0)
response, err := fakeClient.Get(key, false, false) response, err := fakeClient.Get(key, false, false)
@ -179,6 +183,7 @@ func TestListEmptyPersistentVolumesList(t *testing.T) {
storage, _, fakeClient, _ := newStorage(t) storage, _, fakeClient, _ := newStorage(t)
fakeClient.ChangeIndex = 1 fakeClient.ChangeIndex = 1
key := storage.KeyRootFunc(ctx) key := storage.KeyRootFunc(ctx)
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{}, R: &etcd.Response{},
E: fakeClient.NewError(tools.EtcdErrorCodeNotFound), E: fakeClient.NewError(tools.EtcdErrorCodeNotFound),
@ -202,6 +207,7 @@ func TestListPersistentVolumesList(t *testing.T) {
storage, _, fakeClient, _ := newStorage(t) storage, _, fakeClient, _ := newStorage(t)
fakeClient.ChangeIndex = 1 fakeClient.ChangeIndex = 1
key := storage.KeyRootFunc(ctx) key := storage.KeyRootFunc(ctx)
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
@ -262,6 +268,7 @@ func TestEtcdUpdatePersistentVolumes(t *testing.T) {
persistentVolume := validChangedPersistentVolume() persistentVolume := validChangedPersistentVolume()
key, _ := storage.KeyFunc(ctx, "foo") key, _ := storage.KeyFunc(ctx, "foo")
key = etcdtest.AddPrefix(key)
fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, validNewPersistentVolume("foo")), 0) fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, validNewPersistentVolume("foo")), 0)
_, _, err := storage.Update(ctx, persistentVolume) _, _, err := storage.Update(ctx, persistentVolume)
@ -291,6 +298,7 @@ func TestDeletePersistentVolumes(t *testing.T) {
persistentVolume := validNewPersistentVolume("foo") persistentVolume := validNewPersistentVolume("foo")
name := persistentVolume.Name name := persistentVolume.Name
key, _ := storage.KeyFunc(ctx, name) key, _ := storage.KeyFunc(ctx, name)
key = etcdtest.AddPrefix(key)
fakeClient.ChangeIndex = 1 fakeClient.ChangeIndex = 1
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
@ -313,6 +321,7 @@ func TestEtcdUpdateStatus(t *testing.T) {
fakeClient.TestIndex = true fakeClient.TestIndex = true
key, _ := storage.KeyFunc(ctx, "foo") key, _ := storage.KeyFunc(ctx, "foo")
key = etcdtest.AddPrefix(key)
pvStart := validNewPersistentVolume("foo") pvStart := validNewPersistentVolume("foo")
fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, pvStart), 1) fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, pvStart), 1)
@ -336,6 +345,7 @@ func TestEtcdUpdateStatus(t *testing.T) {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }
var pvOut api.PersistentVolume var pvOut api.PersistentVolume
key, _ = storage.KeyFunc(ctx, "foo")
if err := helper.ExtractObj(key, &pvOut, false); err != nil { if err := helper.ExtractObj(key, &pvOut, false); err != nil {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }

View File

@ -34,7 +34,7 @@ type REST struct {
// NewREST returns a RESTStorage object that will work against PersistentVolumeClaim objects. // NewREST returns a RESTStorage object that will work against PersistentVolumeClaim objects.
func NewStorage(h tools.EtcdHelper) (*REST, *StatusREST) { func NewStorage(h tools.EtcdHelper) (*REST, *StatusREST) {
prefix := "/registry/persistentvolumeclaims" prefix := "/persistentvolumeclaims"
store := &etcdgeneric.Etcd{ store := &etcdgeneric.Etcd{
NewFunc: func() runtime.Object { return &api.PersistentVolumeClaim{} }, NewFunc: func() runtime.Object { return &api.PersistentVolumeClaim{} },
NewListFunc: func() runtime.Object { return &api.PersistentVolumeClaimList{} }, NewListFunc: func() runtime.Object { return &api.PersistentVolumeClaimList{} },

View File

@ -28,6 +28,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/registrytest" "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/registrytest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools" "github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools/etcdtest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/coreos/go-etcd/etcd" "github.com/coreos/go-etcd/etcd"
@ -40,7 +41,7 @@ type testRegistry struct {
func newStorage(t *testing.T) (*REST, *StatusREST, *tools.FakeEtcdClient, tools.EtcdHelper) { func newStorage(t *testing.T) (*REST, *StatusREST, *tools.FakeEtcdClient, tools.EtcdHelper) {
fakeEtcdClient := tools.NewFakeEtcdClient(t) fakeEtcdClient := tools.NewFakeEtcdClient(t)
fakeEtcdClient.TestIndex = true fakeEtcdClient.TestIndex = true
helper := tools.NewEtcdHelper(fakeEtcdClient, latest.Codec) helper := tools.NewEtcdHelper(fakeEtcdClient, latest.Codec, etcdtest.PathPrefix())
storage, statusStorage := NewStorage(helper) storage, statusStorage := NewStorage(helper)
return storage, statusStorage, fakeEtcdClient, helper return storage, statusStorage, fakeEtcdClient, helper
} }
@ -95,6 +96,7 @@ func TestDelete(t *testing.T) {
pv := validChangedPersistentVolumeClaim() pv := validChangedPersistentVolumeClaim()
key, _ := storage.KeyFunc(ctx, pv.Name) key, _ := storage.KeyFunc(ctx, pv.Name)
key = etcdtest.AddPrefix(key)
createFn := func() runtime.Object { createFn := func() runtime.Object {
fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{ fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
@ -119,6 +121,7 @@ func TestEtcdListPersistentVolumeClaims(t *testing.T) {
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
registry, _, fakeClient, _ := newStorage(t) registry, _, fakeClient, _ := newStorage(t)
key := registry.KeyRootFunc(ctx) key := registry.KeyRootFunc(ctx)
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
@ -152,6 +155,7 @@ func TestEtcdGetPersistentVolumeClaims(t *testing.T) {
persistentVolume := validNewPersistentVolumeClaim("foo", api.NamespaceDefault) persistentVolume := validNewPersistentVolumeClaim("foo", api.NamespaceDefault)
name := persistentVolume.Name name := persistentVolume.Name
key, _ := registry.KeyFunc(ctx, name) key, _ := registry.KeyFunc(ctx, name)
key = etcdtest.AddPrefix(key)
fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, persistentVolume), 0) fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, persistentVolume), 0)
response, err := fakeClient.Get(key, false, false) response, err := fakeClient.Get(key, false, false)
@ -181,6 +185,7 @@ func TestListEmptyPersistentVolumeClaimsList(t *testing.T) {
registry, _, fakeClient, _ := newStorage(t) registry, _, fakeClient, _ := newStorage(t)
fakeClient.ChangeIndex = 1 fakeClient.ChangeIndex = 1
key := registry.KeyRootFunc(ctx) key := registry.KeyRootFunc(ctx)
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{}, R: &etcd.Response{},
E: fakeClient.NewError(tools.EtcdErrorCodeNotFound), E: fakeClient.NewError(tools.EtcdErrorCodeNotFound),
@ -204,6 +209,7 @@ func TestListPersistentVolumeClaimsList(t *testing.T) {
registry, _, fakeClient, _ := newStorage(t) registry, _, fakeClient, _ := newStorage(t)
fakeClient.ChangeIndex = 1 fakeClient.ChangeIndex = 1
key := registry.KeyRootFunc(ctx) key := registry.KeyRootFunc(ctx)
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
@ -264,6 +270,7 @@ func TestEtcdUpdatePersistentVolumeClaims(t *testing.T) {
persistentVolume := validChangedPersistentVolumeClaim() persistentVolume := validChangedPersistentVolumeClaim()
key, _ := registry.KeyFunc(ctx, "foo") key, _ := registry.KeyFunc(ctx, "foo")
key = etcdtest.AddPrefix(key)
fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, validNewPersistentVolumeClaim("foo", api.NamespaceDefault)), 0) fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, validNewPersistentVolumeClaim("foo", api.NamespaceDefault)), 0)
_, _, err := registry.Update(ctx, persistentVolume) _, _, err := registry.Update(ctx, persistentVolume)
@ -293,6 +300,7 @@ func TestDeletePersistentVolumeClaims(t *testing.T) {
pvClaim := validNewPersistentVolumeClaim("foo", api.NamespaceDefault) pvClaim := validNewPersistentVolumeClaim("foo", api.NamespaceDefault)
name := pvClaim.Name name := pvClaim.Name
key, _ := registry.KeyFunc(ctx, name) key, _ := registry.KeyFunc(ctx, name)
key = etcdtest.AddPrefix(key)
fakeClient.ChangeIndex = 1 fakeClient.ChangeIndex = 1
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
@ -315,6 +323,7 @@ func TestEtcdUpdateStatus(t *testing.T) {
fakeClient.TestIndex = true fakeClient.TestIndex = true
key, _ := storage.KeyFunc(ctx, "foo") key, _ := storage.KeyFunc(ctx, "foo")
key = etcdtest.AddPrefix(key)
pvcStart := validNewPersistentVolumeClaim("foo", api.NamespaceDefault) pvcStart := validNewPersistentVolumeClaim("foo", api.NamespaceDefault)
fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, pvcStart), 1) fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, pvcStart), 1)
@ -339,6 +348,7 @@ func TestEtcdUpdateStatus(t *testing.T) {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }
var pvcOut api.PersistentVolumeClaim var pvcOut api.PersistentVolumeClaim
key, _ = storage.KeyFunc(ctx, "foo")
if err := helper.ExtractObj(key, &pvcOut, false); err != nil { if err := helper.ExtractObj(key, &pvcOut, false); err != nil {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }

View File

@ -56,7 +56,7 @@ type REST struct {
// NewStorage returns a RESTStorage object that will work against pods. // NewStorage returns a RESTStorage object that will work against pods.
func NewStorage(h tools.EtcdHelper, k client.ConnectionInfoGetter) PodStorage { func NewStorage(h tools.EtcdHelper, k client.ConnectionInfoGetter) PodStorage {
prefix := "/registry/pods" prefix := "/pods"
store := &etcdgeneric.Etcd{ store := &etcdgeneric.Etcd{
NewFunc: func() runtime.Object { return &api.Pod{} }, NewFunc: func() runtime.Object { return &api.Pod{} },
NewListFunc: func() runtime.Object { return &api.PodList{} }, NewListFunc: func() runtime.Object { return &api.PodList{} },

View File

@ -33,6 +33,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/pod" "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/pod"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools" "github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools/etcdtest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/coreos/go-etcd/etcd" "github.com/coreos/go-etcd/etcd"
@ -41,7 +42,7 @@ import (
func newHelper(t *testing.T) (*tools.FakeEtcdClient, tools.EtcdHelper) { func newHelper(t *testing.T) (*tools.FakeEtcdClient, tools.EtcdHelper) {
fakeEtcdClient := tools.NewFakeEtcdClient(t) fakeEtcdClient := tools.NewFakeEtcdClient(t)
fakeEtcdClient.TestIndex = true fakeEtcdClient.TestIndex = true
helper := tools.NewEtcdHelper(fakeEtcdClient, latest.Codec) helper := tools.NewEtcdHelper(fakeEtcdClient, latest.Codec, etcdtest.PathPrefix())
return fakeEtcdClient, helper return fakeEtcdClient, helper
} }
@ -108,11 +109,14 @@ func TestCreate(t *testing.T) {
func TestDelete(t *testing.T) { func TestDelete(t *testing.T) {
fakeEtcdClient, helper := newHelper(t) fakeEtcdClient, helper := newHelper(t)
storage := NewStorage(helper, nil).Pod storage := NewStorage(helper, nil).Pod
ctx := api.NewDefaultContext()
key, _ := storage.Etcd.KeyFunc(ctx, "foo")
key = etcdtest.AddPrefix(key)
test := resttest.New(t, storage, fakeEtcdClient.SetError) test := resttest.New(t, storage, fakeEtcdClient.SetError)
createFn := func() runtime.Object { createFn := func() runtime.Object {
pod := validChangedPod() pod := validChangedPod()
fakeEtcdClient.Data["/registry/pods/default/foo"] = tools.EtcdResponseWithError{ fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
Value: runtime.EncodeOrDie(latest.Codec, pod), Value: runtime.EncodeOrDie(latest.Codec, pod),
@ -123,10 +127,10 @@ func TestDelete(t *testing.T) {
return pod return pod
} }
gracefulSetFn := func() bool { gracefulSetFn := func() bool {
if fakeEtcdClient.Data["/registry/pods/default/foo"].R.Node == nil { if fakeEtcdClient.Data[key].R.Node == nil {
return false return false
} }
return fakeEtcdClient.Data["/registry/pods/default/foo"].R.Node.TTL == 30 return fakeEtcdClient.Data[key].R.Node.TTL == 30
} }
test.TestDelete(createFn, gracefulSetFn) test.TestDelete(createFn, gracefulSetFn)
} }
@ -160,9 +164,10 @@ func TestCreateSetsFields(t *testing.T) {
if err != fakeEtcdClient.Err { if err != fakeEtcdClient.Err {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
ctx := api.NewDefaultContext()
key, _ := storage.Etcd.KeyFunc(ctx, "foo")
actual := &api.Pod{} actual := &api.Pod{}
if err := helper.ExtractObj("/registry/pods/default/foo", actual, false); err != nil { if err := helper.ExtractObj(key, actual, false); err != nil {
t.Fatalf("unexpected extraction error: %v", err) t.Fatalf("unexpected extraction error: %v", err)
} }
if actual.Name != pod.Name { if actual.Name != pod.Name {
@ -189,12 +194,15 @@ func TestListError(t *testing.T) {
func TestListEmptyPodList(t *testing.T) { func TestListEmptyPodList(t *testing.T) {
fakeEtcdClient, helper := newHelper(t) fakeEtcdClient, helper := newHelper(t)
fakeEtcdClient.ChangeIndex = 1 fakeEtcdClient.ChangeIndex = 1
fakeEtcdClient.Data["/registry/pods"] = tools.EtcdResponseWithError{ ctx := api.NewContext()
storage := NewStorage(helper, nil).Pod
key := storage.Etcd.KeyRootFunc(ctx)
key = etcdtest.AddPrefix(key)
fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{}, R: &etcd.Response{},
E: fakeEtcdClient.NewError(tools.EtcdErrorCodeNotFound), E: fakeEtcdClient.NewError(tools.EtcdErrorCodeNotFound),
} }
storage := NewStorage(helper, nil).Pod
pods, err := storage.List(api.NewContext(), labels.Everything(), fields.Everything()) pods, err := storage.List(api.NewContext(), labels.Everything(), fields.Everything())
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
@ -210,7 +218,11 @@ func TestListEmptyPodList(t *testing.T) {
func TestListPodList(t *testing.T) { func TestListPodList(t *testing.T) {
fakeEtcdClient, helper := newHelper(t) fakeEtcdClient, helper := newHelper(t)
fakeEtcdClient.Data["/registry/pods/default"] = tools.EtcdResponseWithError{ ctx := api.NewDefaultContext()
storage := NewStorage(helper, nil).Pod
key := storage.Etcd.KeyRootFunc(ctx)
key = etcdtest.AddPrefix(key)
fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
Nodes: []*etcd.Node{ Nodes: []*etcd.Node{
@ -231,7 +243,6 @@ func TestListPodList(t *testing.T) {
}, },
}, },
} }
storage := NewStorage(helper, nil).Pod
podsObj, err := storage.List(api.NewDefaultContext(), labels.Everything(), fields.Everything()) podsObj, err := storage.List(api.NewDefaultContext(), labels.Everything(), fields.Everything())
pods := podsObj.(*api.PodList) pods := podsObj.(*api.PodList)
@ -252,7 +263,11 @@ func TestListPodList(t *testing.T) {
func TestListPodListSelection(t *testing.T) { func TestListPodListSelection(t *testing.T) {
fakeEtcdClient, helper := newHelper(t) fakeEtcdClient, helper := newHelper(t)
fakeEtcdClient.Data["/registry/pods/default"] = tools.EtcdResponseWithError{ ctx := api.NewDefaultContext()
storage := NewStorage(helper, nil).Pod
rootKey := etcdtest.AddPrefix("pods/default")
key := etcdtest.AddPrefix("pods/default/zot")
fakeEtcdClient.Data[rootKey] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
Nodes: []*etcd.Node{ Nodes: []*etcd.Node{
@ -280,7 +295,7 @@ func TestListPodListSelection(t *testing.T) {
}, },
}, },
} }
fakeEtcdClient.Data["/registry/pods/default/zot"] = tools.EtcdResponseWithError{ fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
Value: runtime.EncodeOrDie(latest.Codec, &api.Pod{ Value: runtime.EncodeOrDie(latest.Codec, &api.Pod{
@ -289,9 +304,6 @@ func TestListPodListSelection(t *testing.T) {
}, },
}, },
} }
storage := NewStorage(helper, nil).Pod
ctx := api.NewDefaultContext()
table := []struct { table := []struct {
label, field string label, field string
@ -377,7 +389,8 @@ func TestGet(t *testing.T) {
expect.Spec.Host = "machine" expect.Spec.Host = "machine"
fakeEtcdClient, helper := newHelper(t) fakeEtcdClient, helper := newHelper(t)
fakeEtcdClient.Data["/registry/pods/test/foo"] = tools.EtcdResponseWithError{ key := etcdtest.AddPrefix("/pods/test/foo")
fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
Value: runtime.EncodeOrDie(latest.Codec, expect), Value: runtime.EncodeOrDie(latest.Codec, expect),
@ -420,6 +433,8 @@ func TestPodStorageValidatesCreate(t *testing.T) {
func TestCreatePod(t *testing.T) { func TestCreatePod(t *testing.T) {
_, helper := newHelper(t) _, helper := newHelper(t)
storage := NewStorage(helper, nil).Pod storage := NewStorage(helper, nil).Pod
ctx := api.NewDefaultContext()
key, _ := storage.Etcd.KeyFunc(ctx, "foo")
pod := validNewPod() pod := validNewPod()
obj, err := storage.Create(api.NewDefaultContext(), pod) obj, err := storage.Create(api.NewDefaultContext(), pod)
@ -430,7 +445,7 @@ func TestCreatePod(t *testing.T) {
t.Fatalf("unexpected object: %#v", obj) t.Fatalf("unexpected object: %#v", obj)
} }
actual := &api.Pod{} actual := &api.Pod{}
if err := helper.ExtractObj("/registry/pods/default/foo", actual, false); err != nil { if err := helper.ExtractObj(key, actual, false); err != nil {
t.Fatalf("unexpected extraction error: %v", err) t.Fatalf("unexpected extraction error: %v", err)
} }
if !api.HasObjectMetaSystemFieldValues(&actual.ObjectMeta) { if !api.HasObjectMetaSystemFieldValues(&actual.ObjectMeta) {
@ -459,7 +474,11 @@ func TestCreateWithConflictingNamespace(t *testing.T) {
func TestUpdateWithConflictingNamespace(t *testing.T) { func TestUpdateWithConflictingNamespace(t *testing.T) {
fakeEtcdClient, helper := newHelper(t) fakeEtcdClient, helper := newHelper(t)
fakeEtcdClient.Data["/registry/pods/default/foo"] = tools.EtcdResponseWithError{ storage := NewStorage(helper, nil).Pod
ctx := api.NewDefaultContext()
key, _ := storage.Etcd.KeyFunc(ctx, "foo")
key = etcdtest.AddPrefix(key)
fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
Value: runtime.EncodeOrDie(latest.Codec, &api.Pod{ Value: runtime.EncodeOrDie(latest.Codec, &api.Pod{
@ -470,7 +489,6 @@ func TestUpdateWithConflictingNamespace(t *testing.T) {
}, },
}, },
} }
storage := NewStorage(helper, nil).Pod
pod := validChangedPod() pod := validChangedPod()
pod.Namespace = "not-default" pod.Namespace = "not-default"
@ -578,16 +596,19 @@ func TestResourceLocation(t *testing.T) {
}, },
} }
ctx := api.NewDefaultContext()
for _, tc := range testCases { for _, tc := range testCases {
fakeEtcdClient, helper := newHelper(t) fakeEtcdClient, helper := newHelper(t)
fakeEtcdClient.Data["/registry/pods/default/foo"] = tools.EtcdResponseWithError{ storage := NewStorage(helper, nil).Pod
key, _ := storage.Etcd.KeyFunc(ctx, "foo")
key = etcdtest.AddPrefix(key)
fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
Value: runtime.EncodeOrDie(latest.Codec, &tc.pod), Value: runtime.EncodeOrDie(latest.Codec, &tc.pod),
}, },
}, },
} }
storage := NewStorage(helper, nil).Pod
redirector := rest.Redirector(storage) redirector := rest.Redirector(storage)
location, _, err := redirector.ResourceLocation(api.NewDefaultContext(), tc.query) location, _, err := redirector.ResourceLocation(api.NewDefaultContext(), tc.query)
@ -610,7 +631,11 @@ func TestResourceLocation(t *testing.T) {
func TestDeletePod(t *testing.T) { func TestDeletePod(t *testing.T) {
fakeEtcdClient, helper := newHelper(t) fakeEtcdClient, helper := newHelper(t)
fakeEtcdClient.ChangeIndex = 1 fakeEtcdClient.ChangeIndex = 1
fakeEtcdClient.Data["/registry/pods/default/foo"] = tools.EtcdResponseWithError{ storage := NewStorage(helper, nil).Pod
ctx := api.NewDefaultContext()
key, _ := storage.Etcd.KeyFunc(ctx, "foo")
key = etcdtest.AddPrefix(key)
fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
Value: runtime.EncodeOrDie(latest.Codec, &api.Pod{ Value: runtime.EncodeOrDie(latest.Codec, &api.Pod{
@ -625,8 +650,6 @@ func TestDeletePod(t *testing.T) {
}, },
}, },
} }
storage := NewStorage(helper, nil).Pod
_, err := storage.Delete(api.NewDefaultContext(), "foo", nil) _, err := storage.Delete(api.NewDefaultContext(), "foo", nil)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
@ -643,6 +666,9 @@ func TestEtcdGetDifferentNamespace(t *testing.T) {
key1, _ := registry.KeyFunc(ctx1, "foo") key1, _ := registry.KeyFunc(ctx1, "foo")
key2, _ := registry.KeyFunc(ctx2, "foo") key2, _ := registry.KeyFunc(ctx2, "foo")
key1 = etcdtest.AddPrefix(key1)
key2 = etcdtest.AddPrefix(key2)
fakeClient.Set(key1, runtime.EncodeOrDie(latest.Codec, &api.Pod{ObjectMeta: api.ObjectMeta{Namespace: "default", Name: "foo"}}), 0) fakeClient.Set(key1, runtime.EncodeOrDie(latest.Codec, &api.Pod{ObjectMeta: api.ObjectMeta{Namespace: "default", Name: "foo"}}), 0)
fakeClient.Set(key2, runtime.EncodeOrDie(latest.Codec, &api.Pod{ObjectMeta: api.ObjectMeta{Namespace: "other", Name: "foo"}}), 0) fakeClient.Set(key2, runtime.EncodeOrDie(latest.Codec, &api.Pod{ObjectMeta: api.ObjectMeta{Namespace: "other", Name: "foo"}}), 0)
@ -676,6 +702,7 @@ func TestEtcdGet(t *testing.T) {
registry, _, _, fakeClient, _ := newStorage(t) registry, _, _, fakeClient, _ := newStorage(t)
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
key, _ := registry.KeyFunc(ctx, "foo") key, _ := registry.KeyFunc(ctx, "foo")
key = etcdtest.AddPrefix(key)
fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}), 0) fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}), 0)
obj, err := registry.Get(ctx, "foo") obj, err := registry.Get(ctx, "foo")
if err != nil { if err != nil {
@ -691,6 +718,7 @@ func TestEtcdGetNotFound(t *testing.T) {
registry, _, _, fakeClient, _ := newStorage(t) registry, _, _, fakeClient, _ := newStorage(t)
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
key, _ := registry.KeyFunc(ctx, "foo") key, _ := registry.KeyFunc(ctx, "foo")
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: nil, Node: nil,
@ -708,6 +736,7 @@ func TestEtcdCreate(t *testing.T) {
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
fakeClient.TestIndex = true fakeClient.TestIndex = true
key, _ := registry.KeyFunc(ctx, "foo") key, _ := registry.KeyFunc(ctx, "foo")
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: nil, Node: nil,
@ -752,6 +781,7 @@ func TestEtcdCreateBindingNoPod(t *testing.T) {
fakeClient.TestIndex = true fakeClient.TestIndex = true
key, _ := registry.KeyFunc(ctx, "foo") key, _ := registry.KeyFunc(ctx, "foo")
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: nil, Node: nil,
@ -798,6 +828,7 @@ func TestEtcdCreateAlreadyExisting(t *testing.T) {
registry, _, _, fakeClient, _ := newStorage(t) registry, _, _, fakeClient, _ := newStorage(t)
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
key, _ := registry.KeyFunc(ctx, "foo") key, _ := registry.KeyFunc(ctx, "foo")
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
@ -817,6 +848,7 @@ func TestEtcdCreateWithContainersNotFound(t *testing.T) {
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
fakeClient.TestIndex = true fakeClient.TestIndex = true
key, _ := registry.KeyFunc(ctx, "foo") key, _ := registry.KeyFunc(ctx, "foo")
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: nil, Node: nil,
@ -901,6 +933,7 @@ func TestEtcdCreateWithExistingContainers(t *testing.T) {
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
fakeClient.TestIndex = true fakeClient.TestIndex = true
key, _ := registry.KeyFunc(ctx, "foo") key, _ := registry.KeyFunc(ctx, "foo")
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: nil, Node: nil,
@ -983,6 +1016,7 @@ func TestEtcdCreateBinding(t *testing.T) {
} }
for k, test := range testCases { for k, test := range testCases {
key, _ := registry.KeyFunc(ctx, "foo") key, _ := registry.KeyFunc(ctx, "foo")
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: nil, Node: nil,
@ -1012,6 +1046,7 @@ func TestEtcdUpdateNotFound(t *testing.T) {
fakeClient.TestIndex = true fakeClient.TestIndex = true
key, _ := registry.KeyFunc(ctx, "foo") key, _ := registry.KeyFunc(ctx, "foo")
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{}, R: &etcd.Response{},
E: tools.EtcdErrorNotFound, E: tools.EtcdErrorNotFound,
@ -1038,6 +1073,7 @@ func TestEtcdUpdateNotScheduled(t *testing.T) {
fakeClient.TestIndex = true fakeClient.TestIndex = true
key, _ := registry.KeyFunc(ctx, "foo") key, _ := registry.KeyFunc(ctx, "foo")
key = etcdtest.AddPrefix(key)
fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, validNewPod()), 1) fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, validNewPod()), 1)
podIn := validChangedPod() podIn := validChangedPod()
@ -1062,6 +1098,7 @@ func TestEtcdUpdateScheduled(t *testing.T) {
fakeClient.TestIndex = true fakeClient.TestIndex = true
key, _ := registry.KeyFunc(ctx, "foo") key, _ := registry.KeyFunc(ctx, "foo")
key = etcdtest.AddPrefix(key)
fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &api.Pod{ fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &api.Pod{
ObjectMeta: api.ObjectMeta{ ObjectMeta: api.ObjectMeta{
Name: "foo", Name: "foo",
@ -1122,6 +1159,7 @@ func TestEtcdUpdateStatus(t *testing.T) {
fakeClient.TestIndex = true fakeClient.TestIndex = true
key, _ := registry.KeyFunc(ctx, "foo") key, _ := registry.KeyFunc(ctx, "foo")
key = etcdtest.AddPrefix(key)
podStart := api.Pod{ podStart := api.Pod{
ObjectMeta: api.ObjectMeta{ ObjectMeta: api.ObjectMeta{
Name: "foo", Name: "foo",
@ -1177,6 +1215,7 @@ func TestEtcdUpdateStatus(t *testing.T) {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }
var podOut api.Pod var podOut api.Pod
key, _ = registry.KeyFunc(ctx, "foo")
if err := helper.ExtractObj(key, &podOut, false); err != nil { if err := helper.ExtractObj(key, &podOut, false); err != nil {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }
@ -1191,6 +1230,7 @@ func TestEtcdDeletePod(t *testing.T) {
fakeClient.TestIndex = true fakeClient.TestIndex = true
key, _ := registry.KeyFunc(ctx, "foo") key, _ := registry.KeyFunc(ctx, "foo")
key = etcdtest.AddPrefix(key)
fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &api.Pod{ fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &api.Pod{
ObjectMeta: api.ObjectMeta{Name: "foo"}, ObjectMeta: api.ObjectMeta{Name: "foo"},
Spec: api.PodSpec{Host: "machine"}, Spec: api.PodSpec{Host: "machine"},
@ -1212,6 +1252,7 @@ func TestEtcdDeletePodMultipleContainers(t *testing.T) {
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
fakeClient.TestIndex = true fakeClient.TestIndex = true
key, _ := registry.KeyFunc(ctx, "foo") key, _ := registry.KeyFunc(ctx, "foo")
key = etcdtest.AddPrefix(key)
fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &api.Pod{ fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &api.Pod{
ObjectMeta: api.ObjectMeta{Name: "foo"}, ObjectMeta: api.ObjectMeta{Name: "foo"},
Spec: api.PodSpec{Host: "machine"}, Spec: api.PodSpec{Host: "machine"},
@ -1233,6 +1274,7 @@ func TestEtcdEmptyList(t *testing.T) {
registry, _, _, fakeClient, _ := newStorage(t) registry, _, _, fakeClient, _ := newStorage(t)
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
key := registry.KeyRootFunc(ctx) key := registry.KeyRootFunc(ctx)
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
@ -1256,6 +1298,7 @@ func TestEtcdListNotFound(t *testing.T) {
registry, _, _, fakeClient, _ := newStorage(t) registry, _, _, fakeClient, _ := newStorage(t)
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
key := registry.KeyRootFunc(ctx) key := registry.KeyRootFunc(ctx)
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{}, R: &etcd.Response{},
E: tools.EtcdErrorNotFound, E: tools.EtcdErrorNotFound,
@ -1274,6 +1317,7 @@ func TestEtcdList(t *testing.T) {
registry, _, _, fakeClient, _ := newStorage(t) registry, _, _, fakeClient, _ := newStorage(t)
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
key := registry.KeyRootFunc(ctx) key := registry.KeyRootFunc(ctx)
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{

View File

@ -34,7 +34,7 @@ type REST struct {
// NewREST returns a RESTStorage object that will work against pod templates. // NewREST returns a RESTStorage object that will work against pod templates.
func NewREST(h tools.EtcdHelper) *REST { func NewREST(h tools.EtcdHelper) *REST {
prefix := "/registry/podtemplates" prefix := "/podtemplates"
store := etcdgeneric.Etcd{ store := etcdgeneric.Etcd{
NewFunc: func() runtime.Object { return &api.PodTemplate{} }, NewFunc: func() runtime.Object { return &api.PodTemplate{} },
NewListFunc: func() runtime.Object { return &api.PodTemplateList{} }, NewListFunc: func() runtime.Object { return &api.PodTemplateList{} },

View File

@ -23,12 +23,13 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest/resttest" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest/resttest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta3" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta3"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools" "github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools/etcdtest"
) )
func newHelper(t *testing.T) (*tools.FakeEtcdClient, tools.EtcdHelper) { func newHelper(t *testing.T) (*tools.FakeEtcdClient, tools.EtcdHelper) {
fakeEtcdClient := tools.NewFakeEtcdClient(t) fakeEtcdClient := tools.NewFakeEtcdClient(t)
fakeEtcdClient.TestIndex = true fakeEtcdClient.TestIndex = true
helper := tools.NewEtcdHelper(fakeEtcdClient, v1beta3.Codec) helper := tools.NewEtcdHelper(fakeEtcdClient, v1beta3.Codec, etcdtest.PathPrefix())
return fakeEtcdClient, helper return fakeEtcdClient, helper
} }
@ -79,8 +80,9 @@ func TestUpdate(t *testing.T) {
fakeEtcdClient, helper := newHelper(t) fakeEtcdClient, helper := newHelper(t)
storage := NewREST(helper) storage := NewREST(helper)
test := resttest.New(t, storage, fakeEtcdClient.SetError) test := resttest.New(t, storage, fakeEtcdClient.SetError)
key := etcdtest.AddPrefix("podtemplates/default/foo")
fakeEtcdClient.ExpectNotFoundGet("/registry/podtemplates/default/foo") fakeEtcdClient.ExpectNotFoundGet(key)
fakeEtcdClient.ChangeIndex = 2 fakeEtcdClient.ChangeIndex = 2
pod := validNewPodTemplate("foo") pod := validNewPodTemplate("foo")
existing := validNewPodTemplate("exists") existing := validNewPodTemplate("exists")

View File

@ -34,7 +34,7 @@ type REST struct {
// NewStorage returns a RESTStorage object that will work against ResourceQuota objects. // NewStorage returns a RESTStorage object that will work against ResourceQuota objects.
func NewStorage(h tools.EtcdHelper) (*REST, *StatusREST) { func NewStorage(h tools.EtcdHelper) (*REST, *StatusREST) {
prefix := "/registry/resourcequotas" prefix := "/resourcequotas"
store := &etcdgeneric.Etcd{ store := &etcdgeneric.Etcd{
NewFunc: func() runtime.Object { return &api.ResourceQuota{} }, NewFunc: func() runtime.Object { return &api.ResourceQuota{} },
NewListFunc: func() runtime.Object { return &api.ResourceQuotaList{} }, NewListFunc: func() runtime.Object { return &api.ResourceQuotaList{} },

View File

@ -32,6 +32,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/resourcequota" "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/resourcequota"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools" "github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools/etcdtest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/coreos/go-etcd/etcd" "github.com/coreos/go-etcd/etcd"
@ -40,7 +41,7 @@ import (
func newHelper(t *testing.T) (*tools.FakeEtcdClient, tools.EtcdHelper) { func newHelper(t *testing.T) (*tools.FakeEtcdClient, tools.EtcdHelper) {
fakeEtcdClient := tools.NewFakeEtcdClient(t) fakeEtcdClient := tools.NewFakeEtcdClient(t)
fakeEtcdClient.TestIndex = true fakeEtcdClient.TestIndex = true
helper := tools.NewEtcdHelper(fakeEtcdClient, latest.Codec) helper := tools.NewEtcdHelper(fakeEtcdClient, latest.Codec, etcdtest.PathPrefix())
return fakeEtcdClient, helper return fakeEtcdClient, helper
} }
@ -123,6 +124,7 @@ func TestCreateRegistryError(t *testing.T) {
func TestCreateSetsFields(t *testing.T) { func TestCreateSetsFields(t *testing.T) {
fakeEtcdClient, helper := newHelper(t) fakeEtcdClient, helper := newHelper(t)
storage, _ := NewStorage(helper) storage, _ := NewStorage(helper)
ctx := api.NewDefaultContext()
resourcequota := validNewResourceQuota() resourcequota := validNewResourceQuota()
_, err := storage.Create(api.NewDefaultContext(), resourcequota) _, err := storage.Create(api.NewDefaultContext(), resourcequota)
if err != fakeEtcdClient.Err { if err != fakeEtcdClient.Err {
@ -130,7 +132,8 @@ func TestCreateSetsFields(t *testing.T) {
} }
actual := &api.ResourceQuota{} actual := &api.ResourceQuota{}
if err := helper.ExtractObj("/registry/resourcequotas/default/foo", actual, false); err != nil { key, _ := storage.Etcd.KeyFunc(ctx, "foo")
if err := helper.ExtractObj(key, actual, false); err != nil {
t.Fatalf("unexpected extraction error: %v", err) t.Fatalf("unexpected extraction error: %v", err)
} }
if actual.Name != resourcequota.Name { if actual.Name != resourcequota.Name {
@ -157,12 +160,16 @@ func TestListError(t *testing.T) {
func TestListEmptyResourceQuotaList(t *testing.T) { func TestListEmptyResourceQuotaList(t *testing.T) {
fakeEtcdClient, helper := newHelper(t) fakeEtcdClient, helper := newHelper(t)
fakeEtcdClient.ChangeIndex = 1 fakeEtcdClient.ChangeIndex = 1
fakeEtcdClient.Data["/registry/resourcequotas"] = tools.EtcdResponseWithError{ storage, _ := NewStorage(helper)
ctx := api.NewContext()
key := storage.Etcd.KeyRootFunc(ctx)
key = etcdtest.AddPrefix(key)
fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{}, R: &etcd.Response{},
E: fakeEtcdClient.NewError(tools.EtcdErrorCodeNotFound), E: fakeEtcdClient.NewError(tools.EtcdErrorCodeNotFound),
} }
storage, _ := NewStorage(helper)
resourcequotas, err := storage.List(api.NewContext(), labels.Everything(), fields.Everything()) resourcequotas, err := storage.List(api.NewContext(), labels.Everything(), fields.Everything())
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
@ -178,7 +185,11 @@ func TestListEmptyResourceQuotaList(t *testing.T) {
func TestListResourceQuotaList(t *testing.T) { func TestListResourceQuotaList(t *testing.T) {
fakeEtcdClient, helper := newHelper(t) fakeEtcdClient, helper := newHelper(t)
fakeEtcdClient.Data["/registry/resourcequotas/default"] = tools.EtcdResponseWithError{ storage, _ := NewStorage(helper)
ctx := api.NewDefaultContext()
key := storage.Etcd.KeyRootFunc(ctx)
key = etcdtest.AddPrefix(key)
fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
Nodes: []*etcd.Node{ Nodes: []*etcd.Node{
@ -196,7 +207,6 @@ func TestListResourceQuotaList(t *testing.T) {
}, },
}, },
} }
storage, _ := NewStorage(helper)
resourcequotasObj, err := storage.List(api.NewDefaultContext(), labels.Everything(), fields.Everything()) resourcequotasObj, err := storage.List(api.NewDefaultContext(), labels.Everything(), fields.Everything())
resourcequotas := resourcequotasObj.(*api.ResourceQuotaList) resourcequotas := resourcequotasObj.(*api.ResourceQuotaList)
if err != nil { if err != nil {
@ -216,7 +226,11 @@ func TestListResourceQuotaList(t *testing.T) {
func TestListResourceQuotaListSelection(t *testing.T) { func TestListResourceQuotaListSelection(t *testing.T) {
fakeEtcdClient, helper := newHelper(t) fakeEtcdClient, helper := newHelper(t)
fakeEtcdClient.Data["/registry/resourcequotas/default"] = tools.EtcdResponseWithError{ storage, _ := NewStorage(helper)
ctx := api.NewDefaultContext()
key := storage.Etcd.KeyRootFunc(ctx)
key = etcdtest.AddPrefix(key)
fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
Nodes: []*etcd.Node{ Nodes: []*etcd.Node{
@ -236,8 +250,6 @@ func TestListResourceQuotaListSelection(t *testing.T) {
}, },
}, },
} }
storage, _ := NewStorage(helper)
ctx := api.NewDefaultContext()
table := []struct { table := []struct {
label, field string label, field string
@ -302,14 +314,16 @@ func TestResourceQuotaDecode(t *testing.T) {
func TestGet(t *testing.T) { func TestGet(t *testing.T) {
expect := validNewResourceQuota() expect := validNewResourceQuota()
fakeEtcdClient, helper := newHelper(t) fakeEtcdClient, helper := newHelper(t)
fakeEtcdClient.Data["/registry/resourcequotas/test/foo"] = tools.EtcdResponseWithError{ storage, _ := NewStorage(helper)
key := "/resourcequotas/test/foo"
key = etcdtest.AddPrefix(key)
fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
Value: runtime.EncodeOrDie(latest.Codec, expect), Value: runtime.EncodeOrDie(latest.Codec, expect),
}, },
}, },
} }
storage, _ := NewStorage(helper)
obj, err := storage.Get(api.WithNamespace(api.NewContext(), "test"), "foo") obj, err := storage.Get(api.WithNamespace(api.NewContext(), "test"), "foo")
resourcequota := obj.(*api.ResourceQuota) resourcequota := obj.(*api.ResourceQuota)
if err != nil { if err != nil {
@ -324,7 +338,11 @@ func TestGet(t *testing.T) {
func TestDeleteResourceQuota(t *testing.T) { func TestDeleteResourceQuota(t *testing.T) {
fakeEtcdClient, helper := newHelper(t) fakeEtcdClient, helper := newHelper(t)
fakeEtcdClient.ChangeIndex = 1 fakeEtcdClient.ChangeIndex = 1
fakeEtcdClient.Data["/registry/resourcequotas/default/foo"] = tools.EtcdResponseWithError{ storage, _ := NewStorage(helper)
ctx := api.NewDefaultContext()
key, _ := storage.Etcd.KeyFunc(ctx, "foo")
key = etcdtest.AddPrefix(key)
fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
Value: runtime.EncodeOrDie(latest.Codec, &api.ResourceQuota{ Value: runtime.EncodeOrDie(latest.Codec, &api.ResourceQuota{
@ -339,7 +357,6 @@ func TestDeleteResourceQuota(t *testing.T) {
}, },
}, },
} }
storage, _ := NewStorage(helper)
_, err := storage.Delete(api.NewDefaultContext(), "foo", nil) _, err := storage.Delete(api.NewDefaultContext(), "foo", nil)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
@ -356,6 +373,9 @@ func TestEtcdGetDifferentNamespace(t *testing.T) {
key1, _ := registry.KeyFunc(ctx1, "foo") key1, _ := registry.KeyFunc(ctx1, "foo")
key2, _ := registry.KeyFunc(ctx2, "foo") key2, _ := registry.KeyFunc(ctx2, "foo")
key1 = etcdtest.AddPrefix(key1)
key2 = etcdtest.AddPrefix(key2)
fakeClient.Set(key1, runtime.EncodeOrDie(latest.Codec, &api.ResourceQuota{ObjectMeta: api.ObjectMeta{Namespace: "default", Name: "foo"}}), 0) fakeClient.Set(key1, runtime.EncodeOrDie(latest.Codec, &api.ResourceQuota{ObjectMeta: api.ObjectMeta{Namespace: "default", Name: "foo"}}), 0)
fakeClient.Set(key2, runtime.EncodeOrDie(latest.Codec, &api.ResourceQuota{ObjectMeta: api.ObjectMeta{Namespace: "other", Name: "foo"}}), 0) fakeClient.Set(key2, runtime.EncodeOrDie(latest.Codec, &api.ResourceQuota{ObjectMeta: api.ObjectMeta{Namespace: "other", Name: "foo"}}), 0)
@ -389,6 +409,7 @@ func TestEtcdGet(t *testing.T) {
registry, _, fakeClient, _ := newStorage(t) registry, _, fakeClient, _ := newStorage(t)
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
key, _ := registry.KeyFunc(ctx, "foo") key, _ := registry.KeyFunc(ctx, "foo")
key = etcdtest.AddPrefix(key)
fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &api.ResourceQuota{ObjectMeta: api.ObjectMeta{Name: "foo"}}), 0) fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &api.ResourceQuota{ObjectMeta: api.ObjectMeta{Name: "foo"}}), 0)
obj, err := registry.Get(ctx, "foo") obj, err := registry.Get(ctx, "foo")
if err != nil { if err != nil {
@ -404,6 +425,7 @@ func TestEtcdGetNotFound(t *testing.T) {
registry, _, fakeClient, _ := newStorage(t) registry, _, fakeClient, _ := newStorage(t)
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
key, _ := registry.KeyFunc(ctx, "foo") key, _ := registry.KeyFunc(ctx, "foo")
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: nil, Node: nil,
@ -432,6 +454,7 @@ func TestEtcdCreateAlreadyExisting(t *testing.T) {
registry, _, fakeClient, _ := newStorage(t) registry, _, fakeClient, _ := newStorage(t)
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
key, _ := registry.KeyFunc(ctx, "foo") key, _ := registry.KeyFunc(ctx, "foo")
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
@ -452,6 +475,7 @@ func TestEtcdUpdateStatus(t *testing.T) {
fakeClient.TestIndex = true fakeClient.TestIndex = true
key, _ := registry.KeyFunc(ctx, "foo") key, _ := registry.KeyFunc(ctx, "foo")
key = etcdtest.AddPrefix(key)
resourcequotaStart := validNewResourceQuota() resourcequotaStart := validNewResourceQuota()
fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, resourcequotaStart), 1) fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, resourcequotaStart), 1)
@ -491,6 +515,7 @@ func TestEtcdUpdateStatus(t *testing.T) {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }
var resourcequotaOut api.ResourceQuota var resourcequotaOut api.ResourceQuota
key, _ = registry.KeyFunc(ctx, "foo")
if err := helper.ExtractObj(key, &resourcequotaOut, false); err != nil { if err := helper.ExtractObj(key, &resourcequotaOut, false); err != nil {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }
@ -503,6 +528,7 @@ func TestEtcdEmptyList(t *testing.T) {
registry, _, fakeClient, _ := newStorage(t) registry, _, fakeClient, _ := newStorage(t)
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
key := registry.KeyRootFunc(ctx) key := registry.KeyRootFunc(ctx)
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
@ -526,6 +552,7 @@ func TestEtcdListNotFound(t *testing.T) {
registry, _, fakeClient, _ := newStorage(t) registry, _, fakeClient, _ := newStorage(t)
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
key := registry.KeyRootFunc(ctx) key := registry.KeyRootFunc(ctx)
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{}, R: &etcd.Response{},
E: tools.EtcdErrorNotFound, E: tools.EtcdErrorNotFound,
@ -544,6 +571,7 @@ func TestEtcdList(t *testing.T) {
registry, _, fakeClient, _ := newStorage(t) registry, _, fakeClient, _ := newStorage(t)
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
key := registry.KeyRootFunc(ctx) key := registry.KeyRootFunc(ctx)
key = etcdtest.AddPrefix(key)
fakeClient.Data[key] = tools.EtcdResponseWithError{ fakeClient.Data[key] = tools.EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{

View File

@ -31,16 +31,17 @@ type registry struct {
// NewEtcdRegistry returns a registry which will store Secret in the given helper // NewEtcdRegistry returns a registry which will store Secret in the given helper
func NewEtcdRegistry(h tools.EtcdHelper) generic.Registry { func NewEtcdRegistry(h tools.EtcdHelper) generic.Registry {
prefix := "/secrets"
return registry{ return registry{
Etcd: &etcdgeneric.Etcd{ Etcd: &etcdgeneric.Etcd{
NewFunc: func() runtime.Object { return &api.Secret{} }, NewFunc: func() runtime.Object { return &api.Secret{} },
NewListFunc: func() runtime.Object { return &api.SecretList{} }, NewListFunc: func() runtime.Object { return &api.SecretList{} },
EndpointName: "secrets", EndpointName: "secrets",
KeyRootFunc: func(ctx api.Context) string { KeyRootFunc: func(ctx api.Context) string {
return etcdgeneric.NamespaceKeyRootFunc(ctx, "/registry/secrets") return etcdgeneric.NamespaceKeyRootFunc(ctx, prefix)
}, },
KeyFunc: func(ctx api.Context, id string) (string, error) { KeyFunc: func(ctx api.Context, id string) (string, error) {
return etcdgeneric.NamespaceKeyFunc(ctx, "/registry/secrets", id) return etcdgeneric.NamespaceKeyFunc(ctx, prefix, id)
}, },
Helper: h, Helper: h,
}, },

View File

@ -27,6 +27,7 @@ import (
etcdgeneric "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic/etcd" etcdgeneric "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic/etcd"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools" "github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools/etcdtest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/coreos/go-etcd/etcd" "github.com/coreos/go-etcd/etcd"
@ -35,7 +36,7 @@ import (
func NewTestSecretEtcdRegistry(t *testing.T) (*tools.FakeEtcdClient, generic.Registry) { func NewTestSecretEtcdRegistry(t *testing.T) (*tools.FakeEtcdClient, generic.Registry) {
f := tools.NewFakeEtcdClient(t) f := tools.NewFakeEtcdClient(t)
f.TestIndex = true f.TestIndex = true
h := tools.NewEtcdHelper(f, testapi.Codec()) h := tools.NewEtcdHelper(f, testapi.Codec(), etcdtest.PathPrefix())
return f, NewEtcdRegistry(h) return f, NewEtcdRegistry(h)
} }
@ -65,10 +66,11 @@ func TestSecretCreate(t *testing.T) {
R: &etcd.Response{}, R: &etcd.Response{},
E: tools.EtcdErrorNotFound, E: tools.EtcdErrorNotFound,
} }
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
key := "foo" key := "foo"
path, err := etcdgeneric.NamespaceKeyFunc(ctx, "/registry/secrets", key) path, err := etcdgeneric.NamespaceKeyFunc(ctx, "/secrets", key)
path = etcdtest.AddPrefix(path)
if err != nil { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error: %v", err)
} }

View File

@ -23,7 +23,9 @@ import (
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"os/exec" "os/exec"
"path"
"reflect" "reflect"
"strings"
"github.com/GoogleCloudPlatform/kubernetes/pkg/conversion" "github.com/GoogleCloudPlatform/kubernetes/pkg/conversion"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
@ -38,15 +40,18 @@ type EtcdHelper struct {
Codec runtime.Codec Codec runtime.Codec
// optional, no atomic operations can be performed without this interface // optional, no atomic operations can be performed without this interface
Versioner EtcdVersioner Versioner EtcdVersioner
// prefix for all etcd keys
PathPrefix string
} }
// NewEtcdHelper creates a helper that works against objects that use the internal // NewEtcdHelper creates a helper that works against objects that use the internal
// Kubernetes API objects. // Kubernetes API objects.
func NewEtcdHelper(client EtcdGetSet, codec runtime.Codec) EtcdHelper { func NewEtcdHelper(client EtcdGetSet, codec runtime.Codec, prefix string) EtcdHelper {
return EtcdHelper{ return EtcdHelper{
Client: client, Client: client,
Codec: codec, Codec: codec,
Versioner: APIObjectVersioner{}, Versioner: APIObjectVersioner{},
PathPrefix: prefix,
} }
} }
@ -136,6 +141,7 @@ func (h *EtcdHelper) ExtractToList(key string, listObj runtime.Object) error {
if err != nil { if err != nil {
return err return err
} }
key = h.PrefixEtcdKey(key)
nodes, index, err := h.listEtcdNode(key) nodes, index, err := h.listEtcdNode(key)
if err != nil { if err != nil {
return err return err
@ -158,7 +164,7 @@ func (h *EtcdHelper) ExtractObjToList(key string, listObj runtime.Object) error
if err != nil { if err != nil {
return err return err
} }
key = h.PrefixEtcdKey(key)
response, err := h.Client.Get(key, false, false) response, err := h.Client.Get(key, false, false)
if err != nil { if err != nil {
if IsEtcdNotFound(err) { if IsEtcdNotFound(err) {
@ -185,6 +191,7 @@ func (h *EtcdHelper) ExtractObjToList(key string, listObj runtime.Object) error
// a zero object of the requested type, or an error, depending on ignoreNotFound. Treats // a zero object of the requested type, or an error, depending on ignoreNotFound. Treats
// empty responses and nil response nodes exactly like a not found error. // empty responses and nil response nodes exactly like a not found error.
func (h *EtcdHelper) ExtractObj(key string, objPtr runtime.Object, ignoreNotFound bool) error { func (h *EtcdHelper) ExtractObj(key string, objPtr runtime.Object, ignoreNotFound bool) error {
key = h.PrefixEtcdKey(key)
_, _, err := h.bodyAndExtractObj(key, objPtr, ignoreNotFound) _, _, err := h.bodyAndExtractObj(key, objPtr, ignoreNotFound)
return err return err
} }
@ -233,6 +240,7 @@ func (h *EtcdHelper) extractObj(response *etcd.Response, inErr error, objPtr run
// and 0 means forever. If no error is returned and out is not nil, out will be set to the read value // and 0 means forever. If no error is returned and out is not nil, out will be set to the read value
// from etcd. // from etcd.
func (h *EtcdHelper) CreateObj(key string, obj, out runtime.Object, ttl uint64) error { func (h *EtcdHelper) CreateObj(key string, obj, out runtime.Object, ttl uint64) error {
key = h.PrefixEtcdKey(key)
data, err := h.Codec.Encode(obj) data, err := h.Codec.Encode(obj)
if err != nil { if err != nil {
return err return err
@ -242,6 +250,7 @@ func (h *EtcdHelper) CreateObj(key string, obj, out runtime.Object, ttl uint64)
return errors.New("resourceVersion may not be set on objects to be created") return errors.New("resourceVersion may not be set on objects to be created")
} }
} }
response, err := h.Client.Create(key, string(data), ttl) response, err := h.Client.Create(key, string(data), ttl)
if err != nil { if err != nil {
return err return err
@ -257,15 +266,18 @@ func (h *EtcdHelper) CreateObj(key string, obj, out runtime.Object, ttl uint64)
// Delete removes the specified key. // Delete removes the specified key.
func (h *EtcdHelper) Delete(key string, recursive bool) error { func (h *EtcdHelper) Delete(key string, recursive bool) error {
key = h.PrefixEtcdKey(key)
_, err := h.Client.Delete(key, recursive) _, err := h.Client.Delete(key, recursive)
return err return err
} }
// DeleteObj removes the specified key and returns the value that existed at that spot. // DeleteObj removes the specified key and returns the value that existed at that spot.
func (h *EtcdHelper) DeleteObj(key string, out runtime.Object) error { func (h *EtcdHelper) DeleteObj(key string, out runtime.Object) error {
key = h.PrefixEtcdKey(key)
if _, err := conversion.EnforcePtr(out); err != nil { if _, err := conversion.EnforcePtr(out); err != nil {
panic("unable to convert output object to pointer") panic("unable to convert output object to pointer")
} }
response, err := h.Client.Delete(key, false) response, err := h.Client.Delete(key, false)
if !IsEtcdNotFound(err) { if !IsEtcdNotFound(err) {
// if the object that existed prior to the delete is returned by etcd, update out. // if the object that existed prior to the delete is returned by etcd, update out.
@ -285,6 +297,7 @@ func (h *EtcdHelper) SetObj(key string, obj, out runtime.Object, ttl uint64) err
if err != nil { if err != nil {
return err return err
} }
key = h.PrefixEtcdKey(key)
create := true create := true
if h.Versioner != nil { if h.Versioner != nil {
@ -346,6 +359,7 @@ func (h *EtcdHelper) GuaranteedUpdate(key string, ptrToType runtime.Object, igno
// Panic is appropriate, because this is a programming error. // Panic is appropriate, because this is a programming error.
panic("need ptr to type") panic("need ptr to type")
} }
key = h.PrefixEtcdKey(key)
for { for {
obj := reflect.New(v.Type()).Interface().(runtime.Object) obj := reflect.New(v.Type()).Interface().(runtime.Object)
origBody, index, err := h.bodyAndExtractObj(key, obj, ignoreNotFound) origBody, index, err := h.bodyAndExtractObj(key, obj, ignoreNotFound)
@ -386,6 +400,13 @@ func (h *EtcdHelper) GuaranteedUpdate(key string, ptrToType runtime.Object, igno
} }
} }
func (h *EtcdHelper) PrefixEtcdKey(key string) string {
if strings.HasPrefix(key, path.Join("/", h.PathPrefix)) {
return key
}
return path.Join("/", h.PathPrefix, key)
}
// GetEtcdVersion performs a version check against the provided Etcd server, returning a triplet // GetEtcdVersion performs a version check against the provided Etcd server, returning a triplet
// of the release version, internal version, and error (if any). // of the release version, internal version, and error (if any).
func GetEtcdVersion(host string) (releaseVersion, internalVersion string, err error) { func GetEtcdVersion(host string) (releaseVersion, internalVersion string, err error) {

View File

@ -21,6 +21,7 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"path"
"reflect" "reflect"
"sync" "sync"
"testing" "testing"
@ -29,6 +30,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/testapi" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/testapi"
"github.com/GoogleCloudPlatform/kubernetes/pkg/conversion" "github.com/GoogleCloudPlatform/kubernetes/pkg/conversion"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools/etcdtest"
"github.com/coreos/go-etcd/etcd" "github.com/coreos/go-etcd/etcd"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -79,7 +81,9 @@ func getEncodedPod(name string) string {
func TestExtractToList(t *testing.T) { func TestExtractToList(t *testing.T) {
fakeClient := NewFakeEtcdClient(t) fakeClient := NewFakeEtcdClient(t)
fakeClient.Data["/some/key"] = EtcdResponseWithError{ helper := NewEtcdHelper(fakeClient, testapi.Codec(), etcdtest.PathPrefix())
key := etcdtest.AddPrefix("/some/key")
fakeClient.Data[key] = EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
EtcdIndex: 10, EtcdIndex: 10,
Node: &etcd.Node{ Node: &etcd.Node{
@ -135,7 +139,6 @@ func TestExtractToList(t *testing.T) {
} }
var got api.PodList var got api.PodList
helper := NewEtcdHelper(fakeClient, testapi.Codec())
err := helper.ExtractToList("/some/key", &got) err := helper.ExtractToList("/some/key", &got)
if err != nil { if err != nil {
t.Errorf("Unexpected error %v", err) t.Errorf("Unexpected error %v", err)
@ -148,7 +151,9 @@ func TestExtractToList(t *testing.T) {
// TestExtractToListAcrossDirectories ensures that the client excludes directories and flattens tree-response - simulates cross-namespace query // TestExtractToListAcrossDirectories ensures that the client excludes directories and flattens tree-response - simulates cross-namespace query
func TestExtractToListAcrossDirectories(t *testing.T) { func TestExtractToListAcrossDirectories(t *testing.T) {
fakeClient := NewFakeEtcdClient(t) fakeClient := NewFakeEtcdClient(t)
fakeClient.Data["/some/key"] = EtcdResponseWithError{ helper := NewEtcdHelper(fakeClient, testapi.Codec(), etcdtest.PathPrefix())
key := etcdtest.AddPrefix("/some/key")
fakeClient.Data[key] = EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
EtcdIndex: 10, EtcdIndex: 10,
Node: &etcd.Node{ Node: &etcd.Node{
@ -218,7 +223,6 @@ func TestExtractToListAcrossDirectories(t *testing.T) {
} }
var got api.PodList var got api.PodList
helper := NewEtcdHelper(fakeClient, testapi.Codec())
err := helper.ExtractToList("/some/key", &got) err := helper.ExtractToList("/some/key", &got)
if err != nil { if err != nil {
t.Errorf("Unexpected error %v", err) t.Errorf("Unexpected error %v", err)
@ -230,7 +234,9 @@ func TestExtractToListAcrossDirectories(t *testing.T) {
func TestExtractToListExcludesDirectories(t *testing.T) { func TestExtractToListExcludesDirectories(t *testing.T) {
fakeClient := NewFakeEtcdClient(t) fakeClient := NewFakeEtcdClient(t)
fakeClient.Data["/some/key"] = EtcdResponseWithError{ helper := NewEtcdHelper(fakeClient, testapi.Codec(), etcdtest.PathPrefix())
key := etcdtest.AddPrefix("/some/key")
fakeClient.Data[key] = EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
EtcdIndex: 10, EtcdIndex: 10,
Node: &etcd.Node{ Node: &etcd.Node{
@ -288,7 +294,6 @@ func TestExtractToListExcludesDirectories(t *testing.T) {
} }
var got api.PodList var got api.PodList
helper := NewEtcdHelper(fakeClient, testapi.Codec())
err := helper.ExtractToList("/some/key", &got) err := helper.ExtractToList("/some/key", &got)
if err != nil { if err != nil {
t.Errorf("Unexpected error %v", err) t.Errorf("Unexpected error %v", err)
@ -300,6 +305,8 @@ func TestExtractToListExcludesDirectories(t *testing.T) {
func TestExtractObj(t *testing.T) { func TestExtractObj(t *testing.T) {
fakeClient := NewFakeEtcdClient(t) fakeClient := NewFakeEtcdClient(t)
helper := NewEtcdHelper(fakeClient, testapi.Codec(), etcdtest.PathPrefix())
key := etcdtest.AddPrefix("/some/key")
expect := api.Pod{ expect := api.Pod{
ObjectMeta: api.ObjectMeta{Name: "foo"}, ObjectMeta: api.ObjectMeta{Name: "foo"},
Spec: api.PodSpec{ Spec: api.PodSpec{
@ -307,8 +314,7 @@ func TestExtractObj(t *testing.T) {
DNSPolicy: api.DNSClusterFirst, DNSPolicy: api.DNSClusterFirst,
}, },
} }
fakeClient.Set("/some/key", runtime.EncodeOrDie(testapi.Codec(), &expect), 0) fakeClient.Set(key, runtime.EncodeOrDie(testapi.Codec(), &expect), 0)
helper := NewEtcdHelper(fakeClient, testapi.Codec())
var got api.Pod var got api.Pod
err := helper.ExtractObj("/some/key", &got, false) err := helper.ExtractObj("/some/key", &got, false)
if err != nil { if err != nil {
@ -321,7 +327,9 @@ func TestExtractObj(t *testing.T) {
func TestExtractObjNotFoundErr(t *testing.T) { func TestExtractObjNotFoundErr(t *testing.T) {
fakeClient := NewFakeEtcdClient(t) fakeClient := NewFakeEtcdClient(t)
fakeClient.Data["/some/key"] = EtcdResponseWithError{ helper := NewEtcdHelper(fakeClient, testapi.Codec(), etcdtest.PathPrefix())
key1 := etcdtest.AddPrefix("/some/key")
fakeClient.Data[key1] = EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: nil, Node: nil,
}, },
@ -329,19 +337,20 @@ func TestExtractObjNotFoundErr(t *testing.T) {
ErrorCode: 100, ErrorCode: 100,
}, },
} }
fakeClient.Data["/some/key2"] = EtcdResponseWithError{ key2 := etcdtest.AddPrefix("/some/key2")
fakeClient.Data[key2] = EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: nil, Node: nil,
}, },
} }
fakeClient.Data["/some/key3"] = EtcdResponseWithError{ key3 := etcdtest.AddPrefix("/some/key3")
fakeClient.Data[key3] = EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
Value: "", Value: "",
}, },
}, },
} }
helper := NewEtcdHelper(fakeClient, codec)
try := func(key string) { try := func(key string) {
var got api.Pod var got api.Pod
err := helper.ExtractObj(key, &got, false) err := helper.ExtractObj(key, &got, false)
@ -362,7 +371,7 @@ func TestExtractObjNotFoundErr(t *testing.T) {
func TestCreateObj(t *testing.T) { func TestCreateObj(t *testing.T) {
obj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} obj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}
fakeClient := NewFakeEtcdClient(t) fakeClient := NewFakeEtcdClient(t)
helper := NewEtcdHelper(fakeClient, testapi.Codec()) helper := NewEtcdHelper(fakeClient, testapi.Codec(), etcdtest.PathPrefix())
returnedObj := &api.Pod{} returnedObj := &api.Pod{}
err := helper.CreateObj("/some/key", obj, returnedObj, 5) err := helper.CreateObj("/some/key", obj, returnedObj, 5)
if err != nil { if err != nil {
@ -372,7 +381,8 @@ func TestCreateObj(t *testing.T) {
if err != nil { if err != nil {
t.Errorf("Unexpected error %#v", err) t.Errorf("Unexpected error %#v", err)
} }
node := fakeClient.Data["/some/key"].R.Node key := etcdtest.AddPrefix("/some/key")
node := fakeClient.Data[key].R.Node
if e, a := string(data), node.Value; e != a { if e, a := string(data), node.Value; e != a {
t.Errorf("Wanted %v, got %v", e, a) t.Errorf("Wanted %v, got %v", e, a)
} }
@ -387,7 +397,7 @@ func TestCreateObj(t *testing.T) {
func TestCreateObjNilOutParam(t *testing.T) { func TestCreateObjNilOutParam(t *testing.T) {
obj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} obj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}
fakeClient := NewFakeEtcdClient(t) fakeClient := NewFakeEtcdClient(t)
helper := NewEtcdHelper(fakeClient, testapi.Codec()) helper := NewEtcdHelper(fakeClient, testapi.Codec(), etcdtest.PathPrefix())
err := helper.CreateObj("/some/key", obj, nil, 5) err := helper.CreateObj("/some/key", obj, nil, 5)
if err != nil { if err != nil {
t.Errorf("Unexpected error %#v", err) t.Errorf("Unexpected error %#v", err)
@ -397,7 +407,7 @@ func TestCreateObjNilOutParam(t *testing.T) {
func TestSetObj(t *testing.T) { func TestSetObj(t *testing.T) {
obj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} obj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}
fakeClient := NewFakeEtcdClient(t) fakeClient := NewFakeEtcdClient(t)
helper := NewEtcdHelper(fakeClient, testapi.Codec()) helper := NewEtcdHelper(fakeClient, testapi.Codec(), etcdtest.PathPrefix())
returnedObj := &api.Pod{} returnedObj := &api.Pod{}
err := helper.SetObj("/some/key", obj, returnedObj, 5) err := helper.SetObj("/some/key", obj, returnedObj, 5)
if err != nil { if err != nil {
@ -408,7 +418,8 @@ func TestSetObj(t *testing.T) {
t.Errorf("Unexpected error %#v", err) t.Errorf("Unexpected error %#v", err)
} }
expect := string(data) expect := string(data)
got := fakeClient.Data["/some/key"].R.Node.Value key := etcdtest.AddPrefix("/some/key")
got := fakeClient.Data[key].R.Node.Value
if expect != got { if expect != got {
t.Errorf("Wanted %v, got %v", expect, got) t.Errorf("Wanted %v, got %v", expect, got)
} }
@ -424,7 +435,7 @@ func TestSetObjFailCAS(t *testing.T) {
obj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "1"}} obj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "1"}}
fakeClient := NewFakeEtcdClient(t) fakeClient := NewFakeEtcdClient(t)
fakeClient.CasErr = fakeClient.NewError(123) fakeClient.CasErr = fakeClient.NewError(123)
helper := NewEtcdHelper(fakeClient, testapi.Codec()) helper := NewEtcdHelper(fakeClient, testapi.Codec(), etcdtest.PathPrefix())
err := helper.SetObj("/some/key", obj, nil, 5) err := helper.SetObj("/some/key", obj, nil, 5)
if err == nil { if err == nil {
t.Errorf("Expecting error.") t.Errorf("Expecting error.")
@ -435,7 +446,9 @@ func TestSetObjWithVersion(t *testing.T) {
obj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "1"}} obj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "1"}}
fakeClient := NewFakeEtcdClient(t) fakeClient := NewFakeEtcdClient(t)
fakeClient.TestIndex = true fakeClient.TestIndex = true
fakeClient.Data["/some/key"] = EtcdResponseWithError{ helper := NewEtcdHelper(fakeClient, testapi.Codec(), etcdtest.PathPrefix())
key := etcdtest.AddPrefix("/some/key")
fakeClient.Data[key] = EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
Value: runtime.EncodeOrDie(testapi.Codec(), obj), Value: runtime.EncodeOrDie(testapi.Codec(), obj),
@ -444,7 +457,6 @@ func TestSetObjWithVersion(t *testing.T) {
}, },
} }
helper := NewEtcdHelper(fakeClient, testapi.Codec())
returnedObj := &api.Pod{} returnedObj := &api.Pod{}
err := helper.SetObj("/some/key", obj, returnedObj, 7) err := helper.SetObj("/some/key", obj, returnedObj, 7)
if err != nil { if err != nil {
@ -455,7 +467,7 @@ func TestSetObjWithVersion(t *testing.T) {
t.Fatalf("Unexpected error %#v", err) t.Fatalf("Unexpected error %#v", err)
} }
expect := string(data) expect := string(data)
got := fakeClient.Data["/some/key"].R.Node.Value got := fakeClient.Data[key].R.Node.Value
if expect != got { if expect != got {
t.Errorf("Wanted %v, got %v", expect, got) t.Errorf("Wanted %v, got %v", expect, got)
} }
@ -470,9 +482,10 @@ func TestSetObjWithVersion(t *testing.T) {
func TestSetObjWithoutResourceVersioner(t *testing.T) { func TestSetObjWithoutResourceVersioner(t *testing.T) {
obj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} obj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}
fakeClient := NewFakeEtcdClient(t) fakeClient := NewFakeEtcdClient(t)
helper := EtcdHelper{fakeClient, testapi.Codec(), nil} helper := EtcdHelper{fakeClient, testapi.Codec(), nil, etcdtest.PathPrefix()}
returnedObj := &api.Pod{} returnedObj := &api.Pod{}
err := helper.SetObj("/some/key", obj, returnedObj, 3) err := helper.SetObj("/some/key", obj, returnedObj, 3)
key := etcdtest.AddPrefix("/some/key")
if err != nil { if err != nil {
t.Errorf("Unexpected error %#v", err) t.Errorf("Unexpected error %#v", err)
} }
@ -481,7 +494,7 @@ func TestSetObjWithoutResourceVersioner(t *testing.T) {
t.Errorf("Unexpected error %#v", err) t.Errorf("Unexpected error %#v", err)
} }
expect := string(data) expect := string(data)
got := fakeClient.Data["/some/key"].R.Node.Value got := fakeClient.Data[key].R.Node.Value
if expect != got { if expect != got {
t.Errorf("Wanted %v, got %v", expect, got) t.Errorf("Wanted %v, got %v", expect, got)
} }
@ -496,7 +509,7 @@ func TestSetObjWithoutResourceVersioner(t *testing.T) {
func TestSetObjNilOutParam(t *testing.T) { func TestSetObjNilOutParam(t *testing.T) {
obj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} obj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}
fakeClient := NewFakeEtcdClient(t) fakeClient := NewFakeEtcdClient(t)
helper := EtcdHelper{fakeClient, testapi.Codec(), nil} helper := EtcdHelper{fakeClient, testapi.Codec(), nil, etcdtest.PathPrefix()}
err := helper.SetObj("/some/key", obj, nil, 3) err := helper.SetObj("/some/key", obj, nil, 3)
if err != nil { if err != nil {
t.Errorf("Unexpected error %#v", err) t.Errorf("Unexpected error %#v", err)
@ -506,10 +519,11 @@ func TestSetObjNilOutParam(t *testing.T) {
func TestGuaranteedUpdate(t *testing.T) { func TestGuaranteedUpdate(t *testing.T) {
fakeClient := NewFakeEtcdClient(t) fakeClient := NewFakeEtcdClient(t)
fakeClient.TestIndex = true fakeClient.TestIndex = true
helper := NewEtcdHelper(fakeClient, codec) helper := NewEtcdHelper(fakeClient, codec, etcdtest.PathPrefix())
key := etcdtest.AddPrefix("/some/key")
// Create a new node. // Create a new node.
fakeClient.ExpectNotFoundGet("/some/key") fakeClient.ExpectNotFoundGet(key)
obj := &TestResource{ObjectMeta: api.ObjectMeta{Name: "foo"}, Value: 1} obj := &TestResource{ObjectMeta: api.ObjectMeta{Name: "foo"}, Value: 1}
err := helper.GuaranteedUpdate("/some/key", &TestResource{}, true, func(in runtime.Object) (runtime.Object, uint64, error) { err := helper.GuaranteedUpdate("/some/key", &TestResource{}, true, func(in runtime.Object) (runtime.Object, uint64, error) {
return obj, 0, nil return obj, 0, nil
@ -522,7 +536,7 @@ func TestGuaranteedUpdate(t *testing.T) {
t.Errorf("Unexpected error %#v", err) t.Errorf("Unexpected error %#v", err)
} }
expect := string(data) expect := string(data)
got := fakeClient.Data["/some/key"].R.Node.Value got := fakeClient.Data[key].R.Node.Value
if expect != got { if expect != got {
t.Errorf("Wanted %v, got %v", expect, got) t.Errorf("Wanted %v, got %v", expect, got)
} }
@ -547,7 +561,7 @@ func TestGuaranteedUpdate(t *testing.T) {
t.Errorf("Unexpected error %#v", err) t.Errorf("Unexpected error %#v", err)
} }
expect = string(data) expect = string(data)
got = fakeClient.Data["/some/key"].R.Node.Value got = fakeClient.Data[key].R.Node.Value
if expect != got { if expect != got {
t.Errorf("Wanted %v, got %v", expect, got) t.Errorf("Wanted %v, got %v", expect, got)
} }
@ -560,10 +574,11 @@ func TestGuaranteedUpdate(t *testing.T) {
func TestGuaranteedUpdateNoChange(t *testing.T) { func TestGuaranteedUpdateNoChange(t *testing.T) {
fakeClient := NewFakeEtcdClient(t) fakeClient := NewFakeEtcdClient(t)
fakeClient.TestIndex = true fakeClient.TestIndex = true
helper := NewEtcdHelper(fakeClient, codec) helper := NewEtcdHelper(fakeClient, codec, etcdtest.PathPrefix())
key := etcdtest.AddPrefix("/some/key")
// Create a new node. // Create a new node.
fakeClient.ExpectNotFoundGet("/some/key") fakeClient.ExpectNotFoundGet(key)
obj := &TestResource{ObjectMeta: api.ObjectMeta{Name: "foo"}, Value: 1} obj := &TestResource{ObjectMeta: api.ObjectMeta{Name: "foo"}, Value: 1}
err := helper.GuaranteedUpdate("/some/key", &TestResource{}, true, func(in runtime.Object) (runtime.Object, uint64, error) { err := helper.GuaranteedUpdate("/some/key", &TestResource{}, true, func(in runtime.Object) (runtime.Object, uint64, error) {
return obj, 0, nil return obj, 0, nil
@ -591,10 +606,11 @@ func TestGuaranteedUpdateNoChange(t *testing.T) {
func TestGuaranteedUpdateKeyNotFound(t *testing.T) { func TestGuaranteedUpdateKeyNotFound(t *testing.T) {
fakeClient := NewFakeEtcdClient(t) fakeClient := NewFakeEtcdClient(t)
fakeClient.TestIndex = true fakeClient.TestIndex = true
helper := NewEtcdHelper(fakeClient, codec) helper := NewEtcdHelper(fakeClient, codec, etcdtest.PathPrefix())
key := etcdtest.AddPrefix("/some/key")
// Create a new node. // Create a new node.
fakeClient.ExpectNotFoundGet("/some/key") fakeClient.ExpectNotFoundGet(key)
obj := &TestResource{ObjectMeta: api.ObjectMeta{Name: "foo"}, Value: 1} obj := &TestResource{ObjectMeta: api.ObjectMeta{Name: "foo"}, Value: 1}
f := func(in runtime.Object) (runtime.Object, uint64, error) { f := func(in runtime.Object) (runtime.Object, uint64, error) {
@ -617,9 +633,10 @@ func TestGuaranteedUpdateKeyNotFound(t *testing.T) {
func TestGuaranteedUpdate_CreateCollision(t *testing.T) { func TestGuaranteedUpdate_CreateCollision(t *testing.T) {
fakeClient := NewFakeEtcdClient(t) fakeClient := NewFakeEtcdClient(t)
fakeClient.TestIndex = true fakeClient.TestIndex = true
helper := NewEtcdHelper(fakeClient, codec) helper := NewEtcdHelper(fakeClient, codec, etcdtest.PathPrefix())
key := etcdtest.AddPrefix("/some/key")
fakeClient.ExpectNotFoundGet("/some/key") fakeClient.ExpectNotFoundGet(key)
const concurrency = 10 const concurrency = 10
var wgDone sync.WaitGroup var wgDone sync.WaitGroup
@ -654,7 +671,7 @@ func TestGuaranteedUpdate_CreateCollision(t *testing.T) {
wgDone.Wait() wgDone.Wait()
// Check that stored TestResource has received all updates. // Check that stored TestResource has received all updates.
body := fakeClient.Data["/some/key"].R.Node.Value body := fakeClient.Data[key].R.Node.Value
stored := &TestResource{} stored := &TestResource{}
if err := codec.DecodeInto([]byte(body), stored); err != nil { if err := codec.DecodeInto([]byte(body), stored); err != nil {
t.Errorf("Error decoding stored value: %v", body) t.Errorf("Error decoding stored value: %v", body)
@ -708,3 +725,23 @@ func TestGetEtcdVersion_ErrorStatus(t *testing.T) {
_, _, err = GetEtcdVersion(testServer.URL) _, _, err = GetEtcdVersion(testServer.URL)
assert.NotNil(t, err) assert.NotNil(t, err)
} }
func TestPrefixEtcdKey(t *testing.T) {
fakeClient := NewFakeEtcdClient(t)
prefix := path.Join("/", etcdtest.PathPrefix())
helper := NewEtcdHelper(fakeClient, testapi.Codec(), prefix)
baseKey := "/some/key"
// Verify prefix is added
keyBefore := baseKey
keyAfter := helper.PrefixEtcdKey(keyBefore)
assert.Equal(t, keyAfter, path.Join(prefix, baseKey), "Prefix incorrectly added by EtcdHelper")
// Verify prefix is not added
keyBefore = path.Join(prefix, baseKey)
keyAfter = helper.PrefixEtcdKey(keyBefore)
assert.Equal(t, keyBefore, keyAfter, "Prefix incorrectly added by EtcdHelper")
}

View File

@ -71,6 +71,7 @@ func ParseWatchResourceVersion(resourceVersion, kind string) (uint64, error) {
// watch.Interface. resourceVersion may be used to specify what version to begin // watch.Interface. resourceVersion may be used to specify what version to begin
// watching (e.g., for reconnecting without missing any updates). // watching (e.g., for reconnecting without missing any updates).
func (h *EtcdHelper) WatchList(key string, resourceVersion uint64, filter FilterFunc) (watch.Interface, error) { func (h *EtcdHelper) WatchList(key string, resourceVersion uint64, filter FilterFunc) (watch.Interface, error) {
key = h.PrefixEtcdKey(key)
w := newEtcdWatcher(true, exceptKey(key), filter, h.Codec, h.Versioner, nil) w := newEtcdWatcher(true, exceptKey(key), filter, h.Codec, h.Versioner, nil)
go w.etcdWatch(h.Client, key, resourceVersion) go w.etcdWatch(h.Client, key, resourceVersion)
return w, nil return w, nil
@ -80,6 +81,7 @@ func (h *EtcdHelper) WatchList(key string, resourceVersion uint64, filter Filter
// API objects and sent down the returned watch.Interface. // API objects and sent down the returned watch.Interface.
// Errors will be sent down the channel. // Errors will be sent down the channel.
func (h *EtcdHelper) Watch(key string, resourceVersion uint64, filter FilterFunc) (watch.Interface, error) { func (h *EtcdHelper) Watch(key string, resourceVersion uint64, filter FilterFunc) (watch.Interface, error) {
key = h.PrefixEtcdKey(key)
w := newEtcdWatcher(false, nil, filter, h.Codec, h.Versioner, nil) w := newEtcdWatcher(false, nil, filter, h.Codec, h.Versioner, nil)
go w.etcdWatch(h.Client, key, resourceVersion) go w.etcdWatch(h.Client, key, resourceVersion)
return w, nil return w, nil
@ -102,6 +104,7 @@ func (h *EtcdHelper) Watch(key string, resourceVersion uint64, filter FilterFunc
// //
// Errors will be sent down the channel. // Errors will be sent down the channel.
func (h *EtcdHelper) WatchAndTransform(key string, resourceVersion uint64, transform TransformFunc) watch.Interface { func (h *EtcdHelper) WatchAndTransform(key string, resourceVersion uint64, transform TransformFunc) watch.Interface {
key = h.PrefixEtcdKey(key)
w := newEtcdWatcher(false, nil, Everything, h.Codec, h.Versioner, transform) w := newEtcdWatcher(false, nil, Everything, h.Codec, h.Versioner, transform)
go w.etcdWatch(h.Client, key, resourceVersion) go w.etcdWatch(h.Client, key, resourceVersion)
return w return w

View File

@ -25,6 +25,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools/etcdtest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch" "github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
"github.com/coreos/go-etcd/etcd" "github.com/coreos/go-etcd/etcd"
) )
@ -205,7 +206,7 @@ func TestWatchEtcdError(t *testing.T) {
fakeClient := NewFakeEtcdClient(t) fakeClient := NewFakeEtcdClient(t)
fakeClient.expectNotFoundGetSet["/some/key"] = struct{}{} fakeClient.expectNotFoundGetSet["/some/key"] = struct{}{}
fakeClient.WatchImmediateError = fmt.Errorf("immediate error") fakeClient.WatchImmediateError = fmt.Errorf("immediate error")
h := EtcdHelper{fakeClient, codec, versioner} h := EtcdHelper{fakeClient, codec, versioner, etcdtest.PathPrefix()}
watching, err := h.Watch("/some/key", 4, Everything) watching, err := h.Watch("/some/key", 4, Everything)
if err != nil { if err != nil {
@ -232,10 +233,12 @@ func TestWatchEtcdError(t *testing.T) {
func TestWatch(t *testing.T) { func TestWatch(t *testing.T) {
codec := latest.Codec codec := latest.Codec
fakeClient := NewFakeEtcdClient(t) fakeClient := NewFakeEtcdClient(t)
fakeClient.expectNotFoundGetSet["/some/key"] = struct{}{} key := "/some/key"
h := EtcdHelper{fakeClient, codec, versioner} prefixedKey := etcdtest.AddPrefix(key)
fakeClient.expectNotFoundGetSet[prefixedKey] = struct{}{}
h := EtcdHelper{fakeClient, codec, versioner, etcdtest.PathPrefix()}
watching, err := h.Watch("/some/key", 0, Everything) watching, err := h.Watch(key, 0, Everything)
if err != nil { if err != nil {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }
@ -300,6 +303,8 @@ func makeSubsets(ip string, port int) []api.EndpointSubset {
func TestWatchEtcdState(t *testing.T) { func TestWatchEtcdState(t *testing.T) {
codec := latest.Codec codec := latest.Codec
baseKey := "/somekey/foo"
prefixedKey := etcdtest.AddPrefix(baseKey)
type T struct { type T struct {
Type watch.EventType Type watch.EventType
Endpoints []api.EndpointSubset Endpoints []api.EndpointSubset
@ -357,7 +362,7 @@ func TestWatchEtcdState(t *testing.T) {
}, },
"from initial state": { "from initial state": {
Initial: map[string]EtcdResponseWithError{ Initial: map[string]EtcdResponseWithError{
"/somekey/foo": { prefixedKey: {
R: &etcd.Response{ R: &etcd.Response{
Action: "get", Action: "get",
Node: &etcd.Node{ Node: &etcd.Node{
@ -406,8 +411,9 @@ func TestWatchEtcdState(t *testing.T) {
for key, value := range testCase.Initial { for key, value := range testCase.Initial {
fakeClient.Data[key] = value fakeClient.Data[key] = value
} }
h := EtcdHelper{fakeClient, codec, versioner}
watching, err := h.Watch("/somekey/foo", testCase.From, Everything) h := EtcdHelper{fakeClient, codec, versioner, etcdtest.PathPrefix()}
watching, err := h.Watch(baseKey, testCase.From, Everything)
if err != nil { if err != nil {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }
@ -476,10 +482,12 @@ func TestWatchFromZeroIndex(t *testing.T) {
for k, testCase := range testCases { for k, testCase := range testCases {
fakeClient := NewFakeEtcdClient(t) fakeClient := NewFakeEtcdClient(t)
fakeClient.Data["/some/key"] = testCase.Response key := "/some/key"
h := EtcdHelper{fakeClient, codec, versioner} prefixedKey := etcdtest.AddPrefix(key)
fakeClient.Data[prefixedKey] = testCase.Response
h := EtcdHelper{fakeClient, codec, versioner, etcdtest.PathPrefix()}
watching, err := h.Watch("/some/key", 0, Everything) watching, err := h.Watch(key, 0, Everything)
if err != nil { if err != nil {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }
@ -512,9 +520,10 @@ func TestWatchFromZeroIndex(t *testing.T) {
func TestWatchListFromZeroIndex(t *testing.T) { func TestWatchListFromZeroIndex(t *testing.T) {
codec := latest.Codec codec := latest.Codec
pod := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} pod := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}
key := "/some/key"
prefixedKey := etcdtest.AddPrefix(key)
fakeClient := NewFakeEtcdClient(t) fakeClient := NewFakeEtcdClient(t)
fakeClient.Data["/some/key"] = EtcdResponseWithError{ fakeClient.Data[prefixedKey] = EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: &etcd.Node{ Node: &etcd.Node{
Dir: true, Dir: true,
@ -537,9 +546,9 @@ func TestWatchListFromZeroIndex(t *testing.T) {
EtcdIndex: 3, EtcdIndex: 3,
}, },
} }
h := EtcdHelper{fakeClient, codec, versioner} h := EtcdHelper{fakeClient, codec, versioner, etcdtest.PathPrefix()}
watching, err := h.WatchList("/some/key", 0, Everything) watching, err := h.WatchList(key, 0, Everything)
if err != nil { if err != nil {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }
@ -573,11 +582,13 @@ func TestWatchListFromZeroIndex(t *testing.T) {
func TestWatchListIgnoresRootKey(t *testing.T) { func TestWatchListIgnoresRootKey(t *testing.T) {
codec := latest.Codec codec := latest.Codec
pod := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} pod := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}
key := "/some/key"
prefixedKey := etcdtest.AddPrefix(key)
fakeClient := NewFakeEtcdClient(t) fakeClient := NewFakeEtcdClient(t)
h := EtcdHelper{fakeClient, codec, versioner} h := EtcdHelper{fakeClient, codec, versioner, etcdtest.PathPrefix()}
watching, err := h.WatchList("/some/key", 1, Everything) watching, err := h.WatchList(key, 1, Everything)
if err != nil { if err != nil {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }
@ -587,7 +598,7 @@ func TestWatchListIgnoresRootKey(t *testing.T) {
fakeClient.WatchResponse <- &etcd.Response{ fakeClient.WatchResponse <- &etcd.Response{
Action: "delete", Action: "delete",
PrevNode: &etcd.Node{ PrevNode: &etcd.Node{
Key: "/some/key", Key: prefixedKey,
Value: runtime.EncodeOrDie(codec, pod), Value: runtime.EncodeOrDie(codec, pod),
CreatedIndex: 1, CreatedIndex: 1,
ModifiedIndex: 1, ModifiedIndex: 1,
@ -598,7 +609,7 @@ func TestWatchListIgnoresRootKey(t *testing.T) {
fakeClient.WatchResponse <- &etcd.Response{ fakeClient.WatchResponse <- &etcd.Response{
Action: "delete", Action: "delete",
PrevNode: &etcd.Node{ PrevNode: &etcd.Node{
Key: "/some/key", Key: prefixedKey,
Value: "", Value: "",
CreatedIndex: 1, CreatedIndex: 1,
ModifiedIndex: 1, ModifiedIndex: 1,
@ -617,7 +628,9 @@ func TestWatchListIgnoresRootKey(t *testing.T) {
func TestWatchFromNotFound(t *testing.T) { func TestWatchFromNotFound(t *testing.T) {
fakeClient := NewFakeEtcdClient(t) fakeClient := NewFakeEtcdClient(t)
fakeClient.Data["/some/key"] = EtcdResponseWithError{ key := "/some/key"
prefixedKey := etcdtest.AddPrefix(key)
fakeClient.Data[prefixedKey] = EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: nil, Node: nil,
}, },
@ -626,13 +639,12 @@ func TestWatchFromNotFound(t *testing.T) {
ErrorCode: 100, ErrorCode: 100,
}, },
} }
h := EtcdHelper{fakeClient, codec, versioner} h := EtcdHelper{fakeClient, codec, versioner, etcdtest.PathPrefix()}
watching, err := h.Watch("/some/key", 0, Everything) watching, err := h.Watch(key, 0, Everything)
if err != nil { if err != nil {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }
fakeClient.WaitForWatchCompletion() fakeClient.WaitForWatchCompletion()
if fakeClient.WatchIndex != 3 { if fakeClient.WatchIndex != 3 {
t.Errorf("Expected client to wait for %d, got %#v", 3, fakeClient) t.Errorf("Expected client to wait for %d, got %#v", 3, fakeClient)
@ -643,7 +655,9 @@ func TestWatchFromNotFound(t *testing.T) {
func TestWatchFromOtherError(t *testing.T) { func TestWatchFromOtherError(t *testing.T) {
fakeClient := NewFakeEtcdClient(t) fakeClient := NewFakeEtcdClient(t)
fakeClient.Data["/some/key"] = EtcdResponseWithError{ key := "/some/key"
prefixedKey := etcdtest.AddPrefix(key)
fakeClient.Data[prefixedKey] = EtcdResponseWithError{
R: &etcd.Response{ R: &etcd.Response{
Node: nil, Node: nil,
}, },
@ -652,9 +666,8 @@ func TestWatchFromOtherError(t *testing.T) {
ErrorCode: 101, ErrorCode: 101,
}, },
} }
h := EtcdHelper{fakeClient, codec, versioner} h := EtcdHelper{fakeClient, codec, versioner, etcdtest.PathPrefix()}
watching, err := h.Watch(key, 0, Everything)
watching, err := h.Watch("/some/key", 0, Everything)
if err != nil { if err != nil {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }
@ -683,11 +696,13 @@ func TestWatchFromOtherError(t *testing.T) {
func TestWatchPurposefulShutdown(t *testing.T) { func TestWatchPurposefulShutdown(t *testing.T) {
fakeClient := NewFakeEtcdClient(t) fakeClient := NewFakeEtcdClient(t)
h := EtcdHelper{fakeClient, codec, versioner} h := EtcdHelper{fakeClient, codec, versioner, etcdtest.PathPrefix()}
fakeClient.expectNotFoundGetSet["/some/key"] = struct{}{} key := "/some/key"
prefixedKey := etcdtest.AddPrefix(key)
fakeClient.expectNotFoundGetSet[prefixedKey] = struct{}{}
// Test purposeful shutdown // Test purposeful shutdown
watching, err := h.Watch("/some/key", 0, Everything) watching, err := h.Watch(key, 0, Everything)
if err != nil { if err != nil {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }

17
pkg/tools/etcdtest/doc.go Normal file
View File

@ -0,0 +1,17 @@
/*
Copyright 2014 Google Inc. 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 etcdtest

View File

@ -0,0 +1,32 @@
/*
Copyright 2014 Google Inc. 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 etcdtest
import (
"os"
"path"
)
// Returns the prefix set via the ETCD_PREFIX environment variable (if any).
func PathPrefix() string {
return path.Join("/", os.Getenv("ETCD_PREFIX"))
}
// Adds the ETCD_PREFIX to the provided key
func AddPrefix(in string) string {
return path.Join(PathPrefix(), in)
}

View File

@ -46,6 +46,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/auth/user" "github.com/GoogleCloudPlatform/kubernetes/pkg/auth/user"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client" "github.com/GoogleCloudPlatform/kubernetes/pkg/client"
"github.com/GoogleCloudPlatform/kubernetes/pkg/master" "github.com/GoogleCloudPlatform/kubernetes/pkg/master"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools/etcdtest"
"github.com/GoogleCloudPlatform/kubernetes/plugin/pkg/admission/admit" "github.com/GoogleCloudPlatform/kubernetes/plugin/pkg/admission/admit"
"github.com/GoogleCloudPlatform/kubernetes/plugin/pkg/auth/authenticator/token/tokentest" "github.com/GoogleCloudPlatform/kubernetes/plugin/pkg/auth/authenticator/token/tokentest"
) )
@ -377,7 +378,7 @@ func TestAuthModeAlwaysAllow(t *testing.T) {
// Set up a master // Set up a master
helper, err := master.NewEtcdHelper(newEtcdClient(), testapi.Version()) helper, err := master.NewEtcdHelper(newEtcdClient(), testapi.Version(), etcdtest.PathPrefix())
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
@ -516,8 +517,7 @@ func TestAuthModeAlwaysDeny(t *testing.T) {
deleteAllEtcdKeys() deleteAllEtcdKeys()
// Set up a master // Set up a master
helper, err := master.NewEtcdHelper(newEtcdClient(), testapi.Version(), etcdtest.PathPrefix())
helper, err := master.NewEtcdHelper(newEtcdClient(), testapi.Version())
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
@ -583,8 +583,7 @@ func TestAliceNotForbiddenOrUnauthorized(t *testing.T) {
// This file has alice and bob in it. // This file has alice and bob in it.
// Set up a master // Set up a master
helper, err := master.NewEtcdHelper(newEtcdClient(), testapi.Version(), etcdtest.PathPrefix())
helper, err := master.NewEtcdHelper(newEtcdClient(), testapi.Version())
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
@ -672,8 +671,7 @@ func TestBobIsForbidden(t *testing.T) {
// This file has alice and bob in it. // This file has alice and bob in it.
// Set up a master // Set up a master
helper, err := master.NewEtcdHelper(newEtcdClient(), testapi.Version(), etcdtest.PathPrefix())
helper, err := master.NewEtcdHelper(newEtcdClient(), testapi.Version())
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
@ -733,8 +731,7 @@ func TestUnknownUserIsUnauthorized(t *testing.T) {
// This file has alice and bob in it. // This file has alice and bob in it.
// Set up a master // Set up a master
helper, err := master.NewEtcdHelper(newEtcdClient(), testapi.Version(), etcdtest.PathPrefix())
helper, err := master.NewEtcdHelper(newEtcdClient(), testapi.Version())
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
@ -810,8 +807,7 @@ func TestNamespaceAuthorization(t *testing.T) {
deleteAllEtcdKeys() deleteAllEtcdKeys()
// This file has alice and bob in it. // This file has alice and bob in it.
helper, err := master.NewEtcdHelper(newEtcdClient(), testapi.Version(), etcdtest.PathPrefix())
helper, err := master.NewEtcdHelper(newEtcdClient(), testapi.Version())
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
@ -925,8 +921,7 @@ func TestKindAuthorization(t *testing.T) {
// This file has alice and bob in it. // This file has alice and bob in it.
// Set up a master // Set up a master
helper, err := master.NewEtcdHelper(newEtcdClient(), testapi.Version(), etcdtest.PathPrefix())
helper, err := master.NewEtcdHelper(newEtcdClient(), testapi.Version())
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
@ -1028,8 +1023,7 @@ func TestReadOnlyAuthorization(t *testing.T) {
// This file has alice and bob in it. // This file has alice and bob in it.
// Set up a master // Set up a master
helper, err := master.NewEtcdHelper(newEtcdClient(), testapi.Version(), etcdtest.PathPrefix())
helper, err := master.NewEtcdHelper(newEtcdClient(), testapi.Version())
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }

View File

@ -26,6 +26,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/testapi" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/testapi"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools" "github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools/etcdtest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch" "github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
) )
@ -92,8 +93,9 @@ func TestExtractObj(t *testing.T) {
func TestWatch(t *testing.T) { func TestWatch(t *testing.T) {
client := newEtcdClient() client := newEtcdClient()
helper := tools.NewEtcdHelper(client, testapi.Codec()) helper := tools.NewEtcdHelper(client, testapi.Codec(), etcdtest.PathPrefix())
withEtcdKey(func(key string) { withEtcdKey(func(key string) {
key = etcdtest.AddPrefix(key)
resp, err := client.Set(key, runtime.EncodeOrDie(testapi.Codec(), &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}), 0) resp, err := client.Set(key, runtime.EncodeOrDie(testapi.Codec(), &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}), 0)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)

View File

@ -33,6 +33,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/client" "github.com/GoogleCloudPlatform/kubernetes/pkg/client"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/record" "github.com/GoogleCloudPlatform/kubernetes/pkg/client/record"
"github.com/GoogleCloudPlatform/kubernetes/pkg/master" "github.com/GoogleCloudPlatform/kubernetes/pkg/master"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools/etcdtest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util/wait" "github.com/GoogleCloudPlatform/kubernetes/pkg/util/wait"
"github.com/GoogleCloudPlatform/kubernetes/plugin/pkg/admission/admit" "github.com/GoogleCloudPlatform/kubernetes/plugin/pkg/admission/admit"
"github.com/GoogleCloudPlatform/kubernetes/plugin/pkg/scheduler" "github.com/GoogleCloudPlatform/kubernetes/plugin/pkg/scheduler"
@ -45,7 +46,7 @@ func init() {
} }
func TestUnschedulableNodes(t *testing.T) { func TestUnschedulableNodes(t *testing.T) {
helper, err := master.NewEtcdHelper(newEtcdClient(), testapi.Version()) helper, err := master.NewEtcdHelper(newEtcdClient(), testapi.Version(), etcdtest.PathPrefix())
if err != nil { if err != nil {
t.Fatalf("Couldn't create etcd helper: %v", err) t.Fatalf("Couldn't create etcd helper: %v", err)
} }

View File

@ -30,6 +30,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver" "github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client" "github.com/GoogleCloudPlatform/kubernetes/pkg/client"
"github.com/GoogleCloudPlatform/kubernetes/pkg/master" "github.com/GoogleCloudPlatform/kubernetes/pkg/master"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools/etcdtest"
"github.com/GoogleCloudPlatform/kubernetes/plugin/pkg/admission/admit" "github.com/GoogleCloudPlatform/kubernetes/plugin/pkg/admission/admit"
) )
@ -50,7 +51,7 @@ func deleteSecretOrErrorf(t *testing.T, c *client.Client, ns, name string) {
// TestSecrets tests apiserver-side behavior of creation of secret objects and their use by pods. // TestSecrets tests apiserver-side behavior of creation of secret objects and their use by pods.
func TestSecrets(t *testing.T) { func TestSecrets(t *testing.T) {
helper, err := master.NewEtcdHelper(newEtcdClient(), testapi.Version()) helper, err := master.NewEtcdHelper(newEtcdClient(), testapi.Version(), etcdtest.PathPrefix())
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }

View File

@ -29,6 +29,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver" "github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client" "github.com/GoogleCloudPlatform/kubernetes/pkg/client"
"github.com/GoogleCloudPlatform/kubernetes/pkg/master" "github.com/GoogleCloudPlatform/kubernetes/pkg/master"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools/etcdtest"
"github.com/GoogleCloudPlatform/kubernetes/plugin/pkg/admission/admit" "github.com/GoogleCloudPlatform/kubernetes/plugin/pkg/admission/admit"
"github.com/coreos/go-etcd/etcd" "github.com/coreos/go-etcd/etcd"
@ -66,7 +67,7 @@ func deleteAllEtcdKeys() {
} }
func runAMaster(t *testing.T) (*master.Master, *httptest.Server) { func runAMaster(t *testing.T) (*master.Master, *httptest.Server) {
helper, err := master.NewEtcdHelper(newEtcdClient(), testapi.Version()) helper, err := master.NewEtcdHelper(newEtcdClient(), testapi.Version(), etcdtest.PathPrefix())
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }