Commit 75ebde38 authored by Brian Grant's avatar Brian Grant

Merge pull request #3999 from nikhiljindal/go-restful

Moving /watch, /proxy and /redirect registrations to go-restful
parents acbadc8a 18609e17
...@@ -55,7 +55,7 @@ var codec = runtime.CodecFor(api.Scheme, testVersion) ...@@ -55,7 +55,7 @@ var codec = runtime.CodecFor(api.Scheme, testVersion)
var accessor = meta.NewAccessor() var accessor = meta.NewAccessor()
var versioner runtime.ResourceVersioner = accessor var versioner runtime.ResourceVersioner = accessor
var selfLinker runtime.SelfLinker = accessor var selfLinker runtime.SelfLinker = accessor
var mapper meta.RESTMapper var mapper, namespaceMapper, legacyNamespaceMapper meta.RESTMapper // The mappers with namespace and with legacy namespace scopes.
var admissionControl admission.Interface var admissionControl admission.Interface
func interfacesFor(version string) (*meta.VersionInterfaces, error) { func interfacesFor(version string) (*meta.VersionInterfaces, error) {
...@@ -71,6 +71,19 @@ func interfacesFor(version string) (*meta.VersionInterfaces, error) { ...@@ -71,6 +71,19 @@ func interfacesFor(version string) (*meta.VersionInterfaces, error) {
} }
} }
func newMapper() *meta.DefaultRESTMapper {
return meta.NewDefaultRESTMapper(
versions,
func(version string) (*meta.VersionInterfaces, bool) {
interfaces, err := interfacesFor(version)
if err != nil {
return nil, false
}
return interfaces, true
},
)
}
func init() { func init() {
// Certain API objects are returned regardless of the contents of storage: // Certain API objects are returned regardless of the contents of storage:
// api.Status is returned in errors // api.Status is returned in errors
...@@ -83,26 +96,20 @@ func init() { ...@@ -83,26 +96,20 @@ func init() {
api.Scheme.AddKnownTypes(testVersion, &Simple{}, &SimpleList{}, api.Scheme.AddKnownTypes(testVersion, &Simple{}, &SimpleList{},
&api.Status{}) &api.Status{})
defMapper := meta.NewDefaultRESTMapper( nsMapper := newMapper()
versions, legacyNsMapper := newMapper()
func(version string) (*meta.VersionInterfaces, bool) {
interfaces, err := interfacesFor(version)
if err != nil {
return nil, false
}
return interfaces, true
},
)
// enumerate all supported versions, get the kinds, and register with the mapper how to address our resources // enumerate all supported versions, get the kinds, and register with the mapper how to address our resources
for _, version := range versions { for _, version := range versions {
for kind := range api.Scheme.KnownTypes(version) { for kind := range api.Scheme.KnownTypes(version) {
mixedCase := true mixedCase := true
scope := meta.RESTScopeNamespaceLegacy legacyNsMapper.Add(meta.RESTScopeNamespaceLegacy, kind, version, mixedCase)
defMapper.Add(scope, kind, version, mixedCase) nsMapper.Add(meta.RESTScopeNamespace, kind, version, mixedCase)
} }
} }
mapper = defMapper mapper = legacyNsMapper
legacyNamespaceMapper = legacyNsMapper
namespaceMapper = nsMapper
admissionControl = admit.NewAlwaysAdmit() admissionControl = admit.NewAlwaysAdmit()
} }
...@@ -274,7 +281,7 @@ func TestNotFound(t *testing.T) { ...@@ -274,7 +281,7 @@ func TestNotFound(t *testing.T) {
"PUT without extra segment": {"PUT", "/prefix/version/foo", http.StatusMethodNotAllowed}, "PUT without extra segment": {"PUT", "/prefix/version/foo", http.StatusMethodNotAllowed},
"PUT with extra segment": {"PUT", "/prefix/version/foo/bar/baz", http.StatusNotFound}, "PUT with extra segment": {"PUT", "/prefix/version/foo/bar/baz", http.StatusNotFound},
"watch missing storage": {"GET", "/prefix/version/watch/", http.StatusNotFound}, "watch missing storage": {"GET", "/prefix/version/watch/", http.StatusNotFound},
"watch with bad method": {"POST", "/prefix/version/watch/foo/bar", http.StatusNotFound}, "watch with bad method": {"POST", "/prefix/version/watch/foo/bar", http.StatusMethodNotAllowed},
} }
handler := Handle(map[string]RESTStorage{ handler := Handle(map[string]RESTStorage{
"foo": &SimpleRESTStorage{}, "foo": &SimpleRESTStorage{},
...@@ -318,15 +325,15 @@ func TestUnimplementedRESTStorage(t *testing.T) { ...@@ -318,15 +325,15 @@ func TestUnimplementedRESTStorage(t *testing.T) {
ErrCode int ErrCode int
} }
cases := map[string]T{ cases := map[string]T{
"GET object": {"GET", "/prefix/version/foo/bar", http.StatusNotFound}, "GET object": {"GET", "/prefix/version/foo/bar", http.StatusNotFound},
"GET list": {"GET", "/prefix/version/foo", http.StatusNotFound}, "GET list": {"GET", "/prefix/version/foo", http.StatusNotFound},
"POST list": {"POST", "/prefix/version/foo", http.StatusNotFound}, "POST list": {"POST", "/prefix/version/foo", http.StatusNotFound},
"PUT object": {"PUT", "/prefix/version/foo/bar", http.StatusNotFound}, "PUT object": {"PUT", "/prefix/version/foo/bar", http.StatusNotFound},
"DELETE object": {"DELETE", "/prefix/version/foo/bar", http.StatusNotFound}, "DELETE object": {"DELETE", "/prefix/version/foo/bar", http.StatusNotFound},
//"watch list": {"GET", "/prefix/version/watch/foo"}, "watch list": {"GET", "/prefix/version/watch/foo", http.StatusNotFound},
//"watch object": {"GET", "/prefix/version/watch/foo/bar"}, "watch object": {"GET", "/prefix/version/watch/foo/bar", http.StatusNotFound},
"proxy object": {"GET", "/prefix/version/proxy/foo/bar", http.StatusMethodNotAllowed}, "proxy object": {"GET", "/prefix/version/proxy/foo/bar", http.StatusNotFound},
"redirect object": {"GET", "/prefix/version/redirect/foo/bar", http.StatusMethodNotAllowed}, "redirect object": {"GET", "/prefix/version/redirect/foo/bar", http.StatusNotFound},
} }
handler := Handle(map[string]RESTStorage{ handler := Handle(map[string]RESTStorage{
"foo": UnimplementedRESTStorage{}, "foo": UnimplementedRESTStorage{},
...@@ -347,9 +354,8 @@ func TestUnimplementedRESTStorage(t *testing.T) { ...@@ -347,9 +354,8 @@ func TestUnimplementedRESTStorage(t *testing.T) {
} }
defer response.Body.Close() defer response.Body.Close()
data, _ := ioutil.ReadAll(response.Body) data, _ := ioutil.ReadAll(response.Body)
t.Logf("resp: %s", string(data))
if response.StatusCode != v.ErrCode { if response.StatusCode != v.ErrCode {
t.Errorf("%s: expected %d for %s, Got %s", k, http.StatusNotFound, v.Method, string(data)) t.Errorf("%s: expected %d for %s, Got %s", k, v.ErrCode, v.Method, string(data))
continue continue
} }
} }
......
...@@ -236,18 +236,30 @@ func TestProxy(t *testing.T) { ...@@ -236,18 +236,30 @@ func TestProxy(t *testing.T) {
resourceLocation: proxyServer.URL, resourceLocation: proxyServer.URL,
expectedResourceNamespace: item.reqNamespace, expectedResourceNamespace: item.reqNamespace,
} }
handler := Handle(map[string]RESTStorage{
namespaceHandler := Handle(map[string]RESTStorage{
"foo": simpleStorage,
}, codec, "/prefix", "version", selfLinker, admissionControl, namespaceMapper)
namespaceServer := httptest.NewServer(namespaceHandler)
defer namespaceServer.Close()
legacyNamespaceHandler := Handle(map[string]RESTStorage{
"foo": simpleStorage, "foo": simpleStorage,
}, codec, "/prefix", "version", selfLinker, admissionControl, mapper) }, codec, "/prefix", "version", selfLinker, admissionControl, legacyNamespaceMapper)
server := httptest.NewServer(handler) legacyNamespaceServer := httptest.NewServer(legacyNamespaceHandler)
defer server.Close() defer legacyNamespaceServer.Close()
// test each supported URL pattern for finding the redirection resource in the proxy in a particular namespace // test each supported URL pattern for finding the redirection resource in the proxy in a particular namespace
proxyTestPatterns := []string{ serverPatterns := []struct {
"/prefix/version/proxy/foo/id" + item.path + "?namespace=" + item.reqNamespace, server *httptest.Server
"/prefix/version/proxy/ns/" + item.reqNamespace + "/foo/id" + item.path, proxyTestPattern string
}{
{namespaceServer, "/prefix/version/proxy/ns/" + item.reqNamespace + "/foo/id" + item.path},
{legacyNamespaceServer, "/prefix/version/proxy/foo/id" + item.path + "?namespace=" + item.reqNamespace},
} }
for _, proxyTestPattern := range proxyTestPatterns {
for _, serverPattern := range serverPatterns {
server := serverPattern.server
proxyTestPattern := serverPattern.proxyTestPattern
req, err := http.NewRequest( req, err := http.NewRequest(
item.method, item.method,
server.URL+proxyTestPattern, server.URL+proxyTestPattern,
...@@ -268,7 +280,7 @@ func TestProxy(t *testing.T) { ...@@ -268,7 +280,7 @@ func TestProxy(t *testing.T) {
} }
resp.Body.Close() resp.Body.Close()
if e, a := item.respBody, string(gotResp); e != a { if e, a := item.respBody, string(gotResp); e != a {
t.Errorf("%v - expected %v, got %v", item.method, e, a) t.Errorf("%v - expected %v, got %v. url: %#v", item.method, e, a, req.URL)
} }
} }
} }
......
...@@ -84,7 +84,7 @@ func TestRedirectWithNamespaces(t *testing.T) { ...@@ -84,7 +84,7 @@ func TestRedirectWithNamespaces(t *testing.T) {
} }
handler := Handle(map[string]RESTStorage{ handler := Handle(map[string]RESTStorage{
"foo": simpleStorage, "foo": simpleStorage,
}, codec, "/prefix", "version", selfLinker, admissionControl, mapper) }, codec, "/prefix", "version", selfLinker, admissionControl, namespaceMapper)
server := httptest.NewServer(handler) server := httptest.NewServer(handler)
defer server.Close() defer server.Close()
......
...@@ -317,6 +317,8 @@ func New(c *Config) *Master { ...@@ -317,6 +317,8 @@ func New(c *Config) *Master {
m.mux = mux m.mux = mux
m.handlerContainer = NewHandlerContainer(mux) m.handlerContainer = NewHandlerContainer(mux)
} }
// Use CurlyRouter to be able to use regular expressions in paths. Regular expressions are required in paths for example for proxy (where the path is proxy/{kind}/{name}/{*})
m.handlerContainer.Router(restful.CurlyRouter{})
m.muxHelper = &apiserver.MuxHelper{m.mux, []string{}} m.muxHelper = &apiserver.MuxHelper{m.mux, []string{}}
m.masterServices = util.NewRunner(m.serviceWriterLoop, m.roServiceWriterLoop) m.masterServices = util.NewRunner(m.serviceWriterLoop, m.roServiceWriterLoop)
...@@ -401,14 +403,14 @@ func (m *Master) init(c *Config) { ...@@ -401,14 +403,14 @@ func (m *Master) init(c *Config) {
} }
apiVersions := []string{"v1beta1", "v1beta2"} apiVersions := []string{"v1beta1", "v1beta2"}
if err := apiserver.NewAPIGroupVersion(m.api_v1beta1()).InstallREST(m.handlerContainer, m.muxHelper, c.APIPrefix, "v1beta1"); err != nil { if err := apiserver.NewAPIGroupVersion(m.api_v1beta1()).InstallREST(m.handlerContainer, c.APIPrefix, "v1beta1"); err != nil {
glog.Fatalf("Unable to setup API v1beta1: %v", err) glog.Fatalf("Unable to setup API v1beta1: %v", err)
} }
if err := apiserver.NewAPIGroupVersion(m.api_v1beta2()).InstallREST(m.handlerContainer, m.muxHelper, c.APIPrefix, "v1beta2"); err != nil { if err := apiserver.NewAPIGroupVersion(m.api_v1beta2()).InstallREST(m.handlerContainer, c.APIPrefix, "v1beta2"); err != nil {
glog.Fatalf("Unable to setup API v1beta2: %v", err) glog.Fatalf("Unable to setup API v1beta2: %v", err)
} }
if c.EnableV1Beta3 { if c.EnableV1Beta3 {
if err := apiserver.NewAPIGroupVersion(m.api_v1beta3()).InstallREST(m.handlerContainer, m.muxHelper, c.APIPrefix, "v1beta3"); err != nil { if err := apiserver.NewAPIGroupVersion(m.api_v1beta3()).InstallREST(m.handlerContainer, c.APIPrefix, "v1beta3"); err != nil {
glog.Fatalf("Unable to setup API v1beta3: %v", err) glog.Fatalf("Unable to setup API v1beta3: %v", err)
} }
apiVersions = []string{"v1beta1", "v1beta2", "v1beta3"} apiVersions = []string{"v1beta1", "v1beta2", "v1beta3"}
......
...@@ -259,7 +259,6 @@ func getTestRequests() []struct { ...@@ -259,7 +259,6 @@ func getTestRequests() []struct {
{"DELETE", "/api/v1beta1/foo" + timeoutFlag, "", code404}, {"DELETE", "/api/v1beta1/foo" + timeoutFlag, "", code404},
// Special verbs on nodes // Special verbs on nodes
// TODO: Will become 405 once these are converted to go-restful
{"GET", "/api/v1beta1/proxy/minions/a", "", code404}, {"GET", "/api/v1beta1/proxy/minions/a", "", code404},
{"GET", "/api/v1beta1/redirect/minions/a", "", code404}, {"GET", "/api/v1beta1/redirect/minions/a", "", code404},
// TODO: test .../watch/..., which doesn't end before the test timeout. // TODO: test .../watch/..., which doesn't end before the test timeout.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment