Add groupless API server tests
This commit is contained in:
		@@ -64,7 +64,12 @@ var newGroupVersion = unversioned.GroupVersion{Group: testAPIGroup, Version: "ve
 | 
				
			|||||||
var newVersion = newGroupVersion.String()
 | 
					var newVersion = newGroupVersion.String()
 | 
				
			||||||
var prefix = "apis"
 | 
					var prefix = "apis"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var versions = []string{testVersion, newVersion}
 | 
					var grouplessGroupVersion = unversioned.GroupVersion{Group: "", Version: "v1"}
 | 
				
			||||||
 | 
					var grouplessVersion = grouplessGroupVersion.String()
 | 
				
			||||||
 | 
					var grouplessPrefix = "api"
 | 
				
			||||||
 | 
					var grouplessCodec = runtime.CodecFor(api.Scheme, grouplessVersion)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var versions = []string{grouplessVersion, testVersion, newVersion}
 | 
				
			||||||
var codec = runtime.CodecFor(api.Scheme, testVersion)
 | 
					var codec = runtime.CodecFor(api.Scheme, testVersion)
 | 
				
			||||||
var newCodec = runtime.CodecFor(api.Scheme, newVersion)
 | 
					var newCodec = runtime.CodecFor(api.Scheme, newVersion)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -89,6 +94,12 @@ func interfacesFor(version string) (*meta.VersionInterfaces, error) {
 | 
				
			|||||||
			ObjectConvertor:  api.Scheme,
 | 
								ObjectConvertor:  api.Scheme,
 | 
				
			||||||
			MetadataAccessor: accessor,
 | 
								MetadataAccessor: accessor,
 | 
				
			||||||
		}, nil
 | 
							}, nil
 | 
				
			||||||
 | 
						case grouplessVersion:
 | 
				
			||||||
 | 
							return &meta.VersionInterfaces{
 | 
				
			||||||
 | 
								Codec:            grouplessCodec,
 | 
				
			||||||
 | 
								ObjectConvertor:  api.Scheme,
 | 
				
			||||||
 | 
								MetadataAccessor: accessor,
 | 
				
			||||||
 | 
							}, nil
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return nil, fmt.Errorf("unsupported storage version: %s (valid: %s)", version, strings.Join(versions, ", "))
 | 
							return nil, fmt.Errorf("unsupported storage version: %s (valid: %s)", version, strings.Join(versions, ", "))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -98,6 +109,22 @@ func newMapper() *meta.DefaultRESTMapper {
 | 
				
			|||||||
	return meta.NewDefaultRESTMapper("testgroup", versions, interfacesFor)
 | 
						return meta.NewDefaultRESTMapper("testgroup", versions, interfacesFor)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func addGrouplessTypes() {
 | 
				
			||||||
 | 
						type ListOptions struct {
 | 
				
			||||||
 | 
							runtime.Object
 | 
				
			||||||
 | 
							unversioned.TypeMeta `json:",inline"`
 | 
				
			||||||
 | 
							LabelSelector        string `json:"labelSelector,omitempty"`
 | 
				
			||||||
 | 
							FieldSelector        string `json:"fieldSelector,omitempty"`
 | 
				
			||||||
 | 
							Watch                bool   `json:"watch,omitempty"`
 | 
				
			||||||
 | 
							ResourceVersion      string `json:"resourceVersion,omitempty"`
 | 
				
			||||||
 | 
							TimeoutSeconds       *int64 `json:"timeoutSeconds,omitempty"`
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						api.Scheme.AddKnownTypes(
 | 
				
			||||||
 | 
							grouplessVersion, &apiservertesting.Simple{}, &apiservertesting.SimpleList{}, &unversioned.Status{},
 | 
				
			||||||
 | 
							&ListOptions{}, &api.DeleteOptions{}, &apiservertesting.SimpleGetOptions{}, &apiservertesting.SimpleRoot{})
 | 
				
			||||||
 | 
						api.Scheme.AddKnownTypes(grouplessVersion, &api.Pod{})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func addTestTypes() {
 | 
					func addTestTypes() {
 | 
				
			||||||
	type ListOptions struct {
 | 
						type ListOptions struct {
 | 
				
			||||||
		runtime.Object
 | 
							runtime.Object
 | 
				
			||||||
@@ -137,6 +164,7 @@ func init() {
 | 
				
			|||||||
	api.Scheme.AddKnownTypes(
 | 
						api.Scheme.AddKnownTypes(
 | 
				
			||||||
		"", &apiservertesting.Simple{}, &apiservertesting.SimpleList{}, &unversioned.Status{},
 | 
							"", &apiservertesting.Simple{}, &apiservertesting.SimpleList{}, &unversioned.Status{},
 | 
				
			||||||
		&api.ListOptions{}, &apiservertesting.SimpleGetOptions{}, &apiservertesting.SimpleRoot{})
 | 
							&api.ListOptions{}, &apiservertesting.SimpleGetOptions{}, &apiservertesting.SimpleRoot{})
 | 
				
			||||||
 | 
						addGrouplessTypes()
 | 
				
			||||||
	addTestTypes()
 | 
						addTestTypes()
 | 
				
			||||||
	addNewTestTypes()
 | 
						addNewTestTypes()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -160,6 +188,11 @@ func init() {
 | 
				
			|||||||
	admissionControl = admit.NewAlwaysAdmit()
 | 
						admissionControl = admit.NewAlwaysAdmit()
 | 
				
			||||||
	requestContextMapper = api.NewRequestContextMapper()
 | 
						requestContextMapper = api.NewRequestContextMapper()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						api.Scheme.AddFieldLabelConversionFunc(grouplessVersion, "Simple",
 | 
				
			||||||
 | 
							func(label, value string) (string, string, error) {
 | 
				
			||||||
 | 
								return label, value, nil
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
	api.Scheme.AddFieldLabelConversionFunc(testVersion, "Simple",
 | 
						api.Scheme.AddFieldLabelConversionFunc(testVersion, "Simple",
 | 
				
			||||||
		func(label, value string) (string, string, error) {
 | 
							func(label, value string) (string, string, error) {
 | 
				
			||||||
			return label, value, nil
 | 
								return label, value, nil
 | 
				
			||||||
@@ -175,76 +208,93 @@ func init() {
 | 
				
			|||||||
// defaultAPIServer exposes nested objects for testability.
 | 
					// defaultAPIServer exposes nested objects for testability.
 | 
				
			||||||
type defaultAPIServer struct {
 | 
					type defaultAPIServer struct {
 | 
				
			||||||
	http.Handler
 | 
						http.Handler
 | 
				
			||||||
	group     *APIGroupVersion
 | 
					 | 
				
			||||||
	container *restful.Container
 | 
						container *restful.Container
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// uses the default settings
 | 
					// uses the default settings
 | 
				
			||||||
func handle(storage map[string]rest.Storage) http.Handler {
 | 
					func handle(storage map[string]rest.Storage) http.Handler {
 | 
				
			||||||
	return handleInternal(true, storage, admissionControl, selfLinker)
 | 
						return handleInternal(storage, admissionControl, selfLinker)
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// uses the default settings for a v1 compatible api
 | 
					 | 
				
			||||||
func handleNew(storage map[string]rest.Storage) http.Handler {
 | 
					 | 
				
			||||||
	return handleInternal(false, storage, admissionControl, selfLinker)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// tests with a deny admission controller
 | 
					// tests with a deny admission controller
 | 
				
			||||||
func handleDeny(storage map[string]rest.Storage) http.Handler {
 | 
					func handleDeny(storage map[string]rest.Storage) http.Handler {
 | 
				
			||||||
	return handleInternal(true, storage, deny.NewAlwaysDeny(), selfLinker)
 | 
						return handleInternal(storage, deny.NewAlwaysDeny(), selfLinker)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// tests using the new namespace scope mechanism
 | 
					// tests using the new namespace scope mechanism
 | 
				
			||||||
func handleNamespaced(storage map[string]rest.Storage) http.Handler {
 | 
					func handleNamespaced(storage map[string]rest.Storage) http.Handler {
 | 
				
			||||||
	return handleInternal(false, storage, admissionControl, selfLinker)
 | 
						return handleInternal(storage, admissionControl, selfLinker)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// tests using a custom self linker
 | 
					// tests using a custom self linker
 | 
				
			||||||
func handleLinker(storage map[string]rest.Storage, selfLinker runtime.SelfLinker) http.Handler {
 | 
					func handleLinker(storage map[string]rest.Storage, selfLinker runtime.SelfLinker) http.Handler {
 | 
				
			||||||
	return handleInternal(true, storage, admissionControl, selfLinker)
 | 
						return handleInternal(storage, admissionControl, selfLinker)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func newTestRequestInfoResolver() *RequestInfoResolver {
 | 
					func newTestRequestInfoResolver() *RequestInfoResolver {
 | 
				
			||||||
	return &RequestInfoResolver{sets.NewString("api", "apis"), sets.NewString("api")}
 | 
						return &RequestInfoResolver{sets.NewString("api", "apis"), sets.NewString("api")}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func handleInternal(legacy bool, storage map[string]rest.Storage, admissionControl admission.Interface, selfLinker runtime.SelfLinker) http.Handler {
 | 
					func handleInternal(storage map[string]rest.Storage, admissionControl admission.Interface, selfLinker runtime.SelfLinker) http.Handler {
 | 
				
			||||||
	group := &APIGroupVersion{
 | 
						container := restful.NewContainer()
 | 
				
			||||||
 | 
						container.Router(restful.CurlyRouter{})
 | 
				
			||||||
 | 
						mux := container.ServeMux
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						template := APIGroupVersion{
 | 
				
			||||||
		Storage: storage,
 | 
							Storage: storage,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Root:                "/" + prefix,
 | 
					 | 
				
			||||||
		RequestInfoResolver: newTestRequestInfoResolver(),
 | 
							RequestInfoResolver: newTestRequestInfoResolver(),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Creater:   api.Scheme,
 | 
							Creater:   api.Scheme,
 | 
				
			||||||
		Convertor: api.Scheme,
 | 
							Convertor: api.Scheme,
 | 
				
			||||||
		Typer:     api.Scheme,
 | 
							Typer:     api.Scheme,
 | 
				
			||||||
		Linker:    selfLinker,
 | 
							Linker:    selfLinker,
 | 
				
			||||||
 | 
							Mapper:    namespaceMapper,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Admit:   admissionControl,
 | 
							Admit:   admissionControl,
 | 
				
			||||||
		Context: requestContextMapper,
 | 
							Context: requestContextMapper,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if legacy {
 | 
					
 | 
				
			||||||
 | 
						// groupless v1 version
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							group := template
 | 
				
			||||||
 | 
							group.Root = "/" + grouplessPrefix
 | 
				
			||||||
 | 
							group.GroupVersion = grouplessGroupVersion
 | 
				
			||||||
 | 
							group.ServerGroupVersion = &grouplessGroupVersion
 | 
				
			||||||
 | 
							group.Codec = grouplessCodec
 | 
				
			||||||
 | 
							if err := (&group).InstallREST(container); err != nil {
 | 
				
			||||||
 | 
								panic(fmt.Sprintf("unable to install container %s: %v", group.GroupVersion, err))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// group version 1
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							group := template
 | 
				
			||||||
 | 
							group.Root = "/" + prefix
 | 
				
			||||||
		group.GroupVersion = testGroupVersion
 | 
							group.GroupVersion = testGroupVersion
 | 
				
			||||||
		group.ServerGroupVersion = &testGroupVersion
 | 
							group.ServerGroupVersion = &testGroupVersion
 | 
				
			||||||
		group.Codec = codec
 | 
							group.Codec = codec
 | 
				
			||||||
		group.Mapper = namespaceMapper
 | 
							if err := (&group).InstallREST(container); err != nil {
 | 
				
			||||||
	} else {
 | 
								panic(fmt.Sprintf("unable to install container %s: %v", group.GroupVersion, err))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// group version 2
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							group := template
 | 
				
			||||||
 | 
							group.Root = "/" + prefix
 | 
				
			||||||
		group.GroupVersion = newGroupVersion
 | 
							group.GroupVersion = newGroupVersion
 | 
				
			||||||
		group.ServerGroupVersion = &newGroupVersion
 | 
							group.ServerGroupVersion = &newGroupVersion
 | 
				
			||||||
		group.Codec = newCodec
 | 
							group.Codec = newCodec
 | 
				
			||||||
		group.Mapper = namespaceMapper
 | 
							if err := (&group).InstallREST(container); err != nil {
 | 
				
			||||||
 | 
								panic(fmt.Sprintf("unable to install container %s: %v", group.GroupVersion, err))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	container := restful.NewContainer()
 | 
					 | 
				
			||||||
	container.Router(restful.CurlyRouter{})
 | 
					 | 
				
			||||||
	mux := container.ServeMux
 | 
					 | 
				
			||||||
	if err := group.InstallREST(container); err != nil {
 | 
					 | 
				
			||||||
		panic(fmt.Sprintf("unable to install container %s: %v", group.GroupVersion, err))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	ws := new(restful.WebService)
 | 
						ws := new(restful.WebService)
 | 
				
			||||||
	InstallSupport(mux, ws, false)
 | 
						InstallSupport(mux, ws, false)
 | 
				
			||||||
	container.Add(ws)
 | 
						container.Add(ws)
 | 
				
			||||||
	return &defaultAPIServer{mux, group, container}
 | 
						return &defaultAPIServer{mux, container}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestSimpleSetupRight(t *testing.T) {
 | 
					func TestSimpleSetupRight(t *testing.T) {
 | 
				
			||||||
@@ -602,6 +652,33 @@ func TestNotFound(t *testing.T) {
 | 
				
			|||||||
		Status int
 | 
							Status int
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	cases := map[string]T{
 | 
						cases := map[string]T{
 | 
				
			||||||
 | 
							// Positive checks to make sure everything is wired correctly
 | 
				
			||||||
 | 
							"groupless GET root":       {"GET", "/" + grouplessPrefix + "/" + grouplessVersion + "/simpleroots", http.StatusOK},
 | 
				
			||||||
 | 
							"groupless GET namespaced": {"GET", "/" + grouplessPrefix + "/" + grouplessVersion + "/namespaces/ns/simples", http.StatusOK},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							"groupless GET long prefix": {"GET", "/" + grouplessPrefix + "/", http.StatusNotFound},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							"groupless root PATCH method":                 {"PATCH", "/" + grouplessPrefix + "/" + grouplessVersion + "/simpleroots", http.StatusMethodNotAllowed},
 | 
				
			||||||
 | 
							"groupless root GET missing storage":          {"GET", "/" + grouplessPrefix + "/" + grouplessVersion + "/blah", http.StatusNotFound},
 | 
				
			||||||
 | 
							"groupless root GET with extra segment":       {"GET", "/" + grouplessPrefix + "/" + grouplessVersion + "/simpleroots/bar/baz", http.StatusNotFound},
 | 
				
			||||||
 | 
							"groupless root DELETE without extra segment": {"DELETE", "/" + grouplessPrefix + "/" + grouplessVersion + "/simpleroots", http.StatusMethodNotAllowed},
 | 
				
			||||||
 | 
							"groupless root DELETE with extra segment":    {"DELETE", "/" + grouplessPrefix + "/" + grouplessVersion + "/simpleroots/bar/baz", http.StatusNotFound},
 | 
				
			||||||
 | 
							"groupless root PUT without extra segment":    {"PUT", "/" + grouplessPrefix + "/" + grouplessVersion + "/simpleroots", http.StatusMethodNotAllowed},
 | 
				
			||||||
 | 
							"groupless root PUT with extra segment":       {"PUT", "/" + grouplessPrefix + "/" + grouplessVersion + "/simpleroots/bar/baz", http.StatusNotFound},
 | 
				
			||||||
 | 
							"groupless root watch missing storage":        {"GET", "/" + grouplessPrefix + "/" + grouplessVersion + "/watch/", http.StatusNotFound},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							"groupless namespaced PATCH method":                 {"PATCH", "/" + grouplessPrefix + "/" + grouplessVersion + "/namespaces/ns/simples", http.StatusMethodNotAllowed},
 | 
				
			||||||
 | 
							"groupless namespaced GET long prefix":              {"GET", "/" + grouplessPrefix + "/", http.StatusNotFound},
 | 
				
			||||||
 | 
							"groupless namespaced GET missing storage":          {"GET", "/" + grouplessPrefix + "/" + grouplessVersion + "/blah", http.StatusNotFound},
 | 
				
			||||||
 | 
							"groupless namespaced GET with extra segment":       {"GET", "/" + grouplessPrefix + "/" + grouplessVersion + "/namespaces/ns/simples/bar/baz", http.StatusNotFound},
 | 
				
			||||||
 | 
							"groupless namespaced POST with extra segment":      {"POST", "/" + grouplessPrefix + "/" + grouplessVersion + "/namespaces/ns/simples/bar", http.StatusMethodNotAllowed},
 | 
				
			||||||
 | 
							"groupless namespaced DELETE without extra segment": {"DELETE", "/" + grouplessPrefix + "/" + grouplessVersion + "/namespaces/ns/simples", http.StatusMethodNotAllowed},
 | 
				
			||||||
 | 
							"groupless namespaced DELETE with extra segment":    {"DELETE", "/" + grouplessPrefix + "/" + grouplessVersion + "/namespaces/ns/simples/bar/baz", http.StatusNotFound},
 | 
				
			||||||
 | 
							"groupless namespaced PUT without extra segment":    {"PUT", "/" + grouplessPrefix + "/" + grouplessVersion + "/namespaces/ns/simples", http.StatusMethodNotAllowed},
 | 
				
			||||||
 | 
							"groupless namespaced PUT with extra segment":       {"PUT", "/" + grouplessPrefix + "/" + grouplessVersion + "/namespaces/ns/simples/bar/baz", http.StatusNotFound},
 | 
				
			||||||
 | 
							"groupless namespaced watch missing storage":        {"GET", "/" + grouplessPrefix + "/" + grouplessVersion + "/watch/", http.StatusNotFound},
 | 
				
			||||||
 | 
							"groupless namespaced watch with bad method":        {"POST", "/" + grouplessPrefix + "/" + grouplessVersion + "/watch/namespaces/ns/simples/bar", http.StatusMethodNotAllowed},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Positive checks to make sure everything is wired correctly
 | 
							// Positive checks to make sure everything is wired correctly
 | 
				
			||||||
		"GET root": {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simpleroots", http.StatusOK},
 | 
							"GET root": {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simpleroots", http.StatusOK},
 | 
				
			||||||
		// TODO: JTL: "GET root item":       {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simpleroots/bar", http.StatusOK},
 | 
							// TODO: JTL: "GET root item":       {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simpleroots/bar", http.StatusOK},
 | 
				
			||||||
@@ -676,6 +753,16 @@ func TestUnimplementedRESTStorage(t *testing.T) {
 | 
				
			|||||||
		ErrCode int
 | 
							ErrCode int
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	cases := map[string]T{
 | 
						cases := map[string]T{
 | 
				
			||||||
 | 
							"groupless GET object":      {"GET", "/" + grouplessPrefix + "/" + grouplessVersion + "/foo/bar", http.StatusNotFound},
 | 
				
			||||||
 | 
							"groupless GET list":        {"GET", "/" + grouplessPrefix + "/" + grouplessVersion + "/foo", http.StatusNotFound},
 | 
				
			||||||
 | 
							"groupless POST list":       {"POST", "/" + grouplessPrefix + "/" + grouplessVersion + "/foo", http.StatusNotFound},
 | 
				
			||||||
 | 
							"groupless PUT object":      {"PUT", "/" + grouplessPrefix + "/" + grouplessVersion + "/foo/bar", http.StatusNotFound},
 | 
				
			||||||
 | 
							"groupless DELETE object":   {"DELETE", "/" + grouplessPrefix + "/" + grouplessVersion + "/foo/bar", http.StatusNotFound},
 | 
				
			||||||
 | 
							"groupless watch list":      {"GET", "/" + grouplessPrefix + "/" + grouplessVersion + "/watch/foo", http.StatusNotFound},
 | 
				
			||||||
 | 
							"groupless watch object":    {"GET", "/" + grouplessPrefix + "/" + grouplessVersion + "/watch/foo/bar", http.StatusNotFound},
 | 
				
			||||||
 | 
							"groupless proxy object":    {"GET", "/" + grouplessPrefix + "/" + grouplessVersion + "/proxy/foo/bar", http.StatusNotFound},
 | 
				
			||||||
 | 
							"groupless redirect object": {"GET", "/" + grouplessPrefix + "/" + grouplessVersion + "/redirect/foo/bar", http.StatusNotFound},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		"GET object":      {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/foo/bar", http.StatusNotFound},
 | 
							"GET object":      {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/foo/bar", http.StatusNotFound},
 | 
				
			||||||
		"GET list":        {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/foo", http.StatusNotFound},
 | 
							"GET list":        {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/foo", http.StatusNotFound},
 | 
				
			||||||
		"POST list":       {"POST", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/foo", http.StatusNotFound},
 | 
							"POST list":       {"POST", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/foo", http.StatusNotFound},
 | 
				
			||||||
@@ -750,6 +837,84 @@ func TestList(t *testing.T) {
 | 
				
			|||||||
		label     string
 | 
							label     string
 | 
				
			||||||
		field     string
 | 
							field     string
 | 
				
			||||||
	}{
 | 
						}{
 | 
				
			||||||
 | 
							// Groupless API
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// legacy namespace param is ignored
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								url:       "/" + grouplessPrefix + "/" + grouplessVersion + "/simple?namespace=",
 | 
				
			||||||
 | 
								namespace: "",
 | 
				
			||||||
 | 
								selfLink:  "/" + grouplessPrefix + "/" + grouplessVersion + "/simple",
 | 
				
			||||||
 | 
								legacy:    true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								url:       "/" + grouplessPrefix + "/" + grouplessVersion + "/simple?namespace=other",
 | 
				
			||||||
 | 
								namespace: "",
 | 
				
			||||||
 | 
								selfLink:  "/" + grouplessPrefix + "/" + grouplessVersion + "/simple",
 | 
				
			||||||
 | 
								legacy:    true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								url:       "/" + grouplessPrefix + "/" + grouplessVersion + "/simple?namespace=other&labelSelector=a%3Db&fieldSelector=c%3Dd",
 | 
				
			||||||
 | 
								namespace: "",
 | 
				
			||||||
 | 
								selfLink:  "/" + grouplessPrefix + "/" + grouplessVersion + "/simple",
 | 
				
			||||||
 | 
								legacy:    true,
 | 
				
			||||||
 | 
								label:     "a=b",
 | 
				
			||||||
 | 
								field:     "c=d",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							// legacy api version is honored
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								url:       "/" + grouplessPrefix + "/" + grouplessVersion + "/simple",
 | 
				
			||||||
 | 
								namespace: "",
 | 
				
			||||||
 | 
								selfLink:  "/" + grouplessPrefix + "/" + grouplessVersion + "/simple",
 | 
				
			||||||
 | 
								legacy:    true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								url:       "/" + grouplessPrefix + "/" + grouplessVersion + "/namespaces/other/simple",
 | 
				
			||||||
 | 
								namespace: "other",
 | 
				
			||||||
 | 
								selfLink:  "/" + grouplessPrefix + "/" + grouplessVersion + "/namespaces/other/simple",
 | 
				
			||||||
 | 
								legacy:    true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								url:       "/" + grouplessPrefix + "/" + grouplessVersion + "/namespaces/other/simple?labelSelector=a%3Db&fieldSelector=c%3Dd",
 | 
				
			||||||
 | 
								namespace: "other",
 | 
				
			||||||
 | 
								selfLink:  "/" + grouplessPrefix + "/" + grouplessVersion + "/namespaces/other/simple",
 | 
				
			||||||
 | 
								legacy:    true,
 | 
				
			||||||
 | 
								label:     "a=b",
 | 
				
			||||||
 | 
								field:     "c=d",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							// list items across all namespaces
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								url:       "/" + grouplessPrefix + "/" + grouplessVersion + "/simple",
 | 
				
			||||||
 | 
								namespace: "",
 | 
				
			||||||
 | 
								selfLink:  "/" + grouplessPrefix + "/" + grouplessVersion + "/simple",
 | 
				
			||||||
 | 
								legacy:    true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							// list items in a namespace in the path
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								url:       "/" + grouplessPrefix + "/" + grouplessVersion + "/namespaces/default/simple",
 | 
				
			||||||
 | 
								namespace: "default",
 | 
				
			||||||
 | 
								selfLink:  "/" + grouplessPrefix + "/" + grouplessVersion + "/namespaces/default/simple",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								url:       "/" + grouplessPrefix + "/" + grouplessVersion + "/namespaces/other/simple",
 | 
				
			||||||
 | 
								namespace: "other",
 | 
				
			||||||
 | 
								selfLink:  "/" + grouplessPrefix + "/" + grouplessVersion + "/namespaces/other/simple",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								url:       "/" + grouplessPrefix + "/" + grouplessVersion + "/namespaces/other/simple?labelSelector=a%3Db&fieldSelector=c%3Dd",
 | 
				
			||||||
 | 
								namespace: "other",
 | 
				
			||||||
 | 
								selfLink:  "/" + grouplessPrefix + "/" + grouplessVersion + "/namespaces/other/simple",
 | 
				
			||||||
 | 
								label:     "a=b",
 | 
				
			||||||
 | 
								field:     "c=d",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							// list items across all namespaces
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								url:       "/" + grouplessPrefix + "/" + grouplessVersion + "/simple",
 | 
				
			||||||
 | 
								namespace: "",
 | 
				
			||||||
 | 
								selfLink:  "/" + grouplessPrefix + "/" + grouplessVersion + "/simple",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Group API
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// legacy namespace param is ignored
 | 
							// legacy namespace param is ignored
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			url:       "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simple?namespace=",
 | 
								url:       "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simple?namespace=",
 | 
				
			||||||
@@ -833,12 +998,7 @@ func TestList(t *testing.T) {
 | 
				
			|||||||
			namespace:   testCase.namespace,
 | 
								namespace:   testCase.namespace,
 | 
				
			||||||
			expectedSet: testCase.selfLink,
 | 
								expectedSet: testCase.selfLink,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		var handler http.Handler
 | 
							var handler = handleInternal(storage, admissionControl, selfLinker)
 | 
				
			||||||
		if testCase.legacy {
 | 
					 | 
				
			||||||
			handler = handleLinker(storage, selfLinker)
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			handler = handleInternal(false, storage, admissionControl, selfLinker)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		server := httptest.NewServer(handler)
 | 
							server := httptest.NewServer(handler)
 | 
				
			||||||
		defer server.Close()
 | 
							defer server.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -848,7 +1008,7 @@ func TestList(t *testing.T) {
 | 
				
			|||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if resp.StatusCode != http.StatusOK {
 | 
							if resp.StatusCode != http.StatusOK {
 | 
				
			||||||
			t.Errorf("%d: unexpected status: %d, Expected: %d, %#v", i, resp.StatusCode, http.StatusOK, resp)
 | 
								t.Errorf("%d: unexpected status: %d from url %s, Expected: %d, %#v", i, resp.StatusCode, testCase.url, http.StatusOK, resp)
 | 
				
			||||||
			body, err := ioutil.ReadAll(resp.Body)
 | 
								body, err := ioutil.ReadAll(resp.Body)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				t.Errorf("%d: unexpected error: %v", i, err)
 | 
									t.Errorf("%d: unexpected error: %v", i, err)
 | 
				
			||||||
@@ -1263,7 +1423,7 @@ func TestGetNamespaceSelfLink(t *testing.T) {
 | 
				
			|||||||
		namespace:   "foo",
 | 
							namespace:   "foo",
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	storage["simple"] = &simpleStorage
 | 
						storage["simple"] = &simpleStorage
 | 
				
			||||||
	handler := handleInternal(false, storage, admissionControl, selfLinker)
 | 
						handler := handleInternal(storage, admissionControl, selfLinker)
 | 
				
			||||||
	server := httptest.NewServer(handler)
 | 
						server := httptest.NewServer(handler)
 | 
				
			||||||
	defer server.Close()
 | 
						defer server.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2470,7 +2630,7 @@ func TestCreateInvokesAdmissionControl(t *testing.T) {
 | 
				
			|||||||
		namespace:   "other",
 | 
							namespace:   "other",
 | 
				
			||||||
		expectedSet: "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/other/foo/bar",
 | 
							expectedSet: "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/other/foo/bar",
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	handler := handleInternal(true, map[string]rest.Storage{"foo": &storage}, deny.NewAlwaysDeny(), selfLinker)
 | 
						handler := handleInternal(map[string]rest.Storage{"foo": &storage}, deny.NewAlwaysDeny(), selfLinker)
 | 
				
			||||||
	server := httptest.NewServer(handler)
 | 
						server := httptest.NewServer(handler)
 | 
				
			||||||
	defer server.Close()
 | 
						defer server.Close()
 | 
				
			||||||
	client := http.Client{}
 | 
						client := http.Client{}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user