Merge pull request #131656 from karlkfi/karl-request-methods
refactor: Add request method constants Kubernetes-commit: 0f9987650cca2f24787e4cd38d257b77aabf68db
This commit is contained in:
		
						commit
						1527793495
					
				| 
						 | 
				
			
			@ -567,7 +567,7 @@ func (s *ConnecterRESTStorage) Connect(ctx context.Context, id string, options r
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func (s *ConnecterRESTStorage) ConnectMethods() []string {
 | 
			
		||||
	return []string{"GET", "POST", "PUT", "DELETE"}
 | 
			
		||||
	return []string{request.MethodGet, request.MethodPost, request.MethodPut, request.MethodDelete}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ConnecterRESTStorage) NewConnectOptions() (runtime.Object, bool, string) {
 | 
			
		||||
| 
						 | 
				
			
			@ -741,64 +741,64 @@ func TestNotFound(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
	cases := map[string]T{
 | 
			
		||||
		// Positive checks to make sure everything is wired correctly
 | 
			
		||||
		"groupless GET root":       {"GET", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/simpleroots", http.StatusOK},
 | 
			
		||||
		"groupless GET namespaced": {"GET", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/ns/simples", http.StatusOK},
 | 
			
		||||
		"groupless GET root":       {request.MethodGet, "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/simpleroots", http.StatusOK},
 | 
			
		||||
		"groupless GET namespaced": {request.MethodGet, "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/ns/simples", http.StatusOK},
 | 
			
		||||
 | 
			
		||||
		"groupless GET long prefix": {"GET", "/" + grouplessPrefix + "/", http.StatusNotFound},
 | 
			
		||||
		"groupless GET long prefix": {request.MethodGet, "/" + grouplessPrefix + "/", http.StatusNotFound},
 | 
			
		||||
 | 
			
		||||
		"groupless root PATCH method":                 {"PATCH", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/simpleroots", http.StatusMethodNotAllowed},
 | 
			
		||||
		"groupless root GET missing storage":          {"GET", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/blah", http.StatusNotFound},
 | 
			
		||||
		"groupless root GET with extra segment":       {"GET", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/simpleroots/bar/baz", http.StatusNotFound},
 | 
			
		||||
		"groupless root DELETE without extra segment": {"DELETE", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/simpleroots", http.StatusMethodNotAllowed},
 | 
			
		||||
		"groupless root DELETE with extra segment":    {"DELETE", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/simpleroots/bar/baz", http.StatusNotFound},
 | 
			
		||||
		"groupless root PUT without extra segment":    {"PUT", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/simpleroots", http.StatusMethodNotAllowed},
 | 
			
		||||
		"groupless root PUT with extra segment":       {"PUT", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/simpleroots/bar/baz", http.StatusNotFound},
 | 
			
		||||
		"groupless root watch missing storage":        {"GET", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/watch/", http.StatusInternalServerError},
 | 
			
		||||
		"groupless root PATCH method":                 {request.MethodPatch, "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/simpleroots", http.StatusMethodNotAllowed},
 | 
			
		||||
		"groupless root GET missing storage":          {request.MethodGet, "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/blah", http.StatusNotFound},
 | 
			
		||||
		"groupless root GET with extra segment":       {request.MethodGet, "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/simpleroots/bar/baz", http.StatusNotFound},
 | 
			
		||||
		"groupless root DELETE without extra segment": {request.MethodDelete, "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/simpleroots", http.StatusMethodNotAllowed},
 | 
			
		||||
		"groupless root DELETE with extra segment":    {request.MethodDelete, "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/simpleroots/bar/baz", http.StatusNotFound},
 | 
			
		||||
		"groupless root PUT without extra segment":    {request.MethodPut, "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/simpleroots", http.StatusMethodNotAllowed},
 | 
			
		||||
		"groupless root PUT with extra segment":       {request.MethodPut, "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/simpleroots/bar/baz", http.StatusNotFound},
 | 
			
		||||
		"groupless root watch missing storage":        {request.MethodGet, "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/watch/", http.StatusInternalServerError},
 | 
			
		||||
 | 
			
		||||
		"groupless namespaced PATCH method":                 {"PATCH", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/ns/simples", http.StatusMethodNotAllowed},
 | 
			
		||||
		"groupless namespaced GET long prefix":              {"GET", "/" + grouplessPrefix + "/", http.StatusNotFound},
 | 
			
		||||
		"groupless namespaced GET missing storage":          {"GET", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/blah", http.StatusNotFound},
 | 
			
		||||
		"groupless namespaced GET with extra segment":       {"GET", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/ns/simples/bar/baz", http.StatusNotFound},
 | 
			
		||||
		"groupless namespaced POST with extra segment":      {"POST", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/ns/simples/bar", http.StatusMethodNotAllowed},
 | 
			
		||||
		"groupless namespaced DELETE without extra segment": {"DELETE", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/ns/simples", http.StatusMethodNotAllowed},
 | 
			
		||||
		"groupless namespaced DELETE with extra segment":    {"DELETE", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/ns/simples/bar/baz", http.StatusNotFound},
 | 
			
		||||
		"groupless namespaced PUT without extra segment":    {"PUT", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/ns/simples", http.StatusMethodNotAllowed},
 | 
			
		||||
		"groupless namespaced PUT with extra segment":       {"PUT", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/ns/simples/bar/baz", http.StatusNotFound},
 | 
			
		||||
		"groupless namespaced watch missing storage":        {"GET", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/watch/", http.StatusInternalServerError},
 | 
			
		||||
		"groupless namespaced watch with bad method":        {"POST", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/watch/namespaces/ns/simples/bar", http.StatusMethodNotAllowed},
 | 
			
		||||
		"groupless namespaced watch param with bad method":  {"POST", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/ns/simples/bar?watch=true", http.StatusMethodNotAllowed},
 | 
			
		||||
		"groupless namespaced PATCH method":                 {request.MethodPatch, "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/ns/simples", http.StatusMethodNotAllowed},
 | 
			
		||||
		"groupless namespaced GET long prefix":              {request.MethodGet, "/" + grouplessPrefix + "/", http.StatusNotFound},
 | 
			
		||||
		"groupless namespaced GET missing storage":          {request.MethodGet, "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/blah", http.StatusNotFound},
 | 
			
		||||
		"groupless namespaced GET with extra segment":       {request.MethodGet, "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/ns/simples/bar/baz", http.StatusNotFound},
 | 
			
		||||
		"groupless namespaced POST with extra segment":      {request.MethodPost, "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/ns/simples/bar", http.StatusMethodNotAllowed},
 | 
			
		||||
		"groupless namespaced DELETE without extra segment": {request.MethodDelete, "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/ns/simples", http.StatusMethodNotAllowed},
 | 
			
		||||
		"groupless namespaced DELETE with extra segment":    {request.MethodDelete, "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/ns/simples/bar/baz", http.StatusNotFound},
 | 
			
		||||
		"groupless namespaced PUT without extra segment":    {request.MethodPut, "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/ns/simples", http.StatusMethodNotAllowed},
 | 
			
		||||
		"groupless namespaced PUT with extra segment":       {request.MethodPut, "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/ns/simples/bar/baz", http.StatusNotFound},
 | 
			
		||||
		"groupless namespaced watch missing storage":        {request.MethodGet, "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/watch/", http.StatusInternalServerError},
 | 
			
		||||
		"groupless namespaced watch with bad method":        {request.MethodPost, "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/watch/namespaces/ns/simples/bar", http.StatusMethodNotAllowed},
 | 
			
		||||
		"groupless namespaced watch param with bad method":  {request.MethodPost, "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/ns/simples/bar?watch=true", http.StatusMethodNotAllowed},
 | 
			
		||||
 | 
			
		||||
		// Positive checks to make sure everything is wired correctly
 | 
			
		||||
		"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},
 | 
			
		||||
		"GET namespaced": {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/ns/simples", http.StatusOK},
 | 
			
		||||
		// TODO: JTL: "GET namespaced item": {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/ns/simples/bar", http.StatusOK},
 | 
			
		||||
		"GET root": {request.MethodGet, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simpleroots", http.StatusOK},
 | 
			
		||||
		// TODO: JTL: "GET root item":       {request.MethodGet, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simpleroots/bar", http.StatusOK},
 | 
			
		||||
		"GET namespaced": {request.MethodGet, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/ns/simples", http.StatusOK},
 | 
			
		||||
		// TODO: JTL: "GET namespaced item": {request.MethodGet, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/ns/simples/bar", http.StatusOK},
 | 
			
		||||
 | 
			
		||||
		"GET long prefix": {"GET", "/" + prefix + "/", http.StatusNotFound},
 | 
			
		||||
		"GET long prefix": {request.MethodGet, "/" + prefix + "/", http.StatusNotFound},
 | 
			
		||||
 | 
			
		||||
		"root PATCH method":           {"PATCH", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simpleroots", http.StatusMethodNotAllowed},
 | 
			
		||||
		"root GET missing storage":    {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/blah", http.StatusNotFound},
 | 
			
		||||
		"root GET with extra segment": {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simpleroots/bar/baz", http.StatusNotFound},
 | 
			
		||||
		// TODO: JTL: "root POST with extra segment":      {"POST", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simpleroots/bar", http.StatusMethodNotAllowed},
 | 
			
		||||
		"root DELETE without extra segment": {"DELETE", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simpleroots", http.StatusMethodNotAllowed},
 | 
			
		||||
		"root DELETE with extra segment":    {"DELETE", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simpleroots/bar/baz", http.StatusNotFound},
 | 
			
		||||
		"root PUT without extra segment":    {"PUT", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simpleroots", http.StatusMethodNotAllowed},
 | 
			
		||||
		"root PUT with extra segment":       {"PUT", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simpleroots/bar/baz", http.StatusNotFound},
 | 
			
		||||
		"root watch missing storage":        {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/watch/", http.StatusInternalServerError},
 | 
			
		||||
		// TODO: JTL: "root watch with bad method":        {"POST", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/watch/simpleroot/bar", http.StatusMethodNotAllowed},
 | 
			
		||||
		"root PATCH method":           {request.MethodPatch, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simpleroots", http.StatusMethodNotAllowed},
 | 
			
		||||
		"root GET missing storage":    {request.MethodGet, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/blah", http.StatusNotFound},
 | 
			
		||||
		"root GET with extra segment": {request.MethodGet, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simpleroots/bar/baz", http.StatusNotFound},
 | 
			
		||||
		// TODO: JTL: "root POST with extra segment":      {request.MethodPost, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simpleroots/bar", http.StatusMethodNotAllowed},
 | 
			
		||||
		"root DELETE without extra segment": {request.MethodDelete, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simpleroots", http.StatusMethodNotAllowed},
 | 
			
		||||
		"root DELETE with extra segment":    {request.MethodDelete, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simpleroots/bar/baz", http.StatusNotFound},
 | 
			
		||||
		"root PUT without extra segment":    {request.MethodPut, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simpleroots", http.StatusMethodNotAllowed},
 | 
			
		||||
		"root PUT with extra segment":       {request.MethodPut, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simpleroots/bar/baz", http.StatusNotFound},
 | 
			
		||||
		"root watch missing storage":        {request.MethodGet, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/watch/", http.StatusInternalServerError},
 | 
			
		||||
		// TODO: JTL: "root watch with bad method":        {request.MethodPost, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/watch/simpleroot/bar", http.StatusMethodNotAllowed},
 | 
			
		||||
 | 
			
		||||
		"namespaced PATCH method":                 {"PATCH", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/ns/simples", http.StatusMethodNotAllowed},
 | 
			
		||||
		"namespaced GET long prefix":              {"GET", "/" + prefix + "/", http.StatusNotFound},
 | 
			
		||||
		"namespaced GET missing storage":          {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/blah", http.StatusNotFound},
 | 
			
		||||
		"namespaced GET with extra segment":       {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/ns/simples/bar/baz", http.StatusNotFound},
 | 
			
		||||
		"namespaced POST with extra segment":      {"POST", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/ns/simples/bar", http.StatusMethodNotAllowed},
 | 
			
		||||
		"namespaced DELETE without extra segment": {"DELETE", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/ns/simples", http.StatusMethodNotAllowed},
 | 
			
		||||
		"namespaced DELETE with extra segment":    {"DELETE", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/ns/simples/bar/baz", http.StatusNotFound},
 | 
			
		||||
		"namespaced PUT without extra segment":    {"PUT", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/ns/simples", http.StatusMethodNotAllowed},
 | 
			
		||||
		"namespaced PUT with extra segment":       {"PUT", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/ns/simples/bar/baz", http.StatusNotFound},
 | 
			
		||||
		"namespaced watch missing storage":        {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/watch/", http.StatusInternalServerError},
 | 
			
		||||
		"namespaced watch with bad method":        {"POST", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/watch/namespaces/ns/simples/bar", http.StatusMethodNotAllowed},
 | 
			
		||||
		"namespaced watch param with bad method":  {"POST", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/ns/simples/bar?watch=true", http.StatusMethodNotAllowed},
 | 
			
		||||
		"namespaced PATCH method":                 {request.MethodPatch, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/ns/simples", http.StatusMethodNotAllowed},
 | 
			
		||||
		"namespaced GET long prefix":              {request.MethodGet, "/" + prefix + "/", http.StatusNotFound},
 | 
			
		||||
		"namespaced GET missing storage":          {request.MethodGet, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/blah", http.StatusNotFound},
 | 
			
		||||
		"namespaced GET with extra segment":       {request.MethodGet, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/ns/simples/bar/baz", http.StatusNotFound},
 | 
			
		||||
		"namespaced POST with extra segment":      {request.MethodPost, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/ns/simples/bar", http.StatusMethodNotAllowed},
 | 
			
		||||
		"namespaced DELETE without extra segment": {request.MethodDelete, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/ns/simples", http.StatusMethodNotAllowed},
 | 
			
		||||
		"namespaced DELETE with extra segment":    {request.MethodDelete, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/ns/simples/bar/baz", http.StatusNotFound},
 | 
			
		||||
		"namespaced PUT without extra segment":    {request.MethodPut, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/ns/simples", http.StatusMethodNotAllowed},
 | 
			
		||||
		"namespaced PUT with extra segment":       {request.MethodPut, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/ns/simples/bar/baz", http.StatusNotFound},
 | 
			
		||||
		"namespaced watch missing storage":        {request.MethodGet, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/watch/", http.StatusInternalServerError},
 | 
			
		||||
		"namespaced watch with bad method":        {request.MethodPost, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/watch/namespaces/ns/simples/bar", http.StatusMethodNotAllowed},
 | 
			
		||||
		"namespaced watch param with bad method":  {request.MethodPost, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/ns/simples/bar?watch=true", http.StatusMethodNotAllowed},
 | 
			
		||||
	}
 | 
			
		||||
	handler := handle(map[string]rest.Storage{
 | 
			
		||||
		"simples":     &SimpleRESTStorage{},
 | 
			
		||||
| 
						 | 
				
			
			@ -853,23 +853,23 @@ func TestUnimplementedRESTStorage(t *testing.T) {
 | 
			
		|||
		ErrCode int
 | 
			
		||||
	}
 | 
			
		||||
	cases := map[string]T{
 | 
			
		||||
		"groupless GET object":    {"GET", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/foo/bar", http.StatusNotFound},
 | 
			
		||||
		"groupless GET list":      {"GET", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/foo", http.StatusNotFound},
 | 
			
		||||
		"groupless POST list":     {"POST", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/foo", http.StatusNotFound},
 | 
			
		||||
		"groupless PUT object":    {"PUT", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/foo/bar", http.StatusNotFound},
 | 
			
		||||
		"groupless DELETE object": {"DELETE", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/foo/bar", http.StatusNotFound},
 | 
			
		||||
		"groupless watch list":    {"GET", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/watch/foo", http.StatusNotFound},
 | 
			
		||||
		"groupless watch object":  {"GET", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/watch/foo/bar", http.StatusNotFound},
 | 
			
		||||
		"groupless proxy object":  {"GET", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/proxy/foo/bar", http.StatusNotFound},
 | 
			
		||||
		"groupless GET object":    {request.MethodGet, "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/foo/bar", http.StatusNotFound},
 | 
			
		||||
		"groupless GET list":      {request.MethodGet, "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/foo", http.StatusNotFound},
 | 
			
		||||
		"groupless POST list":     {request.MethodPost, "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/foo", http.StatusNotFound},
 | 
			
		||||
		"groupless PUT object":    {request.MethodPut, "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/foo/bar", http.StatusNotFound},
 | 
			
		||||
		"groupless DELETE object": {request.MethodDelete, "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/foo/bar", http.StatusNotFound},
 | 
			
		||||
		"groupless watch list":    {request.MethodGet, "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/watch/foo", http.StatusNotFound},
 | 
			
		||||
		"groupless watch object":  {request.MethodGet, "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/watch/foo/bar", http.StatusNotFound},
 | 
			
		||||
		"groupless proxy object":  {request.MethodGet, "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/proxy/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},
 | 
			
		||||
		"POST list":     {"POST", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/foo", http.StatusNotFound},
 | 
			
		||||
		"PUT object":    {"PUT", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/foo/bar", http.StatusNotFound},
 | 
			
		||||
		"DELETE object": {"DELETE", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/foo/bar", http.StatusNotFound},
 | 
			
		||||
		"watch list":    {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/watch/foo", http.StatusNotFound},
 | 
			
		||||
		"watch object":  {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/watch/foo/bar", http.StatusNotFound},
 | 
			
		||||
		"proxy object":  {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/proxy/foo/bar", http.StatusNotFound},
 | 
			
		||||
		"GET object":    {request.MethodGet, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/foo/bar", http.StatusNotFound},
 | 
			
		||||
		"GET list":      {request.MethodGet, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/foo", http.StatusNotFound},
 | 
			
		||||
		"POST list":     {request.MethodPost, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/foo", http.StatusNotFound},
 | 
			
		||||
		"PUT object":    {request.MethodPut, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/foo/bar", http.StatusNotFound},
 | 
			
		||||
		"DELETE object": {request.MethodDelete, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/foo/bar", http.StatusNotFound},
 | 
			
		||||
		"watch list":    {request.MethodGet, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/watch/foo", http.StatusNotFound},
 | 
			
		||||
		"watch object":  {request.MethodGet, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/watch/foo/bar", http.StatusNotFound},
 | 
			
		||||
		"proxy object":  {request.MethodGet, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/proxy/foo/bar", http.StatusNotFound},
 | 
			
		||||
	}
 | 
			
		||||
	handler := handle(map[string]rest.Storage{
 | 
			
		||||
		"foo": UnimplementedRESTStorage{},
 | 
			
		||||
| 
						 | 
				
			
			@ -931,14 +931,14 @@ func TestSomeUnimplementedRESTStorage(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	cases := map[string]T{
 | 
			
		||||
		"groupless POST list":         {"POST", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/default/foo", http.StatusMethodNotAllowed},
 | 
			
		||||
		"groupless PUT object":        {"PUT", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/default/foo/bar", http.StatusMethodNotAllowed},
 | 
			
		||||
		"groupless DELETE object":     {"DELETE", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/default/foo/bar", http.StatusMethodNotAllowed},
 | 
			
		||||
		"groupless DELETE collection": {"DELETE", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/default/foo", http.StatusMethodNotAllowed},
 | 
			
		||||
		"POST list":                   {"POST", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/default/foo", http.StatusMethodNotAllowed},
 | 
			
		||||
		"PUT object":                  {"PUT", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/default/foo/bar", http.StatusMethodNotAllowed},
 | 
			
		||||
		"DELETE object":               {"DELETE", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/default/foo/bar", http.StatusMethodNotAllowed},
 | 
			
		||||
		"DELETE collection":           {"DELETE", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/default/foo", http.StatusMethodNotAllowed},
 | 
			
		||||
		"groupless POST list":         {request.MethodPost, "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/default/foo", http.StatusMethodNotAllowed},
 | 
			
		||||
		"groupless PUT object":        {request.MethodPut, "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/default/foo/bar", http.StatusMethodNotAllowed},
 | 
			
		||||
		"groupless DELETE object":     {request.MethodDelete, "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/default/foo/bar", http.StatusMethodNotAllowed},
 | 
			
		||||
		"groupless DELETE collection": {request.MethodDelete, "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/default/foo", http.StatusMethodNotAllowed},
 | 
			
		||||
		"POST list":                   {request.MethodPost, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/default/foo", http.StatusMethodNotAllowed},
 | 
			
		||||
		"PUT object":                  {request.MethodPut, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/default/foo/bar", http.StatusMethodNotAllowed},
 | 
			
		||||
		"DELETE object":               {request.MethodDelete, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/default/foo/bar", http.StatusMethodNotAllowed},
 | 
			
		||||
		"DELETE collection":           {request.MethodDelete, "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/default/foo", http.StatusMethodNotAllowed},
 | 
			
		||||
	}
 | 
			
		||||
	handler := handle(map[string]rest.Storage{
 | 
			
		||||
		"foo": OnlyGetRESTStorage{},
 | 
			
		||||
| 
						 | 
				
			
			@ -1158,12 +1158,12 @@ func TestRequestsWithInvalidQuery(t *testing.T) {
 | 
			
		|||
		postfix string
 | 
			
		||||
		method  string
 | 
			
		||||
	}{
 | 
			
		||||
		{"/simple?labelSelector=<invalid>", http.MethodGet},
 | 
			
		||||
		{"/simple/foo?gracePeriodSeconds=<invalid>", http.MethodDelete},
 | 
			
		||||
		// {"/simple?labelSelector=<value>", http.MethodDelete}, TODO: implement DeleteCollection in  SimpleRESTStorage
 | 
			
		||||
		// {"/simple/foo?export=<invalid>", http.MethodGet}, TODO: there is no invalid bool in conversion. Should we be more strict?
 | 
			
		||||
		// {"/simple/foo?resourceVersion=<invalid>", http.MethodGet}, TODO: there is no invalid resourceVersion. Should we be more strict?
 | 
			
		||||
		// {"/withoptions?labelSelector=<invalid>", http.MethodGet}, TODO: SimpleGetOptions is always valid. Add more validation that can fail.
 | 
			
		||||
		{"/simple?labelSelector=<invalid>", request.MethodGet},
 | 
			
		||||
		{"/simple/foo?gracePeriodSeconds=<invalid>", request.MethodDelete},
 | 
			
		||||
		// {"/simple?labelSelector=<value>", request.MethodDelete}, TODO: implement DeleteCollection in  SimpleRESTStorage
 | 
			
		||||
		// {"/simple/foo?export=<invalid>", request.MethodGet}, TODO: there is no invalid bool in conversion. Should we be more strict?
 | 
			
		||||
		// {"/simple/foo?resourceVersion=<invalid>", request.MethodGet}, TODO: there is no invalid resourceVersion. Should we be more strict?
 | 
			
		||||
		// {"/withoptions?labelSelector=<invalid>", request.MethodGet}, TODO: SimpleGetOptions is always valid. Add more validation that can fail.
 | 
			
		||||
	} {
 | 
			
		||||
		baseURL := server.URL + "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/default"
 | 
			
		||||
		url := baseURL + test.postfix
 | 
			
		||||
| 
						 | 
				
			
			@ -1228,7 +1228,7 @@ func TestListCompression(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
		defer server.Close()
 | 
			
		||||
 | 
			
		||||
		req, err := http.NewRequest("GET", server.URL+testCase.url, nil)
 | 
			
		||||
		req, err := http.NewRequest(request.MethodGet, server.URL+testCase.url, nil)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Errorf("%d: unexpected error: %v", i, err)
 | 
			
		||||
			continue
 | 
			
		||||
| 
						 | 
				
			
			@ -1289,7 +1289,7 @@ func TestLogs(t *testing.T) {
 | 
			
		|||
	defer server.Close()
 | 
			
		||||
	client := http.Client{}
 | 
			
		||||
 | 
			
		||||
	request, err := http.NewRequest("GET", server.URL+"/logs", nil)
 | 
			
		||||
	request, err := http.NewRequest(request.MethodGet, server.URL+"/logs", nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -1526,7 +1526,7 @@ func TestGetCompression(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	for _, test := range tests {
 | 
			
		||||
		req, err := http.NewRequest("GET", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/id", nil)
 | 
			
		||||
		req, err := http.NewRequest(request.MethodGet, server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/id", nil)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Fatalf("unexpected error creating request: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -1603,7 +1603,7 @@ func TestGetPretty(t *testing.T) {
 | 
			
		|||
			t.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
		u.RawQuery = test.params.Encode()
 | 
			
		||||
		req := &http.Request{Method: "GET", URL: u}
 | 
			
		||||
		req := &http.Request{Method: request.MethodGet, URL: u}
 | 
			
		||||
		req.Header = http.Header{}
 | 
			
		||||
		req.Header.Set("Accept", test.accept)
 | 
			
		||||
		req.Header.Set("User-Agent", test.userAgent)
 | 
			
		||||
| 
						 | 
				
			
			@ -1802,7 +1802,7 @@ func TestGetTable(t *testing.T) {
 | 
			
		|||
				t.Fatal(err)
 | 
			
		||||
			}
 | 
			
		||||
			u.RawQuery = test.params.Encode()
 | 
			
		||||
			req := &http.Request{Method: "GET", URL: u}
 | 
			
		||||
			req := &http.Request{Method: request.MethodGet, URL: u}
 | 
			
		||||
			req.Header = http.Header{}
 | 
			
		||||
			req.Header.Set("Accept", test.accept)
 | 
			
		||||
			resp, err := http.DefaultClient.Do(req)
 | 
			
		||||
| 
						 | 
				
			
			@ -2012,7 +2012,7 @@ func TestWatchTable(t *testing.T) {
 | 
			
		|||
			test.params["watch"] = []string{"1"}
 | 
			
		||||
 | 
			
		||||
			u.RawQuery = test.params.Encode()
 | 
			
		||||
			req := &http.Request{Method: "GET", URL: u}
 | 
			
		||||
			req := &http.Request{Method: request.MethodGet, URL: u}
 | 
			
		||||
			req.Header = http.Header{}
 | 
			
		||||
			req.Header.Set("Accept", test.accept)
 | 
			
		||||
			resp, err := http.DefaultClient.Do(req)
 | 
			
		||||
| 
						 | 
				
			
			@ -2207,7 +2207,7 @@ func TestGetPartialObjectMetadata(t *testing.T) {
 | 
			
		|||
			t.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
		u.RawQuery = test.params.Encode()
 | 
			
		||||
		req := &http.Request{Method: "GET", URL: u}
 | 
			
		||||
		req := &http.Request{Method: request.MethodGet, URL: u}
 | 
			
		||||
		req.Header = http.Header{}
 | 
			
		||||
		req.Header.Set("Accept", test.accept)
 | 
			
		||||
		resp, err := http.DefaultClient.Do(req)
 | 
			
		||||
| 
						 | 
				
			
			@ -2271,7 +2271,7 @@ func TestGetBinary(t *testing.T) {
 | 
			
		|||
	server := httptest.NewServer(handle(map[string]rest.Storage{"simple": &simpleStorage}))
 | 
			
		||||
	defer server.Close()
 | 
			
		||||
 | 
			
		||||
	req, err := http.NewRequest("GET", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/binary", nil)
 | 
			
		||||
	req, err := http.NewRequest(request.MethodGet, server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/binary", nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -2327,7 +2327,7 @@ func TestGetWithOptionsRouteParams(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
	routes := ws[0].Routes()
 | 
			
		||||
	for i := range routes {
 | 
			
		||||
		if routes[i].Method == "GET" && routes[i].Operation == "readNamespacedSimple" {
 | 
			
		||||
		if routes[i].Method == request.MethodGet && routes[i].Operation == "readNamespacedSimple" {
 | 
			
		||||
			validateSimpleGetOptionsParams(t, &routes[i])
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -2768,7 +2768,7 @@ func TestDelete(t *testing.T) {
 | 
			
		|||
	defer server.Close()
 | 
			
		||||
 | 
			
		||||
	client := http.Client{}
 | 
			
		||||
	request, err := http.NewRequest("DELETE", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, nil)
 | 
			
		||||
	request, err := http.NewRequest(request.MethodDelete, server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -2803,7 +2803,7 @@ func TestDeleteWithOptions(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	client := http.Client{}
 | 
			
		||||
	request, err := http.NewRequest("DELETE", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader(body))
 | 
			
		||||
	request, err := http.NewRequest(request.MethodDelete, server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader(body))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -2843,7 +2843,7 @@ func TestDeleteWithOptionsQuery(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	client := http.Client{}
 | 
			
		||||
	request, err := http.NewRequest("DELETE", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID+"?gracePeriodSeconds="+strconv.FormatInt(grace, 10), nil)
 | 
			
		||||
	request, err := http.NewRequest(request.MethodDelete, server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID+"?gracePeriodSeconds="+strconv.FormatInt(grace, 10), nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -2886,7 +2886,7 @@ func TestDeleteWithOptionsQueryAndBody(t *testing.T) {
 | 
			
		|||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	client := http.Client{}
 | 
			
		||||
	request, err := http.NewRequest("DELETE", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID+"?gracePeriodSeconds="+strconv.FormatInt(grace+10, 10), bytes.NewReader(body))
 | 
			
		||||
	request, err := http.NewRequest(request.MethodDelete, server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID+"?gracePeriodSeconds="+strconv.FormatInt(grace+10, 10), bytes.NewReader(body))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -2925,7 +2925,7 @@ func TestDeleteInvokesAdmissionControl(t *testing.T) {
 | 
			
		|||
		defer server.Close()
 | 
			
		||||
 | 
			
		||||
		client := http.Client{}
 | 
			
		||||
		request, err := http.NewRequest("DELETE", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, nil)
 | 
			
		||||
		request, err := http.NewRequest(request.MethodDelete, server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, nil)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Errorf("unexpected error: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -2951,7 +2951,7 @@ func TestDeleteMissing(t *testing.T) {
 | 
			
		|||
	defer server.Close()
 | 
			
		||||
 | 
			
		||||
	client := http.Client{}
 | 
			
		||||
	request, err := http.NewRequest("DELETE", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, nil)
 | 
			
		||||
	request, err := http.NewRequest(request.MethodDelete, server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -2988,7 +2988,7 @@ func TestUpdate(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	client := http.Client{}
 | 
			
		||||
	request, err := http.NewRequest("PUT", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader(body))
 | 
			
		||||
	request, err := http.NewRequest(request.MethodPut, server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader(body))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -3030,7 +3030,7 @@ func TestUpdateInvokesAdmissionControl(t *testing.T) {
 | 
			
		|||
		}
 | 
			
		||||
 | 
			
		||||
		client := http.Client{}
 | 
			
		||||
		request, err := http.NewRequest("PUT", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader(body))
 | 
			
		||||
		request, err := http.NewRequest(request.MethodPut, server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader(body))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Errorf("unexpected error: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -3066,7 +3066,7 @@ func TestUpdateRequiresMatchingName(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	client := http.Client{}
 | 
			
		||||
	request, err := http.NewRequest("PUT", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader(body))
 | 
			
		||||
	request, err := http.NewRequest(request.MethodPut, server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader(body))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -3103,7 +3103,7 @@ func TestUpdateAllowsMissingNamespace(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	client := http.Client{}
 | 
			
		||||
	request, err := http.NewRequest("PUT", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader(body))
 | 
			
		||||
	request, err := http.NewRequest(request.MethodPut, server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader(body))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -3143,7 +3143,7 @@ func TestUpdateDisallowsMismatchedNamespaceOnError(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	client := http.Client{}
 | 
			
		||||
	request, err := http.NewRequest("PUT", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader(body))
 | 
			
		||||
	request, err := http.NewRequest(request.MethodPut, server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader(body))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -3182,7 +3182,7 @@ func TestUpdatePreventsMismatchedNamespace(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	client := http.Client{}
 | 
			
		||||
	request, err := http.NewRequest("PUT", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader(body))
 | 
			
		||||
	request, err := http.NewRequest(request.MethodPut, server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader(body))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -3219,7 +3219,7 @@ func TestUpdateMissing(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	client := http.Client{}
 | 
			
		||||
	request, err := http.NewRequest("PUT", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader(body))
 | 
			
		||||
	request, err := http.NewRequest(request.MethodPut, server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader(body))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -3249,7 +3249,7 @@ func TestCreateNotFound(t *testing.T) {
 | 
			
		|||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	request, err := http.NewRequest("POST", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple", bytes.NewBuffer(data))
 | 
			
		||||
	request, err := http.NewRequest(request.MethodPost, server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple", bytes.NewBuffer(data))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -3275,7 +3275,7 @@ func TestCreateChecksDecode(t *testing.T) {
 | 
			
		|||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	request, err := http.NewRequest("POST", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple", bytes.NewBuffer(data))
 | 
			
		||||
	request, err := http.NewRequest(request.MethodPost, server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple", bytes.NewBuffer(data))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -3363,14 +3363,14 @@ func TestParentResourceIsRequired(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
	// resource is NOT registered in the root scope
 | 
			
		||||
	w := httptest.NewRecorder()
 | 
			
		||||
	handler.ServeHTTP(w, &http.Request{Method: "GET", URL: &url.URL{Path: "/" + prefix + "/simple/test/sub"}})
 | 
			
		||||
	handler.ServeHTTP(w, &http.Request{Method: request.MethodGet, URL: &url.URL{Path: "/" + prefix + "/simple/test/sub"}})
 | 
			
		||||
	if w.Code != http.StatusNotFound {
 | 
			
		||||
		t.Errorf("expected not found: %#v", w)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// resource is registered in the namespace scope
 | 
			
		||||
	w = httptest.NewRecorder()
 | 
			
		||||
	handler.ServeHTTP(w, &http.Request{Method: "GET", URL: &url.URL{Path: "/" + prefix + "/" + newGroupVersion.Group + "/" + newGroupVersion.Version + "/namespaces/test/simple/test/sub"}})
 | 
			
		||||
	handler.ServeHTTP(w, &http.Request{Method: request.MethodGet, URL: &url.URL{Path: "/" + prefix + "/" + newGroupVersion.Group + "/" + newGroupVersion.Version + "/namespaces/test/simple/test/sub"}})
 | 
			
		||||
	if w.Code != http.StatusOK {
 | 
			
		||||
		t.Fatalf("expected OK: %#v", w)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -3395,7 +3395,7 @@ func TestNamedCreaterWithName(t *testing.T) {
 | 
			
		|||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	request, err := http.NewRequest("POST", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+pathName+"/sub", bytes.NewBuffer(data))
 | 
			
		||||
	request, err := http.NewRequest(request.MethodPost, server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+pathName+"/sub", bytes.NewBuffer(data))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -3433,7 +3433,7 @@ func TestNamedCreaterWithoutName(t *testing.T) {
 | 
			
		|||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	request, err := http.NewRequest("POST", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/foo", bytes.NewBuffer(data))
 | 
			
		||||
	request, err := http.NewRequest(request.MethodPost, server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/foo", bytes.NewBuffer(data))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -3507,7 +3507,7 @@ func TestNamedCreaterWithGenerateName(t *testing.T) {
 | 
			
		|||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	request, err := http.NewRequest("POST", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/foo", bytes.NewBuffer(data))
 | 
			
		||||
	request, err := http.NewRequest(request.MethodPost, server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/foo", bytes.NewBuffer(data))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -3554,7 +3554,7 @@ func TestUpdateChecksDecode(t *testing.T) {
 | 
			
		|||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	request, err := http.NewRequest("PUT", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/bar", bytes.NewBuffer(data))
 | 
			
		||||
	request, err := http.NewRequest(request.MethodPut, server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/bar", bytes.NewBuffer(data))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -3592,7 +3592,7 @@ func TestCreate(t *testing.T) {
 | 
			
		|||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	request, err := http.NewRequest("POST", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/foo", bytes.NewBuffer(data))
 | 
			
		||||
	request, err := http.NewRequest(request.MethodPost, server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/foo", bytes.NewBuffer(data))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -3654,7 +3654,7 @@ func TestCreateYAML(t *testing.T) {
 | 
			
		|||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	request, err := http.NewRequest("POST", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/foo", bytes.NewBuffer(data))
 | 
			
		||||
	request, err := http.NewRequest(request.MethodPost, server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/foo", bytes.NewBuffer(data))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -3710,7 +3710,7 @@ func TestCreateInNamespace(t *testing.T) {
 | 
			
		|||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	request, err := http.NewRequest("POST", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/other/foo", bytes.NewBuffer(data))
 | 
			
		||||
	request, err := http.NewRequest(request.MethodPost, server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/other/foo", bytes.NewBuffer(data))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -3767,7 +3767,7 @@ func TestCreateInvokeAdmissionControl(t *testing.T) {
 | 
			
		|||
		if err != nil {
 | 
			
		||||
			t.Errorf("unexpected error: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
		request, err := http.NewRequest("POST", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/other/foo", bytes.NewBuffer(data))
 | 
			
		||||
		request, err := http.NewRequest(request.MethodPost, server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/other/foo", bytes.NewBuffer(data))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Errorf("unexpected error: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -3818,7 +3818,7 @@ func TestDelayReturnsError(t *testing.T) {
 | 
			
		|||
	server := httptest.NewServer(handler)
 | 
			
		||||
	defer server.Close()
 | 
			
		||||
 | 
			
		||||
	status := expectAPIStatus(t, "DELETE", fmt.Sprintf("%s/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/foo/bar", server.URL), nil, http.StatusConflict)
 | 
			
		||||
	status := expectAPIStatus(t, request.MethodDelete, fmt.Sprintf("%s/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/foo/bar", server.URL), nil, http.StatusConflict)
 | 
			
		||||
	if status.Status != metav1.StatusFailure || status.Message == "" || status.Details == nil || status.Reason != metav1.StatusReasonAlreadyExists {
 | 
			
		||||
		t.Errorf("Unexpected status %#v", status)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -3849,7 +3849,7 @@ func TestWriteJSONDecodeError(t *testing.T) {
 | 
			
		|||
	// Unless specific metav1.Status() parameters are implemented for the particular error in question, such that
 | 
			
		||||
	// the status code is defined, metav1 errors where error.status == metav1.StatusFailure
 | 
			
		||||
	// will throw a '500 Internal Server Error'. Non-metav1 type errors will always throw a '500 Internal Server Error'.
 | 
			
		||||
	status := expectAPIStatus(t, "GET", server.URL, nil, http.StatusInternalServerError)
 | 
			
		||||
	status := expectAPIStatus(t, request.MethodGet, server.URL, nil, http.StatusInternalServerError)
 | 
			
		||||
	if status.Reason != metav1.StatusReasonUnknown {
 | 
			
		||||
		t.Errorf("unexpected reason %#v", status)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -3903,7 +3903,7 @@ func TestCreateTimeout(t *testing.T) {
 | 
			
		|||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	itemOut := expectAPIStatus(t, "POST", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/foo?timeout=4ms", data, http.StatusGatewayTimeout)
 | 
			
		||||
	itemOut := expectAPIStatus(t, request.MethodPost, server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/foo?timeout=4ms", data, http.StatusGatewayTimeout)
 | 
			
		||||
	if itemOut.Status != metav1.StatusFailure || itemOut.Reason != metav1.StatusReasonTimeout {
 | 
			
		||||
		t.Errorf("Unexpected status %#v", itemOut)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -3921,7 +3921,7 @@ func TestCreateChecksAPIVersion(t *testing.T) {
 | 
			
		|||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	request, err := http.NewRequest("POST", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple", bytes.NewBuffer(data))
 | 
			
		||||
	request, err := http.NewRequest(request.MethodPost, server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple", bytes.NewBuffer(data))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -3962,7 +3962,7 @@ func TestCreateDefaultsAPIVersion(t *testing.T) {
 | 
			
		|||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	request, err := http.NewRequest("POST", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple", bytes.NewBuffer(data))
 | 
			
		||||
	request, err := http.NewRequest(request.MethodPost, server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple", bytes.NewBuffer(data))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -3986,7 +3986,7 @@ func TestUpdateChecksAPIVersion(t *testing.T) {
 | 
			
		|||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	request, err := http.NewRequest("PUT", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/bar", bytes.NewBuffer(data))
 | 
			
		||||
	request, err := http.NewRequest(request.MethodPut, server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/bar", bytes.NewBuffer(data))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -4094,37 +4094,37 @@ unknown: baz`)
 | 
			
		|||
			expectedStatusCode int
 | 
			
		||||
		}{
 | 
			
		||||
			// Create
 | 
			
		||||
			{name: "post-strict-validation", path: "/namespaces/default/simples", verb: "POST", data: invalidJSONDataPost, queryParams: strictFieldValidation, expectedStatusCode: http.StatusBadRequest, expectedErr: strictDecodingErr},
 | 
			
		||||
			{name: "post-warn-validation", path: "/namespaces/default/simples", verb: "POST", data: invalidJSONDataPost, queryParams: warnFieldValidation, expectedStatusCode: http.StatusCreated, expectedWarns: strictDecodingWarns},
 | 
			
		||||
			{name: "post-ignore-validation", path: "/namespaces/default/simples", verb: "POST", data: invalidJSONDataPost, queryParams: ignoreFieldValidation, expectedStatusCode: http.StatusCreated},
 | 
			
		||||
			{name: "post-strict-validation", path: "/namespaces/default/simples", verb: request.MethodPost, data: invalidJSONDataPost, queryParams: strictFieldValidation, expectedStatusCode: http.StatusBadRequest, expectedErr: strictDecodingErr},
 | 
			
		||||
			{name: "post-warn-validation", path: "/namespaces/default/simples", verb: request.MethodPost, data: invalidJSONDataPost, queryParams: warnFieldValidation, expectedStatusCode: http.StatusCreated, expectedWarns: strictDecodingWarns},
 | 
			
		||||
			{name: "post-ignore-validation", path: "/namespaces/default/simples", verb: request.MethodPost, data: invalidJSONDataPost, queryParams: ignoreFieldValidation, expectedStatusCode: http.StatusCreated},
 | 
			
		||||
 | 
			
		||||
			{name: "post-strict-validation-yaml", path: "/namespaces/default/simples", verb: "POST", data: invalidYAMLDataPost, queryParams: strictFieldValidation, contentType: "application/yaml", expectedStatusCode: http.StatusBadRequest, expectedErr: strictDecodingErrYAML},
 | 
			
		||||
			{name: "post-warn-validation-yaml", path: "/namespaces/default/simples", verb: "POST", data: invalidYAMLDataPost, queryParams: warnFieldValidation, contentType: "application/yaml", expectedStatusCode: http.StatusCreated, expectedWarns: strictDecodingWarnsYAML},
 | 
			
		||||
			{name: "post-ignore-validation-yaml", path: "/namespaces/default/simples", verb: "POST", data: invalidYAMLDataPost, queryParams: ignoreFieldValidation, contentType: "application/yaml", expectedStatusCode: http.StatusCreated},
 | 
			
		||||
			{name: "post-strict-validation-yaml", path: "/namespaces/default/simples", verb: request.MethodPost, data: invalidYAMLDataPost, queryParams: strictFieldValidation, contentType: "application/yaml", expectedStatusCode: http.StatusBadRequest, expectedErr: strictDecodingErrYAML},
 | 
			
		||||
			{name: "post-warn-validation-yaml", path: "/namespaces/default/simples", verb: request.MethodPost, data: invalidYAMLDataPost, queryParams: warnFieldValidation, contentType: "application/yaml", expectedStatusCode: http.StatusCreated, expectedWarns: strictDecodingWarnsYAML},
 | 
			
		||||
			{name: "post-ignore-validation-yaml", path: "/namespaces/default/simples", verb: request.MethodPost, data: invalidYAMLDataPost, queryParams: ignoreFieldValidation, contentType: "application/yaml", expectedStatusCode: http.StatusCreated},
 | 
			
		||||
 | 
			
		||||
			// Update
 | 
			
		||||
			{name: "put-strict-validation", path: "/namespaces/default/simples/id", verb: "PUT", data: invalidJSONDataPut, queryParams: strictFieldValidation, expectedStatusCode: http.StatusBadRequest, expectedErr: strictDecodingErr},
 | 
			
		||||
			{name: "put-warn-validation", path: "/namespaces/default/simples/id", verb: "PUT", data: invalidJSONDataPut, queryParams: warnFieldValidation, expectedStatusCode: http.StatusOK, expectedWarns: strictDecodingWarns},
 | 
			
		||||
			{name: "put-ignore-validation", path: "/namespaces/default/simples/id", verb: "PUT", data: invalidJSONDataPut, queryParams: ignoreFieldValidation, expectedStatusCode: http.StatusOK},
 | 
			
		||||
			{name: "put-strict-validation", path: "/namespaces/default/simples/id", verb: request.MethodPut, data: invalidJSONDataPut, queryParams: strictFieldValidation, expectedStatusCode: http.StatusBadRequest, expectedErr: strictDecodingErr},
 | 
			
		||||
			{name: "put-warn-validation", path: "/namespaces/default/simples/id", verb: request.MethodPut, data: invalidJSONDataPut, queryParams: warnFieldValidation, expectedStatusCode: http.StatusOK, expectedWarns: strictDecodingWarns},
 | 
			
		||||
			{name: "put-ignore-validation", path: "/namespaces/default/simples/id", verb: request.MethodPut, data: invalidJSONDataPut, queryParams: ignoreFieldValidation, expectedStatusCode: http.StatusOK},
 | 
			
		||||
 | 
			
		||||
			{name: "put-strict-validation-yaml", path: "/namespaces/default/simples/id", verb: "PUT", data: invalidYAMLDataPut, queryParams: strictFieldValidation, contentType: "application/yaml", expectedStatusCode: http.StatusBadRequest, expectedErr: strictDecodingErrYAMLPut},
 | 
			
		||||
			{name: "put-warn-validation-yaml", path: "/namespaces/default/simples/id", verb: "PUT", data: invalidYAMLDataPut, queryParams: warnFieldValidation, contentType: "application/yaml", expectedStatusCode: http.StatusOK, expectedWarns: strictDecodingWarnsYAMLPut},
 | 
			
		||||
			{name: "put-ignore-validation-yaml", path: "/namespaces/default/simples/id", verb: "PUT", data: invalidYAMLDataPut, queryParams: ignoreFieldValidation, contentType: "application/yaml", expectedStatusCode: http.StatusOK},
 | 
			
		||||
			{name: "put-strict-validation-yaml", path: "/namespaces/default/simples/id", verb: request.MethodPut, data: invalidYAMLDataPut, queryParams: strictFieldValidation, contentType: "application/yaml", expectedStatusCode: http.StatusBadRequest, expectedErr: strictDecodingErrYAMLPut},
 | 
			
		||||
			{name: "put-warn-validation-yaml", path: "/namespaces/default/simples/id", verb: request.MethodPut, data: invalidYAMLDataPut, queryParams: warnFieldValidation, contentType: "application/yaml", expectedStatusCode: http.StatusOK, expectedWarns: strictDecodingWarnsYAMLPut},
 | 
			
		||||
			{name: "put-ignore-validation-yaml", path: "/namespaces/default/simples/id", verb: request.MethodPut, data: invalidYAMLDataPut, queryParams: ignoreFieldValidation, contentType: "application/yaml", expectedStatusCode: http.StatusOK},
 | 
			
		||||
 | 
			
		||||
			// MergePatch
 | 
			
		||||
			{name: "merge-patch-strict-validation", path: "/namespaces/default/simples/id", verb: "PATCH", data: invalidMergePatch, queryParams: strictFieldValidation, contentType: "application/merge-patch+json; charset=UTF-8", expectedStatusCode: http.StatusUnprocessableEntity, expectedErr: strictDecodingErr},
 | 
			
		||||
			{name: "merge-patch-warn-validation", path: "/namespaces/default/simples/id", verb: "PATCH", data: invalidMergePatch, queryParams: warnFieldValidation, contentType: "application/merge-patch+json; charset=UTF-8", expectedStatusCode: http.StatusOK, expectedWarns: strictDecodingWarns},
 | 
			
		||||
			{name: "merge-patch-ignore-validation", path: "/namespaces/default/simples/id", verb: "PATCH", data: invalidMergePatch, queryParams: ignoreFieldValidation, contentType: "application/merge-patch+json; charset=UTF-8", expectedStatusCode: http.StatusOK},
 | 
			
		||||
			{name: "merge-patch-strict-validation", path: "/namespaces/default/simples/id", verb: request.MethodPatch, data: invalidMergePatch, queryParams: strictFieldValidation, contentType: "application/merge-patch+json; charset=UTF-8", expectedStatusCode: http.StatusUnprocessableEntity, expectedErr: strictDecodingErr},
 | 
			
		||||
			{name: "merge-patch-warn-validation", path: "/namespaces/default/simples/id", verb: request.MethodPatch, data: invalidMergePatch, queryParams: warnFieldValidation, contentType: "application/merge-patch+json; charset=UTF-8", expectedStatusCode: http.StatusOK, expectedWarns: strictDecodingWarns},
 | 
			
		||||
			{name: "merge-patch-ignore-validation", path: "/namespaces/default/simples/id", verb: request.MethodPatch, data: invalidMergePatch, queryParams: ignoreFieldValidation, contentType: "application/merge-patch+json; charset=UTF-8", expectedStatusCode: http.StatusOK},
 | 
			
		||||
 | 
			
		||||
			// JSON Patch
 | 
			
		||||
			{name: "json-patch-strict-validation", path: "/namespaces/default/simples/id", verb: "PATCH", data: invalidJSONPatch, queryParams: strictFieldValidation, contentType: "application/json-patch+json; charset=UTF-8", expectedStatusCode: http.StatusUnprocessableEntity, expectedErr: jsonPatchStrictDecodingErr},
 | 
			
		||||
			{name: "json-patch-warn-validation", path: "/namespaces/default/simples/id", verb: "PATCH", data: invalidJSONPatch, queryParams: warnFieldValidation, contentType: "application/json-patch+json; charset=UTF-8", expectedStatusCode: http.StatusOK, expectedWarns: jsonPatchStrictDecodingWarns},
 | 
			
		||||
			{name: "json-patch-ignore-validation", path: "/namespaces/default/simples/id", verb: "PATCH", data: invalidJSONPatch, queryParams: ignoreFieldValidation, contentType: "application/json-patch+json; charset=UTF-8", expectedStatusCode: http.StatusOK},
 | 
			
		||||
			{name: "json-patch-strict-validation", path: "/namespaces/default/simples/id", verb: request.MethodPatch, data: invalidJSONPatch, queryParams: strictFieldValidation, contentType: "application/json-patch+json; charset=UTF-8", expectedStatusCode: http.StatusUnprocessableEntity, expectedErr: jsonPatchStrictDecodingErr},
 | 
			
		||||
			{name: "json-patch-warn-validation", path: "/namespaces/default/simples/id", verb: request.MethodPatch, data: invalidJSONPatch, queryParams: warnFieldValidation, contentType: "application/json-patch+json; charset=UTF-8", expectedStatusCode: http.StatusOK, expectedWarns: jsonPatchStrictDecodingWarns},
 | 
			
		||||
			{name: "json-patch-ignore-validation", path: "/namespaces/default/simples/id", verb: request.MethodPatch, data: invalidJSONPatch, queryParams: ignoreFieldValidation, contentType: "application/json-patch+json; charset=UTF-8", expectedStatusCode: http.StatusOK},
 | 
			
		||||
 | 
			
		||||
			// SMP
 | 
			
		||||
			{name: "strategic-merge-patch-strict-validation", path: "/namespaces/default/simples/id", verb: "PATCH", data: invalidSMP, queryParams: strictFieldValidation, contentType: "application/strategic-merge-patch+json; charset=UTF-8", expectedStatusCode: http.StatusUnprocessableEntity, expectedErr: strictDecodingErr},
 | 
			
		||||
			{name: "strategic-merge-patch-warn-validation", path: "/namespaces/default/simples/id", verb: "PATCH", data: invalidSMP, queryParams: warnFieldValidation, contentType: "application/strategic-merge-patch+json; charset=UTF-8", expectedStatusCode: http.StatusOK, expectedWarns: strictDecodingWarns},
 | 
			
		||||
			{name: "strategic-merge-patch-ignore-validation", path: "/namespaces/default/simples/id", verb: "PATCH", data: invalidSMP, queryParams: ignoreFieldValidation, contentType: "application/strategic-merge-patch+json; charset=UTF-8", expectedStatusCode: http.StatusOK},
 | 
			
		||||
			{name: "strategic-merge-patch-strict-validation", path: "/namespaces/default/simples/id", verb: request.MethodPatch, data: invalidSMP, queryParams: strictFieldValidation, contentType: "application/strategic-merge-patch+json; charset=UTF-8", expectedStatusCode: http.StatusUnprocessableEntity, expectedErr: strictDecodingErr},
 | 
			
		||||
			{name: "strategic-merge-patch-warn-validation", path: "/namespaces/default/simples/id", verb: request.MethodPatch, data: invalidSMP, queryParams: warnFieldValidation, contentType: "application/strategic-merge-patch+json; charset=UTF-8", expectedStatusCode: http.StatusOK, expectedWarns: strictDecodingWarns},
 | 
			
		||||
			{name: "strategic-merge-patch-ignore-validation", path: "/namespaces/default/simples/id", verb: request.MethodPatch, data: invalidSMP, queryParams: ignoreFieldValidation, contentType: "application/strategic-merge-patch+json; charset=UTF-8", expectedStatusCode: http.StatusOK},
 | 
			
		||||
		}
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -4209,37 +4209,37 @@ other: bar`)
 | 
			
		|||
			expectedStatusCode int
 | 
			
		||||
		}{
 | 
			
		||||
			// Create
 | 
			
		||||
			{name: "post-strict-validation", path: "/namespaces/default/simples", verb: "POST", data: validJSONDataPost, queryParams: strictFieldValidation, expectedStatusCode: http.StatusCreated},
 | 
			
		||||
			{name: "post-warn-validation", path: "/namespaces/default/simples", verb: "POST", data: validJSONDataPost, queryParams: warnFieldValidation, expectedStatusCode: http.StatusCreated},
 | 
			
		||||
			{name: "post-ignore-validation", path: "/namespaces/default/simples", verb: "POST", data: validJSONDataPost, queryParams: ignoreFieldValidation, expectedStatusCode: http.StatusCreated},
 | 
			
		||||
			{name: "post-strict-validation", path: "/namespaces/default/simples", verb: request.MethodPost, data: validJSONDataPost, queryParams: strictFieldValidation, expectedStatusCode: http.StatusCreated},
 | 
			
		||||
			{name: "post-warn-validation", path: "/namespaces/default/simples", verb: request.MethodPost, data: validJSONDataPost, queryParams: warnFieldValidation, expectedStatusCode: http.StatusCreated},
 | 
			
		||||
			{name: "post-ignore-validation", path: "/namespaces/default/simples", verb: request.MethodPost, data: validJSONDataPost, queryParams: ignoreFieldValidation, expectedStatusCode: http.StatusCreated},
 | 
			
		||||
 | 
			
		||||
			{name: "post-strict-validation-yaml", path: "/namespaces/default/simples", verb: "POST", data: validYAMLDataPost, queryParams: strictFieldValidation, contentType: "application/yaml", expectedStatusCode: http.StatusCreated},
 | 
			
		||||
			{name: "post-warn-validation-yaml", path: "/namespaces/default/simples", verb: "POST", data: validYAMLDataPost, queryParams: warnFieldValidation, contentType: "application/yaml", expectedStatusCode: http.StatusCreated},
 | 
			
		||||
			{name: "post-ignore-validation-yaml", path: "/namespaces/default/simples", verb: "POST", data: validYAMLDataPost, queryParams: ignoreFieldValidation, contentType: "application/yaml", expectedStatusCode: http.StatusCreated},
 | 
			
		||||
			{name: "post-strict-validation-yaml", path: "/namespaces/default/simples", verb: request.MethodPost, data: validYAMLDataPost, queryParams: strictFieldValidation, contentType: "application/yaml", expectedStatusCode: http.StatusCreated},
 | 
			
		||||
			{name: "post-warn-validation-yaml", path: "/namespaces/default/simples", verb: request.MethodPost, data: validYAMLDataPost, queryParams: warnFieldValidation, contentType: "application/yaml", expectedStatusCode: http.StatusCreated},
 | 
			
		||||
			{name: "post-ignore-validation-yaml", path: "/namespaces/default/simples", verb: request.MethodPost, data: validYAMLDataPost, queryParams: ignoreFieldValidation, contentType: "application/yaml", expectedStatusCode: http.StatusCreated},
 | 
			
		||||
 | 
			
		||||
			// Update
 | 
			
		||||
			{name: "put-strict-validation", path: "/namespaces/default/simples/id", verb: "PUT", data: validJSONDataPut, queryParams: strictFieldValidation, expectedStatusCode: http.StatusOK},
 | 
			
		||||
			{name: "put-warn-validation", path: "/namespaces/default/simples/id", verb: "PUT", data: validJSONDataPut, queryParams: warnFieldValidation, expectedStatusCode: http.StatusOK},
 | 
			
		||||
			{name: "put-ignore-validation", path: "/namespaces/default/simples/id", verb: "PUT", data: validJSONDataPut, queryParams: ignoreFieldValidation, expectedStatusCode: http.StatusOK},
 | 
			
		||||
			{name: "put-strict-validation", path: "/namespaces/default/simples/id", verb: request.MethodPut, data: validJSONDataPut, queryParams: strictFieldValidation, expectedStatusCode: http.StatusOK},
 | 
			
		||||
			{name: "put-warn-validation", path: "/namespaces/default/simples/id", verb: request.MethodPut, data: validJSONDataPut, queryParams: warnFieldValidation, expectedStatusCode: http.StatusOK},
 | 
			
		||||
			{name: "put-ignore-validation", path: "/namespaces/default/simples/id", verb: request.MethodPut, data: validJSONDataPut, queryParams: ignoreFieldValidation, expectedStatusCode: http.StatusOK},
 | 
			
		||||
 | 
			
		||||
			{name: "put-strict-validation-yaml", path: "/namespaces/default/simples/id", verb: "PUT", data: validYAMLDataPut, queryParams: strictFieldValidation, contentType: "application/yaml", expectedStatusCode: http.StatusOK},
 | 
			
		||||
			{name: "put-warn-validation-yaml", path: "/namespaces/default/simples/id", verb: "PUT", data: validYAMLDataPut, queryParams: warnFieldValidation, contentType: "application/yaml", expectedStatusCode: http.StatusOK},
 | 
			
		||||
			{name: "put-ignore-validation-yaml", path: "/namespaces/default/simples/id", verb: "PUT", data: validYAMLDataPut, queryParams: ignoreFieldValidation, contentType: "application/yaml", expectedStatusCode: http.StatusOK},
 | 
			
		||||
			{name: "put-strict-validation-yaml", path: "/namespaces/default/simples/id", verb: request.MethodPut, data: validYAMLDataPut, queryParams: strictFieldValidation, contentType: "application/yaml", expectedStatusCode: http.StatusOK},
 | 
			
		||||
			{name: "put-warn-validation-yaml", path: "/namespaces/default/simples/id", verb: request.MethodPut, data: validYAMLDataPut, queryParams: warnFieldValidation, contentType: "application/yaml", expectedStatusCode: http.StatusOK},
 | 
			
		||||
			{name: "put-ignore-validation-yaml", path: "/namespaces/default/simples/id", verb: request.MethodPut, data: validYAMLDataPut, queryParams: ignoreFieldValidation, contentType: "application/yaml", expectedStatusCode: http.StatusOK},
 | 
			
		||||
 | 
			
		||||
			// MergePatch
 | 
			
		||||
			{name: "merge-patch-strict-validation", path: "/namespaces/default/simples/id", verb: "PATCH", data: validMergePatch, queryParams: strictFieldValidation, contentType: "application/merge-patch+json; charset=UTF-8", expectedStatusCode: http.StatusOK},
 | 
			
		||||
			{name: "merge-patch-warn-validation", path: "/namespaces/default/simples/id", verb: "PATCH", data: validMergePatch, queryParams: warnFieldValidation, contentType: "application/merge-patch+json; charset=UTF-8", expectedStatusCode: http.StatusOK},
 | 
			
		||||
			{name: "merge-patch-ignore-validation", path: "/namespaces/default/simples/id", verb: "PATCH", data: validMergePatch, queryParams: ignoreFieldValidation, contentType: "application/merge-patch+json; charset=UTF-8", expectedStatusCode: http.StatusOK},
 | 
			
		||||
			{name: "merge-patch-strict-validation", path: "/namespaces/default/simples/id", verb: request.MethodPatch, data: validMergePatch, queryParams: strictFieldValidation, contentType: "application/merge-patch+json; charset=UTF-8", expectedStatusCode: http.StatusOK},
 | 
			
		||||
			{name: "merge-patch-warn-validation", path: "/namespaces/default/simples/id", verb: request.MethodPatch, data: validMergePatch, queryParams: warnFieldValidation, contentType: "application/merge-patch+json; charset=UTF-8", expectedStatusCode: http.StatusOK},
 | 
			
		||||
			{name: "merge-patch-ignore-validation", path: "/namespaces/default/simples/id", verb: request.MethodPatch, data: validMergePatch, queryParams: ignoreFieldValidation, contentType: "application/merge-patch+json; charset=UTF-8", expectedStatusCode: http.StatusOK},
 | 
			
		||||
 | 
			
		||||
			// JSON Patch
 | 
			
		||||
			{name: "json-patch-strict-validation", path: "/namespaces/default/simples/id", verb: "PATCH", data: validJSONPatch, queryParams: strictFieldValidation, contentType: "application/json-patch+json; charset=UTF-8", expectedStatusCode: http.StatusOK},
 | 
			
		||||
			{name: "json-patch-warn-validation", path: "/namespaces/default/simples/id", verb: "PATCH", data: validJSONPatch, queryParams: warnFieldValidation, contentType: "application/json-patch+json; charset=UTF-8", expectedStatusCode: http.StatusOK},
 | 
			
		||||
			{name: "json-patch-ignore-validation", path: "/namespaces/default/simples/id", verb: "PATCH", data: validJSONPatch, queryParams: ignoreFieldValidation, contentType: "application/json-patch+json; charset=UTF-8", expectedStatusCode: http.StatusOK},
 | 
			
		||||
			{name: "json-patch-strict-validation", path: "/namespaces/default/simples/id", verb: request.MethodPatch, data: validJSONPatch, queryParams: strictFieldValidation, contentType: "application/json-patch+json; charset=UTF-8", expectedStatusCode: http.StatusOK},
 | 
			
		||||
			{name: "json-patch-warn-validation", path: "/namespaces/default/simples/id", verb: request.MethodPatch, data: validJSONPatch, queryParams: warnFieldValidation, contentType: "application/json-patch+json; charset=UTF-8", expectedStatusCode: http.StatusOK},
 | 
			
		||||
			{name: "json-patch-ignore-validation", path: "/namespaces/default/simples/id", verb: request.MethodPatch, data: validJSONPatch, queryParams: ignoreFieldValidation, contentType: "application/json-patch+json; charset=UTF-8", expectedStatusCode: http.StatusOK},
 | 
			
		||||
 | 
			
		||||
			// SMP
 | 
			
		||||
			{name: "strategic-merge-patch-strict-validation", path: "/namespaces/default/simples/id", verb: "PATCH", data: validSMP, queryParams: strictFieldValidation, contentType: "application/strategic-merge-patch+json; charset=UTF-8", expectedStatusCode: http.StatusOK},
 | 
			
		||||
			{name: "strategic-merge-patch-warn-validation", path: "/namespaces/default/simples/id", verb: "PATCH", data: validSMP, queryParams: warnFieldValidation, contentType: "application/strategic-merge-patch+json; charset=UTF-8", expectedStatusCode: http.StatusOK},
 | 
			
		||||
			{name: "strategic-merge-patch-ignore-validation", path: "/namespaces/default/simples/id", verb: "PATCH", data: validSMP, queryParams: ignoreFieldValidation, contentType: "application/strategic-merge-patch+json; charset=UTF-8", expectedStatusCode: http.StatusOK},
 | 
			
		||||
			{name: "strategic-merge-patch-strict-validation", path: "/namespaces/default/simples/id", verb: request.MethodPatch, data: validSMP, queryParams: strictFieldValidation, contentType: "application/strategic-merge-patch+json; charset=UTF-8", expectedStatusCode: http.StatusOK},
 | 
			
		||||
			{name: "strategic-merge-patch-warn-validation", path: "/namespaces/default/simples/id", verb: request.MethodPatch, data: validSMP, queryParams: warnFieldValidation, contentType: "application/strategic-merge-patch+json; charset=UTF-8", expectedStatusCode: http.StatusOK},
 | 
			
		||||
			{name: "strategic-merge-patch-ignore-validation", path: "/namespaces/default/simples/id", verb: request.MethodPatch, data: validSMP, queryParams: ignoreFieldValidation, contentType: "application/strategic-merge-patch+json; charset=UTF-8", expectedStatusCode: http.StatusOK},
 | 
			
		||||
		}
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -4421,7 +4421,7 @@ func BenchmarkUpdateProtobuf(b *testing.B) {
 | 
			
		|||
 | 
			
		||||
	b.ResetTimer()
 | 
			
		||||
	for i := 0; i < b.N; i++ {
 | 
			
		||||
		request, err := http.NewRequest("PUT", dest.String(), bytes.NewReader(data))
 | 
			
		||||
		request, err := http.NewRequest(request.MethodPut, dest.String(), bytes.NewReader(data))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			b.Fatalf("unexpected error: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,6 +30,7 @@ import (
 | 
			
		|||
	"k8s.io/apimachinery/pkg/runtime"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/util/wait"
 | 
			
		||||
	auditinternal "k8s.io/apiserver/pkg/apis/audit"
 | 
			
		||||
	"k8s.io/apiserver/pkg/endpoints/request"
 | 
			
		||||
	genericapitesting "k8s.io/apiserver/pkg/endpoints/testing"
 | 
			
		||||
	"k8s.io/apiserver/pkg/registry/rest"
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -156,7 +157,7 @@ func TestAudit(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			"get",
 | 
			
		||||
			func(server string) (*http.Request, error) {
 | 
			
		||||
				return http.NewRequest("GET", server+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/other/simple/c", bytes.NewBuffer(simpleFooJSON))
 | 
			
		||||
				return http.NewRequest(request.MethodGet, server+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/other/simple/c", bytes.NewBuffer(simpleFooJSON))
 | 
			
		||||
			},
 | 
			
		||||
			200,
 | 
			
		||||
			2,
 | 
			
		||||
| 
						 | 
				
			
			@ -169,7 +170,7 @@ func TestAudit(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			"list",
 | 
			
		||||
			func(server string) (*http.Request, error) {
 | 
			
		||||
				return http.NewRequest("GET", server+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/other/simple?labelSelector=a%3Dfoobar", nil)
 | 
			
		||||
				return http.NewRequest(request.MethodGet, server+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/other/simple?labelSelector=a%3Dfoobar", nil)
 | 
			
		||||
			},
 | 
			
		||||
			200,
 | 
			
		||||
			2,
 | 
			
		||||
| 
						 | 
				
			
			@ -182,7 +183,7 @@ func TestAudit(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			"create",
 | 
			
		||||
			func(server string) (*http.Request, error) {
 | 
			
		||||
				return http.NewRequest("POST", server+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple", bytes.NewBuffer(simpleFooJSON))
 | 
			
		||||
				return http.NewRequest(request.MethodPost, server+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple", bytes.NewBuffer(simpleFooJSON))
 | 
			
		||||
			},
 | 
			
		||||
			201,
 | 
			
		||||
			2,
 | 
			
		||||
| 
						 | 
				
			
			@ -195,7 +196,7 @@ func TestAudit(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			"not-allowed-named-create",
 | 
			
		||||
			func(server string) (*http.Request, error) {
 | 
			
		||||
				return http.NewRequest("POST", server+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/named", bytes.NewBuffer(simpleFooJSON))
 | 
			
		||||
				return http.NewRequest(request.MethodPost, server+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/named", bytes.NewBuffer(simpleFooJSON))
 | 
			
		||||
			},
 | 
			
		||||
			405,
 | 
			
		||||
			2,
 | 
			
		||||
| 
						 | 
				
			
			@ -208,7 +209,7 @@ func TestAudit(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			"delete",
 | 
			
		||||
			func(server string) (*http.Request, error) {
 | 
			
		||||
				return http.NewRequest("DELETE", server+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/a", nil)
 | 
			
		||||
				return http.NewRequest(request.MethodDelete, server+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/a", nil)
 | 
			
		||||
			},
 | 
			
		||||
			200,
 | 
			
		||||
			2,
 | 
			
		||||
| 
						 | 
				
			
			@ -221,7 +222,7 @@ func TestAudit(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			"delete-with-options-in-body",
 | 
			
		||||
			func(server string) (*http.Request, error) {
 | 
			
		||||
				return http.NewRequest("DELETE", server+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/a", bytes.NewBuffer([]byte(`{"kind":"DeleteOptions"}`)))
 | 
			
		||||
				return http.NewRequest(request.MethodDelete, server+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/a", bytes.NewBuffer([]byte(`{"kind":"DeleteOptions"}`)))
 | 
			
		||||
			},
 | 
			
		||||
			200,
 | 
			
		||||
			2,
 | 
			
		||||
| 
						 | 
				
			
			@ -234,7 +235,7 @@ func TestAudit(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			"update",
 | 
			
		||||
			func(server string) (*http.Request, error) {
 | 
			
		||||
				return http.NewRequest("PUT", server+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/other/simple/c", bytes.NewBuffer(simpleCPrimeJSON))
 | 
			
		||||
				return http.NewRequest(request.MethodPut, server+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/other/simple/c", bytes.NewBuffer(simpleCPrimeJSON))
 | 
			
		||||
			},
 | 
			
		||||
			200,
 | 
			
		||||
			2,
 | 
			
		||||
| 
						 | 
				
			
			@ -247,7 +248,7 @@ func TestAudit(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			"update-wrong-namespace",
 | 
			
		||||
			func(server string) (*http.Request, error) {
 | 
			
		||||
				return http.NewRequest("PUT", server+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/c", bytes.NewBuffer(simpleCPrimeJSON))
 | 
			
		||||
				return http.NewRequest(request.MethodPut, server+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/c", bytes.NewBuffer(simpleCPrimeJSON))
 | 
			
		||||
			},
 | 
			
		||||
			400,
 | 
			
		||||
			2,
 | 
			
		||||
| 
						 | 
				
			
			@ -260,7 +261,7 @@ func TestAudit(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			"patch",
 | 
			
		||||
			func(server string) (*http.Request, error) {
 | 
			
		||||
				req, _ := http.NewRequest("PATCH", server+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/other/simple/c", bytes.NewReader([]byte(`{"labels":{"foo":"bar"}}`)))
 | 
			
		||||
				req, _ := http.NewRequest(request.MethodPatch, server+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/other/simple/c", bytes.NewReader([]byte(`{"labels":{"foo":"bar"}}`)))
 | 
			
		||||
				req.Header.Set("Content-Type", "application/merge-patch+json; charset=UTF-8")
 | 
			
		||||
				return req, nil
 | 
			
		||||
			},
 | 
			
		||||
| 
						 | 
				
			
			@ -275,7 +276,7 @@ func TestAudit(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			"watch",
 | 
			
		||||
			func(server string) (*http.Request, error) {
 | 
			
		||||
				return http.NewRequest("GET", server+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/other/simple?watch=true", nil)
 | 
			
		||||
				return http.NewRequest(request.MethodGet, server+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/other/simple?watch=true", nil)
 | 
			
		||||
			},
 | 
			
		||||
			200,
 | 
			
		||||
			3,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,25 +22,22 @@ import (
 | 
			
		|||
	"reflect"
 | 
			
		||||
	"sort"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"sync/atomic"
 | 
			
		||||
 | 
			
		||||
	apidiscoveryv2 "k8s.io/api/apidiscovery/v2"
 | 
			
		||||
	apidiscoveryv2beta1 "k8s.io/api/apidiscovery/v2beta1"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/runtime/schema"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/runtime/serializer"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/version"
 | 
			
		||||
	apidiscoveryv2conversion "k8s.io/apiserver/pkg/apis/apidiscovery/v2"
 | 
			
		||||
	genericfeatures "k8s.io/apiserver/pkg/features"
 | 
			
		||||
 | 
			
		||||
	"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
 | 
			
		||||
 | 
			
		||||
	"k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
 | 
			
		||||
	"k8s.io/apiserver/pkg/endpoints/metrics"
 | 
			
		||||
 | 
			
		||||
	"sync/atomic"
 | 
			
		||||
 | 
			
		||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/runtime"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/runtime/schema"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/runtime/serializer"
 | 
			
		||||
	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/version"
 | 
			
		||||
	apidiscoveryv2conversion "k8s.io/apiserver/pkg/apis/apidiscovery/v2"
 | 
			
		||||
	"k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
 | 
			
		||||
	"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
 | 
			
		||||
	"k8s.io/apiserver/pkg/endpoints/metrics"
 | 
			
		||||
	"k8s.io/apiserver/pkg/endpoints/request"
 | 
			
		||||
	genericfeatures "k8s.io/apiserver/pkg/features"
 | 
			
		||||
	utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
			
		||||
	"k8s.io/klog/v2"
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -163,7 +160,7 @@ func NewResourceManager(path string) ResourceManager {
 | 
			
		|||
		serializer:        codecs,
 | 
			
		||||
		versionPriorities: make(map[groupVersionKey]priorityInfo),
 | 
			
		||||
	}
 | 
			
		||||
	rdm.serveHTTPFunc = metrics.InstrumentHandlerFunc("GET",
 | 
			
		||||
	rdm.serveHTTPFunc = metrics.InstrumentHandlerFunc(request.MethodGet,
 | 
			
		||||
		/* group = */ "",
 | 
			
		||||
		/* version = */ "",
 | 
			
		||||
		/* resource = */ "",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,7 +22,6 @@ import (
 | 
			
		|||
	"math/rand"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"net/http/httptest"
 | 
			
		||||
 | 
			
		||||
	"sort"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
| 
						 | 
				
			
			@ -43,6 +42,7 @@ import (
 | 
			
		|||
	"k8s.io/apimachinery/pkg/version"
 | 
			
		||||
	apidiscoveryv2conversion "k8s.io/apiserver/pkg/apis/apidiscovery/v2"
 | 
			
		||||
	discoveryendpoint "k8s.io/apiserver/pkg/endpoints/discovery/aggregated"
 | 
			
		||||
	"k8s.io/apiserver/pkg/endpoints/request"
 | 
			
		||||
	genericfeatures "k8s.io/apiserver/pkg/features"
 | 
			
		||||
	utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
			
		||||
	featuregatetesting "k8s.io/component-base/featuregate/testing"
 | 
			
		||||
| 
						 | 
				
			
			@ -133,7 +133,7 @@ func fetchPath(handler http.Handler, acceptPrefix string, path string, etag stri
 | 
			
		|||
func fetchPathHelper(handler http.Handler, accept string, path string, etag string) (*http.Response, []byte) {
 | 
			
		||||
	// Expect json-formatted apis group list
 | 
			
		||||
	w := httptest.NewRecorder()
 | 
			
		||||
	req := httptest.NewRequest("GET", discoveryPath, nil)
 | 
			
		||||
	req := httptest.NewRequest(request.MethodGet, discoveryPath, nil)
 | 
			
		||||
 | 
			
		||||
	// Ask for JSON response
 | 
			
		||||
	req.Header.Set("Accept", accept)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,6 +24,7 @@ import (
 | 
			
		|||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/stretchr/testify/assert"
 | 
			
		||||
	"k8s.io/apiserver/pkg/endpoints/request"
 | 
			
		||||
	genericfeatures "k8s.io/apiserver/pkg/features"
 | 
			
		||||
	utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
			
		||||
	featuregatetesting "k8s.io/component-base/featuregate/testing"
 | 
			
		||||
| 
						 | 
				
			
			@ -42,7 +43,7 @@ const aggregatedProtoAccept = protobufAccept + aggregatedAcceptSuffix
 | 
			
		|||
 | 
			
		||||
func fetchPath(handler http.Handler, path, accept string) string {
 | 
			
		||||
	w := httptest.NewRecorder()
 | 
			
		||||
	req := httptest.NewRequest("GET", discoveryPath, nil)
 | 
			
		||||
	req := httptest.NewRequest(request.MethodGet, discoveryPath, nil)
 | 
			
		||||
 | 
			
		||||
	// Ask for JSON response
 | 
			
		||||
	req.Header.Set("Accept", accept)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -204,7 +204,7 @@ func TestAudit(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			"read-only empty",
 | 
			
		||||
			shortRunningPath,
 | 
			
		||||
			"GET",
 | 
			
		||||
			request.MethodGet,
 | 
			
		||||
			"",
 | 
			
		||||
			nil,
 | 
			
		||||
			func(http.ResponseWriter, *http.Request) {},
 | 
			
		||||
| 
						 | 
				
			
			@ -226,7 +226,7 @@ func TestAudit(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			"short running with auditID",
 | 
			
		||||
			shortRunningPath,
 | 
			
		||||
			"GET",
 | 
			
		||||
			request.MethodGet,
 | 
			
		||||
			uuid.New().String(),
 | 
			
		||||
			nil,
 | 
			
		||||
			func(w http.ResponseWriter, req *http.Request) {
 | 
			
		||||
| 
						 | 
				
			
			@ -250,7 +250,7 @@ func TestAudit(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			"read-only panic",
 | 
			
		||||
			shortRunningPath,
 | 
			
		||||
			"GET",
 | 
			
		||||
			request.MethodGet,
 | 
			
		||||
			"",
 | 
			
		||||
			nil,
 | 
			
		||||
			func(w http.ResponseWriter, req *http.Request) {
 | 
			
		||||
| 
						 | 
				
			
			@ -275,7 +275,7 @@ func TestAudit(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			"writing empty",
 | 
			
		||||
			shortRunningPath,
 | 
			
		||||
			"PUT",
 | 
			
		||||
			request.MethodPut,
 | 
			
		||||
			"",
 | 
			
		||||
			nil,
 | 
			
		||||
			func(http.ResponseWriter, *http.Request) {},
 | 
			
		||||
| 
						 | 
				
			
			@ -297,7 +297,7 @@ func TestAudit(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			"writing sleep",
 | 
			
		||||
			shortRunningPath,
 | 
			
		||||
			"PUT",
 | 
			
		||||
			request.MethodPut,
 | 
			
		||||
			"",
 | 
			
		||||
			nil,
 | 
			
		||||
			func(w http.ResponseWriter, req *http.Request) {
 | 
			
		||||
| 
						 | 
				
			
			@ -322,7 +322,7 @@ func TestAudit(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			"writing 403+write",
 | 
			
		||||
			shortRunningPath,
 | 
			
		||||
			"PUT",
 | 
			
		||||
			request.MethodPut,
 | 
			
		||||
			"",
 | 
			
		||||
			nil,
 | 
			
		||||
			func(w http.ResponseWriter, req *http.Request) {
 | 
			
		||||
| 
						 | 
				
			
			@ -347,7 +347,7 @@ func TestAudit(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			"writing panic",
 | 
			
		||||
			shortRunningPath,
 | 
			
		||||
			"PUT",
 | 
			
		||||
			request.MethodPut,
 | 
			
		||||
			"",
 | 
			
		||||
			nil,
 | 
			
		||||
			func(w http.ResponseWriter, req *http.Request) {
 | 
			
		||||
| 
						 | 
				
			
			@ -371,7 +371,7 @@ func TestAudit(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			"writing write+panic",
 | 
			
		||||
			shortRunningPath,
 | 
			
		||||
			"PUT",
 | 
			
		||||
			request.MethodPut,
 | 
			
		||||
			"",
 | 
			
		||||
			nil,
 | 
			
		||||
			func(w http.ResponseWriter, req *http.Request) {
 | 
			
		||||
| 
						 | 
				
			
			@ -397,7 +397,7 @@ func TestAudit(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			"empty longrunning",
 | 
			
		||||
			longRunningPath,
 | 
			
		||||
			"GET",
 | 
			
		||||
			request.MethodGet,
 | 
			
		||||
			"",
 | 
			
		||||
			nil,
 | 
			
		||||
			func(http.ResponseWriter, *http.Request) {},
 | 
			
		||||
| 
						 | 
				
			
			@ -425,7 +425,7 @@ func TestAudit(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			"empty longrunning with audit id",
 | 
			
		||||
			longRunningPath,
 | 
			
		||||
			"GET",
 | 
			
		||||
			request.MethodGet,
 | 
			
		||||
			uuid.New().String(),
 | 
			
		||||
			nil,
 | 
			
		||||
			func(w http.ResponseWriter, req *http.Request) {
 | 
			
		||||
| 
						 | 
				
			
			@ -455,7 +455,7 @@ func TestAudit(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			"sleep longrunning",
 | 
			
		||||
			longRunningPath,
 | 
			
		||||
			"GET",
 | 
			
		||||
			request.MethodGet,
 | 
			
		||||
			"",
 | 
			
		||||
			nil,
 | 
			
		||||
			func(http.ResponseWriter, *http.Request) {
 | 
			
		||||
| 
						 | 
				
			
			@ -485,7 +485,7 @@ func TestAudit(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			"sleep+403 longrunning",
 | 
			
		||||
			longRunningPath,
 | 
			
		||||
			"GET",
 | 
			
		||||
			request.MethodGet,
 | 
			
		||||
			"",
 | 
			
		||||
			nil,
 | 
			
		||||
			func(w http.ResponseWriter, req *http.Request) {
 | 
			
		||||
| 
						 | 
				
			
			@ -516,7 +516,7 @@ func TestAudit(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			"write longrunning",
 | 
			
		||||
			longRunningPath,
 | 
			
		||||
			"GET",
 | 
			
		||||
			request.MethodGet,
 | 
			
		||||
			"",
 | 
			
		||||
			nil,
 | 
			
		||||
			func(w http.ResponseWriter, req *http.Request) {
 | 
			
		||||
| 
						 | 
				
			
			@ -546,7 +546,7 @@ func TestAudit(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			"403+write longrunning",
 | 
			
		||||
			longRunningPath,
 | 
			
		||||
			"GET",
 | 
			
		||||
			request.MethodGet,
 | 
			
		||||
			"",
 | 
			
		||||
			nil,
 | 
			
		||||
			func(w http.ResponseWriter, req *http.Request) {
 | 
			
		||||
| 
						 | 
				
			
			@ -577,7 +577,7 @@ func TestAudit(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			"panic longrunning",
 | 
			
		||||
			longRunningPath,
 | 
			
		||||
			"GET",
 | 
			
		||||
			request.MethodGet,
 | 
			
		||||
			"",
 | 
			
		||||
			nil,
 | 
			
		||||
			func(w http.ResponseWriter, req *http.Request) {
 | 
			
		||||
| 
						 | 
				
			
			@ -601,7 +601,7 @@ func TestAudit(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			"write+panic longrunning",
 | 
			
		||||
			longRunningPath,
 | 
			
		||||
			"GET",
 | 
			
		||||
			request.MethodGet,
 | 
			
		||||
			"",
 | 
			
		||||
			nil,
 | 
			
		||||
			func(w http.ResponseWriter, req *http.Request) {
 | 
			
		||||
| 
						 | 
				
			
			@ -632,7 +632,7 @@ func TestAudit(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			"omit RequestReceived",
 | 
			
		||||
			shortRunningPath,
 | 
			
		||||
			"GET",
 | 
			
		||||
			request.MethodGet,
 | 
			
		||||
			"",
 | 
			
		||||
			[]auditinternal.Stage{auditinternal.StageRequestReceived},
 | 
			
		||||
			func(w http.ResponseWriter, req *http.Request) {
 | 
			
		||||
| 
						 | 
				
			
			@ -651,7 +651,7 @@ func TestAudit(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			"emit Panic only",
 | 
			
		||||
			longRunningPath,
 | 
			
		||||
			"GET",
 | 
			
		||||
			request.MethodGet,
 | 
			
		||||
			"",
 | 
			
		||||
			[]auditinternal.Stage{auditinternal.StageRequestReceived, auditinternal.StageResponseStarted, auditinternal.StageResponseComplete},
 | 
			
		||||
			func(w http.ResponseWriter, req *http.Request) {
 | 
			
		||||
| 
						 | 
				
			
			@ -743,7 +743,7 @@ func TestAudit(t *testing.T) {
 | 
			
		|||
func TestAuditNoPanicOnNilUser(t *testing.T) {
 | 
			
		||||
	fakeRuleEvaluator := policy.NewFakePolicyRuleEvaluator(auditinternal.LevelRequestResponse, nil)
 | 
			
		||||
	handler := WithAudit(&fakeHTTPHandler{}, &fakeAuditSink{}, fakeRuleEvaluator, nil)
 | 
			
		||||
	req, _ := http.NewRequest("GET", "/api/v1/namespaces/default/pods", nil)
 | 
			
		||||
	req, _ := http.NewRequest(request.MethodGet, "/api/v1/namespaces/default/pods", nil)
 | 
			
		||||
	req = withTestContext(req, nil, nil)
 | 
			
		||||
	req.RemoteAddr = "127.0.0.1"
 | 
			
		||||
	handler.ServeHTTP(httptest.NewRecorder(), req)
 | 
			
		||||
| 
						 | 
				
			
			@ -758,7 +758,7 @@ func TestAuditLevelNone(t *testing.T) {
 | 
			
		|||
	fakeRuleEvaluator := policy.NewFakePolicyRuleEvaluator(auditinternal.LevelNone, nil)
 | 
			
		||||
	handler = WithAudit(handler, sink, fakeRuleEvaluator, nil)
 | 
			
		||||
 | 
			
		||||
	req, _ := http.NewRequest("GET", "/api/v1/namespaces/default/pods", nil)
 | 
			
		||||
	req, _ := http.NewRequest(request.MethodGet, "/api/v1/namespaces/default/pods", nil)
 | 
			
		||||
	req.RemoteAddr = "127.0.0.1"
 | 
			
		||||
	req = withTestContext(req, &user.DefaultInfo{Name: "admin"}, nil)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -814,7 +814,7 @@ func TestAuditIDHttpHeader(t *testing.T) {
 | 
			
		|||
			handler = WithAudit(handler, sink, fakeRuleEvaluator, nil)
 | 
			
		||||
			handler = WithAuditInit(handler)
 | 
			
		||||
 | 
			
		||||
			req, _ := http.NewRequest("GET", "/api/v1/namespaces/default/pods", nil)
 | 
			
		||||
			req, _ := http.NewRequest(request.MethodGet, "/api/v1/namespaces/default/pods", nil)
 | 
			
		||||
			req.RemoteAddr = "127.0.0.1"
 | 
			
		||||
			req = withTestContext(req, &user.DefaultInfo{Name: "admin"}, nil)
 | 
			
		||||
			if test.requestHeader != "" {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,6 +26,7 @@ import (
 | 
			
		|||
 | 
			
		||||
	auditinternal "k8s.io/apiserver/pkg/apis/audit"
 | 
			
		||||
	"k8s.io/apiserver/pkg/audit/policy"
 | 
			
		||||
	"k8s.io/apiserver/pkg/endpoints/request"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestFailedAuthnAudit(t *testing.T) {
 | 
			
		||||
| 
						 | 
				
			
			@ -36,7 +37,7 @@ func TestFailedAuthnAudit(t *testing.T) {
 | 
			
		|||
			http.Error(w, "", http.StatusUnauthorized)
 | 
			
		||||
		}),
 | 
			
		||||
		sink, fakeRuleEvaluator)
 | 
			
		||||
	req, _ := http.NewRequest("GET", "/api/v1/namespaces/default/pods", nil)
 | 
			
		||||
	req, _ := http.NewRequest(request.MethodGet, "/api/v1/namespaces/default/pods", nil)
 | 
			
		||||
	req.RemoteAddr = "127.0.0.1"
 | 
			
		||||
	req = withTestContext(req, nil, nil)
 | 
			
		||||
	req.SetBasicAuth("username", "password")
 | 
			
		||||
| 
						 | 
				
			
			@ -68,7 +69,7 @@ func TestFailedMultipleAuthnAudit(t *testing.T) {
 | 
			
		|||
			http.Error(w, "", http.StatusUnauthorized)
 | 
			
		||||
		}),
 | 
			
		||||
		sink, fakeRuleEvaluator)
 | 
			
		||||
	req, _ := http.NewRequest("GET", "/api/v1/namespaces/default/pods", nil)
 | 
			
		||||
	req, _ := http.NewRequest(request.MethodGet, "/api/v1/namespaces/default/pods", nil)
 | 
			
		||||
	req.RemoteAddr = "127.0.0.1"
 | 
			
		||||
	req = withTestContext(req, nil, nil)
 | 
			
		||||
	req.SetBasicAuth("username", "password")
 | 
			
		||||
| 
						 | 
				
			
			@ -101,7 +102,7 @@ func TestFailedAuthnAuditWithoutAuthorization(t *testing.T) {
 | 
			
		|||
			http.Error(w, "", http.StatusUnauthorized)
 | 
			
		||||
		}),
 | 
			
		||||
		sink, fakeRuleEvaluator)
 | 
			
		||||
	req, _ := http.NewRequest("GET", "/api/v1/namespaces/default/pods", nil)
 | 
			
		||||
	req, _ := http.NewRequest(request.MethodGet, "/api/v1/namespaces/default/pods", nil)
 | 
			
		||||
	req.RemoteAddr = "127.0.0.1"
 | 
			
		||||
	req = withTestContext(req, nil, nil)
 | 
			
		||||
	handler.ServeHTTP(httptest.NewRecorder(), req)
 | 
			
		||||
| 
						 | 
				
			
			@ -132,7 +133,7 @@ func TestFailedAuthnAuditOmitted(t *testing.T) {
 | 
			
		|||
			http.Error(w, "", http.StatusUnauthorized)
 | 
			
		||||
		}),
 | 
			
		||||
		sink, fakeRuleEvaluator)
 | 
			
		||||
	req, _ := http.NewRequest("GET", "/api/v1/namespaces/default/pods", nil)
 | 
			
		||||
	req, _ := http.NewRequest(request.MethodGet, "/api/v1/namespaces/default/pods", nil)
 | 
			
		||||
	req.RemoteAddr = "127.0.0.1"
 | 
			
		||||
	req = withTestContext(req, nil, nil)
 | 
			
		||||
	handler.ServeHTTP(httptest.NewRecorder(), req)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,16 +19,17 @@ package filters
 | 
			
		|||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"net/http/httptest"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"k8s.io/apimachinery/pkg/fields"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/labels"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/selection"
 | 
			
		||||
	genericfeatures "k8s.io/apiserver/pkg/features"
 | 
			
		||||
	utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
			
		||||
	featuregatetesting "k8s.io/component-base/featuregate/testing"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"net/http/httptest"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/stretchr/testify/assert"
 | 
			
		||||
	batch "k8s.io/api/batch/v1"
 | 
			
		||||
| 
						 | 
				
			
			@ -52,7 +53,7 @@ func TestGetAuthorizerAttributes(t *testing.T) {
 | 
			
		|||
		EnableAuthorizationSelector bool
 | 
			
		||||
	}{
 | 
			
		||||
		"non-resource root": {
 | 
			
		||||
			Verb: "POST",
 | 
			
		||||
			Verb: http.MethodPost,
 | 
			
		||||
			Path: "/",
 | 
			
		||||
			ExpectedAttributes: &authorizer.AttributesRecord{
 | 
			
		||||
				Verb: "post",
 | 
			
		||||
| 
						 | 
				
			
			@ -60,7 +61,7 @@ func TestGetAuthorizerAttributes(t *testing.T) {
 | 
			
		|||
			},
 | 
			
		||||
		},
 | 
			
		||||
		"non-resource api prefix": {
 | 
			
		||||
			Verb: "GET",
 | 
			
		||||
			Verb: http.MethodGet,
 | 
			
		||||
			Path: "/api/",
 | 
			
		||||
			ExpectedAttributes: &authorizer.AttributesRecord{
 | 
			
		||||
				Verb: "get",
 | 
			
		||||
| 
						 | 
				
			
			@ -68,7 +69,7 @@ func TestGetAuthorizerAttributes(t *testing.T) {
 | 
			
		|||
			},
 | 
			
		||||
		},
 | 
			
		||||
		"non-resource group api prefix": {
 | 
			
		||||
			Verb: "GET",
 | 
			
		||||
			Verb: http.MethodGet,
 | 
			
		||||
			Path: "/apis/extensions/",
 | 
			
		||||
			ExpectedAttributes: &authorizer.AttributesRecord{
 | 
			
		||||
				Verb: "get",
 | 
			
		||||
| 
						 | 
				
			
			@ -77,7 +78,7 @@ func TestGetAuthorizerAttributes(t *testing.T) {
 | 
			
		|||
		},
 | 
			
		||||
 | 
			
		||||
		"resource": {
 | 
			
		||||
			Verb: "POST",
 | 
			
		||||
			Verb: http.MethodPost,
 | 
			
		||||
			Path: "/api/v1/nodes/mynode",
 | 
			
		||||
			ExpectedAttributes: &authorizer.AttributesRecord{
 | 
			
		||||
				Verb:            "create",
 | 
			
		||||
| 
						 | 
				
			
			@ -89,7 +90,7 @@ func TestGetAuthorizerAttributes(t *testing.T) {
 | 
			
		|||
			},
 | 
			
		||||
		},
 | 
			
		||||
		"namespaced resource": {
 | 
			
		||||
			Verb: "PUT",
 | 
			
		||||
			Verb: http.MethodPut,
 | 
			
		||||
			Path: "/api/v1/namespaces/myns/pods/mypod",
 | 
			
		||||
			ExpectedAttributes: &authorizer.AttributesRecord{
 | 
			
		||||
				Verb:            "update",
 | 
			
		||||
| 
						 | 
				
			
			@ -102,7 +103,7 @@ func TestGetAuthorizerAttributes(t *testing.T) {
 | 
			
		|||
			},
 | 
			
		||||
		},
 | 
			
		||||
		"API group resource": {
 | 
			
		||||
			Verb: "GET",
 | 
			
		||||
			Verb: http.MethodGet,
 | 
			
		||||
			Path: "/apis/batch/v1/namespaces/myns/jobs",
 | 
			
		||||
			ExpectedAttributes: &authorizer.AttributesRecord{
 | 
			
		||||
				Verb:            "list",
 | 
			
		||||
| 
						 | 
				
			
			@ -115,7 +116,7 @@ func TestGetAuthorizerAttributes(t *testing.T) {
 | 
			
		|||
			},
 | 
			
		||||
		},
 | 
			
		||||
		"disabled, ignore good field selector": {
 | 
			
		||||
			Verb: "GET",
 | 
			
		||||
			Verb: http.MethodGet,
 | 
			
		||||
			Path: "/apis/batch/v1/namespaces/myns/jobs?fieldSelector%=foo%3Dbar",
 | 
			
		||||
			ExpectedAttributes: &authorizer.AttributesRecord{
 | 
			
		||||
				Verb:            "list",
 | 
			
		||||
| 
						 | 
				
			
			@ -128,7 +129,7 @@ func TestGetAuthorizerAttributes(t *testing.T) {
 | 
			
		|||
			},
 | 
			
		||||
		},
 | 
			
		||||
		"enabled, good field selector": {
 | 
			
		||||
			Verb: "GET",
 | 
			
		||||
			Verb: http.MethodGet,
 | 
			
		||||
			Path: "/apis/batch/v1/namespaces/myns/jobs?fieldSelector=foo%3D%3Dbar",
 | 
			
		||||
			ExpectedAttributes: &authorizer.AttributesRecord{
 | 
			
		||||
				Verb:            "list",
 | 
			
		||||
| 
						 | 
				
			
			@ -145,7 +146,7 @@ func TestGetAuthorizerAttributes(t *testing.T) {
 | 
			
		|||
			EnableAuthorizationSelector: true,
 | 
			
		||||
		},
 | 
			
		||||
		"enabled, bad field selector": {
 | 
			
		||||
			Verb: "GET",
 | 
			
		||||
			Verb: http.MethodGet,
 | 
			
		||||
			Path: "/apis/batch/v1/namespaces/myns/jobs?fieldSelector=%2Abar",
 | 
			
		||||
			ExpectedAttributes: &authorizer.AttributesRecord{
 | 
			
		||||
				Verb:                    "list",
 | 
			
		||||
| 
						 | 
				
			
			@ -160,7 +161,7 @@ func TestGetAuthorizerAttributes(t *testing.T) {
 | 
			
		|||
			EnableAuthorizationSelector: true,
 | 
			
		||||
		},
 | 
			
		||||
		"disabled, ignore good label selector": {
 | 
			
		||||
			Verb: "GET",
 | 
			
		||||
			Verb: http.MethodGet,
 | 
			
		||||
			Path: "/apis/batch/v1/namespaces/myns/jobs?labelSelector%=foo%3Dbar",
 | 
			
		||||
			ExpectedAttributes: &authorizer.AttributesRecord{
 | 
			
		||||
				Verb:            "list",
 | 
			
		||||
| 
						 | 
				
			
			@ -173,7 +174,7 @@ func TestGetAuthorizerAttributes(t *testing.T) {
 | 
			
		|||
			},
 | 
			
		||||
		},
 | 
			
		||||
		"enabled, good label selector": {
 | 
			
		||||
			Verb: "GET",
 | 
			
		||||
			Verb: http.MethodGet,
 | 
			
		||||
			Path: "/apis/batch/v1/namespaces/myns/jobs?labelSelector=foo%3D%3Dbar",
 | 
			
		||||
			ExpectedAttributes: &authorizer.AttributesRecord{
 | 
			
		||||
				Verb:            "list",
 | 
			
		||||
| 
						 | 
				
			
			@ -190,7 +191,7 @@ func TestGetAuthorizerAttributes(t *testing.T) {
 | 
			
		|||
			EnableAuthorizationSelector: true,
 | 
			
		||||
		},
 | 
			
		||||
		"enabled, bad label selector": {
 | 
			
		||||
			Verb: "GET",
 | 
			
		||||
			Verb: http.MethodGet,
 | 
			
		||||
			Path: "/apis/batch/v1/namespaces/myns/jobs?labelSelector=%2Abar",
 | 
			
		||||
			ExpectedAttributes: &authorizer.AttributesRecord{
 | 
			
		||||
				Verb:                    "list",
 | 
			
		||||
| 
						 | 
				
			
			@ -284,7 +285,7 @@ func TestAuditAnnotation(t *testing.T) {
 | 
			
		|||
		handler := WithAuthorization(&fakeHTTPHandler{}, tc.authorizer, negotiatedSerializer)
 | 
			
		||||
		// TODO: fake audit injector
 | 
			
		||||
 | 
			
		||||
		req, _ := http.NewRequest("GET", "/api/v1/namespaces/default/pods", nil)
 | 
			
		||||
		req, _ := http.NewRequest(http.MethodGet, "/api/v1/namespaces/default/pods", nil)
 | 
			
		||||
		req = withTestContext(req, nil, &auditinternal.Event{Level: auditinternal.LevelMetadata})
 | 
			
		||||
		ae := audit.AuditEventFrom(req.Context())
 | 
			
		||||
		req.RemoteAddr = "127.0.0.1"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -532,7 +532,7 @@ func TestImpersonationFilter(t *testing.T) {
 | 
			
		|||
				ctx = request.WithUser(request.NewContext(), tc.user)
 | 
			
		||||
			}()
 | 
			
		||||
 | 
			
		||||
			req, err := http.NewRequest("GET", server.URL, nil)
 | 
			
		||||
			req, err := http.NewRequest(http.MethodGet, server.URL, nil)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				t.Errorf("%s: unexpected error: %v", tc.name, err)
 | 
			
		||||
				return
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -258,7 +258,7 @@ func TestRecordAuthorizationMetricsMetrics(t *testing.T) {
 | 
			
		|||
			handler := WithAuthorization(&fakeHTTPHandler{}, tt.authorizer, negotiatedSerializer)
 | 
			
		||||
			// TODO: fake audit injector
 | 
			
		||||
 | 
			
		||||
			req, _ := http.NewRequest("GET", "/api/v1/namespaces/default/pods", nil)
 | 
			
		||||
			req, _ := http.NewRequest(http.MethodGet, "/api/v1/namespaces/default/pods", nil)
 | 
			
		||||
			req = withTestContext(req, nil, audit)
 | 
			
		||||
			req.RemoteAddr = "127.0.0.1"
 | 
			
		||||
			handler.ServeHTTP(httptest.NewRecorder(), req)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1233,7 +1233,7 @@ func TestPerRequestWithSlowReader(t *testing.T) {
 | 
			
		|||
		defer close(clientErrCh)
 | 
			
		||||
 | 
			
		||||
		// we don't set up a request context with deadline on the client-side
 | 
			
		||||
		req, err := http.NewRequestWithContext(context.Background(), "GET", server.URL+"/foo", nil)
 | 
			
		||||
		req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, server.URL+"/foo", nil)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Errorf("failed to create a new request: %v", err)
 | 
			
		||||
			return
 | 
			
		||||
| 
						 | 
				
			
			@ -1313,7 +1313,7 @@ func TestPerRequestWithSlowReader(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
func sendWithTrace(t *testing.T, client *http.Client, url string, f func(*testing.T, httptrace.GotConnInfo)) (*http.Response, error) {
 | 
			
		||||
	t.Helper()
 | 
			
		||||
	req, err := http.NewRequest("GET", url, nil)
 | 
			
		||||
	req, err := http.NewRequest(http.MethodGet, url, nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("failed to create new request: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -237,7 +237,7 @@ func TestDeleteCollectionWithNoContextDeadlineEnforced(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
	handler := DeleteCollection(fakeCollectionDeleterFunc(fakeDeleterFn), false, scope, nil)
 | 
			
		||||
 | 
			
		||||
	request, err := http.NewRequest("GET", "/test", nil)
 | 
			
		||||
	request, err := http.NewRequest(request.MethodGet, "/test", nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -80,9 +80,9 @@ func TestLazyVerb(t *testing.T) {
 | 
			
		|||
	assert.Equal(t, "unknown", fmt.Sprintf("%v", &lazyVerb{}))
 | 
			
		||||
 | 
			
		||||
	u, _ := url.Parse("?watch=true")
 | 
			
		||||
	req := &http.Request{Method: "GET", URL: u}
 | 
			
		||||
	req := &http.Request{Method: request.MethodGet, URL: u}
 | 
			
		||||
	verbWithReq := &lazyVerb{req: req}
 | 
			
		||||
	assert.Equal(t, "WATCH", fmt.Sprintf("%v", verbWithReq))
 | 
			
		||||
	assert.Equal(t, request.MethodWatch, fmt.Sprintf("%v", verbWithReq))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestLazyApiGroup(t *testing.T) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -64,9 +64,9 @@ func TestForbidden(t *testing.T) {
 | 
			
		|||
		contentType string
 | 
			
		||||
	}{
 | 
			
		||||
		{`{"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"forbidden: User \"NAME\" cannot GET path \"/whatever\"","reason":"Forbidden","details":{},"code":403}
 | 
			
		||||
`, authorizer.AttributesRecord{User: u, Verb: "GET", Path: "/whatever"}, "", "application/json"},
 | 
			
		||||
`, authorizer.AttributesRecord{User: u, Verb: request.MethodGet, Path: "/whatever"}, "", "application/json"},
 | 
			
		||||
		{`{"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"forbidden: User \"NAME\" cannot GET path \"/\u0026lt;script\u0026gt;\"","reason":"Forbidden","details":{},"code":403}
 | 
			
		||||
`, authorizer.AttributesRecord{User: u, Verb: "GET", Path: "/<script>"}, "", "application/json"},
 | 
			
		||||
`, authorizer.AttributesRecord{User: u, Verb: request.MethodGet, Path: "/<script>"}, "", "application/json"},
 | 
			
		||||
		{`{"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"pod is forbidden: User \"NAME\" cannot get resource \"pod\" in API group \"\" at the cluster scope","reason":"Forbidden","details":{"kind":"pod"},"code":403}
 | 
			
		||||
`, authorizer.AttributesRecord{User: u, Verb: "get", Resource: "pod", ResourceRequest: true}, "", "application/json"},
 | 
			
		||||
		{`{"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"pod \"mypod\" is forbidden: User \"NAME\" cannot get resource \"pod\" in API group \"\" at the cluster scope","reason":"Forbidden","details":{"name":"mypod","kind":"pod"},"code":403}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -181,7 +181,7 @@ func TestLimitedReadBody(t *testing.T) {
 | 
			
		|||
			defer metrics.RequestBodySizes.Reset()
 | 
			
		||||
			defer legacyregistry.Reset()
 | 
			
		||||
 | 
			
		||||
			req, err := http.NewRequest("POST", "/", tc.requestBody)
 | 
			
		||||
			req, err := http.NewRequest(request.MethodPost, "/", tc.requestBody)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				t.Errorf("err not expected: got %v", err)
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -42,6 +42,7 @@ import (
 | 
			
		|||
	"k8s.io/apiserver/pkg/endpoints/handlers"
 | 
			
		||||
	"k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
 | 
			
		||||
	"k8s.io/apiserver/pkg/endpoints/metrics"
 | 
			
		||||
	"k8s.io/apiserver/pkg/endpoints/request"
 | 
			
		||||
	utilwarning "k8s.io/apiserver/pkg/endpoints/warning"
 | 
			
		||||
	"k8s.io/apiserver/pkg/features"
 | 
			
		||||
	"k8s.io/apiserver/pkg/registry/rest"
 | 
			
		||||
| 
						 | 
				
			
			@ -62,9 +63,9 @@ type APIInstaller struct {
 | 
			
		|||
	minRequestTimeout time.Duration
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Struct capturing information about an action ("GET", "POST", "WATCH", "PROXY", etc).
 | 
			
		||||
// Struct capturing information about an action (MethodGet, MethodPost, MethodWatch, MethodProxy, etc).
 | 
			
		||||
type action struct {
 | 
			
		||||
	Verb          string               // Verb identifying the action ("GET", "POST", "WATCH", "PROXY", etc).
 | 
			
		||||
	Verb          string               // Verb identifying the action (MethodGet, MethodPost, MethodWatch, MethodProxy, etc).
 | 
			
		||||
	Path          string               // The path of the action
 | 
			
		||||
	Params        []*restful.Parameter // List of parameters associated with the action.
 | 
			
		||||
	Namer         handlers.ScopeNamer
 | 
			
		||||
| 
						 | 
				
			
			@ -175,17 +176,17 @@ type documentable interface {
 | 
			
		|||
 | 
			
		||||
// toDiscoveryKubeVerb maps an action.Verb to the logical kube verb, used for discovery
 | 
			
		||||
var toDiscoveryKubeVerb = map[string]string{
 | 
			
		||||
	"CONNECT":          "", // do not list in discovery.
 | 
			
		||||
	"DELETE":           "delete",
 | 
			
		||||
	"DELETECOLLECTION": "deletecollection",
 | 
			
		||||
	"GET":              "get",
 | 
			
		||||
	"LIST":             "list",
 | 
			
		||||
	"PATCH":            "patch",
 | 
			
		||||
	"POST":             "create",
 | 
			
		||||
	"PROXY":            "proxy",
 | 
			
		||||
	"PUT":              "update",
 | 
			
		||||
	"WATCH":            "watch",
 | 
			
		||||
	"WATCHLIST":        "watch",
 | 
			
		||||
	request.MethodConnect:          "", // do not list in discovery.
 | 
			
		||||
	request.MethodDelete:           "delete",
 | 
			
		||||
	request.MethodDeleteCollection: "deletecollection",
 | 
			
		||||
	request.MethodGet:              "get",
 | 
			
		||||
	request.MethodList:             "list",
 | 
			
		||||
	request.MethodPatch:            "patch",
 | 
			
		||||
	request.MethodPost:             "create",
 | 
			
		||||
	request.MethodProxy:            "proxy",
 | 
			
		||||
	request.MethodPut:              "update",
 | 
			
		||||
	request.MethodWatch:            "watch",
 | 
			
		||||
	request.MethodWatchList:        "watch",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Install handlers for API resources.
 | 
			
		||||
| 
						 | 
				
			
			@ -520,24 +521,24 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
 | 
			
		|||
 | 
			
		||||
		// Handler for standard REST verbs (GET, PUT, POST and DELETE).
 | 
			
		||||
		// Add actions at the resource path: /api/apiVersion/resource
 | 
			
		||||
		actions = appendIf(actions, action{"LIST", resourcePath, resourceParams, namer, false}, isLister)
 | 
			
		||||
		actions = appendIf(actions, action{"POST", resourcePath, resourceParams, namer, false}, isCreater)
 | 
			
		||||
		actions = appendIf(actions, action{"DELETECOLLECTION", resourcePath, resourceParams, namer, false}, isCollectionDeleter)
 | 
			
		||||
		actions = appendIf(actions, action{request.MethodList, resourcePath, resourceParams, namer, false}, isLister)
 | 
			
		||||
		actions = appendIf(actions, action{request.MethodPost, resourcePath, resourceParams, namer, false}, isCreater)
 | 
			
		||||
		actions = appendIf(actions, action{request.MethodDeleteCollection, resourcePath, resourceParams, namer, false}, isCollectionDeleter)
 | 
			
		||||
		// DEPRECATED in 1.11
 | 
			
		||||
		actions = appendIf(actions, action{"WATCHLIST", "watch/" + resourcePath, resourceParams, namer, false}, allowWatchList)
 | 
			
		||||
		actions = appendIf(actions, action{request.MethodWatchList, "watch/" + resourcePath, resourceParams, namer, false}, allowWatchList)
 | 
			
		||||
 | 
			
		||||
		// Add actions at the item path: /api/apiVersion/resource/{name}
 | 
			
		||||
		actions = appendIf(actions, action{"GET", itemPath, nameParams, namer, false}, isGetter)
 | 
			
		||||
		actions = appendIf(actions, action{request.MethodGet, itemPath, nameParams, namer, false}, isGetter)
 | 
			
		||||
		if getSubpath {
 | 
			
		||||
			actions = appendIf(actions, action{"GET", itemPath + "/{path:*}", proxyParams, namer, false}, isGetter)
 | 
			
		||||
			actions = appendIf(actions, action{request.MethodGet, itemPath + "/{path:*}", proxyParams, namer, false}, isGetter)
 | 
			
		||||
		}
 | 
			
		||||
		actions = appendIf(actions, action{"PUT", itemPath, nameParams, namer, false}, isUpdater)
 | 
			
		||||
		actions = appendIf(actions, action{"PATCH", itemPath, nameParams, namer, false}, isPatcher)
 | 
			
		||||
		actions = appendIf(actions, action{"DELETE", itemPath, nameParams, namer, false}, isGracefulDeleter)
 | 
			
		||||
		actions = appendIf(actions, action{request.MethodPut, itemPath, nameParams, namer, false}, isUpdater)
 | 
			
		||||
		actions = appendIf(actions, action{request.MethodPatch, itemPath, nameParams, namer, false}, isPatcher)
 | 
			
		||||
		actions = appendIf(actions, action{request.MethodDelete, itemPath, nameParams, namer, false}, isGracefulDeleter)
 | 
			
		||||
		// DEPRECATED in 1.11
 | 
			
		||||
		actions = appendIf(actions, action{"WATCH", "watch/" + itemPath, nameParams, namer, false}, isWatcher)
 | 
			
		||||
		actions = appendIf(actions, action{"CONNECT", itemPath, nameParams, namer, false}, isConnecter)
 | 
			
		||||
		actions = appendIf(actions, action{"CONNECT", itemPath + "/{path:*}", proxyParams, namer, false}, isConnecter && connectSubpath)
 | 
			
		||||
		actions = appendIf(actions, action{request.MethodWatch, "watch/" + itemPath, nameParams, namer, false}, isWatcher)
 | 
			
		||||
		actions = appendIf(actions, action{request.MethodConnect, itemPath, nameParams, namer, false}, isConnecter)
 | 
			
		||||
		actions = appendIf(actions, action{request.MethodConnect, itemPath + "/{path:*}", proxyParams, namer, false}, isConnecter && connectSubpath)
 | 
			
		||||
	default:
 | 
			
		||||
		namespaceParamName := "namespaces"
 | 
			
		||||
		// Handler for standard REST verbs (GET, PUT, POST and DELETE).
 | 
			
		||||
| 
						 | 
				
			
			@ -565,31 +566,31 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
 | 
			
		|||
			ClusterScoped: false,
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		actions = appendIf(actions, action{"LIST", resourcePath, resourceParams, namer, false}, isLister)
 | 
			
		||||
		actions = appendIf(actions, action{"POST", resourcePath, resourceParams, namer, false}, isCreater)
 | 
			
		||||
		actions = appendIf(actions, action{"DELETECOLLECTION", resourcePath, resourceParams, namer, false}, isCollectionDeleter)
 | 
			
		||||
		actions = appendIf(actions, action{request.MethodList, resourcePath, resourceParams, namer, false}, isLister)
 | 
			
		||||
		actions = appendIf(actions, action{request.MethodPost, resourcePath, resourceParams, namer, false}, isCreater)
 | 
			
		||||
		actions = appendIf(actions, action{request.MethodDeleteCollection, resourcePath, resourceParams, namer, false}, isCollectionDeleter)
 | 
			
		||||
		// DEPRECATED in 1.11
 | 
			
		||||
		actions = appendIf(actions, action{"WATCHLIST", "watch/" + resourcePath, resourceParams, namer, false}, allowWatchList)
 | 
			
		||||
		actions = appendIf(actions, action{request.MethodWatchList, "watch/" + resourcePath, resourceParams, namer, false}, allowWatchList)
 | 
			
		||||
 | 
			
		||||
		actions = appendIf(actions, action{"GET", itemPath, nameParams, namer, false}, isGetter)
 | 
			
		||||
		actions = appendIf(actions, action{request.MethodGet, itemPath, nameParams, namer, false}, isGetter)
 | 
			
		||||
		if getSubpath {
 | 
			
		||||
			actions = appendIf(actions, action{"GET", itemPath + "/{path:*}", proxyParams, namer, false}, isGetter)
 | 
			
		||||
			actions = appendIf(actions, action{request.MethodGet, itemPath + "/{path:*}", proxyParams, namer, false}, isGetter)
 | 
			
		||||
		}
 | 
			
		||||
		actions = appendIf(actions, action{"PUT", itemPath, nameParams, namer, false}, isUpdater)
 | 
			
		||||
		actions = appendIf(actions, action{"PATCH", itemPath, nameParams, namer, false}, isPatcher)
 | 
			
		||||
		actions = appendIf(actions, action{"DELETE", itemPath, nameParams, namer, false}, isGracefulDeleter)
 | 
			
		||||
		actions = appendIf(actions, action{request.MethodPut, itemPath, nameParams, namer, false}, isUpdater)
 | 
			
		||||
		actions = appendIf(actions, action{request.MethodPatch, itemPath, nameParams, namer, false}, isPatcher)
 | 
			
		||||
		actions = appendIf(actions, action{request.MethodDelete, itemPath, nameParams, namer, false}, isGracefulDeleter)
 | 
			
		||||
		// DEPRECATED in 1.11
 | 
			
		||||
		actions = appendIf(actions, action{"WATCH", "watch/" + itemPath, nameParams, namer, false}, isWatcher)
 | 
			
		||||
		actions = appendIf(actions, action{"CONNECT", itemPath, nameParams, namer, false}, isConnecter)
 | 
			
		||||
		actions = appendIf(actions, action{"CONNECT", itemPath + "/{path:*}", proxyParams, namer, false}, isConnecter && connectSubpath)
 | 
			
		||||
		actions = appendIf(actions, action{request.MethodWatch, "watch/" + itemPath, nameParams, namer, false}, isWatcher)
 | 
			
		||||
		actions = appendIf(actions, action{request.MethodConnect, itemPath, nameParams, namer, false}, isConnecter)
 | 
			
		||||
		actions = appendIf(actions, action{request.MethodConnect, itemPath + "/{path:*}", proxyParams, namer, false}, isConnecter && connectSubpath)
 | 
			
		||||
 | 
			
		||||
		// list or post across namespace.
 | 
			
		||||
		// For ex: LIST all pods in all namespaces by sending a LIST request at /api/apiVersion/pods.
 | 
			
		||||
		// TODO: more strongly type whether a resource allows these actions on "all namespaces" (bulk delete)
 | 
			
		||||
		if !isSubresource {
 | 
			
		||||
			actions = appendIf(actions, action{"LIST", resource, params, namer, true}, isLister)
 | 
			
		||||
			actions = appendIf(actions, action{request.MethodList, resource, params, namer, true}, isLister)
 | 
			
		||||
			// DEPRECATED in 1.11
 | 
			
		||||
			actions = appendIf(actions, action{"WATCHLIST", "watch/" + resource, params, namer, true}, allowWatchList)
 | 
			
		||||
			actions = appendIf(actions, action{request.MethodWatchList, "watch/" + resource, params, namer, true}, allowWatchList)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -740,7 +741,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
 | 
			
		|||
			requestScope = "resource"
 | 
			
		||||
			operationSuffix = operationSuffix + "WithPath"
 | 
			
		||||
		}
 | 
			
		||||
		if strings.Contains(action.Path, "/{name}") || action.Verb == "POST" {
 | 
			
		||||
		if strings.Contains(action.Path, "/{name}") || action.Verb == request.MethodPost {
 | 
			
		||||
			requestScope = "resource"
 | 
			
		||||
		}
 | 
			
		||||
		if action.AllNamespaces {
 | 
			
		||||
| 
						 | 
				
			
			@ -794,7 +795,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
 | 
			
		|||
		}
 | 
			
		||||
 | 
			
		||||
		switch action.Verb {
 | 
			
		||||
		case "GET": // Get a resource.
 | 
			
		||||
		case request.MethodGet: // Get a resource.
 | 
			
		||||
			var handler restful.RouteFunction
 | 
			
		||||
			if isGetterWithOptions {
 | 
			
		||||
				handler = restfulGetResourceWithOptions(getterWithOptions, reqScope, isSubresource)
 | 
			
		||||
| 
						 | 
				
			
			@ -828,7 +829,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
 | 
			
		|||
			}
 | 
			
		||||
			addParams(route, action.Params)
 | 
			
		||||
			routes = append(routes, route)
 | 
			
		||||
		case "LIST": // List all resources of a kind.
 | 
			
		||||
		case request.MethodList: // List all resources of a kind.
 | 
			
		||||
			doc := "list objects of kind " + kind
 | 
			
		||||
			if isSubresource {
 | 
			
		||||
				doc = "list " + subresource + " of objects of kind " + kind
 | 
			
		||||
| 
						 | 
				
			
			@ -861,7 +862,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
 | 
			
		|||
			}
 | 
			
		||||
			addParams(route, action.Params)
 | 
			
		||||
			routes = append(routes, route)
 | 
			
		||||
		case "PUT": // Update a resource.
 | 
			
		||||
		case request.MethodPut: // Update a resource.
 | 
			
		||||
			doc := "replace the specified " + kind
 | 
			
		||||
			if isSubresource {
 | 
			
		||||
				doc = "replace " + subresource + " of the specified " + kind
 | 
			
		||||
| 
						 | 
				
			
			@ -884,7 +885,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
 | 
			
		|||
			}
 | 
			
		||||
			addParams(route, action.Params)
 | 
			
		||||
			routes = append(routes, route)
 | 
			
		||||
		case "PATCH": // Partially update a resource
 | 
			
		||||
		case request.MethodPatch: // Partially update a resource
 | 
			
		||||
			doc := "partially update the specified " + kind
 | 
			
		||||
			if isSubresource {
 | 
			
		||||
				doc = "partially update " + subresource + " of the specified " + kind
 | 
			
		||||
| 
						 | 
				
			
			@ -916,7 +917,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
 | 
			
		|||
			}
 | 
			
		||||
			addParams(route, action.Params)
 | 
			
		||||
			routes = append(routes, route)
 | 
			
		||||
		case "POST": // Create a resource.
 | 
			
		||||
		case request.MethodPost: // Create a resource.
 | 
			
		||||
			var handler restful.RouteFunction
 | 
			
		||||
			if isNamedCreater {
 | 
			
		||||
				handler = restfulCreateNamedResource(namedCreater, reqScope, admit)
 | 
			
		||||
| 
						 | 
				
			
			@ -947,7 +948,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
 | 
			
		|||
			}
 | 
			
		||||
			addParams(route, action.Params)
 | 
			
		||||
			routes = append(routes, route)
 | 
			
		||||
		case "DELETE": // Delete a resource.
 | 
			
		||||
		case request.MethodDelete: // Delete a resource.
 | 
			
		||||
			article := GetArticleForNoun(kind, " ")
 | 
			
		||||
			doc := "delete" + article + kind
 | 
			
		||||
			if isSubresource {
 | 
			
		||||
| 
						 | 
				
			
			@ -976,7 +977,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
 | 
			
		|||
			}
 | 
			
		||||
			addParams(route, action.Params)
 | 
			
		||||
			routes = append(routes, route)
 | 
			
		||||
		case "DELETECOLLECTION":
 | 
			
		||||
		case request.MethodDeleteCollection:
 | 
			
		||||
			doc := "delete collection of " + kind
 | 
			
		||||
			if isSubresource {
 | 
			
		||||
				doc = "delete collection of " + subresource + " of a " + kind
 | 
			
		||||
| 
						 | 
				
			
			@ -1003,7 +1004,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
 | 
			
		|||
			addParams(route, action.Params)
 | 
			
		||||
			routes = append(routes, route)
 | 
			
		||||
		// deprecated in 1.11
 | 
			
		||||
		case "WATCH": // Watch a resource.
 | 
			
		||||
		case request.MethodWatch: // Watch a resource.
 | 
			
		||||
			doc := "watch changes to an object of kind " + kind
 | 
			
		||||
			if isSubresource {
 | 
			
		||||
				doc = "watch changes to " + subresource + " of an object of kind " + kind
 | 
			
		||||
| 
						 | 
				
			
			@ -1024,7 +1025,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
 | 
			
		|||
			addParams(route, action.Params)
 | 
			
		||||
			routes = append(routes, route)
 | 
			
		||||
		// deprecated in 1.11
 | 
			
		||||
		case "WATCHLIST": // Watch all resources of a kind.
 | 
			
		||||
		case request.MethodWatchList: // Watch all resources of a kind.
 | 
			
		||||
			doc := "watch individual changes to a list of " + kind
 | 
			
		||||
			if isSubresource {
 | 
			
		||||
				doc = "watch individual changes to a list of " + subresource + " of " + kind
 | 
			
		||||
| 
						 | 
				
			
			@ -1044,7 +1045,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
 | 
			
		|||
			}
 | 
			
		||||
			addParams(route, action.Params)
 | 
			
		||||
			routes = append(routes, route)
 | 
			
		||||
		case "CONNECT":
 | 
			
		||||
		case request.MethodConnect:
 | 
			
		||||
			for _, method := range connecter.ConnectMethods() {
 | 
			
		||||
				connectProducedObject := storageMeta.ProducesObject(method)
 | 
			
		||||
				if connectProducedObject == nil {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -322,20 +322,20 @@ var (
 | 
			
		|||
	// these are the valid request methods which we report in our metrics. Any other request methods
 | 
			
		||||
	// will be aggregated under 'unknown'
 | 
			
		||||
	validRequestMethods = utilsets.NewString(
 | 
			
		||||
		"APPLY",
 | 
			
		||||
		"CONNECT",
 | 
			
		||||
		"CREATE",
 | 
			
		||||
		"DELETE",
 | 
			
		||||
		"DELETECOLLECTION",
 | 
			
		||||
		"GET",
 | 
			
		||||
		"LIST",
 | 
			
		||||
		"PATCH",
 | 
			
		||||
		"POST",
 | 
			
		||||
		"PROXY",
 | 
			
		||||
		"PUT",
 | 
			
		||||
		"UPDATE",
 | 
			
		||||
		"WATCH",
 | 
			
		||||
		"WATCHLIST")
 | 
			
		||||
		MethodApply,
 | 
			
		||||
		MethodConnect,
 | 
			
		||||
		MethodCreate,
 | 
			
		||||
		MethodDelete,
 | 
			
		||||
		MethodDeleteCollection,
 | 
			
		||||
		MethodGet,
 | 
			
		||||
		MethodList,
 | 
			
		||||
		MethodPatch,
 | 
			
		||||
		MethodPost,
 | 
			
		||||
		MethodProxy,
 | 
			
		||||
		MethodPut,
 | 
			
		||||
		MethodUpdate,
 | 
			
		||||
		MethodWatch,
 | 
			
		||||
		MethodWatchList)
 | 
			
		||||
 | 
			
		||||
	// These are the valid connect requests which we report in our metrics.
 | 
			
		||||
	validConnectRequests = utilsets.NewString(
 | 
			
		||||
| 
						 | 
				
			
			@ -346,6 +346,24 @@ var (
 | 
			
		|||
		"proxy")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	MethodApply            string = request.MethodApply
 | 
			
		||||
	MethodConnect          string = request.MethodConnect
 | 
			
		||||
	MethodCreate           string = request.MethodCreate
 | 
			
		||||
	MethodDelete           string = request.MethodDelete
 | 
			
		||||
	MethodDeleteCollection string = request.MethodDeleteCollection
 | 
			
		||||
	MethodGet              string = request.MethodGet
 | 
			
		||||
	MethodHead             string = request.MethodHead // TODO: why not in validRequestMethods?
 | 
			
		||||
	MethodList             string = request.MethodList
 | 
			
		||||
	MethodPatch            string = request.MethodPatch
 | 
			
		||||
	MethodPost             string = request.MethodPost
 | 
			
		||||
	MethodProxy            string = request.MethodProxy
 | 
			
		||||
	MethodPut              string = request.MethodPut
 | 
			
		||||
	MethodUpdate           string = request.MethodUpdate
 | 
			
		||||
	MethodWatch            string = request.MethodWatch
 | 
			
		||||
	MethodWatchList        string = request.MethodWatchList
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// ReadOnlyKind is a string identifying read only request kind
 | 
			
		||||
	ReadOnlyKind = "readOnly"
 | 
			
		||||
| 
						 | 
				
			
			@ -605,7 +623,7 @@ func MonitorRequest(req *http.Request, verb, group, version, resource, subresour
 | 
			
		|||
		requestSliLatencies.WithContext(req.Context()).WithLabelValues(reportedVerb, group, version, resource, subresource, scope, component).Observe(sliLatency)
 | 
			
		||||
	}
 | 
			
		||||
	// We are only interested in response sizes of read requests.
 | 
			
		||||
	if verb == "GET" || verb == "LIST" {
 | 
			
		||||
	if verb == MethodGet || verb == MethodList {
 | 
			
		||||
		responseSizes.WithContext(req.Context()).WithLabelValues(reportedVerb, group, version, resource, subresource, scope, component).Observe(float64(respSize))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -701,11 +719,11 @@ func CleanListScope(ctx context.Context, opts *metainternalversion.ListOptions)
 | 
			
		|||
// UPPERCASE.
 | 
			
		||||
func CanonicalVerb(verb string, scope string) string {
 | 
			
		||||
	switch verb {
 | 
			
		||||
	case "GET", "HEAD":
 | 
			
		||||
	case MethodGet, MethodHead:
 | 
			
		||||
		if scope != "resource" && scope != "" {
 | 
			
		||||
			return "LIST"
 | 
			
		||||
			return request.MethodList
 | 
			
		||||
		}
 | 
			
		||||
		return "GET"
 | 
			
		||||
		return MethodGet
 | 
			
		||||
	default:
 | 
			
		||||
		return verb
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -715,18 +733,18 @@ func CanonicalVerb(verb string, scope string) string {
 | 
			
		|||
// LIST, APPLY from PATCH and CONNECT from others.
 | 
			
		||||
func CleanVerb(verb string, request *http.Request, requestInfo *request.RequestInfo) string {
 | 
			
		||||
	reportedVerb := verb
 | 
			
		||||
	if suggestedVerb := getVerbIfWatch(request); suggestedVerb == "WATCH" {
 | 
			
		||||
		reportedVerb = "WATCH"
 | 
			
		||||
	if suggestedVerb := getVerbIfWatch(request); suggestedVerb == MethodWatch {
 | 
			
		||||
		reportedVerb = MethodWatch
 | 
			
		||||
	}
 | 
			
		||||
	// normalize the legacy WATCHLIST to WATCH to ensure users aren't surprised by metrics
 | 
			
		||||
	if verb == "WATCHLIST" {
 | 
			
		||||
		reportedVerb = "WATCH"
 | 
			
		||||
	if verb == MethodWatchList {
 | 
			
		||||
		reportedVerb = MethodWatch
 | 
			
		||||
	}
 | 
			
		||||
	if verb == "PATCH" && request.Header.Get("Content-Type") == string(types.ApplyPatchType) {
 | 
			
		||||
		reportedVerb = "APPLY"
 | 
			
		||||
	if verb == MethodPatch && request.Header.Get("Content-Type") == string(types.ApplyPatchType) {
 | 
			
		||||
		reportedVerb = MethodApply
 | 
			
		||||
	}
 | 
			
		||||
	if requestInfo != nil && requestInfo.IsResourceRequest && len(requestInfo.Subresource) > 0 && validConnectRequests.Has(requestInfo.Subresource) {
 | 
			
		||||
		reportedVerb = "CONNECT"
 | 
			
		||||
		reportedVerb = MethodConnect
 | 
			
		||||
	}
 | 
			
		||||
	return reportedVerb
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -761,8 +779,8 @@ func cleanVerb(verb, suggestedVerb string, request *http.Request, requestInfo *r
 | 
			
		|||
	// deprecated path pattern for watch of:
 | 
			
		||||
	//   GET /api/{version}/watch/{resource}
 | 
			
		||||
	// We correct it manually based on the pass verb from the installer.
 | 
			
		||||
	if suggestedVerb == "WATCH" || suggestedVerb == "WATCHLIST" {
 | 
			
		||||
		return "WATCH"
 | 
			
		||||
	if suggestedVerb == MethodWatch || suggestedVerb == MethodWatchList {
 | 
			
		||||
		return MethodWatch
 | 
			
		||||
	}
 | 
			
		||||
	reportedVerb := CleanVerb(verb, request, requestInfo)
 | 
			
		||||
	if validRequestMethods.Has(reportedVerb) {
 | 
			
		||||
| 
						 | 
				
			
			@ -773,11 +791,11 @@ func cleanVerb(verb, suggestedVerb string, request *http.Request, requestInfo *r
 | 
			
		|||
 | 
			
		||||
// getVerbIfWatch additionally ensures that GET or List would be transformed to WATCH
 | 
			
		||||
func getVerbIfWatch(req *http.Request) string {
 | 
			
		||||
	if strings.ToUpper(req.Method) == "GET" || strings.ToUpper(req.Method) == "LIST" {
 | 
			
		||||
	if strings.ToUpper(req.Method) == MethodGet || strings.ToUpper(req.Method) == request.MethodList {
 | 
			
		||||
		// see apimachinery/pkg/runtime/conversion.go Convert_Slice_string_To_bool
 | 
			
		||||
		if values := req.URL.Query()["watch"]; len(values) > 0 {
 | 
			
		||||
			if value := strings.ToLower(values[0]); value != "0" && value != "false" {
 | 
			
		||||
				return "WATCH"
 | 
			
		||||
				return request.MethodWatch
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -48,97 +48,97 @@ func TestCleanVerb(t *testing.T) {
 | 
			
		|||
		},
 | 
			
		||||
		{
 | 
			
		||||
			desc:         "LIST should normally map to LIST",
 | 
			
		||||
			initialVerb:  "LIST",
 | 
			
		||||
			initialVerb:  request.MethodList,
 | 
			
		||||
			request:      nil,
 | 
			
		||||
			expectedVerb: "LIST",
 | 
			
		||||
			expectedVerb: request.MethodList,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			desc:        "LIST should be transformed to WATCH if we have the right query param on the request",
 | 
			
		||||
			initialVerb: "LIST",
 | 
			
		||||
			initialVerb: request.MethodList,
 | 
			
		||||
			request: &http.Request{
 | 
			
		||||
				Method: "GET",
 | 
			
		||||
				Method: request.MethodGet,
 | 
			
		||||
				URL: &url.URL{
 | 
			
		||||
					RawQuery: "watch=true",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			expectedVerb: "WATCH",
 | 
			
		||||
			expectedVerb: request.MethodWatch,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			desc:        "LIST isn't transformed to WATCH if we have query params that do not include watch",
 | 
			
		||||
			initialVerb: "LIST",
 | 
			
		||||
			initialVerb: request.MethodList,
 | 
			
		||||
			request: &http.Request{
 | 
			
		||||
				Method: "GET",
 | 
			
		||||
				Method: request.MethodGet,
 | 
			
		||||
				URL: &url.URL{
 | 
			
		||||
					RawQuery: "blah=asdf&something=else",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			expectedVerb: "LIST",
 | 
			
		||||
			expectedVerb: request.MethodList,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			// The above may seem counter-intuitive, but it actually is needed for cases like
 | 
			
		||||
			// watching a single item, e.g.:
 | 
			
		||||
			//  /api/v1/namespaces/foo/pods/bar?fieldSelector=metadata.name=baz&watch=true
 | 
			
		||||
			desc:        "GET is transformed to WATCH if we have the right query param on the request",
 | 
			
		||||
			initialVerb: "GET",
 | 
			
		||||
			initialVerb: request.MethodGet,
 | 
			
		||||
			request: &http.Request{
 | 
			
		||||
				Method: "GET",
 | 
			
		||||
				Method: request.MethodGet,
 | 
			
		||||
				URL: &url.URL{
 | 
			
		||||
					RawQuery: "watch=true",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			expectedVerb: "WATCH",
 | 
			
		||||
			expectedVerb: request.MethodWatch,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			desc:          "LIST is transformed to WATCH for the old pattern watch",
 | 
			
		||||
			initialVerb:   "LIST",
 | 
			
		||||
			suggestedVerb: "WATCH",
 | 
			
		||||
			initialVerb:   request.MethodList,
 | 
			
		||||
			suggestedVerb: request.MethodWatch,
 | 
			
		||||
			request: &http.Request{
 | 
			
		||||
				Method: "GET",
 | 
			
		||||
				Method: request.MethodGet,
 | 
			
		||||
				URL: &url.URL{
 | 
			
		||||
					RawQuery: "/api/v1/watch/pods",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			expectedVerb: "WATCH",
 | 
			
		||||
			expectedVerb: request.MethodWatch,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			desc:          "LIST is transformed to WATCH for the old pattern watchlist",
 | 
			
		||||
			initialVerb:   "LIST",
 | 
			
		||||
			suggestedVerb: "WATCHLIST",
 | 
			
		||||
			initialVerb:   request.MethodList,
 | 
			
		||||
			suggestedVerb: request.MethodWatchList,
 | 
			
		||||
			request: &http.Request{
 | 
			
		||||
				Method: "GET",
 | 
			
		||||
				Method: request.MethodGet,
 | 
			
		||||
				URL: &url.URL{
 | 
			
		||||
					RawQuery: "/api/v1/watch/pods",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			expectedVerb: "WATCH",
 | 
			
		||||
			expectedVerb: request.MethodWatch,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			desc:         "WATCHLIST should be transformed to WATCH",
 | 
			
		||||
			initialVerb:  "WATCHLIST",
 | 
			
		||||
			initialVerb:  request.MethodWatchList,
 | 
			
		||||
			request:      nil,
 | 
			
		||||
			expectedVerb: "WATCH",
 | 
			
		||||
			expectedVerb: request.MethodWatch,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			desc:        "PATCH should be transformed to APPLY with the right content type",
 | 
			
		||||
			initialVerb: "PATCH",
 | 
			
		||||
			initialVerb: request.MethodPatch,
 | 
			
		||||
			request: &http.Request{
 | 
			
		||||
				Header: http.Header{
 | 
			
		||||
					"Content-Type": []string{"application/apply-patch+yaml"},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			expectedVerb: "APPLY",
 | 
			
		||||
			expectedVerb: request.MethodApply,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			desc:         "PATCH shouldn't be transformed to APPLY without the right content type",
 | 
			
		||||
			initialVerb:  "PATCH",
 | 
			
		||||
			initialVerb:  request.MethodPatch,
 | 
			
		||||
			request:      nil,
 | 
			
		||||
			expectedVerb: "PATCH",
 | 
			
		||||
			expectedVerb: request.MethodPatch,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			desc:         "WATCHLIST should be transformed to WATCH",
 | 
			
		||||
			initialVerb:  "WATCHLIST",
 | 
			
		||||
			initialVerb:  request.MethodWatchList,
 | 
			
		||||
			request:      nil,
 | 
			
		||||
			expectedVerb: "WATCH",
 | 
			
		||||
			expectedVerb: request.MethodWatch,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			desc:         "unexpected verbs should be designated as unknown",
 | 
			
		||||
| 
						 | 
				
			
			@ -148,26 +148,26 @@ func TestCleanVerb(t *testing.T) {
 | 
			
		|||
		},
 | 
			
		||||
		{
 | 
			
		||||
			desc:        "Pod logs should be transformed to CONNECT",
 | 
			
		||||
			initialVerb: "GET",
 | 
			
		||||
			initialVerb: request.MethodGet,
 | 
			
		||||
			request: &http.Request{
 | 
			
		||||
				Method: "GET",
 | 
			
		||||
				Method: request.MethodGet,
 | 
			
		||||
				URL: &url.URL{
 | 
			
		||||
					RawQuery: "/api/v1/namespaces/default/pods/test-pod/log",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			requestInfo: &request.RequestInfo{
 | 
			
		||||
				Verb:              "GET",
 | 
			
		||||
				Verb:              request.MethodGet,
 | 
			
		||||
				Resource:          "pods",
 | 
			
		||||
				IsResourceRequest: true,
 | 
			
		||||
				Subresource:       "log",
 | 
			
		||||
			},
 | 
			
		||||
			expectedVerb: "CONNECT",
 | 
			
		||||
			expectedVerb: request.MethodConnect,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			desc:        "Pod exec should be transformed to CONNECT",
 | 
			
		||||
			initialVerb: "POST",
 | 
			
		||||
			initialVerb: request.MethodPost,
 | 
			
		||||
			request: &http.Request{
 | 
			
		||||
				Method: "POST",
 | 
			
		||||
				Method: request.MethodPost,
 | 
			
		||||
				URL: &url.URL{
 | 
			
		||||
					RawQuery: "/api/v1/namespaces/default/pods/test-pod/exec?command=sh",
 | 
			
		||||
				},
 | 
			
		||||
| 
						 | 
				
			
			@ -180,18 +180,18 @@ func TestCleanVerb(t *testing.T) {
 | 
			
		|||
				},
 | 
			
		||||
			},
 | 
			
		||||
			requestInfo: &request.RequestInfo{
 | 
			
		||||
				Verb:              "POST",
 | 
			
		||||
				Verb:              request.MethodPost,
 | 
			
		||||
				Resource:          "pods",
 | 
			
		||||
				IsResourceRequest: true,
 | 
			
		||||
				Subresource:       "exec",
 | 
			
		||||
			},
 | 
			
		||||
			expectedVerb: "CONNECT",
 | 
			
		||||
			expectedVerb: request.MethodConnect,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			desc:        "Pod portforward should be transformed to CONNECT",
 | 
			
		||||
			initialVerb: "POST",
 | 
			
		||||
			initialVerb: request.MethodPost,
 | 
			
		||||
			request: &http.Request{
 | 
			
		||||
				Method: "POST",
 | 
			
		||||
				Method: request.MethodPost,
 | 
			
		||||
				URL: &url.URL{
 | 
			
		||||
					RawQuery: "/api/v1/namespaces/default/pods/test-pod/portforward",
 | 
			
		||||
				},
 | 
			
		||||
| 
						 | 
				
			
			@ -204,30 +204,30 @@ func TestCleanVerb(t *testing.T) {
 | 
			
		|||
				},
 | 
			
		||||
			},
 | 
			
		||||
			requestInfo: &request.RequestInfo{
 | 
			
		||||
				Verb:              "POST",
 | 
			
		||||
				Verb:              request.MethodPost,
 | 
			
		||||
				Resource:          "pods",
 | 
			
		||||
				IsResourceRequest: true,
 | 
			
		||||
				Subresource:       "portforward",
 | 
			
		||||
			},
 | 
			
		||||
			expectedVerb: "CONNECT",
 | 
			
		||||
			expectedVerb: request.MethodConnect,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			desc:        "Deployment scale should not be transformed to CONNECT",
 | 
			
		||||
			initialVerb: "PUT",
 | 
			
		||||
			initialVerb: request.MethodPut,
 | 
			
		||||
			request: &http.Request{
 | 
			
		||||
				Method: "PUT",
 | 
			
		||||
				Method: request.MethodPut,
 | 
			
		||||
				URL: &url.URL{
 | 
			
		||||
					RawQuery: "/apis/apps/v1/namespaces/default/deployments/test-1/scale",
 | 
			
		||||
				},
 | 
			
		||||
				Header: map[string][]string{},
 | 
			
		||||
			},
 | 
			
		||||
			requestInfo: &request.RequestInfo{
 | 
			
		||||
				Verb:              "PUT",
 | 
			
		||||
				Verb:              request.MethodPut,
 | 
			
		||||
				Resource:          "deployments",
 | 
			
		||||
				IsResourceRequest: true,
 | 
			
		||||
				Subresource:       "scale",
 | 
			
		||||
			},
 | 
			
		||||
			expectedVerb: "PUT",
 | 
			
		||||
			expectedVerb: request.MethodPut,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, tt := range testCases {
 | 
			
		||||
| 
						 | 
				
			
			@ -382,7 +382,7 @@ func TestRecordDroppedRequests(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			desc: "list pods",
 | 
			
		||||
			request: &http.Request{
 | 
			
		||||
				Method: "GET",
 | 
			
		||||
				Method: request.MethodGet,
 | 
			
		||||
				URL: &url.URL{
 | 
			
		||||
					RawPath: "/api/v1/pods",
 | 
			
		||||
				},
 | 
			
		||||
| 
						 | 
				
			
			@ -404,7 +404,7 @@ func TestRecordDroppedRequests(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			desc: "post pods",
 | 
			
		||||
			request: &http.Request{
 | 
			
		||||
				Method: "POST",
 | 
			
		||||
				Method: request.MethodPost,
 | 
			
		||||
				URL: &url.URL{
 | 
			
		||||
					RawPath: "/api/v1/namespaces/foo/pods",
 | 
			
		||||
				},
 | 
			
		||||
| 
						 | 
				
			
			@ -426,7 +426,7 @@ func TestRecordDroppedRequests(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			desc: "dry-run patch job status",
 | 
			
		||||
			request: &http.Request{
 | 
			
		||||
				Method: "PATCH",
 | 
			
		||||
				Method: request.MethodPatch,
 | 
			
		||||
				URL: &url.URL{
 | 
			
		||||
					RawPath:  "/apis/batch/v1/namespaces/foo/jobs/bar/status",
 | 
			
		||||
					RawQuery: "dryRun=All",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,6 +24,7 @@ import (
 | 
			
		|||
	"testing"
 | 
			
		||||
 | 
			
		||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
			
		||||
	"k8s.io/apiserver/pkg/endpoints/request"
 | 
			
		||||
	genericapitesting "k8s.io/apiserver/pkg/endpoints/testing"
 | 
			
		||||
	"k8s.io/apiserver/pkg/registry/rest"
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -46,7 +47,7 @@ func TestPatch(t *testing.T) {
 | 
			
		|||
	defer server.Close()
 | 
			
		||||
 | 
			
		||||
	client := http.Client{}
 | 
			
		||||
	request, err := http.NewRequest("PATCH", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader([]byte(`{"labels":{"foo":"bar"}}`)))
 | 
			
		||||
	request, err := http.NewRequest(request.MethodPatch, server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader([]byte(`{"labels":{"foo":"bar"}}`)))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -81,22 +82,22 @@ func TestForbiddenForceOnNonApply(t *testing.T) {
 | 
			
		|||
	defer server.Close()
 | 
			
		||||
 | 
			
		||||
	client := http.Client{}
 | 
			
		||||
	request, err := http.NewRequest("PATCH", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader([]byte(`{"labels":{"foo":"bar"}}`)))
 | 
			
		||||
	req, err := http.NewRequest(request.MethodPatch, server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader([]byte(`{"labels":{"foo":"bar"}}`)))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	request.Header.Set("Content-Type", "application/merge-patch+json; charset=UTF-8")
 | 
			
		||||
	_, err = client.Do(request)
 | 
			
		||||
	req.Header.Set("Content-Type", "application/merge-patch+json; charset=UTF-8")
 | 
			
		||||
	_, err = client.Do(req)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	request, err = http.NewRequest("PATCH", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID+"?force=true", bytes.NewReader([]byte(`{"labels":{"foo":"bar"}}`)))
 | 
			
		||||
	req, err = http.NewRequest(request.MethodPatch, server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID+"?force=true", bytes.NewReader([]byte(`{"labels":{"foo":"bar"}}`)))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	request.Header.Set("Content-Type", "application/merge-patch+json; charset=UTF-8")
 | 
			
		||||
	response, err := client.Do(request)
 | 
			
		||||
	req.Header.Set("Content-Type", "application/merge-patch+json; charset=UTF-8")
 | 
			
		||||
	response, err := client.Do(req)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -104,12 +105,12 @@ func TestForbiddenForceOnNonApply(t *testing.T) {
 | 
			
		|||
		t.Errorf("Unexpected response %#v", response)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	request, err = http.NewRequest("PATCH", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID+"?force=false", bytes.NewReader([]byte(`{"labels":{"foo":"bar"}}`)))
 | 
			
		||||
	req, err = http.NewRequest(request.MethodPatch, server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID+"?force=false", bytes.NewReader([]byte(`{"labels":{"foo":"bar"}}`)))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	request.Header.Set("Content-Type", "application/merge-patch+json; charset=UTF-8")
 | 
			
		||||
	response, err = client.Do(request)
 | 
			
		||||
	req.Header.Set("Content-Type", "application/merge-patch+json; charset=UTF-8")
 | 
			
		||||
	response, err = client.Do(req)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -136,7 +137,7 @@ func TestPatchRequiresMatchingName(t *testing.T) {
 | 
			
		|||
	defer server.Close()
 | 
			
		||||
 | 
			
		||||
	client := http.Client{}
 | 
			
		||||
	request, err := http.NewRequest("PATCH", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader([]byte(`{"metadata":{"name":"idbar"}}`)))
 | 
			
		||||
	request, err := http.NewRequest(request.MethodPatch, server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader([]byte(`{"metadata":{"name":"idbar"}}`)))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,37 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2025 The Kubernetes Authors.
 | 
			
		||||
 | 
			
		||||
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 request
 | 
			
		||||
 | 
			
		||||
import "net/http"
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	MethodApply            string = "APPLY"
 | 
			
		||||
	MethodConnect          string = http.MethodConnect
 | 
			
		||||
	MethodCreate           string = "CREATE"
 | 
			
		||||
	MethodDelete           string = http.MethodDelete
 | 
			
		||||
	MethodDeleteCollection string = "DELETECOLLECTION"
 | 
			
		||||
	MethodGet              string = http.MethodGet
 | 
			
		||||
	MethodHead             string = http.MethodHead
 | 
			
		||||
	MethodList             string = "LIST"
 | 
			
		||||
	MethodPatch            string = http.MethodPatch
 | 
			
		||||
	MethodPost             string = http.MethodPost
 | 
			
		||||
	MethodProxy            string = "PROXY"
 | 
			
		||||
	MethodPut              string = http.MethodPut
 | 
			
		||||
	MethodUpdate           string = "UPDATE"
 | 
			
		||||
	MethodWatch            string = "WATCH"
 | 
			
		||||
	MethodWatchList        string = "WATCHLIST"
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -175,15 +175,15 @@ func (r *RequestInfoFactory) NewRequestInfo(req *http.Request) (*RequestInfo, er
 | 
			
		|||
 | 
			
		||||
	} else {
 | 
			
		||||
		switch req.Method {
 | 
			
		||||
		case "POST":
 | 
			
		||||
		case MethodPost:
 | 
			
		||||
			requestInfo.Verb = "create"
 | 
			
		||||
		case "GET", "HEAD":
 | 
			
		||||
		case MethodGet, MethodHead:
 | 
			
		||||
			requestInfo.Verb = "get"
 | 
			
		||||
		case "PUT":
 | 
			
		||||
		case MethodPut:
 | 
			
		||||
			requestInfo.Verb = "update"
 | 
			
		||||
		case "PATCH":
 | 
			
		||||
		case MethodPatch:
 | 
			
		||||
			requestInfo.Verb = "patch"
 | 
			
		||||
		case "DELETE":
 | 
			
		||||
		case MethodDelete:
 | 
			
		||||
			requestInfo.Verb = "delete"
 | 
			
		||||
		default:
 | 
			
		||||
			requestInfo.Verb = ""
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -47,49 +47,49 @@ func TestGetAPIRequestInfo(t *testing.T) {
 | 
			
		|||
	}{
 | 
			
		||||
 | 
			
		||||
		// resource paths
 | 
			
		||||
		{"GET", "/api/v1/namespaces", "list", "api", "", "v1", "", "namespaces", "", "", []string{"namespaces"}},
 | 
			
		||||
		{"GET", "/api/v1/namespaces/other", "get", "api", "", "v1", "other", "namespaces", "", "other", []string{"namespaces", "other"}},
 | 
			
		||||
		{MethodGet, "/api/v1/namespaces", "list", "api", "", "v1", "", "namespaces", "", "", []string{"namespaces"}},
 | 
			
		||||
		{MethodGet, "/api/v1/namespaces/other", "get", "api", "", "v1", "other", "namespaces", "", "other", []string{"namespaces", "other"}},
 | 
			
		||||
 | 
			
		||||
		{"GET", "/api/v1/namespaces/other/pods", "list", "api", "", "v1", "other", "pods", "", "", []string{"pods"}},
 | 
			
		||||
		{"GET", "/api/v1/namespaces/other/pods/foo", "get", "api", "", "v1", "other", "pods", "", "foo", []string{"pods", "foo"}},
 | 
			
		||||
		{"HEAD", "/api/v1/namespaces/other/pods/foo", "get", "api", "", "v1", "other", "pods", "", "foo", []string{"pods", "foo"}},
 | 
			
		||||
		{"GET", "/api/v1/pods", "list", "api", "", "v1", namespaceAll, "pods", "", "", []string{"pods"}},
 | 
			
		||||
		{"HEAD", "/api/v1/pods", "list", "api", "", "v1", namespaceAll, "pods", "", "", []string{"pods"}},
 | 
			
		||||
		{"GET", "/api/v1/namespaces/other/pods/foo", "get", "api", "", "v1", "other", "pods", "", "foo", []string{"pods", "foo"}},
 | 
			
		||||
		{"GET", "/api/v1/namespaces/other/pods", "list", "api", "", "v1", "other", "pods", "", "", []string{"pods"}},
 | 
			
		||||
		{MethodGet, "/api/v1/namespaces/other/pods", "list", "api", "", "v1", "other", "pods", "", "", []string{"pods"}},
 | 
			
		||||
		{MethodGet, "/api/v1/namespaces/other/pods/foo", "get", "api", "", "v1", "other", "pods", "", "foo", []string{"pods", "foo"}},
 | 
			
		||||
		{MethodHead, "/api/v1/namespaces/other/pods/foo", "get", "api", "", "v1", "other", "pods", "", "foo", []string{"pods", "foo"}},
 | 
			
		||||
		{MethodGet, "/api/v1/pods", "list", "api", "", "v1", namespaceAll, "pods", "", "", []string{"pods"}},
 | 
			
		||||
		{MethodHead, "/api/v1/pods", "list", "api", "", "v1", namespaceAll, "pods", "", "", []string{"pods"}},
 | 
			
		||||
		{MethodGet, "/api/v1/namespaces/other/pods/foo", "get", "api", "", "v1", "other", "pods", "", "foo", []string{"pods", "foo"}},
 | 
			
		||||
		{MethodGet, "/api/v1/namespaces/other/pods", "list", "api", "", "v1", "other", "pods", "", "", []string{"pods"}},
 | 
			
		||||
 | 
			
		||||
		// special verbs
 | 
			
		||||
		{"GET", "/api/v1/proxy/namespaces/other/pods/foo", "proxy", "api", "", "v1", "other", "pods", "", "foo", []string{"pods", "foo"}},
 | 
			
		||||
		{"GET", "/api/v1/proxy/namespaces/other/pods/foo/subpath/not/a/subresource", "proxy", "api", "", "v1", "other", "pods", "", "foo", []string{"pods", "foo", "subpath", "not", "a", "subresource"}},
 | 
			
		||||
		{"GET", "/api/v1/watch/pods", "watch", "api", "", "v1", namespaceAll, "pods", "", "", []string{"pods"}},
 | 
			
		||||
		{"GET", "/api/v1/pods?watch=true", "watch", "api", "", "v1", namespaceAll, "pods", "", "", []string{"pods"}},
 | 
			
		||||
		{"GET", "/api/v1/pods?watch=false", "list", "api", "", "v1", namespaceAll, "pods", "", "", []string{"pods"}},
 | 
			
		||||
		{"GET", "/api/v1/watch/namespaces/other/pods", "watch", "api", "", "v1", "other", "pods", "", "", []string{"pods"}},
 | 
			
		||||
		{"GET", "/api/v1/namespaces/other/pods?watch=1", "watch", "api", "", "v1", "other", "pods", "", "", []string{"pods"}},
 | 
			
		||||
		{"GET", "/api/v1/namespaces/other/pods?watch=0", "list", "api", "", "v1", "other", "pods", "", "", []string{"pods"}},
 | 
			
		||||
		{MethodGet, "/api/v1/proxy/namespaces/other/pods/foo", "proxy", "api", "", "v1", "other", "pods", "", "foo", []string{"pods", "foo"}},
 | 
			
		||||
		{MethodGet, "/api/v1/proxy/namespaces/other/pods/foo/subpath/not/a/subresource", "proxy", "api", "", "v1", "other", "pods", "", "foo", []string{"pods", "foo", "subpath", "not", "a", "subresource"}},
 | 
			
		||||
		{MethodGet, "/api/v1/watch/pods", "watch", "api", "", "v1", namespaceAll, "pods", "", "", []string{"pods"}},
 | 
			
		||||
		{MethodGet, "/api/v1/pods?watch=true", "watch", "api", "", "v1", namespaceAll, "pods", "", "", []string{"pods"}},
 | 
			
		||||
		{MethodGet, "/api/v1/pods?watch=false", "list", "api", "", "v1", namespaceAll, "pods", "", "", []string{"pods"}},
 | 
			
		||||
		{MethodGet, "/api/v1/watch/namespaces/other/pods", "watch", "api", "", "v1", "other", "pods", "", "", []string{"pods"}},
 | 
			
		||||
		{MethodGet, "/api/v1/namespaces/other/pods?watch=1", "watch", "api", "", "v1", "other", "pods", "", "", []string{"pods"}},
 | 
			
		||||
		{MethodGet, "/api/v1/namespaces/other/pods?watch=0", "list", "api", "", "v1", "other", "pods", "", "", []string{"pods"}},
 | 
			
		||||
 | 
			
		||||
		// subresource identification
 | 
			
		||||
		{"GET", "/api/v1/namespaces/other/pods/foo/status", "get", "api", "", "v1", "other", "pods", "status", "foo", []string{"pods", "foo", "status"}},
 | 
			
		||||
		{"GET", "/api/v1/namespaces/other/pods/foo/proxy/subpath", "get", "api", "", "v1", "other", "pods", "proxy", "foo", []string{"pods", "foo", "proxy", "subpath"}},
 | 
			
		||||
		{"PUT", "/api/v1/namespaces/other/finalize", "update", "api", "", "v1", "other", "namespaces", "finalize", "other", []string{"namespaces", "other", "finalize"}},
 | 
			
		||||
		{"PUT", "/api/v1/namespaces/other/status", "update", "api", "", "v1", "other", "namespaces", "status", "other", []string{"namespaces", "other", "status"}},
 | 
			
		||||
		{MethodGet, "/api/v1/namespaces/other/pods/foo/status", "get", "api", "", "v1", "other", "pods", "status", "foo", []string{"pods", "foo", "status"}},
 | 
			
		||||
		{MethodGet, "/api/v1/namespaces/other/pods/foo/proxy/subpath", "get", "api", "", "v1", "other", "pods", "proxy", "foo", []string{"pods", "foo", "proxy", "subpath"}},
 | 
			
		||||
		{MethodPut, "/api/v1/namespaces/other/finalize", "update", "api", "", "v1", "other", "namespaces", "finalize", "other", []string{"namespaces", "other", "finalize"}},
 | 
			
		||||
		{MethodPut, "/api/v1/namespaces/other/status", "update", "api", "", "v1", "other", "namespaces", "status", "other", []string{"namespaces", "other", "status"}},
 | 
			
		||||
 | 
			
		||||
		// verb identification
 | 
			
		||||
		{"PATCH", "/api/v1/namespaces/other/pods/foo", "patch", "api", "", "v1", "other", "pods", "", "foo", []string{"pods", "foo"}},
 | 
			
		||||
		{"DELETE", "/api/v1/namespaces/other/pods/foo", "delete", "api", "", "v1", "other", "pods", "", "foo", []string{"pods", "foo"}},
 | 
			
		||||
		{"POST", "/api/v1/namespaces/other/pods", "create", "api", "", "v1", "other", "pods", "", "", []string{"pods"}},
 | 
			
		||||
		{MethodPatch, "/api/v1/namespaces/other/pods/foo", "patch", "api", "", "v1", "other", "pods", "", "foo", []string{"pods", "foo"}},
 | 
			
		||||
		{MethodDelete, "/api/v1/namespaces/other/pods/foo", "delete", "api", "", "v1", "other", "pods", "", "foo", []string{"pods", "foo"}},
 | 
			
		||||
		{MethodPost, "/api/v1/namespaces/other/pods", "create", "api", "", "v1", "other", "pods", "", "", []string{"pods"}},
 | 
			
		||||
 | 
			
		||||
		// deletecollection verb identification
 | 
			
		||||
		{"DELETE", "/api/v1/nodes", "deletecollection", "api", "", "v1", "", "nodes", "", "", []string{"nodes"}},
 | 
			
		||||
		{"DELETE", "/api/v1/namespaces", "deletecollection", "api", "", "v1", "", "namespaces", "", "", []string{"namespaces"}},
 | 
			
		||||
		{"DELETE", "/api/v1/namespaces/other/pods", "deletecollection", "api", "", "v1", "other", "pods", "", "", []string{"pods"}},
 | 
			
		||||
		{"DELETE", "/apis/extensions/v1/namespaces/other/pods", "deletecollection", "api", "extensions", "v1", "other", "pods", "", "", []string{"pods"}},
 | 
			
		||||
		{MethodDelete, "/api/v1/nodes", "deletecollection", "api", "", "v1", "", "nodes", "", "", []string{"nodes"}},
 | 
			
		||||
		{MethodDelete, "/api/v1/namespaces", "deletecollection", "api", "", "v1", "", "namespaces", "", "", []string{"namespaces"}},
 | 
			
		||||
		{MethodDelete, "/api/v1/namespaces/other/pods", "deletecollection", "api", "", "v1", "other", "pods", "", "", []string{"pods"}},
 | 
			
		||||
		{MethodDelete, "/apis/extensions/v1/namespaces/other/pods", "deletecollection", "api", "extensions", "v1", "other", "pods", "", "", []string{"pods"}},
 | 
			
		||||
 | 
			
		||||
		// api group identification
 | 
			
		||||
		{"POST", "/apis/extensions/v1/namespaces/other/pods", "create", "api", "extensions", "v1", "other", "pods", "", "", []string{"pods"}},
 | 
			
		||||
		{MethodPost, "/apis/extensions/v1/namespaces/other/pods", "create", "api", "extensions", "v1", "other", "pods", "", "", []string{"pods"}},
 | 
			
		||||
 | 
			
		||||
		// api version identification
 | 
			
		||||
		{"POST", "/apis/extensions/v1beta3/namespaces/other/pods", "create", "api", "extensions", "v1beta3", "other", "pods", "", "", []string{"pods"}},
 | 
			
		||||
		{MethodPost, "/apis/extensions/v1beta3/namespaces/other/pods", "create", "api", "extensions", "v1beta3", "other", "pods", "", "", []string{"pods"}},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	resolver := newTestRequestInfoResolver()
 | 
			
		||||
| 
						 | 
				
			
			@ -136,7 +136,7 @@ func TestGetAPIRequestInfo(t *testing.T) {
 | 
			
		|||
		"missing api group":           "/apis/version/resource",
 | 
			
		||||
	}
 | 
			
		||||
	for k, v := range errorCases {
 | 
			
		||||
		req, err := http.NewRequest("GET", v, nil)
 | 
			
		||||
		req, err := http.NewRequest(MethodGet, v, nil)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Errorf("Unexpected error %v", err)
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -174,7 +174,7 @@ func TestGetNonAPIRequestInfo(t *testing.T) {
 | 
			
		|||
	resolver := newTestRequestInfoResolver()
 | 
			
		||||
 | 
			
		||||
	for testName, tc := range tests {
 | 
			
		||||
		req, _ := http.NewRequest("GET", tc.url, nil)
 | 
			
		||||
		req, _ := http.NewRequest(MethodGet, tc.url, nil)
 | 
			
		||||
 | 
			
		||||
		apiRequestInfo, err := resolver.NewRequestInfo(req)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -206,14 +206,14 @@ func TestSelectorParsing(t *testing.T) {
 | 
			
		|||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name:                  "no selector",
 | 
			
		||||
			method:                "GET",
 | 
			
		||||
			method:                MethodGet,
 | 
			
		||||
			url:                   "/apis/group/version/resource",
 | 
			
		||||
			expectedVerb:          "list",
 | 
			
		||||
			expectedFieldSelector: "",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:                  "metadata.name selector",
 | 
			
		||||
			method:                "GET",
 | 
			
		||||
			method:                MethodGet,
 | 
			
		||||
			url:                   "/apis/group/version/resource?fieldSelector=metadata.name=name1",
 | 
			
		||||
			expectedName:          "name1",
 | 
			
		||||
			expectedVerb:          "list",
 | 
			
		||||
| 
						 | 
				
			
			@ -221,7 +221,7 @@ func TestSelectorParsing(t *testing.T) {
 | 
			
		|||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:                  "metadata.name selector with watch",
 | 
			
		||||
			method:                "GET",
 | 
			
		||||
			method:                MethodGet,
 | 
			
		||||
			url:                   "/apis/group/version/resource?watch=true&fieldSelector=metadata.name=name1",
 | 
			
		||||
			expectedName:          "name1",
 | 
			
		||||
			expectedVerb:          "watch",
 | 
			
		||||
| 
						 | 
				
			
			@ -229,7 +229,7 @@ func TestSelectorParsing(t *testing.T) {
 | 
			
		|||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:                  "random selector",
 | 
			
		||||
			method:                "GET",
 | 
			
		||||
			method:                MethodGet,
 | 
			
		||||
			url:                   "/apis/group/version/resource?fieldSelector=foo=bar&labelSelector=baz=qux",
 | 
			
		||||
			expectedName:          "",
 | 
			
		||||
			expectedVerb:          "list",
 | 
			
		||||
| 
						 | 
				
			
			@ -238,7 +238,7 @@ func TestSelectorParsing(t *testing.T) {
 | 
			
		|||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:                  "invalid selector with metadata.name",
 | 
			
		||||
			method:                "GET",
 | 
			
		||||
			method:                MethodGet,
 | 
			
		||||
			url:                   "/apis/group/version/resource?fieldSelector=metadata.name=name1,foo",
 | 
			
		||||
			expectedName:          "",
 | 
			
		||||
			expectedErr:           fmt.Errorf("invalid selector"),
 | 
			
		||||
| 
						 | 
				
			
			@ -247,7 +247,7 @@ func TestSelectorParsing(t *testing.T) {
 | 
			
		|||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:                  "invalid selector with metadata.name with watch",
 | 
			
		||||
			method:                "GET",
 | 
			
		||||
			method:                MethodGet,
 | 
			
		||||
			url:                   "/apis/group/version/resource?fieldSelector=metadata.name=name1,foo&watch=true",
 | 
			
		||||
			expectedName:          "",
 | 
			
		||||
			expectedErr:           fmt.Errorf("invalid selector"),
 | 
			
		||||
| 
						 | 
				
			
			@ -256,7 +256,7 @@ func TestSelectorParsing(t *testing.T) {
 | 
			
		|||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:                  "invalid selector with metadata.name with watch false",
 | 
			
		||||
			method:                "GET",
 | 
			
		||||
			method:                MethodGet,
 | 
			
		||||
			url:                   "/apis/group/version/resource?fieldSelector=metadata.name=name1,foo&watch=false",
 | 
			
		||||
			expectedName:          "",
 | 
			
		||||
			expectedErr:           fmt.Errorf("invalid selector"),
 | 
			
		||||
| 
						 | 
				
			
			@ -265,7 +265,7 @@ func TestSelectorParsing(t *testing.T) {
 | 
			
		|||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:                  "selector on deletecollection is honored",
 | 
			
		||||
			method:                "DELETE",
 | 
			
		||||
			method:                MethodDelete,
 | 
			
		||||
			url:                   "/apis/group/version/resource?fieldSelector=foo=bar&labelSelector=baz=qux",
 | 
			
		||||
			expectedName:          "",
 | 
			
		||||
			expectedVerb:          "deletecollection",
 | 
			
		||||
| 
						 | 
				
			
			@ -274,7 +274,7 @@ func TestSelectorParsing(t *testing.T) {
 | 
			
		|||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:                  "selector on repeated param matches parsed param",
 | 
			
		||||
			method:                "GET",
 | 
			
		||||
			method:                MethodGet,
 | 
			
		||||
			url:                   "/apis/group/version/resource?fieldSelector=metadata.name=foo&fieldSelector=metadata.name=bar&labelSelector=foo=bar&labelSelector=foo=baz",
 | 
			
		||||
			expectedName:          "foo",
 | 
			
		||||
			expectedVerb:          "list",
 | 
			
		||||
| 
						 | 
				
			
			@ -283,7 +283,7 @@ func TestSelectorParsing(t *testing.T) {
 | 
			
		|||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:                  "selector on other verb is ignored",
 | 
			
		||||
			method:                "GET",
 | 
			
		||||
			method:                MethodGet,
 | 
			
		||||
			url:                   "/apis/group/version/resource/name?fieldSelector=foo=bar&labelSelector=foo=bar",
 | 
			
		||||
			expectedName:          "name",
 | 
			
		||||
			expectedVerb:          "get",
 | 
			
		||||
| 
						 | 
				
			
			@ -292,7 +292,7 @@ func TestSelectorParsing(t *testing.T) {
 | 
			
		|||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:                  "selector on deprecated root type watch is not parsed",
 | 
			
		||||
			method:                "GET",
 | 
			
		||||
			method:                MethodGet,
 | 
			
		||||
			url:                   "/apis/group/version/watch/resource?fieldSelector=metadata.name=foo&labelSelector=foo=bar",
 | 
			
		||||
			expectedName:          "",
 | 
			
		||||
			expectedVerb:          "watch",
 | 
			
		||||
| 
						 | 
				
			
			@ -301,7 +301,7 @@ func TestSelectorParsing(t *testing.T) {
 | 
			
		|||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:                  "selector on deprecated root item watch is not parsed",
 | 
			
		||||
			method:                "GET",
 | 
			
		||||
			method:                MethodGet,
 | 
			
		||||
			url:                   "/apis/group/version/watch/resource/name?fieldSelector=metadata.name=foo&labelSelector=foo=bar",
 | 
			
		||||
			expectedName:          "name",
 | 
			
		||||
			expectedVerb:          "watch",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,6 +24,8 @@ import (
 | 
			
		|||
	"net/url"
 | 
			
		||||
	"testing"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"k8s.io/apiserver/pkg/endpoints/request"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestWithHTTP1(t *testing.T) {
 | 
			
		||||
| 
						 | 
				
			
			@ -222,7 +224,7 @@ func newServer(t *testing.T, h http.Handler, http2 bool) *httptest.Server {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func sendRequest(t *testing.T, server *httptest.Server) {
 | 
			
		||||
	req, err := http.NewRequest("GET", server.URL, nil)
 | 
			
		||||
	req, err := http.NewRequest(request.MethodGet, server.URL, nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("error creating request: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -41,6 +41,7 @@ import (
 | 
			
		|||
	"k8s.io/apimachinery/pkg/runtime/serializer/streaming"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/watch"
 | 
			
		||||
	example "k8s.io/apiserver/pkg/apis/example"
 | 
			
		||||
	"k8s.io/apiserver/pkg/endpoints/request"
 | 
			
		||||
	apitesting "k8s.io/apiserver/pkg/endpoints/testing"
 | 
			
		||||
	"k8s.io/apiserver/pkg/registry/rest"
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -219,7 +220,7 @@ func TestWatchClientClose(t *testing.T) {
 | 
			
		|||
	dest.Path = "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simples"
 | 
			
		||||
	dest.RawQuery = "watch=1"
 | 
			
		||||
 | 
			
		||||
	request, err := http.NewRequest("GET", dest.String(), nil)
 | 
			
		||||
	request, err := http.NewRequest(request.MethodGet, dest.String(), nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -263,7 +264,7 @@ func TestWatchRead(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
	connectHTTP := func(accept string) (io.ReadCloser, string) {
 | 
			
		||||
		client := http.Client{}
 | 
			
		||||
		request, err := http.NewRequest("GET", dest.String(), nil)
 | 
			
		||||
		request, err := http.NewRequest(request.MethodGet, dest.String(), nil)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -415,7 +416,7 @@ func TestWatchHTTPAccept(t *testing.T) {
 | 
			
		|||
	dest.Path = "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/watch/simples"
 | 
			
		||||
	dest.RawQuery = ""
 | 
			
		||||
 | 
			
		||||
	request, err := http.NewRequest("GET", dest.String(), nil)
 | 
			
		||||
	request, err := http.NewRequest(request.MethodGet, dest.String(), nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -565,7 +566,7 @@ func TestWatchProtocolSelection(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	for _, item := range table {
 | 
			
		||||
		request, err := http.NewRequest("GET", dest.String(), nil)
 | 
			
		||||
		request, err := http.NewRequest(request.MethodGet, dest.String(), nil)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Errorf("unexpected error: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -637,13 +638,13 @@ func runWatchHTTPBenchmark(b *testing.B, items []runtime.Object, contentType str
 | 
			
		|||
	dest.Path = "/" + prefix + "/" + newGroupVersion.Group + "/" + newGroupVersion.Version + "/watch/simples"
 | 
			
		||||
	dest.RawQuery = ""
 | 
			
		||||
 | 
			
		||||
	request, err := http.NewRequest("GET", dest.String(), nil)
 | 
			
		||||
	req, err := http.NewRequest(request.MethodGet, dest.String(), nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		b.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	request.Header.Add("Accept", contentType)
 | 
			
		||||
	req.Header.Add("Accept", contentType)
 | 
			
		||||
 | 
			
		||||
	response, err := client.Do(request)
 | 
			
		||||
	response, err := client.Do(req)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		b.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue