2014-06-06 23:40:48 +00:00
/ *
2016-06-03 00:25:58 +00:00
Copyright 2014 The Kubernetes Authors .
2014-06-06 23:40:48 +00:00
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 .
* /
2014-06-23 18:32:11 +00:00
2014-06-06 23:40:48 +00:00
package apiserver
import (
"bytes"
2014-07-31 18:16:13 +00:00
"encoding/json"
"errors"
2014-06-06 23:40:48 +00:00
"fmt"
2015-03-22 03:25:38 +00:00
"io"
2014-06-06 23:40:48 +00:00
"io/ioutil"
"net/http"
"net/http/httptest"
2015-03-23 18:42:39 +00:00
"net/url"
2014-06-06 23:40:48 +00:00
"reflect"
2014-07-31 18:26:34 +00:00
"strings"
2014-06-19 04:04:11 +00:00
"sync"
2014-06-06 23:40:48 +00:00
"testing"
2014-06-25 20:21:32 +00:00
"time"
2014-06-17 01:03:44 +00:00
2015-08-05 22:03:47 +00:00
"k8s.io/kubernetes/pkg/admission"
"k8s.io/kubernetes/pkg/api"
apierrs "k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/api/rest"
2015-09-09 21:59:11 +00:00
"k8s.io/kubernetes/pkg/api/unversioned"
2016-01-13 02:10:38 +00:00
"k8s.io/kubernetes/pkg/api/v1"
2015-10-09 09:07:58 +00:00
apiservertesting "k8s.io/kubernetes/pkg/apiserver/testing"
2015-08-05 22:03:47 +00:00
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util"
2016-03-11 02:43:55 +00:00
"k8s.io/kubernetes/pkg/util/diff"
2015-09-25 18:57:10 +00:00
"k8s.io/kubernetes/pkg/util/sets"
2015-08-05 22:03:47 +00:00
"k8s.io/kubernetes/pkg/version"
"k8s.io/kubernetes/pkg/watch"
2016-04-05 03:07:43 +00:00
"k8s.io/kubernetes/pkg/watch/versioned"
2015-08-05 22:03:47 +00:00
"k8s.io/kubernetes/plugin/pkg/admission/admit"
"k8s.io/kubernetes/plugin/pkg/admission/deny"
2015-03-04 20:57:05 +00:00
"github.com/emicklei/go-restful"
2014-06-06 23:40:48 +00:00
)
2014-09-08 04:14:18 +00:00
func convert ( obj runtime . Object ) ( runtime . Object , error ) {
2014-07-16 21:30:28 +00:00
return obj , nil
}
2015-05-22 15:20:27 +00:00
// This creates fake API versions, similar to api/latest.go.
2015-11-12 20:20:20 +00:00
var testAPIGroup = "test.group"
2016-02-24 19:10:37 +00:00
var testAPIGroup2 = "test.group2"
2015-12-21 05:15:35 +00:00
var testInternalGroupVersion = unversioned . GroupVersion { Group : testAPIGroup , Version : runtime . APIVersionInternal }
2015-11-12 20:20:20 +00:00
var testGroupVersion = unversioned . GroupVersion { Group : testAPIGroup , Version : "version" }
var newGroupVersion = unversioned . GroupVersion { Group : testAPIGroup , Version : "version2" }
2016-02-24 19:10:37 +00:00
var testGroup2Version = unversioned . GroupVersion { Group : testAPIGroup2 , Version : "version" }
var testInternalGroup2Version = unversioned . GroupVersion { Group : testAPIGroup2 , Version : runtime . APIVersionInternal }
2015-11-12 20:20:20 +00:00
var prefix = "apis"
2014-11-11 07:11:45 +00:00
2015-11-13 16:16:26 +00:00
var grouplessGroupVersion = unversioned . GroupVersion { Group : "" , Version : "v1" }
2015-12-21 05:15:35 +00:00
var grouplessInternalGroupVersion = unversioned . GroupVersion { Group : "" , Version : runtime . APIVersionInternal }
2015-11-13 16:16:26 +00:00
var grouplessPrefix = "api"
2015-11-13 13:13:55 +00:00
var groupVersions = [ ] unversioned . GroupVersion { grouplessGroupVersion , testGroupVersion , newGroupVersion }
2015-12-21 05:15:35 +00:00
2015-12-21 05:21:26 +00:00
var codec = api . Codecs . LegacyCodec ( groupVersions ... )
var grouplessCodec = api . Codecs . LegacyCodec ( grouplessGroupVersion )
var testCodec = api . Codecs . LegacyCodec ( testGroupVersion )
var newCodec = api . Codecs . LegacyCodec ( newGroupVersion )
2015-03-25 20:21:40 +00:00
2014-11-11 07:11:45 +00:00
var accessor = meta . NewAccessor ( )
var versioner runtime . ResourceVersioner = accessor
var selfLinker runtime . SelfLinker = accessor
2015-06-10 20:17:04 +00:00
var mapper , namespaceMapper meta . RESTMapper // The mappers with namespace and with legacy namespace scopes.
2015-01-07 19:33:21 +00:00
var admissionControl admission . Interface
2015-02-11 22:09:25 +00:00
var requestContextMapper api . RequestContextMapper
2014-11-11 07:11:45 +00:00
2015-12-08 18:27:26 +00:00
func interfacesFor ( version unversioned . GroupVersion ) ( * meta . VersionInterfaces , error ) {
switch version {
2015-11-13 13:13:55 +00:00
case testGroupVersion :
2015-03-25 20:21:40 +00:00
return & meta . VersionInterfaces {
ObjectConvertor : api . Scheme ,
MetadataAccessor : accessor ,
} , nil
2015-11-13 13:13:55 +00:00
case newGroupVersion :
2014-11-11 07:11:45 +00:00
return & meta . VersionInterfaces {
ObjectConvertor : api . Scheme ,
MetadataAccessor : accessor ,
} , nil
2015-11-13 13:13:55 +00:00
case grouplessGroupVersion :
2015-11-13 16:16:26 +00:00
return & meta . VersionInterfaces {
ObjectConvertor : api . Scheme ,
MetadataAccessor : accessor ,
} , nil
2016-02-24 19:10:37 +00:00
case testGroup2Version :
return & meta . VersionInterfaces {
ObjectConvertor : api . Scheme ,
MetadataAccessor : accessor ,
} , nil
2014-11-11 07:11:45 +00:00
default :
2015-11-13 13:13:55 +00:00
return nil , fmt . Errorf ( "unsupported storage version: %s (valid: %v)" , version , groupVersions )
2014-11-11 07:11:45 +00:00
}
}
2014-08-06 03:10:48 +00:00
2015-01-31 00:08:59 +00:00
func newMapper ( ) * meta . DefaultRESTMapper {
2015-11-16 15:53:05 +00:00
return meta . NewDefaultRESTMapper ( [ ] unversioned . GroupVersion { testGroupVersion , newGroupVersion } , interfacesFor )
2015-01-31 00:08:59 +00:00
}
2015-11-13 16:16:26 +00:00
func addGrouplessTypes ( ) {
2015-12-16 13:02:09 +00:00
type ListOptions struct {
2016-05-26 18:17:14 +00:00
Object runtime . Object
2015-12-16 13:02:09 +00:00
unversioned . TypeMeta ` json:",inline" `
LabelSelector string ` json:"labelSelector,omitempty" `
FieldSelector string ` json:"fieldSelector,omitempty" `
Watch bool ` json:"watch,omitempty" `
ResourceVersion string ` json:"resourceVersion,omitempty" `
TimeoutSeconds * int64 ` json:"timeoutSeconds,omitempty" `
}
2015-12-21 05:15:35 +00:00
api . Scheme . AddKnownTypes ( grouplessGroupVersion ,
& apiservertesting . Simple { } , & apiservertesting . SimpleList { } , & ListOptions { } ,
& api . DeleteOptions { } , & apiservertesting . SimpleGetOptions { } , & apiservertesting . SimpleRoot { } )
api . Scheme . AddKnownTypes ( grouplessInternalGroupVersion ,
& apiservertesting . Simple { } , & apiservertesting . SimpleList { } , & api . ListOptions { } ,
& apiservertesting . SimpleGetOptions { } , & apiservertesting . SimpleRoot { } )
2015-11-13 16:16:26 +00:00
}
2015-05-22 15:20:27 +00:00
func addTestTypes ( ) {
2015-12-16 13:02:09 +00:00
type ListOptions struct {
2016-05-26 18:17:14 +00:00
Object runtime . Object
2015-12-16 13:02:09 +00:00
unversioned . TypeMeta ` json:",inline" `
LabelSelector string ` json:"labelSelector,omitempty" `
FieldSelector string ` json:"fieldSelector,omitempty" `
Watch bool ` json:"watch,omitempty" `
ResourceVersion string ` json:"resourceVersion,omitempty" `
TimeoutSeconds * int64 ` json:"timeoutSeconds,omitempty" `
}
2015-12-21 05:15:35 +00:00
api . Scheme . AddKnownTypes ( testGroupVersion ,
& apiservertesting . Simple { } , & apiservertesting . SimpleList { } , & ListOptions { } ,
2016-02-24 19:10:37 +00:00
& api . DeleteOptions { } , & apiservertesting . SimpleGetOptions { } , & apiservertesting . SimpleRoot { } ,
& SimpleXGSubresource { } )
2016-04-20 17:35:09 +00:00
api . Scheme . AddKnownTypes ( testGroupVersion , & v1 . Pod { } )
2015-12-21 05:15:35 +00:00
api . Scheme . AddKnownTypes ( testInternalGroupVersion ,
& apiservertesting . Simple { } , & apiservertesting . SimpleList { } , & api . ListOptions { } ,
2016-02-24 19:10:37 +00:00
& apiservertesting . SimpleGetOptions { } , & apiservertesting . SimpleRoot { } ,
& SimpleXGSubresource { } )
2016-04-20 17:35:09 +00:00
api . Scheme . AddKnownTypes ( testInternalGroupVersion , & api . Pod { } )
2016-02-24 19:10:37 +00:00
// Register SimpleXGSubresource in both testGroupVersion and testGroup2Version, and also their
// their corresponding internal versions, to verify that the desired group version object is
// served in the tests.
api . Scheme . AddKnownTypes ( testGroup2Version , & SimpleXGSubresource { } )
api . Scheme . AddKnownTypes ( testInternalGroup2Version , & SimpleXGSubresource { } )
2016-04-05 03:07:43 +00:00
versioned . AddToGroupVersion ( api . Scheme , testGroupVersion )
2015-05-22 15:20:27 +00:00
}
func addNewTestTypes ( ) {
2015-12-16 13:02:09 +00:00
type ListOptions struct {
2016-05-26 18:17:14 +00:00
Object runtime . Object
2015-12-16 13:02:09 +00:00
unversioned . TypeMeta ` json:",inline" `
LabelSelector string ` json:"labelSelector,omitempty" `
FieldSelector string ` json:"fieldSelector,omitempty" `
Watch bool ` json:"watch,omitempty" `
ResourceVersion string ` json:"resourceVersion,omitempty" `
TimeoutSeconds * int64 ` json:"timeoutSeconds,omitempty" `
}
2015-12-21 05:15:35 +00:00
api . Scheme . AddKnownTypes ( newGroupVersion ,
& apiservertesting . Simple { } , & apiservertesting . SimpleList { } , & ListOptions { } ,
2016-04-05 03:07:43 +00:00
& api . DeleteOptions { } , & apiservertesting . SimpleGetOptions { } , & apiservertesting . SimpleRoot { } ,
& v1 . Pod { } ,
)
versioned . AddToGroupVersion ( api . Scheme , newGroupVersion )
2015-05-22 15:20:27 +00:00
}
2014-06-20 23:18:36 +00:00
func init ( ) {
2014-11-11 07:11:45 +00:00
// Certain API objects are returned regardless of the contents of storage:
// api.Status is returned in errors
2015-11-13 16:16:26 +00:00
addGrouplessTypes ( )
2015-05-22 15:20:27 +00:00
addTestTypes ( )
addNewTestTypes ( )
2014-11-11 07:11:45 +00:00
2015-01-31 00:08:59 +00:00
nsMapper := newMapper ( )
2015-05-22 15:20:27 +00:00
// enumerate all supported versions, get the kinds, and register with
// the mapper how to address our resources
2015-11-13 13:13:55 +00:00
for _ , gv := range groupVersions {
2015-11-18 15:34:16 +00:00
for kind := range api . Scheme . KnownTypes ( gv ) {
2015-11-16 15:53:05 +00:00
gvk := gv . WithKind ( kind )
2015-09-15 08:59:07 +00:00
root := bool ( kind == "SimpleRoot" )
2015-05-08 04:31:53 +00:00
if root {
2016-02-08 16:19:16 +00:00
nsMapper . Add ( gvk , meta . RESTScopeRoot )
2015-05-08 04:31:53 +00:00
} else {
2016-02-08 16:19:16 +00:00
nsMapper . Add ( gvk , meta . RESTScopeNamespace )
2015-05-08 04:31:53 +00:00
}
2015-01-29 22:46:54 +00:00
}
}
2015-06-10 20:17:04 +00:00
mapper = nsMapper
2015-01-31 00:08:59 +00:00
namespaceMapper = nsMapper
2015-01-07 19:33:21 +00:00
admissionControl = admit . NewAlwaysAdmit ( )
2015-02-11 22:09:25 +00:00
requestContextMapper = api . NewRequestContextMapper ( )
2015-03-25 20:21:40 +00:00
2015-11-13 13:13:55 +00:00
api . Scheme . AddFieldLabelConversionFunc ( grouplessGroupVersion . String ( ) , "Simple" ,
2015-11-13 16:16:26 +00:00
func ( label , value string ) ( string , string , error ) {
return label , value , nil
} ,
)
2015-11-13 13:13:55 +00:00
api . Scheme . AddFieldLabelConversionFunc ( testGroupVersion . String ( ) , "Simple" ,
2015-03-25 20:21:40 +00:00
func ( label , value string ) ( string , string , error ) {
return label , value , nil
} ,
)
2015-11-13 13:13:55 +00:00
api . Scheme . AddFieldLabelConversionFunc ( newGroupVersion . String ( ) , "Simple" ,
2015-03-25 20:21:40 +00:00
func ( label , value string ) ( string , string , error ) {
return label , value , nil
} ,
)
2014-06-20 23:18:36 +00:00
}
2015-03-04 20:57:05 +00:00
// defaultAPIServer exposes nested objects for testability.
type defaultAPIServer struct {
http . Handler
2015-03-22 03:25:38 +00:00
container * restful . Container
2015-03-04 20:57:05 +00:00
}
// uses the default settings
2015-03-21 16:24:16 +00:00
func handle ( storage map [ string ] rest . Storage ) http . Handler {
2015-11-13 16:16:26 +00:00
return handleInternal ( storage , admissionControl , selfLinker )
2015-03-04 20:57:05 +00:00
}
// tests with a deny admission controller
2015-03-21 16:24:16 +00:00
func handleDeny ( storage map [ string ] rest . Storage ) http . Handler {
2015-11-13 16:16:26 +00:00
return handleInternal ( storage , deny . NewAlwaysDeny ( ) , selfLinker )
2015-03-04 20:57:05 +00:00
}
// tests using the new namespace scope mechanism
2015-03-21 16:24:16 +00:00
func handleNamespaced ( storage map [ string ] rest . Storage ) http . Handler {
2015-11-13 16:16:26 +00:00
return handleInternal ( storage , admissionControl , selfLinker )
2015-03-04 20:57:05 +00:00
}
// tests using a custom self linker
2015-03-21 16:24:16 +00:00
func handleLinker ( storage map [ string ] rest . Storage , selfLinker runtime . SelfLinker ) http . Handler {
2015-11-13 16:16:26 +00:00
return handleInternal ( storage , admissionControl , selfLinker )
2015-03-04 20:57:05 +00:00
}
2015-10-20 17:34:26 +00:00
func newTestRequestInfoResolver ( ) * RequestInfoResolver {
return & RequestInfoResolver { sets . NewString ( "api" , "apis" ) , sets . NewString ( "api" ) }
2015-09-25 18:57:10 +00:00
}
2015-11-13 16:16:26 +00:00
func handleInternal ( storage map [ string ] rest . Storage , admissionControl admission . Interface , selfLinker runtime . SelfLinker ) http . Handler {
container := restful . NewContainer ( )
container . Router ( restful . CurlyRouter { } )
mux := container . ServeMux
template := APIGroupVersion {
2015-03-04 20:57:05 +00:00
Storage : storage ,
2015-10-20 17:34:26 +00:00
RequestInfoResolver : newTestRequestInfoResolver ( ) ,
2015-03-04 20:57:05 +00:00
2015-03-22 21:43:00 +00:00
Creater : api . Scheme ,
Convertor : api . Scheme ,
2016-04-29 01:21:35 +00:00
Copier : api . Scheme ,
2015-03-22 21:43:00 +00:00
Typer : api . Scheme ,
Linker : selfLinker ,
2015-11-13 16:16:26 +00:00
Mapper : namespaceMapper ,
2015-03-04 20:57:05 +00:00
2015-12-21 05:15:35 +00:00
ParameterCodec : api . ParameterCodec ,
2015-03-04 20:57:05 +00:00
Admit : admissionControl ,
Context : requestContextMapper ,
}
2015-11-13 16:16:26 +00:00
// groupless v1 version
{
group := template
group . Root = "/" + grouplessPrefix
group . GroupVersion = grouplessGroupVersion
2015-12-08 19:40:23 +00:00
group . OptionsExternalVersion = & grouplessGroupVersion
2015-12-21 05:21:26 +00:00
group . Serializer = api . Codecs
2015-11-13 16:16:26 +00:00
if err := ( & group ) . InstallREST ( container ) ; err != nil {
panic ( fmt . Sprintf ( "unable to install container %s: %v" , group . GroupVersion , err ) )
}
}
// group version 1
{
group := template
group . Root = "/" + prefix
2015-11-12 20:20:20 +00:00
group . GroupVersion = testGroupVersion
2015-12-08 19:40:23 +00:00
group . OptionsExternalVersion = & testGroupVersion
2015-12-21 05:21:26 +00:00
group . Serializer = api . Codecs
2015-11-13 16:16:26 +00:00
if err := ( & group ) . InstallREST ( container ) ; err != nil {
panic ( fmt . Sprintf ( "unable to install container %s: %v" , group . GroupVersion , err ) )
}
}
// group version 2
{
group := template
group . Root = "/" + prefix
2015-11-12 20:20:20 +00:00
group . GroupVersion = newGroupVersion
2015-12-08 19:40:23 +00:00
group . OptionsExternalVersion = & newGroupVersion
2015-12-21 05:21:26 +00:00
group . Serializer = api . Codecs
2015-11-13 16:16:26 +00:00
if err := ( & group ) . InstallREST ( container ) ; err != nil {
panic ( fmt . Sprintf ( "unable to install container %s: %v" , group . GroupVersion , err ) )
}
2015-03-25 20:21:40 +00:00
}
2016-04-27 01:51:37 +00:00
InstallVersionHandler ( mux , container )
2015-11-13 16:16:26 +00:00
return & defaultAPIServer { mux , container }
2015-03-04 20:57:05 +00:00
}
2014-11-06 01:22:18 +00:00
func TestSimpleSetupRight ( t * testing . T ) {
2015-10-09 09:07:58 +00:00
s := & apiservertesting . Simple { ObjectMeta : api . ObjectMeta { Name : "aName" } }
2015-12-10 02:15:02 +00:00
wire , err := runtime . Encode ( codec , s )
2014-11-06 01:22:18 +00:00
if err != nil {
t . Fatal ( err )
}
2015-12-10 02:15:02 +00:00
s2 , err := runtime . Decode ( codec , wire )
2014-11-06 01:22:18 +00:00
if err != nil {
t . Fatal ( err )
}
if ! reflect . DeepEqual ( s , s2 ) {
t . Fatalf ( "encode/decode broken:\n%#v\n%#v\n" , s , s2 )
}
}
2015-04-06 16:58:00 +00:00
func TestSimpleOptionsSetupRight ( t * testing . T ) {
2015-10-09 09:07:58 +00:00
s := & apiservertesting . SimpleGetOptions { }
2015-12-10 02:15:02 +00:00
wire , err := runtime . Encode ( codec , s )
2015-04-06 16:58:00 +00:00
if err != nil {
t . Fatal ( err )
}
2015-12-10 02:15:02 +00:00
s2 , err := runtime . Decode ( codec , wire )
2015-04-06 16:58:00 +00:00
if err != nil {
t . Fatal ( err )
}
if ! reflect . DeepEqual ( s , s2 ) {
t . Fatalf ( "encode/decode broken:\n%#v\n%#v\n" , s , s2 )
}
}
2014-06-06 23:40:48 +00:00
type SimpleRESTStorage struct {
2016-04-20 17:35:09 +00:00
lock sync . Mutex
2015-03-05 03:34:31 +00:00
errors map [ string ] error
2015-10-09 09:07:58 +00:00
list [ ] apiservertesting . Simple
item apiservertesting . Simple
2015-03-05 03:34:31 +00:00
2015-10-09 09:07:58 +00:00
updated * apiservertesting . Simple
created * apiservertesting . Simple
2014-06-25 20:21:32 +00:00
2015-03-22 03:25:38 +00:00
stream * SimpleStream
2015-03-05 03:34:31 +00:00
deleted string
deleteOptions * api . DeleteOptions
2015-02-12 19:21:47 +00:00
actualNamespace string
namespacePresent bool
2014-08-06 21:55:37 +00:00
// These are set when Watch is called
2014-10-30 16:55:17 +00:00
fakeWatch * watch . FakeWatcher
requestedLabelSelector labels . Selector
2015-03-06 23:29:03 +00:00
requestedFieldSelector fields . Selector
2014-10-30 16:55:17 +00:00
requestedResourceVersion string
requestedResourceNamespace string
2014-08-05 20:33:25 +00:00
2014-08-27 23:10:44 +00:00
// The id requested, and location to return for ResourceLocation
2014-08-25 21:36:15 +00:00
requestedResourceLocationID string
2015-03-23 18:42:39 +00:00
resourceLocation * url . URL
2015-10-01 01:13:34 +00:00
resourceLocationTransport http . RoundTripper
2014-10-20 20:25:08 +00:00
expectedResourceNamespace string
2014-08-25 21:36:15 +00:00
2014-06-26 17:51:29 +00:00
// If non-nil, called inside the WorkFunc when answering update, delete, create.
2014-07-28 13:15:50 +00:00
// obj receives the original input to the update, delete, or create call.
2014-09-08 04:14:18 +00:00
injectedFunction func ( obj runtime . Object ) ( returnObj runtime . Object , err error )
2014-06-06 23:40:48 +00:00
}
2015-12-01 23:45:29 +00:00
func ( storage * SimpleRESTStorage ) Export ( ctx api . Context , name string , opts unversioned . ExportOptions ) ( runtime . Object , error ) {
obj , err := storage . Get ( ctx , name )
if err != nil {
return nil , err
}
s , ok := obj . ( * apiservertesting . Simple )
if ! ok {
return nil , fmt . Errorf ( "unexpected object" )
}
// Set a marker to verify the method was called
s . Other = "exported"
return obj , storage . errors [ "export" ]
}
2015-12-16 13:02:09 +00:00
func ( storage * SimpleRESTStorage ) List ( ctx api . Context , options * api . ListOptions ) ( runtime . Object , error ) {
2015-02-12 19:21:47 +00:00
storage . checkContext ( ctx )
2015-10-09 09:07:58 +00:00
result := & apiservertesting . SimpleList {
2014-06-06 23:40:48 +00:00
Items : storage . list ,
}
2015-10-27 13:47:58 +00:00
storage . requestedLabelSelector = labels . Everything ( )
2015-12-16 13:02:09 +00:00
if options != nil && options . LabelSelector != nil {
storage . requestedLabelSelector = options . LabelSelector
2015-10-27 13:47:58 +00:00
}
storage . requestedFieldSelector = fields . Everything ( )
2015-12-16 13:02:09 +00:00
if options != nil && options . FieldSelector != nil {
storage . requestedFieldSelector = options . FieldSelector
2015-10-27 13:47:58 +00:00
}
2014-07-16 05:27:15 +00:00
return result , storage . errors [ "list" ]
2014-06-06 23:40:48 +00:00
}
2015-03-22 03:25:38 +00:00
type SimpleStream struct {
version string
accept string
contentType string
err error
io . Reader
closed bool
}
func ( s * SimpleStream ) Close ( ) error {
s . closed = true
return nil
}
2015-12-08 03:01:12 +00:00
func ( obj * SimpleStream ) GetObjectKind ( ) unversioned . ObjectKind { return unversioned . EmptyObjectKind }
2015-03-22 03:25:38 +00:00
2015-04-06 16:58:00 +00:00
func ( s * SimpleStream ) InputStream ( version , accept string ) ( io . ReadCloser , bool , string , error ) {
2015-03-22 03:25:38 +00:00
s . version = version
s . accept = accept
2015-04-06 16:58:00 +00:00
return s , false , s . contentType , s . err
2015-03-22 03:25:38 +00:00
}
2015-10-11 03:14:18 +00:00
type OutputConnect struct {
2015-04-14 14:57:00 +00:00
response string
}
2015-10-11 03:14:18 +00:00
func ( h * OutputConnect ) ServeHTTP ( w http . ResponseWriter , req * http . Request ) {
2015-04-14 14:57:00 +00:00
w . Write ( [ ] byte ( h . response ) )
}
2014-09-26 15:46:04 +00:00
func ( storage * SimpleRESTStorage ) Get ( ctx api . Context , id string ) ( runtime . Object , error ) {
2015-02-12 19:21:47 +00:00
storage . checkContext ( ctx )
2015-03-22 03:25:38 +00:00
if id == "binary" {
return storage . stream , storage . errors [ "get" ]
}
2015-12-21 05:15:35 +00:00
copied , err := api . Scheme . Copy ( & storage . item )
if err != nil {
panic ( err )
}
return copied , storage . errors [ "get" ]
2014-06-06 23:40:48 +00:00
}
2015-02-12 19:21:47 +00:00
func ( storage * SimpleRESTStorage ) checkContext ( ctx api . Context ) {
storage . actualNamespace , storage . namespacePresent = api . NamespaceFrom ( ctx )
}
2015-03-05 03:34:31 +00:00
func ( storage * SimpleRESTStorage ) Delete ( ctx api . Context , id string , options * api . DeleteOptions ) ( runtime . Object , error ) {
2015-02-12 19:21:47 +00:00
storage . checkContext ( ctx )
2014-06-06 23:40:48 +00:00
storage . deleted = id
2015-03-05 03:34:31 +00:00
storage . deleteOptions = options
2014-07-17 17:05:14 +00:00
if err := storage . errors [ "delete" ] ; err != nil {
return nil , err
2014-06-25 20:21:32 +00:00
}
2015-09-09 21:59:11 +00:00
var obj runtime . Object = & unversioned . Status { Status : unversioned . StatusSuccess }
2015-02-10 14:26:26 +00:00
var err error
if storage . injectedFunction != nil {
2015-10-09 09:07:58 +00:00
obj , err = storage . injectedFunction ( & apiservertesting . Simple { ObjectMeta : api . ObjectMeta { Name : id } } )
2015-02-10 14:26:26 +00:00
}
return obj , err
2014-06-06 23:40:48 +00:00
}
2014-09-08 04:14:18 +00:00
func ( storage * SimpleRESTStorage ) New ( ) runtime . Object {
2015-10-09 09:07:58 +00:00
return & apiservertesting . Simple { }
2014-06-06 23:40:48 +00:00
}
2015-01-12 05:33:25 +00:00
func ( storage * SimpleRESTStorage ) NewList ( ) runtime . Object {
2015-10-09 09:07:58 +00:00
return & apiservertesting . SimpleList { }
2015-01-12 05:33:25 +00:00
}
2015-02-10 14:26:26 +00:00
func ( storage * SimpleRESTStorage ) Create ( ctx api . Context , obj runtime . Object ) ( runtime . Object , error ) {
2015-02-12 19:21:47 +00:00
storage . checkContext ( ctx )
2015-10-09 09:07:58 +00:00
storage . created = obj . ( * apiservertesting . Simple )
2014-07-17 17:05:14 +00:00
if err := storage . errors [ "create" ] ; err != nil {
return nil , err
2014-06-25 20:21:32 +00:00
}
2015-02-10 14:26:26 +00:00
var err error
if storage . injectedFunction != nil {
obj , err = storage . injectedFunction ( obj )
}
return obj , err
2014-06-06 23:40:48 +00:00
}
2016-04-29 01:21:35 +00:00
func ( storage * SimpleRESTStorage ) Update ( ctx api . Context , name string , objInfo rest . UpdatedObjectInfo ) ( runtime . Object , bool , error ) {
2015-02-12 19:21:47 +00:00
storage . checkContext ( ctx )
2016-04-29 01:21:35 +00:00
obj , err := objInfo . UpdatedObject ( ctx , & storage . item )
if err != nil {
return nil , false , err
}
2015-10-09 09:07:58 +00:00
storage . updated = obj . ( * apiservertesting . Simple )
2014-07-17 17:05:14 +00:00
if err := storage . errors [ "update" ] ; err != nil {
2015-02-10 14:26:26 +00:00
return nil , false , err
2014-06-25 20:21:32 +00:00
}
2015-02-10 14:26:26 +00:00
if storage . injectedFunction != nil {
obj , err = storage . injectedFunction ( obj )
}
return obj , false , err
2014-06-06 23:40:48 +00:00
}
2014-07-17 17:05:14 +00:00
// Implement ResourceWatcher.
2015-12-16 13:02:09 +00:00
func ( storage * SimpleRESTStorage ) Watch ( ctx api . Context , options * api . ListOptions ) ( watch . Interface , error ) {
2016-04-20 17:35:09 +00:00
storage . lock . Lock ( )
defer storage . lock . Unlock ( )
2015-02-12 19:21:47 +00:00
storage . checkContext ( ctx )
2015-10-27 13:47:58 +00:00
storage . requestedLabelSelector = labels . Everything ( )
2015-12-16 13:02:09 +00:00
if options != nil && options . LabelSelector != nil {
storage . requestedLabelSelector = options . LabelSelector
2015-10-27 13:47:58 +00:00
}
storage . requestedFieldSelector = fields . Everything ( )
2015-12-16 13:02:09 +00:00
if options != nil && options . FieldSelector != nil {
storage . requestedFieldSelector = options . FieldSelector
2015-10-27 13:47:58 +00:00
}
storage . requestedResourceVersion = ""
if options != nil {
storage . requestedResourceVersion = options . ResourceVersion
}
2015-01-19 21:50:00 +00:00
storage . requestedResourceNamespace = api . NamespaceValue ( ctx )
2014-08-06 21:55:37 +00:00
if err := storage . errors [ "watch" ] ; err != nil {
2014-07-17 17:05:14 +00:00
return nil , err
}
storage . fakeWatch = watch . NewFake ( )
return storage . fakeWatch , nil
}
2016-04-20 17:35:09 +00:00
func ( storage * SimpleRESTStorage ) Watcher ( ) * watch . FakeWatcher {
storage . lock . Lock ( )
defer storage . lock . Unlock ( )
return storage . fakeWatch
}
2014-08-25 21:36:15 +00:00
// Implement Redirector.
2015-03-23 18:42:39 +00:00
var _ = rest . Redirector ( & SimpleRESTStorage { } )
// Implement Redirector.
func ( storage * SimpleRESTStorage ) ResourceLocation ( ctx api . Context , id string ) ( * url . URL , http . RoundTripper , error ) {
2015-02-12 19:21:47 +00:00
storage . checkContext ( ctx )
2014-10-20 20:25:08 +00:00
// validate that the namespace context on the request matches the expected input
2015-01-19 21:50:00 +00:00
storage . requestedResourceNamespace = api . NamespaceValue ( ctx )
2014-10-30 16:55:17 +00:00
if storage . expectedResourceNamespace != storage . requestedResourceNamespace {
2015-03-23 18:42:39 +00:00
return nil , nil , fmt . Errorf ( "Expected request namespace %s, but got namespace %s" , storage . expectedResourceNamespace , storage . requestedResourceNamespace )
2014-10-20 20:25:08 +00:00
}
2014-08-25 21:36:15 +00:00
storage . requestedResourceLocationID = id
if err := storage . errors [ "resourceLocation" ] ; err != nil {
2015-03-23 18:42:39 +00:00
return nil , nil , err
2014-08-25 21:36:15 +00:00
}
2015-03-23 18:42:39 +00:00
// Make a copy so the internal URL never gets mutated
locationCopy := * storage . resourceLocation
2015-10-01 01:13:34 +00:00
return & locationCopy , storage . resourceLocationTransport , nil
2014-08-25 21:36:15 +00:00
}
2015-04-14 14:57:00 +00:00
// Implement Connecter
type ConnecterRESTStorage struct {
2015-10-11 03:14:18 +00:00
connectHandler http . Handler
handlerFunc func ( ) http . Handler
2015-04-14 14:57:00 +00:00
emptyConnectOptions runtime . Object
receivedConnectOptions runtime . Object
receivedID string
2015-10-11 03:14:18 +00:00
receivedResponder rest . Responder
2015-04-14 14:57:00 +00:00
takesPath string
}
// Implement Connecter
var _ = rest . Connecter ( & ConnecterRESTStorage { } )
func ( s * ConnecterRESTStorage ) New ( ) runtime . Object {
2015-10-09 09:07:58 +00:00
return & apiservertesting . Simple { }
2015-04-14 14:57:00 +00:00
}
2015-10-11 03:14:18 +00:00
func ( s * ConnecterRESTStorage ) Connect ( ctx api . Context , id string , options runtime . Object , responder rest . Responder ) ( http . Handler , error ) {
2015-04-14 14:57:00 +00:00
s . receivedConnectOptions = options
s . receivedID = id
2015-10-11 03:14:18 +00:00
s . receivedResponder = responder
if s . handlerFunc != nil {
return s . handlerFunc ( ) , nil
}
2015-04-14 14:57:00 +00:00
return s . connectHandler , nil
}
func ( s * ConnecterRESTStorage ) ConnectMethods ( ) [ ] string {
return [ ] string { "GET" , "POST" , "PUT" , "DELETE" }
}
func ( s * ConnecterRESTStorage ) NewConnectOptions ( ) ( runtime . Object , bool , string ) {
if len ( s . takesPath ) > 0 {
return s . emptyConnectOptions , true , s . takesPath
}
return s . emptyConnectOptions , false , ""
}
2015-03-05 03:34:31 +00:00
type LegacyRESTStorage struct {
* SimpleRESTStorage
}
func ( storage LegacyRESTStorage ) Delete ( ctx api . Context , id string ) ( runtime . Object , error ) {
return storage . SimpleRESTStorage . Delete ( ctx , id , nil )
}
2015-03-22 03:25:38 +00:00
type MetadataRESTStorage struct {
* SimpleRESTStorage
types [ ] string
}
func ( m * MetadataRESTStorage ) ProducesMIMETypes ( method string ) [ ] string {
return m . types
}
2015-04-11 15:13:10 +00:00
var _ rest . StorageMetadata = & MetadataRESTStorage { }
2015-04-06 16:58:00 +00:00
type GetWithOptionsRESTStorage struct {
* SimpleRESTStorage
optionsReceived runtime . Object
2015-04-11 15:13:10 +00:00
takesPath string
2015-04-06 16:58:00 +00:00
}
func ( r * GetWithOptionsRESTStorage ) Get ( ctx api . Context , name string , options runtime . Object ) ( runtime . Object , error ) {
2015-10-09 09:07:58 +00:00
if _ , ok := options . ( * apiservertesting . SimpleGetOptions ) ; ! ok {
2015-04-06 16:58:00 +00:00
return nil , fmt . Errorf ( "Unexpected options object: %#v" , options )
}
r . optionsReceived = options
return r . SimpleRESTStorage . Get ( ctx , name )
}
2015-04-11 15:13:10 +00:00
func ( r * GetWithOptionsRESTStorage ) NewGetOptions ( ) ( runtime . Object , bool , string ) {
if len ( r . takesPath ) > 0 {
2015-10-09 09:07:58 +00:00
return & apiservertesting . SimpleGetOptions { } , true , r . takesPath
2015-04-11 15:13:10 +00:00
}
2015-10-09 09:07:58 +00:00
return & apiservertesting . SimpleGetOptions { } , false , ""
2015-04-06 16:58:00 +00:00
}
2015-04-11 15:13:10 +00:00
var _ rest . GetterWithOptions = & GetWithOptionsRESTStorage { }
2015-05-04 18:38:41 +00:00
type NamedCreaterRESTStorage struct {
* SimpleRESTStorage
createdName string
}
func ( storage * NamedCreaterRESTStorage ) Create ( ctx api . Context , name string , obj runtime . Object ) ( runtime . Object , error ) {
storage . checkContext ( ctx )
2015-10-09 09:07:58 +00:00
storage . created = obj . ( * apiservertesting . Simple )
2015-05-04 18:38:41 +00:00
storage . createdName = name
if err := storage . errors [ "create" ] ; err != nil {
return nil , err
}
var err error
if storage . injectedFunction != nil {
obj , err = storage . injectedFunction ( obj )
}
return obj , err
}
2015-05-08 04:31:53 +00:00
type SimpleTypedStorage struct {
errors map [ string ] error
item runtime . Object
baseType runtime . Object
actualNamespace string
namespacePresent bool
}
func ( storage * SimpleTypedStorage ) New ( ) runtime . Object {
return storage . baseType
}
func ( storage * SimpleTypedStorage ) Get ( ctx api . Context , id string ) ( runtime . Object , error ) {
storage . checkContext ( ctx )
2015-12-21 05:15:35 +00:00
copied , err := api . Scheme . Copy ( storage . item )
if err != nil {
panic ( err )
}
return copied , storage . errors [ "get" ]
2015-05-08 04:31:53 +00:00
}
func ( storage * SimpleTypedStorage ) checkContext ( ctx api . Context ) {
storage . actualNamespace , storage . namespacePresent = api . NamespaceFrom ( ctx )
}
2014-09-08 04:14:18 +00:00
func extractBody ( response * http . Response , object runtime . Object ) ( string , error ) {
2015-12-21 05:15:35 +00:00
return extractBodyDecoder ( response , object , codec )
}
func extractBodyDecoder ( response * http . Response , object runtime . Object , decoder runtime . Decoder ) ( string , error ) {
2014-06-06 23:40:48 +00:00
defer response . Body . Close ( )
body , err := ioutil . ReadAll ( response . Body )
if err != nil {
return string ( body ) , err
}
2015-12-21 05:15:35 +00:00
return string ( body ) , runtime . DecodeInto ( decoder , body , object )
2014-06-06 23:40:48 +00:00
}
2014-07-31 18:16:13 +00:00
func TestNotFound ( t * testing . T ) {
type T struct {
Method string
Path string
2014-11-11 07:11:45 +00:00
Status int
2014-07-31 18:16:13 +00:00
}
cases := map [ string ] T {
2015-11-13 16:16:26 +00:00
// Positive checks to make sure everything is wired correctly
2015-11-13 13:13:55 +00:00
"groupless GET root" : { "GET" , "/" + grouplessPrefix + "/" + grouplessGroupVersion . Version + "/simpleroots" , http . StatusOK } ,
"groupless GET namespaced" : { "GET" , "/" + grouplessPrefix + "/" + grouplessGroupVersion . Version + "/namespaces/ns/simples" , http . StatusOK } ,
2015-11-13 16:16:26 +00:00
"groupless GET long prefix" : { "GET" , "/" + grouplessPrefix + "/" , http . StatusNotFound } ,
2015-11-13 13:13:55 +00:00
"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 . StatusNotFound } ,
2015-11-13 16:16:26 +00:00
2015-11-13 13:13:55 +00:00
"groupless namespaced PATCH method" : { "PATCH" , "/" + grouplessPrefix + "/" + grouplessGroupVersion . Version + "/namespaces/ns/simples" , http . StatusMethodNotAllowed } ,
2015-11-13 16:16:26 +00:00
"groupless namespaced GET long prefix" : { "GET" , "/" + grouplessPrefix + "/" , http . StatusNotFound } ,
2015-11-13 13:13:55 +00:00
"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 . StatusNotFound } ,
"groupless namespaced watch with bad method" : { "POST" , "/" + grouplessPrefix + "/" + grouplessGroupVersion . Version + "/watch/namespaces/ns/simples/bar" , http . StatusMethodNotAllowed } ,
2015-11-13 16:16:26 +00:00
2015-06-10 20:17:04 +00:00
// Positive checks to make sure everything is wired correctly
2015-11-12 20:20:20 +00:00
"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 long prefix" : { "GET" , "/" + 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 . StatusNotFound } ,
// TODO: JTL: "root watch with bad method": {"POST", "/" + 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 . StatusNotFound } ,
"namespaced watch with bad method" : { "POST" , "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/watch/namespaces/ns/simples/bar" , http . StatusMethodNotAllowed } ,
2015-03-04 20:57:05 +00:00
}
2015-03-21 16:24:16 +00:00
handler := handle ( map [ string ] rest . Storage {
2015-06-10 20:17:04 +00:00
"simples" : & SimpleRESTStorage { } ,
"simpleroots" : & SimpleRESTStorage { } ,
2015-03-04 20:57:05 +00:00
} )
2014-07-31 18:16:13 +00:00
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2014-07-31 18:16:13 +00:00
client := http . Client { }
for k , v := range cases {
request , err := http . NewRequest ( v . Method , server . URL + v . Path , nil )
2014-08-04 00:01:15 +00:00
if err != nil {
2014-10-20 22:23:28 +00:00
t . Fatalf ( "unexpected error: %v" , err )
2014-08-04 00:01:15 +00:00
}
2014-07-31 18:16:13 +00:00
response , err := client . Do ( request )
2014-08-04 00:01:15 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
2014-11-11 07:11:45 +00:00
if response . StatusCode != v . Status {
2014-11-20 12:42:48 +00:00
t . Errorf ( "Expected %d for %s (%s), Got %#v" , v . Status , v . Method , k , response )
2015-01-29 22:46:54 +00:00
t . Errorf ( "MAPPER: %v" , mapper )
2014-07-31 18:16:13 +00:00
}
}
}
2015-01-12 05:33:25 +00:00
type UnimplementedRESTStorage struct { }
func ( UnimplementedRESTStorage ) New ( ) runtime . Object {
2015-10-09 09:07:58 +00:00
return & apiservertesting . Simple { }
2015-01-12 05:33:25 +00:00
}
2015-03-21 16:24:16 +00:00
// TestUnimplementedRESTStorage ensures that if a rest.Storage does not implement a given
2015-01-30 20:43:53 +00:00
// method, that it is literally not registered with the server. In the past,
// we registered everything, and returned method not supported if it didn't support
// a verb. Now we literally do not register a storage if it does not implement anything.
// TODO: in future, we should update proxy/redirect
func TestUnimplementedRESTStorage ( t * testing . T ) {
2015-01-12 05:33:25 +00:00
type T struct {
2015-01-30 20:43:53 +00:00
Method string
Path string
ErrCode int
2015-01-12 05:33:25 +00:00
}
cases := map [ string ] T {
2015-11-13 13:13:55 +00:00
"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 redirect object" : { "GET" , "/" + grouplessPrefix + "/" + grouplessGroupVersion . Version + "/redirect/foo/bar" , http . StatusNotFound } ,
2015-11-13 16:16:26 +00:00
2015-11-12 20:20:20 +00:00
"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 } ,
"redirect object" : { "GET" , "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/redirect/foo/bar" , http . StatusNotFound } ,
2015-03-04 20:57:05 +00:00
}
2015-03-21 16:24:16 +00:00
handler := handle ( map [ string ] rest . Storage {
2015-01-12 05:33:25 +00:00
"foo" : UnimplementedRESTStorage { } ,
2015-03-04 20:57:05 +00:00
} )
2015-01-12 05:33:25 +00:00
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2015-01-12 05:33:25 +00:00
client := http . Client { }
for k , v := range cases {
request , err := http . NewRequest ( v . Method , server . URL + v . Path , bytes . NewReader ( [ ] byte ( ` { "kind":"Simple","apiVersion":"version"} ` ) ) )
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
}
response , err := client . Do ( request )
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
}
defer response . Body . Close ( )
2015-06-20 00:16:25 +00:00
data , err := ioutil . ReadAll ( response . Body )
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
}
2015-01-30 20:43:53 +00:00
if response . StatusCode != v . ErrCode {
2015-01-31 00:08:59 +00:00
t . Errorf ( "%s: expected %d for %s, Got %s" , k , v . ErrCode , v . Method , string ( data ) )
2015-01-12 05:33:25 +00:00
continue
}
}
}
2014-07-31 18:16:13 +00:00
func TestVersion ( t * testing . T ) {
2015-03-21 16:24:16 +00:00
handler := handle ( map [ string ] rest . Storage { } )
2014-07-31 18:16:13 +00:00
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2014-07-31 18:16:13 +00:00
client := http . Client { }
request , err := http . NewRequest ( "GET" , server . URL + "/version" , nil )
2014-08-04 00:01:15 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
2014-07-31 18:16:13 +00:00
response , err := client . Do ( request )
2014-08-04 00:01:15 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
2014-07-31 18:16:13 +00:00
var info version . Info
err = json . NewDecoder ( response . Body ) . Decode ( & info )
2014-08-04 00:01:15 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
2014-07-31 18:16:13 +00:00
if ! reflect . DeepEqual ( version . Get ( ) , info ) {
t . Errorf ( "Expected %#v, Got %#v" , version . Get ( ) , info )
}
}
2015-02-12 19:21:47 +00:00
func TestList ( t * testing . T ) {
testCases := [ ] struct {
url string
namespace string
selfLink string
legacy bool
2015-03-22 21:43:00 +00:00
label string
field string
2015-02-12 19:21:47 +00:00
} {
2015-11-13 16:16:26 +00:00
// Groupless API
// legacy namespace param is ignored
{
2015-11-13 13:13:55 +00:00
url : "/" + grouplessPrefix + "/" + grouplessGroupVersion . Version + "/simple?namespace=" ,
2015-11-13 16:16:26 +00:00
namespace : "" ,
2015-11-13 13:13:55 +00:00
selfLink : "/" + grouplessPrefix + "/" + grouplessGroupVersion . Version + "/simple" ,
2015-11-13 16:16:26 +00:00
legacy : true ,
} ,
{
2015-11-13 13:13:55 +00:00
url : "/" + grouplessPrefix + "/" + grouplessGroupVersion . Version + "/simple?namespace=other" ,
2015-11-13 16:16:26 +00:00
namespace : "" ,
2015-11-13 13:13:55 +00:00
selfLink : "/" + grouplessPrefix + "/" + grouplessGroupVersion . Version + "/simple" ,
2015-11-13 16:16:26 +00:00
legacy : true ,
} ,
{
2015-11-13 13:13:55 +00:00
url : "/" + grouplessPrefix + "/" + grouplessGroupVersion . Version + "/simple?namespace=other&labelSelector=a%3Db&fieldSelector=c%3Dd" ,
2015-11-13 16:16:26 +00:00
namespace : "" ,
2015-11-13 13:13:55 +00:00
selfLink : "/" + grouplessPrefix + "/" + grouplessGroupVersion . Version + "/simple" ,
2015-11-13 16:16:26 +00:00
legacy : true ,
label : "a=b" ,
field : "c=d" ,
} ,
// legacy api version is honored
{
2015-11-13 13:13:55 +00:00
url : "/" + grouplessPrefix + "/" + grouplessGroupVersion . Version + "/simple" ,
2015-11-13 16:16:26 +00:00
namespace : "" ,
2015-11-13 13:13:55 +00:00
selfLink : "/" + grouplessPrefix + "/" + grouplessGroupVersion . Version + "/simple" ,
2015-11-13 16:16:26 +00:00
legacy : true ,
} ,
{
2015-11-13 13:13:55 +00:00
url : "/" + grouplessPrefix + "/" + grouplessGroupVersion . Version + "/namespaces/other/simple" ,
2015-11-13 16:16:26 +00:00
namespace : "other" ,
2015-11-13 13:13:55 +00:00
selfLink : "/" + grouplessPrefix + "/" + grouplessGroupVersion . Version + "/namespaces/other/simple" ,
2015-11-13 16:16:26 +00:00
legacy : true ,
} ,
{
2015-11-13 13:13:55 +00:00
url : "/" + grouplessPrefix + "/" + grouplessGroupVersion . Version + "/namespaces/other/simple?labelSelector=a%3Db&fieldSelector=c%3Dd" ,
2015-11-13 16:16:26 +00:00
namespace : "other" ,
2015-11-13 13:13:55 +00:00
selfLink : "/" + grouplessPrefix + "/" + grouplessGroupVersion . Version + "/namespaces/other/simple" ,
2015-11-13 16:16:26 +00:00
legacy : true ,
label : "a=b" ,
field : "c=d" ,
} ,
// list items across all namespaces
{
2015-11-13 13:13:55 +00:00
url : "/" + grouplessPrefix + "/" + grouplessGroupVersion . Version + "/simple" ,
2015-11-13 16:16:26 +00:00
namespace : "" ,
2015-11-13 13:13:55 +00:00
selfLink : "/" + grouplessPrefix + "/" + grouplessGroupVersion . Version + "/simple" ,
2015-11-13 16:16:26 +00:00
legacy : true ,
} ,
// list items in a namespace in the path
{
2015-11-13 13:13:55 +00:00
url : "/" + grouplessPrefix + "/" + grouplessGroupVersion . Version + "/namespaces/default/simple" ,
2015-11-13 16:16:26 +00:00
namespace : "default" ,
2015-11-13 13:13:55 +00:00
selfLink : "/" + grouplessPrefix + "/" + grouplessGroupVersion . Version + "/namespaces/default/simple" ,
2015-11-13 16:16:26 +00:00
} ,
{
2015-11-13 13:13:55 +00:00
url : "/" + grouplessPrefix + "/" + grouplessGroupVersion . Version + "/namespaces/other/simple" ,
2015-11-13 16:16:26 +00:00
namespace : "other" ,
2015-11-13 13:13:55 +00:00
selfLink : "/" + grouplessPrefix + "/" + grouplessGroupVersion . Version + "/namespaces/other/simple" ,
2015-11-13 16:16:26 +00:00
} ,
{
2015-11-13 13:13:55 +00:00
url : "/" + grouplessPrefix + "/" + grouplessGroupVersion . Version + "/namespaces/other/simple?labelSelector=a%3Db&fieldSelector=c%3Dd" ,
2015-11-13 16:16:26 +00:00
namespace : "other" ,
2015-11-13 13:13:55 +00:00
selfLink : "/" + grouplessPrefix + "/" + grouplessGroupVersion . Version + "/namespaces/other/simple" ,
2015-11-13 16:16:26 +00:00
label : "a=b" ,
field : "c=d" ,
} ,
// list items across all namespaces
{
2015-11-13 13:13:55 +00:00
url : "/" + grouplessPrefix + "/" + grouplessGroupVersion . Version + "/simple" ,
2015-11-13 16:16:26 +00:00
namespace : "" ,
2015-11-13 13:13:55 +00:00
selfLink : "/" + grouplessPrefix + "/" + grouplessGroupVersion . Version + "/simple" ,
2015-11-13 16:16:26 +00:00
} ,
// Group API
2015-06-10 20:17:04 +00:00
// legacy namespace param is ignored
2015-03-22 21:43:00 +00:00
{
2015-11-12 20:20:20 +00:00
url : "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/simple?namespace=" ,
2015-03-22 21:43:00 +00:00
namespace : "" ,
2015-11-12 20:20:20 +00:00
selfLink : "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/simple" ,
2015-03-22 21:43:00 +00:00
legacy : true ,
} ,
{
2015-11-12 20:20:20 +00:00
url : "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/simple?namespace=other" ,
2015-06-10 20:17:04 +00:00
namespace : "" ,
2015-11-12 20:20:20 +00:00
selfLink : "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/simple" ,
2015-03-22 21:43:00 +00:00
legacy : true ,
} ,
{
2015-11-16 13:59:01 +00:00
url : "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/simple?namespace=other&labelSelector=a%3Db&fieldSelector=c%3Dd" ,
2015-06-10 20:17:04 +00:00
namespace : "" ,
2015-11-12 20:20:20 +00:00
selfLink : "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/simple" ,
2015-06-10 20:17:04 +00:00
legacy : true ,
label : "a=b" ,
field : "c=d" ,
} ,
// legacy api version is honored
{
2015-11-12 20:20:20 +00:00
url : "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/simple" ,
2015-06-10 20:17:04 +00:00
namespace : "" ,
2015-11-12 20:20:20 +00:00
selfLink : "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/simple" ,
2015-06-10 20:17:04 +00:00
legacy : true ,
} ,
{
2015-11-12 20:20:20 +00:00
url : "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/other/simple" ,
2015-06-10 20:17:04 +00:00
namespace : "other" ,
2015-11-12 20:20:20 +00:00
selfLink : "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/other/simple" ,
2015-06-10 20:17:04 +00:00
legacy : true ,
} ,
{
2015-11-16 13:59:01 +00:00
url : "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/other/simple?labelSelector=a%3Db&fieldSelector=c%3Dd" ,
2015-03-22 21:43:00 +00:00
namespace : "other" ,
2015-11-12 20:20:20 +00:00
selfLink : "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/other/simple" ,
2015-03-22 21:43:00 +00:00
legacy : true ,
label : "a=b" ,
field : "c=d" ,
} ,
2015-02-12 19:21:47 +00:00
// list items across all namespaces
2015-03-22 21:43:00 +00:00
{
2015-11-12 20:20:20 +00:00
url : "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/simple" ,
2015-03-22 21:43:00 +00:00
namespace : "" ,
2015-11-12 20:20:20 +00:00
selfLink : "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/simple" ,
2015-03-22 21:43:00 +00:00
legacy : true ,
} ,
2015-05-22 15:20:27 +00:00
// list items in a namespace in the path
2015-03-22 21:43:00 +00:00
{
2015-11-12 20:20:20 +00:00
url : "/" + prefix + "/" + newGroupVersion . Group + "/" + newGroupVersion . Version + "/namespaces/default/simple" ,
2015-03-22 21:43:00 +00:00
namespace : "default" ,
2015-11-12 20:20:20 +00:00
selfLink : "/" + prefix + "/" + newGroupVersion . Group + "/" + newGroupVersion . Version + "/namespaces/default/simple" ,
2015-03-22 21:43:00 +00:00
} ,
{
2015-11-12 20:20:20 +00:00
url : "/" + prefix + "/" + newGroupVersion . Group + "/" + newGroupVersion . Version + "/namespaces/other/simple" ,
2015-03-22 21:43:00 +00:00
namespace : "other" ,
2015-11-12 20:20:20 +00:00
selfLink : "/" + prefix + "/" + newGroupVersion . Group + "/" + newGroupVersion . Version + "/namespaces/other/simple" ,
2015-03-22 21:43:00 +00:00
} ,
{
2015-11-12 20:20:20 +00:00
url : "/" + prefix + "/" + newGroupVersion . Group + "/" + newGroupVersion . Version + "/namespaces/other/simple?labelSelector=a%3Db&fieldSelector=c%3Dd" ,
2015-03-22 21:43:00 +00:00
namespace : "other" ,
2015-11-12 20:20:20 +00:00
selfLink : "/" + prefix + "/" + newGroupVersion . Group + "/" + newGroupVersion . Version + "/namespaces/other/simple" ,
2015-03-22 21:43:00 +00:00
label : "a=b" ,
field : "c=d" ,
} ,
2015-02-12 19:21:47 +00:00
// list items across all namespaces
2015-03-22 21:43:00 +00:00
{
2015-11-12 20:20:20 +00:00
url : "/" + prefix + "/" + newGroupVersion . Group + "/" + newGroupVersion . Version + "/simple" ,
2015-03-22 21:43:00 +00:00
namespace : "" ,
2015-11-12 20:20:20 +00:00
selfLink : "/" + prefix + "/" + newGroupVersion . Group + "/" + newGroupVersion . Version + "/simple" ,
2015-03-22 21:43:00 +00:00
} ,
2015-02-12 19:21:47 +00:00
}
for i , testCase := range testCases {
2015-03-21 16:24:16 +00:00
storage := map [ string ] rest . Storage { }
2015-02-12 19:21:47 +00:00
simpleStorage := SimpleRESTStorage { expectedResourceNamespace : testCase . namespace }
storage [ "simple" ] = & simpleStorage
selfLinker := & setTestSelfLinker {
t : t ,
namespace : testCase . namespace ,
expectedSet : testCase . selfLink ,
}
2015-11-13 16:16:26 +00:00
var handler = handleInternal ( storage , admissionControl , selfLinker )
2015-02-12 19:21:47 +00:00
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2015-02-12 19:21:47 +00:00
resp , err := http . Get ( server . URL + testCase . url )
if err != nil {
t . Errorf ( "%d: unexpected error: %v" , i , err )
continue
}
2015-12-05 12:27:05 +00:00
defer resp . Body . Close ( )
2015-02-12 19:21:47 +00:00
if resp . StatusCode != http . StatusOK {
2015-11-13 16:16:26 +00:00
t . Errorf ( "%d: unexpected status: %d from url %s, Expected: %d, %#v" , i , resp . StatusCode , testCase . url , http . StatusOK , resp )
2015-06-20 00:16:25 +00:00
body , err := ioutil . ReadAll ( resp . Body )
if err != nil {
t . Errorf ( "%d: unexpected error: %v" , i , err )
continue
}
2015-03-31 22:32:02 +00:00
t . Logf ( "%d: body: %s" , i , string ( body ) )
2015-03-25 20:21:40 +00:00
continue
2015-02-12 19:21:47 +00:00
}
// TODO: future, restore get links
if ! selfLinker . called {
t . Errorf ( "%d: never set self link" , i )
}
if ! simpleStorage . namespacePresent {
t . Errorf ( "%d: namespace not set" , i )
} else if simpleStorage . actualNamespace != testCase . namespace {
t . Errorf ( "%d: unexpected resource namespace: %s" , i , simpleStorage . actualNamespace )
}
2015-03-22 21:43:00 +00:00
if simpleStorage . requestedLabelSelector == nil || simpleStorage . requestedLabelSelector . String ( ) != testCase . label {
t . Errorf ( "%d: unexpected label selector: %v" , i , simpleStorage . requestedLabelSelector )
}
if simpleStorage . requestedFieldSelector == nil || simpleStorage . requestedFieldSelector . String ( ) != testCase . field {
t . Errorf ( "%d: unexpected field selector: %v" , i , simpleStorage . requestedFieldSelector )
}
2015-02-12 19:21:47 +00:00
}
}
2016-08-03 09:41:09 +00:00
func TestLogs ( t * testing . T ) {
handler := handle ( map [ string ] rest . Storage { } )
server := httptest . NewServer ( handler )
defer server . Close ( )
client := http . Client { }
request , err := http . NewRequest ( "GET" , server . URL + "/logs" , nil )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
response , err := client . Do ( request )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
body , err := ioutil . ReadAll ( response . Body )
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
}
t . Logf ( "Data: %s" , string ( body ) )
}
2015-02-12 19:21:47 +00:00
func TestErrorList ( t * testing . T ) {
2015-03-21 16:24:16 +00:00
storage := map [ string ] rest . Storage { }
2015-02-12 19:21:47 +00:00
simpleStorage := SimpleRESTStorage {
errors : map [ string ] error { "list" : fmt . Errorf ( "test Error" ) } ,
2014-09-26 00:20:28 +00:00
}
2015-02-12 19:21:47 +00:00
storage [ "simple" ] = & simpleStorage
2015-03-04 20:57:05 +00:00
handler := handle ( storage )
2014-06-06 23:40:48 +00:00
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2014-06-06 23:40:48 +00:00
2015-11-12 20:20:20 +00:00
resp , err := http . Get ( server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/simple" )
2014-08-04 00:01:15 +00:00
if err != nil {
2015-02-12 19:21:47 +00:00
t . Fatalf ( "unexpected error: %v" , err )
2014-08-04 00:01:15 +00:00
}
2014-06-06 23:40:48 +00:00
2015-02-12 19:21:47 +00:00
if resp . StatusCode != http . StatusInternalServerError {
t . Errorf ( "Unexpected status: %d, Expected: %d, %#v" , resp . StatusCode , http . StatusInternalServerError , resp )
2014-09-26 00:20:28 +00:00
}
2014-06-06 23:40:48 +00:00
}
2015-02-12 19:21:47 +00:00
func TestNonEmptyList ( t * testing . T ) {
2015-03-21 16:24:16 +00:00
storage := map [ string ] rest . Storage { }
2014-06-06 23:40:48 +00:00
simpleStorage := SimpleRESTStorage {
2015-10-09 09:07:58 +00:00
list : [ ] apiservertesting . Simple {
2015-02-12 19:21:47 +00:00
{
ObjectMeta : api . ObjectMeta { Name : "something" , Namespace : "other" } ,
Other : "foo" ,
} ,
} ,
2014-06-06 23:40:48 +00:00
}
storage [ "simple" ] = & simpleStorage
2015-03-04 20:57:05 +00:00
handler := handle ( storage )
2014-06-06 23:40:48 +00:00
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2014-06-06 23:40:48 +00:00
2015-11-12 20:20:20 +00:00
resp , err := http . Get ( server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/simple" )
2014-08-04 00:01:15 +00:00
if err != nil {
2015-02-12 19:21:47 +00:00
t . Fatalf ( "unexpected error: %v" , err )
2014-08-04 00:01:15 +00:00
}
2014-06-06 23:40:48 +00:00
2015-02-12 19:21:47 +00:00
if resp . StatusCode != http . StatusOK {
t . Errorf ( "Unexpected status: %d, Expected: %d, %#v" , resp . StatusCode , http . StatusOK , resp )
2015-06-20 00:16:25 +00:00
body , err := ioutil . ReadAll ( resp . Body )
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
}
2015-02-12 19:21:47 +00:00
t . Logf ( "Data: %s" , string ( body ) )
}
2015-10-09 09:07:58 +00:00
var listOut apiservertesting . SimpleList
2015-02-12 19:21:47 +00:00
body , err := extractBody ( resp , & listOut )
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
}
if len ( listOut . Items ) != 1 {
t . Errorf ( "Unexpected response: %#v" , listOut )
return
}
if listOut . Items [ 0 ] . Other != simpleStorage . list [ 0 ] . Other {
t . Errorf ( "Unexpected data: %#v, %s" , listOut . Items [ 0 ] , string ( body ) )
}
2015-11-12 20:20:20 +00:00
if listOut . SelfLink != "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/simple" {
2015-02-12 19:21:47 +00:00
t . Errorf ( "unexpected list self link: %#v" , listOut )
}
2015-11-12 20:20:20 +00:00
expectedSelfLink := "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/other/simple/something"
2015-02-12 19:21:47 +00:00
if listOut . Items [ 0 ] . ObjectMeta . SelfLink != expectedSelfLink {
t . Errorf ( "Unexpected data: %#v, %s" , listOut . Items [ 0 ] . ObjectMeta . SelfLink , expectedSelfLink )
2014-06-06 23:40:48 +00:00
}
}
2015-02-12 19:21:47 +00:00
func TestSelfLinkSkipsEmptyName ( t * testing . T ) {
2015-03-21 16:24:16 +00:00
storage := map [ string ] rest . Storage { }
2014-06-06 23:40:48 +00:00
simpleStorage := SimpleRESTStorage {
2015-10-09 09:07:58 +00:00
list : [ ] apiservertesting . Simple {
2014-06-12 21:09:40 +00:00
{
2014-11-24 18:35:24 +00:00
ObjectMeta : api . ObjectMeta { Namespace : "other" } ,
Other : "foo" ,
2014-06-06 23:40:48 +00:00
} ,
} ,
}
storage [ "simple" ] = & simpleStorage
2015-03-04 20:57:05 +00:00
handler := handle ( storage )
2014-06-06 23:40:48 +00:00
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2014-06-06 23:40:48 +00:00
2015-11-12 20:20:20 +00:00
resp , err := http . Get ( server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/simple" )
2014-08-04 00:01:15 +00:00
if err != nil {
2015-02-12 19:21:47 +00:00
t . Fatalf ( "unexpected error: %v" , err )
2014-08-04 00:01:15 +00:00
}
2014-06-06 23:40:48 +00:00
2014-07-16 05:27:15 +00:00
if resp . StatusCode != http . StatusOK {
t . Errorf ( "Unexpected status: %d, Expected: %d, %#v" , resp . StatusCode , http . StatusOK , resp )
2015-06-20 00:16:25 +00:00
body , err := ioutil . ReadAll ( resp . Body )
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
}
2014-10-23 20:51:34 +00:00
t . Logf ( "Data: %s" , string ( body ) )
2014-06-06 23:40:48 +00:00
}
2015-10-09 09:07:58 +00:00
var listOut apiservertesting . SimpleList
2014-06-06 23:40:48 +00:00
body , err := extractBody ( resp , & listOut )
2014-08-04 00:01:15 +00:00
if err != nil {
2015-02-12 19:21:47 +00:00
t . Fatalf ( "unexpected error: %v" , err )
2014-08-04 00:01:15 +00:00
}
2014-06-06 23:40:48 +00:00
if len ( listOut . Items ) != 1 {
t . Errorf ( "Unexpected response: %#v" , listOut )
2014-06-20 23:18:36 +00:00
return
2014-06-06 23:40:48 +00:00
}
2014-10-22 17:02:02 +00:00
if listOut . Items [ 0 ] . Other != simpleStorage . list [ 0 ] . Other {
2014-06-06 23:40:48 +00:00
t . Errorf ( "Unexpected data: %#v, %s" , listOut . Items [ 0 ] , string ( body ) )
}
2015-11-12 20:20:20 +00:00
if listOut . SelfLink != "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/simple" {
2015-02-12 19:21:47 +00:00
t . Errorf ( "unexpected list self link: %#v" , listOut )
}
expectedSelfLink := ""
2014-11-24 18:35:24 +00:00
if listOut . Items [ 0 ] . ObjectMeta . SelfLink != expectedSelfLink {
t . Errorf ( "Unexpected data: %#v, %s" , listOut . Items [ 0 ] . ObjectMeta . SelfLink , expectedSelfLink )
}
2014-06-06 23:40:48 +00:00
}
2015-03-22 03:25:38 +00:00
func TestMetadata ( t * testing . T ) {
simpleStorage := & MetadataRESTStorage { & SimpleRESTStorage { } , [ ] string { "text/plain" } }
h := handle ( map [ string ] rest . Storage { "simple" : simpleStorage } )
ws := h . ( * defaultAPIServer ) . container . RegisteredWebServices ( )
if len ( ws ) == 0 {
t . Fatal ( "no web services registered" )
}
matches := map [ string ] int { }
for _ , w := range ws {
for _ , r := range w . Routes ( ) {
s := strings . Join ( r . Produces , "," )
i := matches [ s ]
matches [ s ] = i + 1
}
}
2016-04-16 21:11:43 +00:00
if matches [ "text/plain,application/json,application/yaml,application/vnd.kubernetes.protobuf" ] == 0 ||
2016-04-20 17:35:09 +00:00
matches [ "application/json,application/json;stream=watch,application/vnd.kubernetes.protobuf,application/vnd.kubernetes.protobuf;stream=watch" ] == 0 ||
2016-04-16 21:11:43 +00:00
matches [ "application/json,application/yaml,application/vnd.kubernetes.protobuf" ] == 0 ||
2016-04-20 17:35:09 +00:00
matches [ "application/json" ] == 0 ||
2015-12-21 05:15:35 +00:00
matches [ "*/*" ] == 0 ||
2016-04-16 21:11:43 +00:00
len ( matches ) != 5 {
2015-03-22 03:25:38 +00:00
t . Errorf ( "unexpected mime types: %v" , matches )
}
}
2015-12-01 23:45:29 +00:00
func TestExport ( t * testing . T ) {
storage := map [ string ] rest . Storage { }
simpleStorage := SimpleRESTStorage {
item : apiservertesting . Simple {
ObjectMeta : api . ObjectMeta {
ResourceVersion : "1234" ,
CreationTimestamp : unversioned . NewTime ( time . Unix ( 10 , 10 ) ) ,
} ,
Other : "foo" ,
} ,
}
selfLinker := & setTestSelfLinker {
t : t ,
expectedSet : "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/id" ,
name : "id" ,
namespace : "default" ,
}
storage [ "simple" ] = & simpleStorage
handler := handleLinker ( storage , selfLinker )
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2015-12-01 23:45:29 +00:00
resp , err := http . Get ( server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/id?export=true" )
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
}
if resp . StatusCode != http . StatusOK {
data , _ := ioutil . ReadAll ( resp . Body )
resp . Body . Close ( )
t . Fatalf ( "unexpected response: %#v\n%s\n" , resp , string ( data ) )
}
var itemOut apiservertesting . Simple
body , err := extractBody ( resp , & itemOut )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
if itemOut . Name != simpleStorage . item . Name {
t . Errorf ( "Unexpected data: %#v, expected %#v (%s)" , itemOut , simpleStorage . item , string ( body ) )
}
if itemOut . Other != "exported" {
t . Errorf ( "Expected: exported, saw: %s" , itemOut . Other )
}
if ! selfLinker . called {
t . Errorf ( "Never set self link" )
}
}
2014-06-06 23:40:48 +00:00
func TestGet ( t * testing . T ) {
2015-03-21 16:24:16 +00:00
storage := map [ string ] rest . Storage { }
2014-06-06 23:40:48 +00:00
simpleStorage := SimpleRESTStorage {
2015-10-09 09:07:58 +00:00
item : apiservertesting . Simple {
2014-10-22 17:02:02 +00:00
Other : "foo" ,
2014-06-06 23:40:48 +00:00
} ,
}
2014-09-26 00:20:28 +00:00
selfLinker := & setTestSelfLinker {
t : t ,
2015-11-12 20:20:20 +00:00
expectedSet : "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/id" ,
2015-02-09 14:47:13 +00:00
name : "id" ,
namespace : "default" ,
2014-09-26 00:20:28 +00:00
}
2014-06-06 23:40:48 +00:00
storage [ "simple" ] = & simpleStorage
2015-03-04 20:57:05 +00:00
handler := handleLinker ( storage , selfLinker )
2014-06-06 23:40:48 +00:00
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2014-06-06 23:40:48 +00:00
2015-11-12 20:20:20 +00:00
resp , err := http . Get ( server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/id" )
2015-02-09 14:47:13 +00:00
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
}
if resp . StatusCode != http . StatusOK {
t . Fatalf ( "unexpected response: %#v" , resp )
}
2015-10-09 09:07:58 +00:00
var itemOut apiservertesting . Simple
2014-06-06 23:40:48 +00:00
body , err := extractBody ( resp , & itemOut )
2014-08-04 00:01:15 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
2014-06-06 23:40:48 +00:00
if itemOut . Name != simpleStorage . item . Name {
t . Errorf ( "Unexpected data: %#v, expected %#v (%s)" , itemOut , simpleStorage . item , string ( body ) )
}
2014-09-26 00:20:28 +00:00
if ! selfLinker . called {
t . Errorf ( "Never set self link" )
}
2014-06-06 23:40:48 +00:00
}
2015-03-22 03:25:38 +00:00
func TestGetBinary ( t * testing . T ) {
simpleStorage := SimpleRESTStorage {
stream : & SimpleStream {
contentType : "text/plain" ,
Reader : bytes . NewBufferString ( "response data" ) ,
} ,
}
stream := simpleStorage . stream
server := httptest . NewServer ( handle ( map [ string ] rest . Storage { "simple" : & simpleStorage } ) )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2015-03-22 03:25:38 +00:00
2015-11-12 20:20:20 +00:00
req , err := http . NewRequest ( "GET" , server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/binary" , nil )
2015-06-20 00:16:25 +00:00
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
}
2015-03-22 03:25:38 +00:00
req . Header . Add ( "Accept" , "text/other, */*" )
resp , err := http . DefaultClient . Do ( req )
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
}
if resp . StatusCode != http . StatusOK {
t . Fatalf ( "unexpected response: %#v" , resp )
}
body , err := ioutil . ReadAll ( resp . Body )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
2015-11-12 20:20:20 +00:00
if ! stream . closed || stream . version != testGroupVersion . String ( ) || stream . accept != "text/other, */*" ||
2015-03-22 03:25:38 +00:00
resp . Header . Get ( "Content-Type" ) != stream . contentType || string ( body ) != "response data" {
t . Errorf ( "unexpected stream: %#v" , stream )
}
}
2015-06-26 21:10:28 +00:00
func validateSimpleGetOptionsParams ( t * testing . T , route * restful . Route ) {
// Validate name and description
expectedParams := map [ string ] string {
"param1" : "description for param1" ,
"param2" : "description for param2" ,
"atAPath" : "" ,
}
for _ , p := range route . ParameterDocs {
data := p . Data ( )
if desc , exists := expectedParams [ data . Name ] ; exists {
if desc != data . Description {
t . Errorf ( "unexpected description for parameter %s: %s\n" , data . Name , data . Description )
}
delete ( expectedParams , data . Name )
}
}
if len ( expectedParams ) > 0 {
t . Errorf ( "did not find all expected parameters: %#v" , expectedParams )
}
}
func TestGetWithOptionsRouteParams ( t * testing . T ) {
storage := map [ string ] rest . Storage { }
simpleStorage := GetWithOptionsRESTStorage {
SimpleRESTStorage : & SimpleRESTStorage { } ,
}
storage [ "simple" ] = & simpleStorage
handler := handle ( storage )
ws := handler . ( * defaultAPIServer ) . container . RegisteredWebServices ( )
if len ( ws ) == 0 {
t . Fatal ( "no web services registered" )
}
routes := ws [ 0 ] . Routes ( )
for i := range routes {
if routes [ i ] . Method == "GET" && routes [ i ] . Operation == "readNamespacedSimple" {
validateSimpleGetOptionsParams ( t , & routes [ i ] )
break
}
}
}
2015-04-06 16:58:00 +00:00
func TestGetWithOptions ( t * testing . T ) {
storage := map [ string ] rest . Storage { }
simpleStorage := GetWithOptionsRESTStorage {
SimpleRESTStorage : & SimpleRESTStorage {
2015-10-09 09:07:58 +00:00
item : apiservertesting . Simple {
2015-04-06 16:58:00 +00:00
Other : "foo" ,
} ,
} ,
}
storage [ "simple" ] = & simpleStorage
handler := handle ( storage )
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2015-04-06 16:58:00 +00:00
2015-11-12 20:20:20 +00:00
resp , err := http . Get ( server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/id?param1=test1¶m2=test2" )
2015-04-06 16:58:00 +00:00
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
}
if resp . StatusCode != http . StatusOK {
t . Fatalf ( "unexpected response: %#v" , resp )
}
2015-10-09 09:07:58 +00:00
var itemOut apiservertesting . Simple
2015-04-06 16:58:00 +00:00
body , err := extractBody ( resp , & itemOut )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
if itemOut . Name != simpleStorage . item . Name {
t . Errorf ( "Unexpected data: %#v, expected %#v (%s)" , itemOut , simpleStorage . item , string ( body ) )
}
2015-10-09 09:07:58 +00:00
opts , ok := simpleStorage . optionsReceived . ( * apiservertesting . SimpleGetOptions )
2015-04-06 16:58:00 +00:00
if ! ok {
t . Errorf ( "Unexpected options object received: %#v" , simpleStorage . optionsReceived )
return
}
if opts . Param1 != "test1" || opts . Param2 != "test2" {
t . Errorf ( "Did not receive expected options: %#v" , opts )
}
}
2015-04-11 15:13:10 +00:00
func TestGetWithOptionsAndPath ( t * testing . T ) {
storage := map [ string ] rest . Storage { }
simpleStorage := GetWithOptionsRESTStorage {
SimpleRESTStorage : & SimpleRESTStorage {
2015-10-09 09:07:58 +00:00
item : apiservertesting . Simple {
2015-04-11 15:13:10 +00:00
Other : "foo" ,
} ,
} ,
takesPath : "atAPath" ,
}
storage [ "simple" ] = & simpleStorage
handler := handle ( storage )
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2015-04-11 15:13:10 +00:00
2015-11-12 20:20:20 +00:00
resp , err := http . Get ( server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/id/a/different/path?param1=test1¶m2=test2&atAPath=not" )
2015-04-11 15:13:10 +00:00
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
}
if resp . StatusCode != http . StatusOK {
t . Fatalf ( "unexpected response: %#v" , resp )
}
2015-10-09 09:07:58 +00:00
var itemOut apiservertesting . Simple
2015-04-11 15:13:10 +00:00
body , err := extractBody ( resp , & itemOut )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
if itemOut . Name != simpleStorage . item . Name {
t . Errorf ( "Unexpected data: %#v, expected %#v (%s)" , itemOut , simpleStorage . item , string ( body ) )
}
2015-10-09 09:07:58 +00:00
opts , ok := simpleStorage . optionsReceived . ( * apiservertesting . SimpleGetOptions )
2015-04-11 15:13:10 +00:00
if ! ok {
t . Errorf ( "Unexpected options object received: %#v" , simpleStorage . optionsReceived )
return
}
if opts . Param1 != "test1" || opts . Param2 != "test2" || opts . Path != "a/different/path" {
t . Errorf ( "Did not receive expected options: %#v" , opts )
}
}
2015-02-09 14:47:13 +00:00
func TestGetAlternateSelfLink ( t * testing . T ) {
2015-03-21 16:24:16 +00:00
storage := map [ string ] rest . Storage { }
2015-02-09 14:47:13 +00:00
simpleStorage := SimpleRESTStorage {
2015-10-09 09:07:58 +00:00
item : apiservertesting . Simple {
2015-02-09 14:47:13 +00:00
Other : "foo" ,
} ,
}
selfLinker := & setTestSelfLinker {
t : t ,
2015-11-12 20:20:20 +00:00
expectedSet : "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/test/simple/id" ,
2015-02-09 14:47:13 +00:00
name : "id" ,
namespace : "test" ,
}
storage [ "simple" ] = & simpleStorage
2015-03-04 20:57:05 +00:00
handler := handleLinker ( storage , selfLinker )
2015-02-09 14:47:13 +00:00
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2015-02-09 14:47:13 +00:00
2015-11-12 20:20:20 +00:00
resp , err := http . Get ( server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/test/simple/id" )
2015-02-09 14:47:13 +00:00
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
}
if resp . StatusCode != http . StatusOK {
t . Fatalf ( "unexpected response: %#v" , resp )
}
2015-10-09 09:07:58 +00:00
var itemOut apiservertesting . Simple
2015-02-09 14:47:13 +00:00
body , err := extractBody ( resp , & itemOut )
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
}
if itemOut . Name != simpleStorage . item . Name {
t . Errorf ( "Unexpected data: %#v, expected %#v (%s)" , itemOut , simpleStorage . item , string ( body ) )
}
if ! selfLinker . called {
t . Errorf ( "Never set self link" )
}
}
func TestGetNamespaceSelfLink ( t * testing . T ) {
2015-03-21 16:24:16 +00:00
storage := map [ string ] rest . Storage { }
2015-02-09 14:47:13 +00:00
simpleStorage := SimpleRESTStorage {
2015-10-09 09:07:58 +00:00
item : apiservertesting . Simple {
2015-02-09 14:47:13 +00:00
Other : "foo" ,
} ,
}
selfLinker := & setTestSelfLinker {
t : t ,
2015-11-12 20:20:20 +00:00
expectedSet : "/" + prefix + "/" + newGroupVersion . Group + "/" + newGroupVersion . Version + "/namespaces/foo/simple/id" ,
2015-02-09 14:47:13 +00:00
name : "id" ,
namespace : "foo" ,
}
storage [ "simple" ] = & simpleStorage
2015-11-13 16:16:26 +00:00
handler := handleInternal ( storage , admissionControl , selfLinker )
2015-02-09 14:47:13 +00:00
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2015-02-09 14:47:13 +00:00
2015-11-12 20:20:20 +00:00
resp , err := http . Get ( server . URL + "/" + prefix + "/" + newGroupVersion . Group + "/" + newGroupVersion . Version + "/namespaces/foo/simple/id" )
2015-02-09 14:47:13 +00:00
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
}
if resp . StatusCode != http . StatusOK {
t . Fatalf ( "unexpected response: %#v" , resp )
}
2015-10-09 09:07:58 +00:00
var itemOut apiservertesting . Simple
2015-02-09 14:47:13 +00:00
body , err := extractBody ( resp , & itemOut )
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
}
if itemOut . Name != simpleStorage . item . Name {
t . Errorf ( "Unexpected data: %#v, expected %#v (%s)" , itemOut , simpleStorage . item , string ( body ) )
}
if ! selfLinker . called {
t . Errorf ( "Never set self link" )
}
}
2016-05-05 21:28:54 +00:00
2014-07-16 05:27:15 +00:00
func TestGetMissing ( t * testing . T ) {
2015-03-21 16:24:16 +00:00
storage := map [ string ] rest . Storage { }
2014-07-16 05:27:15 +00:00
simpleStorage := SimpleRESTStorage {
2015-12-10 18:32:29 +00:00
errors : map [ string ] error { "get" : apierrs . NewNotFound ( api . Resource ( "simples" ) , "id" ) } ,
2014-07-16 05:27:15 +00:00
}
storage [ "simple" ] = & simpleStorage
2015-03-04 20:57:05 +00:00
handler := handle ( storage )
2014-07-16 05:27:15 +00:00
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2014-07-16 05:27:15 +00:00
2016-05-05 21:28:54 +00:00
resp , err := http . Get ( server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/id" )
2014-08-04 00:01:15 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
2014-07-16 05:27:15 +00:00
if resp . StatusCode != http . StatusNotFound {
t . Errorf ( "Unexpected response %#v" , resp )
}
}
2016-05-05 21:28:54 +00:00
func TestGetRetryAfter ( t * testing . T ) {
storage := map [ string ] rest . Storage { }
simpleStorage := SimpleRESTStorage {
errors : map [ string ] error { "get" : apierrs . NewServerTimeout ( api . Resource ( "simples" ) , "id" , 2 ) } ,
}
storage [ "simple" ] = & simpleStorage
handler := handle ( storage )
server := httptest . NewServer ( handler )
defer server . Close ( )
resp , err := http . Get ( server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/id" )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
if resp . StatusCode != http . StatusInternalServerError {
t . Errorf ( "Unexpected response %#v" , resp )
}
if resp . Header . Get ( "Retry-After" ) != "2" {
t . Errorf ( "Unexpected Retry-After header: %v" , resp . Header )
}
}
2015-04-14 14:57:00 +00:00
func TestConnect ( t * testing . T ) {
responseText := "Hello World"
itemID := "theID"
connectStorage := & ConnecterRESTStorage {
2015-10-11 03:14:18 +00:00
connectHandler : & OutputConnect {
2015-04-14 14:57:00 +00:00
response : responseText ,
} ,
}
storage := map [ string ] rest . Storage {
2015-05-08 04:31:53 +00:00
"simple" : & SimpleRESTStorage { } ,
2015-04-14 14:57:00 +00:00
"simple/connect" : connectStorage ,
}
handler := handle ( storage )
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2015-04-14 14:57:00 +00:00
2015-11-12 20:20:20 +00:00
resp , err := http . Get ( server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/" + itemID + "/connect" )
2015-04-14 14:57:00 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
if resp . StatusCode != http . StatusOK {
t . Errorf ( "unexpected response: %#v" , resp )
}
defer resp . Body . Close ( )
body , err := ioutil . ReadAll ( resp . Body )
if err != nil {
t . Fatalf ( "Unexpected error: %v" , err )
}
if connectStorage . receivedID != itemID {
t . Errorf ( "Unexpected item id. Expected: %s. Actual: %s." , itemID , connectStorage . receivedID )
}
if string ( body ) != responseText {
t . Errorf ( "Unexpected response. Expected: %s. Actual: %s." , responseText , string ( body ) )
}
}
2015-10-11 03:14:18 +00:00
func TestConnectResponderObject ( t * testing . T ) {
itemID := "theID"
simple := & apiservertesting . Simple { Other : "foo" }
connectStorage := & ConnecterRESTStorage { }
connectStorage . handlerFunc = func ( ) http . Handler {
return http . HandlerFunc ( func ( w http . ResponseWriter , req * http . Request ) {
connectStorage . receivedResponder . Object ( http . StatusCreated , simple )
} )
}
storage := map [ string ] rest . Storage {
"simple" : & SimpleRESTStorage { } ,
"simple/connect" : connectStorage ,
}
handler := handle ( storage )
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2015-10-11 03:14:18 +00:00
2015-11-12 20:20:20 +00:00
resp , err := http . Get ( server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/" + itemID + "/connect" )
2015-10-11 03:14:18 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
if resp . StatusCode != http . StatusCreated {
t . Errorf ( "unexpected response: %#v" , resp )
}
defer resp . Body . Close ( )
body , err := ioutil . ReadAll ( resp . Body )
if err != nil {
t . Fatalf ( "Unexpected error: %v" , err )
}
if connectStorage . receivedID != itemID {
t . Errorf ( "Unexpected item id. Expected: %s. Actual: %s." , itemID , connectStorage . receivedID )
}
2015-12-10 02:15:02 +00:00
obj , err := runtime . Decode ( codec , body )
2015-10-11 03:14:18 +00:00
if err != nil {
t . Fatal ( err )
}
if ! api . Semantic . DeepEqual ( obj , simple ) {
t . Errorf ( "Unexpected response: %#v" , obj )
}
}
func TestConnectResponderError ( t * testing . T ) {
itemID := "theID"
connectStorage := & ConnecterRESTStorage { }
connectStorage . handlerFunc = func ( ) http . Handler {
return http . HandlerFunc ( func ( w http . ResponseWriter , req * http . Request ) {
2015-12-10 18:32:29 +00:00
connectStorage . receivedResponder . Error ( apierrs . NewForbidden ( api . Resource ( "simples" ) , itemID , errors . New ( "you are terminated" ) ) )
2015-10-11 03:14:18 +00:00
} )
}
storage := map [ string ] rest . Storage {
"simple" : & SimpleRESTStorage { } ,
"simple/connect" : connectStorage ,
}
handler := handle ( storage )
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2015-10-11 03:14:18 +00:00
2015-11-12 20:20:20 +00:00
resp , err := http . Get ( server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/" + itemID + "/connect" )
2015-10-11 03:14:18 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
if resp . StatusCode != http . StatusForbidden {
t . Errorf ( "unexpected response: %#v" , resp )
}
defer resp . Body . Close ( )
body , err := ioutil . ReadAll ( resp . Body )
if err != nil {
t . Fatalf ( "Unexpected error: %v" , err )
}
if connectStorage . receivedID != itemID {
t . Errorf ( "Unexpected item id. Expected: %s. Actual: %s." , itemID , connectStorage . receivedID )
}
2015-12-10 02:15:02 +00:00
obj , err := runtime . Decode ( codec , body )
2015-10-11 03:14:18 +00:00
if err != nil {
t . Fatal ( err )
}
if obj . ( * unversioned . Status ) . Code != http . StatusForbidden {
t . Errorf ( "Unexpected response: %#v" , obj )
}
}
2015-06-26 21:10:28 +00:00
func TestConnectWithOptionsRouteParams ( t * testing . T ) {
connectStorage := & ConnecterRESTStorage {
2015-10-11 03:14:18 +00:00
connectHandler : & OutputConnect { } ,
2015-10-09 09:07:58 +00:00
emptyConnectOptions : & apiservertesting . SimpleGetOptions { } ,
2015-06-26 21:10:28 +00:00
}
storage := map [ string ] rest . Storage {
"simple" : & SimpleRESTStorage { } ,
"simple/connect" : connectStorage ,
}
handler := handle ( storage )
ws := handler . ( * defaultAPIServer ) . container . RegisteredWebServices ( )
if len ( ws ) == 0 {
t . Fatal ( "no web services registered" )
}
routes := ws [ 0 ] . Routes ( )
for i := range routes {
switch routes [ i ] . Operation {
case "connectGetNamespacedSimpleConnect" :
case "connectPostNamespacedSimpleConnect" :
case "connectPutNamespacedSimpleConnect" :
case "connectDeleteNamespacedSimpleConnect" :
validateSimpleGetOptionsParams ( t , & routes [ i ] )
}
}
}
2015-04-14 14:57:00 +00:00
func TestConnectWithOptions ( t * testing . T ) {
responseText := "Hello World"
itemID := "theID"
connectStorage := & ConnecterRESTStorage {
2015-10-11 03:14:18 +00:00
connectHandler : & OutputConnect {
2015-04-14 14:57:00 +00:00
response : responseText ,
} ,
2015-10-09 09:07:58 +00:00
emptyConnectOptions : & apiservertesting . SimpleGetOptions { } ,
2015-04-14 14:57:00 +00:00
}
storage := map [ string ] rest . Storage {
2015-05-08 04:31:53 +00:00
"simple" : & SimpleRESTStorage { } ,
2015-04-14 14:57:00 +00:00
"simple/connect" : connectStorage ,
}
handler := handle ( storage )
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2015-04-14 14:57:00 +00:00
2015-11-12 20:20:20 +00:00
resp , err := http . Get ( server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/" + itemID + "/connect?param1=value1¶m2=value2" )
2015-04-14 14:57:00 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
if resp . StatusCode != http . StatusOK {
t . Errorf ( "unexpected response: %#v" , resp )
}
defer resp . Body . Close ( )
body , err := ioutil . ReadAll ( resp . Body )
if err != nil {
t . Fatalf ( "Unexpected error: %v" , err )
}
if connectStorage . receivedID != itemID {
t . Errorf ( "Unexpected item id. Expected: %s. Actual: %s." , itemID , connectStorage . receivedID )
}
if string ( body ) != responseText {
t . Errorf ( "Unexpected response. Expected: %s. Actual: %s." , responseText , string ( body ) )
}
2015-10-11 03:14:18 +00:00
if connectStorage . receivedResponder == nil {
t . Errorf ( "Unexpected responder" )
}
2015-10-09 09:07:58 +00:00
opts , ok := connectStorage . receivedConnectOptions . ( * apiservertesting . SimpleGetOptions )
2015-04-14 14:57:00 +00:00
if ! ok {
2015-11-17 18:21:32 +00:00
t . Fatalf ( "Unexpected options type: %#v" , connectStorage . receivedConnectOptions )
2015-04-14 14:57:00 +00:00
}
if opts . Param1 != "value1" && opts . Param2 != "value2" {
t . Errorf ( "Unexpected options value: %#v" , opts )
}
}
func TestConnectWithOptionsAndPath ( t * testing . T ) {
responseText := "Hello World"
itemID := "theID"
testPath := "a/b/c/def"
connectStorage := & ConnecterRESTStorage {
2015-10-11 03:14:18 +00:00
connectHandler : & OutputConnect {
2015-04-14 14:57:00 +00:00
response : responseText ,
} ,
2015-10-09 09:07:58 +00:00
emptyConnectOptions : & apiservertesting . SimpleGetOptions { } ,
2015-04-14 14:57:00 +00:00
takesPath : "atAPath" ,
}
storage := map [ string ] rest . Storage {
2015-05-08 04:31:53 +00:00
"simple" : & SimpleRESTStorage { } ,
2015-04-14 14:57:00 +00:00
"simple/connect" : connectStorage ,
}
handler := handle ( storage )
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2015-04-14 14:57:00 +00:00
2015-11-12 20:20:20 +00:00
resp , err := http . Get ( server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/" + itemID + "/connect/" + testPath + "?param1=value1¶m2=value2" )
2015-04-14 14:57:00 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
if resp . StatusCode != http . StatusOK {
t . Errorf ( "unexpected response: %#v" , resp )
}
defer resp . Body . Close ( )
body , err := ioutil . ReadAll ( resp . Body )
if err != nil {
t . Fatalf ( "Unexpected error: %v" , err )
}
if connectStorage . receivedID != itemID {
t . Errorf ( "Unexpected item id. Expected: %s. Actual: %s." , itemID , connectStorage . receivedID )
}
if string ( body ) != responseText {
t . Errorf ( "Unexpected response. Expected: %s. Actual: %s." , responseText , string ( body ) )
}
2015-10-09 09:07:58 +00:00
opts , ok := connectStorage . receivedConnectOptions . ( * apiservertesting . SimpleGetOptions )
2015-04-14 14:57:00 +00:00
if ! ok {
2015-11-17 18:21:32 +00:00
t . Fatalf ( "Unexpected options type: %#v" , connectStorage . receivedConnectOptions )
2015-04-14 14:57:00 +00:00
}
if opts . Param1 != "value1" && opts . Param2 != "value2" {
t . Errorf ( "Unexpected options value: %#v" , opts )
}
if opts . Path != testPath {
t . Errorf ( "Unexpected path value. Expected: %s. Actual: %s." , testPath , opts . Path )
}
}
2014-06-06 23:40:48 +00:00
func TestDelete ( t * testing . T ) {
2015-03-21 16:24:16 +00:00
storage := map [ string ] rest . Storage { }
2014-06-06 23:40:48 +00:00
simpleStorage := SimpleRESTStorage { }
ID := "id"
storage [ "simple" ] = & simpleStorage
2015-03-04 20:57:05 +00:00
handler := handle ( storage )
2014-06-06 23:40:48 +00:00
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2014-06-06 23:40:48 +00:00
client := http . Client { }
2015-11-12 20:20:20 +00:00
request , err := http . NewRequest ( "DELETE" , server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/" + ID , nil )
2015-02-09 14:47:13 +00:00
res , err := client . Do ( request )
2014-08-04 00:01:15 +00:00
if err != nil {
2015-02-09 14:47:13 +00:00
t . Fatalf ( "unexpected error: %v" , err )
}
if res . StatusCode != http . StatusOK {
t . Errorf ( "unexpected response: %#v" , res )
2014-08-04 00:01:15 +00:00
}
2014-06-06 23:40:48 +00:00
if simpleStorage . deleted != ID {
2014-07-18 19:03:22 +00:00
t . Errorf ( "Unexpected delete: %s, expected %s" , simpleStorage . deleted , ID )
2014-06-06 23:40:48 +00:00
}
}
2015-03-05 03:34:31 +00:00
func TestDeleteWithOptions ( t * testing . T ) {
2015-03-21 16:24:16 +00:00
storage := map [ string ] rest . Storage { }
2015-03-05 03:34:31 +00:00
simpleStorage := SimpleRESTStorage { }
ID := "id"
storage [ "simple" ] = & simpleStorage
handler := handle ( storage )
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2015-03-05 03:34:31 +00:00
grace := int64 ( 300 )
item := & api . DeleteOptions {
GracePeriodSeconds : & grace ,
}
2015-12-10 02:15:02 +00:00
body , err := runtime . Encode ( codec , item )
2015-03-05 03:34:31 +00:00
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
}
client := http . Client { }
2015-11-12 20:20:20 +00:00
request , err := http . NewRequest ( "DELETE" , server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/" + ID , bytes . NewReader ( body ) )
2015-03-05 03:34:31 +00:00
res , err := client . Do ( request )
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
}
if res . StatusCode != http . StatusOK {
t . Errorf ( "unexpected response: %s %#v" , request . URL , res )
2015-06-20 00:16:25 +00:00
s , err := ioutil . ReadAll ( res . Body )
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
}
2015-03-05 03:34:31 +00:00
t . Logf ( string ( s ) )
}
if simpleStorage . deleted != ID {
t . Errorf ( "Unexpected delete: %s, expected %s" , simpleStorage . deleted , ID )
}
2016-07-02 06:46:00 +00:00
simpleStorage . deleteOptions . GetObjectKind ( ) . SetGroupVersionKind ( unversioned . GroupVersionKind { } )
2015-03-05 03:34:31 +00:00
if ! api . Semantic . DeepEqual ( simpleStorage . deleteOptions , item ) {
2016-03-11 02:43:55 +00:00
t . Errorf ( "unexpected delete options: %s" , diff . ObjectDiff ( simpleStorage . deleteOptions , item ) )
2015-03-05 03:34:31 +00:00
}
}
func TestLegacyDelete ( t * testing . T ) {
2015-03-21 16:24:16 +00:00
storage := map [ string ] rest . Storage { }
2015-03-05 03:34:31 +00:00
simpleStorage := SimpleRESTStorage { }
ID := "id"
storage [ "simple" ] = LegacyRESTStorage { & simpleStorage }
2015-03-21 16:24:16 +00:00
var _ rest . Deleter = storage [ "simple" ] . ( LegacyRESTStorage )
2015-03-05 03:34:31 +00:00
handler := handle ( storage )
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2015-03-05 03:34:31 +00:00
client := http . Client { }
2015-11-12 20:20:20 +00:00
request , err := http . NewRequest ( "DELETE" , server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/" + ID , nil )
2015-03-05 03:34:31 +00:00
res , err := client . Do ( request )
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
}
if res . StatusCode != http . StatusOK {
t . Errorf ( "unexpected response: %#v" , res )
}
if simpleStorage . deleted != ID {
t . Errorf ( "Unexpected delete: %s, expected %s" , simpleStorage . deleted , ID )
}
if simpleStorage . deleteOptions != nil {
t . Errorf ( "unexpected delete options: %#v" , simpleStorage . deleteOptions )
}
}
func TestLegacyDeleteIgnoresOptions ( t * testing . T ) {
2015-03-21 16:24:16 +00:00
storage := map [ string ] rest . Storage { }
2015-03-05 03:34:31 +00:00
simpleStorage := SimpleRESTStorage { }
ID := "id"
storage [ "simple" ] = LegacyRESTStorage { & simpleStorage }
handler := handle ( storage )
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2015-03-05 03:34:31 +00:00
item := api . NewDeleteOptions ( 300 )
2015-12-10 02:15:02 +00:00
body , err := runtime . Encode ( codec , item )
2015-03-05 03:34:31 +00:00
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
}
client := http . Client { }
2015-11-12 20:20:20 +00:00
request , err := http . NewRequest ( "DELETE" , server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/" + ID , bytes . NewReader ( body ) )
2015-03-05 03:34:31 +00:00
res , err := client . Do ( request )
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
}
if res . StatusCode != http . StatusOK {
t . Errorf ( "unexpected response: %#v" , res )
}
if simpleStorage . deleted != ID {
t . Errorf ( "Unexpected delete: %s, expected %s" , simpleStorage . deleted , ID )
}
if simpleStorage . deleteOptions != nil {
t . Errorf ( "unexpected delete options: %#v" , simpleStorage . deleteOptions )
}
}
2015-01-06 20:16:13 +00:00
func TestDeleteInvokesAdmissionControl ( t * testing . T ) {
2015-03-21 16:24:16 +00:00
storage := map [ string ] rest . Storage { }
2015-01-06 20:16:13 +00:00
simpleStorage := SimpleRESTStorage { }
ID := "id"
storage [ "simple" ] = & simpleStorage
2015-03-04 20:57:05 +00:00
handler := handleDeny ( storage )
2015-01-06 20:16:13 +00:00
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2015-01-06 20:16:13 +00:00
client := http . Client { }
2015-11-12 20:20:20 +00:00
request , err := http . NewRequest ( "DELETE" , server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/" + ID , nil )
2015-01-06 20:16:13 +00:00
response , err := client . Do ( request )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
2015-01-07 19:33:21 +00:00
if response . StatusCode != http . StatusForbidden {
2015-01-06 20:16:13 +00:00
t . Errorf ( "Unexpected response %#v" , response )
}
}
2014-07-16 05:27:15 +00:00
func TestDeleteMissing ( t * testing . T ) {
2015-03-21 16:24:16 +00:00
storage := map [ string ] rest . Storage { }
2014-07-16 05:27:15 +00:00
ID := "id"
simpleStorage := SimpleRESTStorage {
2015-12-10 18:32:29 +00:00
errors : map [ string ] error { "delete" : apierrs . NewNotFound ( api . Resource ( "simples" ) , ID ) } ,
2014-07-16 05:27:15 +00:00
}
storage [ "simple" ] = & simpleStorage
2015-03-04 20:57:05 +00:00
handler := handle ( storage )
2014-07-16 05:27:15 +00:00
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2014-07-16 05:27:15 +00:00
client := http . Client { }
2015-11-12 20:20:20 +00:00
request , err := http . NewRequest ( "DELETE" , server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/" + ID , nil )
2014-07-16 05:27:15 +00:00
response , err := client . Do ( request )
2014-08-04 00:01:15 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
2014-07-16 05:27:15 +00:00
if response . StatusCode != http . StatusNotFound {
t . Errorf ( "Unexpected response %#v" , response )
}
}
2015-02-21 18:54:48 +00:00
func TestPatch ( t * testing . T ) {
2015-03-21 16:24:16 +00:00
storage := map [ string ] rest . Storage { }
2015-02-21 18:54:48 +00:00
ID := "id"
2015-10-09 09:07:58 +00:00
item := & apiservertesting . Simple {
2015-02-21 18:54:48 +00:00
ObjectMeta : api . ObjectMeta {
Name : ID ,
Namespace : "" , // update should allow the client to send an empty namespace
2016-04-29 01:21:35 +00:00
UID : "uid" ,
2015-02-21 18:54:48 +00:00
} ,
Other : "bar" ,
}
simpleStorage := SimpleRESTStorage { item : * item }
storage [ "simple" ] = & simpleStorage
selfLinker := & setTestSelfLinker {
t : t ,
2015-11-12 20:20:20 +00:00
expectedSet : "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/" + ID ,
2015-02-21 18:54:48 +00:00
name : ID ,
namespace : api . NamespaceDefault ,
}
handler := handleLinker ( storage , selfLinker )
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2015-02-21 18:54:48 +00:00
client := http . Client { }
2015-11-12 20:20:20 +00:00
request , err := http . NewRequest ( "PATCH" , server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/" + ID , bytes . NewReader ( [ ] byte ( ` { "labels": { "foo":"bar"}} ` ) ) )
2015-09-30 21:03:27 +00:00
request . Header . Set ( "Content-Type" , "application/merge-patch+json; charset=UTF-8" )
2015-02-21 18:54:48 +00:00
_ , err = client . Do ( request )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
if simpleStorage . updated == nil || simpleStorage . updated . Labels [ "foo" ] != "bar" {
t . Errorf ( "Unexpected update value %#v, expected %#v." , simpleStorage . updated , item )
}
if ! selfLinker . called {
t . Errorf ( "Never set self link" )
}
}
func TestPatchRequiresMatchingName ( t * testing . T ) {
2015-03-21 16:24:16 +00:00
storage := map [ string ] rest . Storage { }
2015-02-21 18:54:48 +00:00
ID := "id"
2015-10-09 09:07:58 +00:00
item := & apiservertesting . Simple {
2015-02-21 18:54:48 +00:00
ObjectMeta : api . ObjectMeta {
Name : ID ,
Namespace : "" , // update should allow the client to send an empty namespace
2016-04-29 01:21:35 +00:00
UID : "uid" ,
2015-02-21 18:54:48 +00:00
} ,
Other : "bar" ,
}
simpleStorage := SimpleRESTStorage { item : * item }
storage [ "simple" ] = & simpleStorage
handler := handle ( storage )
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2015-02-21 18:54:48 +00:00
client := http . Client { }
2015-11-12 20:20:20 +00:00
request , err := http . NewRequest ( "PATCH" , server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/" + ID , bytes . NewReader ( [ ] byte ( ` { "metadata": { "name":"idbar"}} ` ) ) )
2015-03-14 00:43:14 +00:00
request . Header . Set ( "Content-Type" , "application/merge-patch+json" )
2015-02-21 18:54:48 +00:00
response , err := client . Do ( request )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
if response . StatusCode != http . StatusBadRequest {
t . Errorf ( "Unexpected response %#v" , response )
}
}
2014-06-06 23:40:48 +00:00
func TestUpdate ( t * testing . T ) {
2015-03-21 16:24:16 +00:00
storage := map [ string ] rest . Storage { }
2014-06-06 23:40:48 +00:00
simpleStorage := SimpleRESTStorage { }
ID := "id"
storage [ "simple" ] = & simpleStorage
2014-09-26 00:20:28 +00:00
selfLinker := & setTestSelfLinker {
t : t ,
2015-11-12 20:20:20 +00:00
expectedSet : "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/" + ID ,
2015-02-09 14:47:13 +00:00
name : ID ,
namespace : api . NamespaceDefault ,
2014-09-26 00:20:28 +00:00
}
2015-03-04 20:57:05 +00:00
handler := handleLinker ( storage , selfLinker )
2014-06-06 23:40:48 +00:00
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2014-06-06 23:40:48 +00:00
2015-10-09 09:07:58 +00:00
item := & apiservertesting . Simple {
2015-02-09 14:47:13 +00:00
ObjectMeta : api . ObjectMeta {
Name : ID ,
Namespace : "" , // update should allow the client to send an empty namespace
} ,
2014-10-22 17:02:02 +00:00
Other : "bar" ,
2014-06-06 23:40:48 +00:00
}
2015-12-21 05:15:35 +00:00
body , err := runtime . Encode ( testCodec , item )
2014-08-04 00:01:15 +00:00
if err != nil {
2014-11-11 07:11:45 +00:00
// The following cases will fail, so die now
t . Fatalf ( "unexpected error: %v" , err )
2014-08-04 00:01:15 +00:00
}
2014-06-06 23:40:48 +00:00
client := http . Client { }
2015-11-12 20:20:20 +00:00
request , err := http . NewRequest ( "PUT" , server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/" + ID , bytes . NewReader ( body ) )
2014-06-06 23:40:48 +00:00
_ , err = client . Do ( request )
2014-08-04 00:01:15 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
2014-11-11 07:11:45 +00:00
if simpleStorage . updated == nil || simpleStorage . updated . Name != item . Name {
2014-06-06 23:40:48 +00:00
t . Errorf ( "Unexpected update value %#v, expected %#v." , simpleStorage . updated , item )
}
2014-09-26 00:20:28 +00:00
if ! selfLinker . called {
t . Errorf ( "Never set self link" )
}
2014-06-06 23:40:48 +00:00
}
2015-01-06 20:16:13 +00:00
func TestUpdateInvokesAdmissionControl ( t * testing . T ) {
2015-03-21 16:24:16 +00:00
storage := map [ string ] rest . Storage { }
2015-01-06 20:16:13 +00:00
simpleStorage := SimpleRESTStorage { }
ID := "id"
storage [ "simple" ] = & simpleStorage
2015-03-04 20:57:05 +00:00
handler := handleDeny ( storage )
2015-01-06 20:16:13 +00:00
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2015-01-06 20:16:13 +00:00
2015-10-09 09:07:58 +00:00
item := & apiservertesting . Simple {
2015-02-09 14:47:13 +00:00
ObjectMeta : api . ObjectMeta {
Name : ID ,
Namespace : api . NamespaceDefault ,
} ,
2015-01-06 20:16:13 +00:00
Other : "bar" ,
}
2015-12-21 05:15:35 +00:00
body , err := runtime . Encode ( testCodec , item )
2015-01-06 20:16:13 +00:00
if err != nil {
// The following cases will fail, so die now
t . Fatalf ( "unexpected error: %v" , err )
}
client := http . Client { }
2015-11-12 20:20:20 +00:00
request , err := http . NewRequest ( "PUT" , server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/" + ID , bytes . NewReader ( body ) )
2015-01-06 20:16:13 +00:00
response , err := client . Do ( request )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
2015-01-07 19:33:21 +00:00
if response . StatusCode != http . StatusForbidden {
2015-01-06 20:16:13 +00:00
t . Errorf ( "Unexpected response %#v" , response )
}
}
2015-02-09 14:47:13 +00:00
func TestUpdateRequiresMatchingName ( t * testing . T ) {
2015-03-21 16:24:16 +00:00
storage := map [ string ] rest . Storage { }
2015-02-09 14:47:13 +00:00
simpleStorage := SimpleRESTStorage { }
ID := "id"
storage [ "simple" ] = & simpleStorage
2015-03-04 20:57:05 +00:00
handler := handleDeny ( storage )
2015-02-09 14:47:13 +00:00
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2015-02-09 14:47:13 +00:00
2015-10-09 09:07:58 +00:00
item := & apiservertesting . Simple {
2015-02-09 14:47:13 +00:00
Other : "bar" ,
}
2015-12-21 05:15:35 +00:00
body , err := runtime . Encode ( testCodec , item )
2015-02-09 14:47:13 +00:00
if err != nil {
// The following cases will fail, so die now
t . Fatalf ( "unexpected error: %v" , err )
}
client := http . Client { }
2015-11-12 20:20:20 +00:00
request , err := http . NewRequest ( "PUT" , server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/" + ID , bytes . NewReader ( body ) )
2015-02-09 14:47:13 +00:00
response , err := client . Do ( request )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
if response . StatusCode != http . StatusBadRequest {
t . Errorf ( "Unexpected response %#v" , response )
}
}
func TestUpdateAllowsMissingNamespace ( t * testing . T ) {
2015-03-21 16:24:16 +00:00
storage := map [ string ] rest . Storage { }
2015-02-09 14:47:13 +00:00
simpleStorage := SimpleRESTStorage { }
ID := "id"
storage [ "simple" ] = & simpleStorage
2015-03-04 20:57:05 +00:00
handler := handle ( storage )
2015-02-09 14:47:13 +00:00
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2015-02-09 14:47:13 +00:00
2015-10-09 09:07:58 +00:00
item := & apiservertesting . Simple {
2015-02-09 14:47:13 +00:00
ObjectMeta : api . ObjectMeta {
Name : ID ,
} ,
Other : "bar" ,
}
2015-12-21 05:15:35 +00:00
body , err := runtime . Encode ( testCodec , item )
2015-02-09 14:47:13 +00:00
if err != nil {
// The following cases will fail, so die now
t . Fatalf ( "unexpected error: %v" , err )
}
client := http . Client { }
2015-11-12 20:20:20 +00:00
request , err := http . NewRequest ( "PUT" , server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/" + ID , bytes . NewReader ( body ) )
2015-02-09 14:47:13 +00:00
response , err := client . Do ( request )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
if response . StatusCode != http . StatusOK {
t . Errorf ( "Unexpected response %#v" , response )
}
}
2015-02-12 19:21:47 +00:00
// when the object name and namespace can't be retrieved, skip name checking
func TestUpdateAllowsMismatchedNamespaceOnError ( t * testing . T ) {
2015-03-21 16:24:16 +00:00
storage := map [ string ] rest . Storage { }
2015-02-12 19:21:47 +00:00
simpleStorage := SimpleRESTStorage { }
ID := "id"
storage [ "simple" ] = & simpleStorage
selfLinker := & setTestSelfLinker {
t : t ,
err : fmt . Errorf ( "test error" ) ,
}
2015-03-04 20:57:05 +00:00
handler := handleLinker ( storage , selfLinker )
2015-02-12 19:21:47 +00:00
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2015-02-12 19:21:47 +00:00
2015-10-09 09:07:58 +00:00
item := & apiservertesting . Simple {
2015-02-12 19:21:47 +00:00
ObjectMeta : api . ObjectMeta {
Name : ID ,
Namespace : "other" , // does not match request
} ,
Other : "bar" ,
}
2015-12-21 05:15:35 +00:00
body , err := runtime . Encode ( testCodec , item )
2015-02-12 19:21:47 +00:00
if err != nil {
// The following cases will fail, so die now
t . Fatalf ( "unexpected error: %v" , err )
}
client := http . Client { }
2015-11-12 20:20:20 +00:00
request , err := http . NewRequest ( "PUT" , server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/" + ID , bytes . NewReader ( body ) )
2015-02-12 19:21:47 +00:00
_ , err = client . Do ( request )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
if simpleStorage . updated == nil || simpleStorage . updated . Name != item . Name {
t . Errorf ( "Unexpected update value %#v, expected %#v." , simpleStorage . updated , item )
}
if selfLinker . called {
t . Errorf ( "self link ignored" )
}
}
2015-02-09 14:47:13 +00:00
func TestUpdatePreventsMismatchedNamespace ( t * testing . T ) {
2015-03-21 16:24:16 +00:00
storage := map [ string ] rest . Storage { }
2015-02-09 14:47:13 +00:00
simpleStorage := SimpleRESTStorage { }
ID := "id"
storage [ "simple" ] = & simpleStorage
2015-03-04 20:57:05 +00:00
handler := handle ( storage )
2015-02-09 14:47:13 +00:00
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2015-02-09 14:47:13 +00:00
2015-10-09 09:07:58 +00:00
item := & apiservertesting . Simple {
2015-02-09 14:47:13 +00:00
ObjectMeta : api . ObjectMeta {
Name : ID ,
Namespace : "other" ,
} ,
Other : "bar" ,
}
2015-12-21 05:15:35 +00:00
body , err := runtime . Encode ( testCodec , item )
2015-02-09 14:47:13 +00:00
if err != nil {
// The following cases will fail, so die now
t . Fatalf ( "unexpected error: %v" , err )
}
client := http . Client { }
2015-11-12 20:20:20 +00:00
request , err := http . NewRequest ( "PUT" , server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/" + ID , bytes . NewReader ( body ) )
2015-02-09 14:47:13 +00:00
response , err := client . Do ( request )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
if response . StatusCode != http . StatusBadRequest {
t . Errorf ( "Unexpected response %#v" , response )
}
}
2014-07-16 05:27:15 +00:00
func TestUpdateMissing ( t * testing . T ) {
2015-03-21 16:24:16 +00:00
storage := map [ string ] rest . Storage { }
2014-07-16 05:27:15 +00:00
ID := "id"
simpleStorage := SimpleRESTStorage {
2015-12-10 18:32:29 +00:00
errors : map [ string ] error { "update" : apierrs . NewNotFound ( api . Resource ( "simples" ) , ID ) } ,
2014-07-16 05:27:15 +00:00
}
storage [ "simple" ] = & simpleStorage
2015-03-04 20:57:05 +00:00
handler := handle ( storage )
2014-07-16 05:27:15 +00:00
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2014-07-16 05:27:15 +00:00
2015-10-09 09:07:58 +00:00
item := & apiservertesting . Simple {
2015-02-09 14:47:13 +00:00
ObjectMeta : api . ObjectMeta {
Name : ID ,
Namespace : api . NamespaceDefault ,
} ,
2014-10-22 17:02:02 +00:00
Other : "bar" ,
2014-07-16 05:27:15 +00:00
}
2015-12-21 05:15:35 +00:00
body , err := runtime . Encode ( testCodec , item )
2014-08-04 00:01:15 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
2014-07-16 05:27:15 +00:00
client := http . Client { }
2015-11-12 20:20:20 +00:00
request , err := http . NewRequest ( "PUT" , server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/" + ID , bytes . NewReader ( body ) )
2014-07-16 05:27:15 +00:00
response , err := client . Do ( request )
2014-08-04 00:01:15 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
2014-07-16 05:27:15 +00:00
if response . StatusCode != http . StatusNotFound {
t . Errorf ( "Unexpected response %#v" , response )
}
}
func TestCreateNotFound ( t * testing . T ) {
2015-03-21 16:24:16 +00:00
handler := handle ( map [ string ] rest . Storage {
2014-07-31 18:16:13 +00:00
"simple" : & SimpleRESTStorage {
// storage.Create can fail with not found error in theory.
2015-08-06 01:09:50 +00:00
// See http://pr.k8s.io/486#discussion_r15037092.
2015-12-10 18:32:29 +00:00
errors : map [ string ] error { "create" : apierrs . NewNotFound ( api . Resource ( "simples" ) , "id" ) } ,
2014-07-31 18:16:13 +00:00
} ,
2015-03-04 20:57:05 +00:00
} )
2014-07-16 05:27:15 +00:00
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2014-07-16 05:27:15 +00:00
client := http . Client { }
2015-10-09 09:07:58 +00:00
simple := & apiservertesting . Simple { Other : "foo" }
2015-12-21 05:15:35 +00:00
data , err := runtime . Encode ( testCodec , simple )
2015-06-20 00:16:25 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
2015-11-12 20:20:20 +00:00
request , err := http . NewRequest ( "POST" , server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple" , bytes . NewBuffer ( data ) )
2014-08-04 00:01:15 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
2014-07-16 05:27:15 +00:00
response , err := client . Do ( request )
2014-08-04 00:01:15 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
2014-07-16 05:27:15 +00:00
if response . StatusCode != http . StatusNotFound {
t . Errorf ( "Unexpected response %#v" , response )
}
}
2015-03-04 20:57:05 +00:00
func TestCreateChecksDecode ( t * testing . T ) {
2015-03-21 16:24:16 +00:00
handler := handle ( map [ string ] rest . Storage { "simple" : & SimpleRESTStorage { } } )
2015-03-04 20:57:05 +00:00
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2015-03-04 20:57:05 +00:00
client := http . Client { }
simple := & api . Pod { }
2016-05-22 21:23:08 +00:00
data , err := runtime . Encode ( testCodec , simple )
2015-06-20 00:16:25 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
2015-11-12 20:20:20 +00:00
request , err := http . NewRequest ( "POST" , server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple" , bytes . NewBuffer ( data ) )
2015-03-04 20:57:05 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
response , err := client . Do ( request )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
if response . StatusCode != http . StatusBadRequest {
t . Errorf ( "Unexpected response %#v" , response )
}
2015-06-20 00:16:25 +00:00
b , err := ioutil . ReadAll ( response . Body )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
} else if ! strings . Contains ( string ( b ) , "cannot be handled as a Simple" ) {
2015-03-04 20:57:05 +00:00
t . Errorf ( "unexpected response: %s" , string ( b ) )
}
}
2015-09-14 20:34:11 +00:00
// TestUpdateREST tests that you can add new rest implementations to a pre-existing
// web service.
func TestUpdateREST ( t * testing . T ) {
makeGroup := func ( storage map [ string ] rest . Storage ) * APIGroupVersion {
return & APIGroupVersion {
2015-10-20 17:34:26 +00:00
Storage : storage ,
2015-11-12 20:20:20 +00:00
Root : "/" + prefix ,
2015-10-20 17:34:26 +00:00
RequestInfoResolver : newTestRequestInfoResolver ( ) ,
Creater : api . Scheme ,
Convertor : api . Scheme ,
2016-04-29 01:21:35 +00:00
Copier : api . Scheme ,
2015-10-20 17:34:26 +00:00
Typer : api . Scheme ,
Linker : selfLinker ,
2015-09-14 20:34:11 +00:00
Admit : admissionControl ,
Context : requestContextMapper ,
Mapper : namespaceMapper ,
2015-12-08 19:40:23 +00:00
GroupVersion : newGroupVersion ,
OptionsExternalVersion : & newGroupVersion ,
2015-12-21 05:15:35 +00:00
2016-04-20 17:35:09 +00:00
Serializer : api . Codecs ,
ParameterCodec : api . ParameterCodec ,
2015-09-14 20:34:11 +00:00
}
}
makeStorage := func ( paths ... string ) map [ string ] rest . Storage {
storage := map [ string ] rest . Storage { }
for _ , s := range paths {
storage [ s ] = & SimpleRESTStorage { }
}
return storage
}
testREST := func ( t * testing . T , container * restful . Container , barCode int ) {
w := httptest . NewRecorder ( )
2015-11-12 20:20:20 +00:00
container . ServeHTTP ( w , & http . Request { Method : "GET" , URL : & url . URL { Path : "/" + prefix + "/" + newGroupVersion . Group + "/" + newGroupVersion . Version + "/namespaces/test/foo/test" } } )
2015-09-14 20:34:11 +00:00
if w . Code != http . StatusOK {
t . Fatalf ( "expected OK: %#v" , w )
}
w = httptest . NewRecorder ( )
2015-11-12 20:20:20 +00:00
container . ServeHTTP ( w , & http . Request { Method : "GET" , URL : & url . URL { Path : "/" + prefix + "/" + newGroupVersion . Group + "/" + newGroupVersion . Version + "/namespaces/test/bar/test" } } )
2015-09-14 20:34:11 +00:00
if w . Code != barCode {
t . Errorf ( "expected response code %d for GET to bar but received %d" , barCode , w . Code )
}
}
storage1 := makeStorage ( "foo" )
group1 := makeGroup ( storage1 )
storage2 := makeStorage ( "bar" )
group2 := makeGroup ( storage2 )
container := restful . NewContainer ( )
// install group1. Ensure that
// 1. Foo storage is accessible
// 2. Bar storage is not accessible
if err := group1 . InstallREST ( container ) ; err != nil {
t . Fatal ( err )
}
testREST ( t , container , http . StatusNotFound )
// update with group2. Ensure that
// 1. Foo storage is still accessible
// 2. Bar storage is now accessible
if err := group2 . UpdateREST ( container ) ; err != nil {
t . Fatal ( err )
}
testREST ( t , container , http . StatusOK )
// try to update a group that does not have an existing webservice with a matching prefix
// should not affect the existing registered webservice
invalidGroup := makeGroup ( storage1 )
invalidGroup . Root = "bad"
if err := invalidGroup . UpdateREST ( container ) ; err == nil {
t . Fatal ( "expected an error from UpdateREST when updating a non-existing prefix but got none" )
}
testREST ( t , container , http . StatusOK )
}
2015-05-08 04:31:53 +00:00
func TestParentResourceIsRequired ( t * testing . T ) {
storage := & SimpleTypedStorage {
2015-10-09 09:07:58 +00:00
baseType : & apiservertesting . SimpleRoot { } , // a root scoped type
item : & apiservertesting . SimpleRoot { } ,
2015-05-08 04:31:53 +00:00
}
group := & APIGroupVersion {
Storage : map [ string ] rest . Storage {
"simple/sub" : storage ,
} ,
2015-11-12 20:20:20 +00:00
Root : "/" + prefix ,
2015-10-20 17:34:26 +00:00
RequestInfoResolver : newTestRequestInfoResolver ( ) ,
Creater : api . Scheme ,
Convertor : api . Scheme ,
2016-04-29 01:21:35 +00:00
Copier : api . Scheme ,
2015-10-20 17:34:26 +00:00
Typer : api . Scheme ,
Linker : selfLinker ,
2015-05-08 04:31:53 +00:00
Admit : admissionControl ,
Context : requestContextMapper ,
Mapper : namespaceMapper ,
2015-12-08 19:40:23 +00:00
GroupVersion : newGroupVersion ,
OptionsExternalVersion : & newGroupVersion ,
2015-12-21 05:15:35 +00:00
2016-04-20 17:35:09 +00:00
Serializer : api . Codecs ,
ParameterCodec : api . ParameterCodec ,
2015-05-08 04:31:53 +00:00
}
container := restful . NewContainer ( )
2015-06-16 02:39:31 +00:00
if err := group . InstallREST ( container ) ; err == nil {
2015-05-08 04:31:53 +00:00
t . Fatal ( "expected error" )
}
storage = & SimpleTypedStorage {
2015-10-09 09:07:58 +00:00
baseType : & apiservertesting . SimpleRoot { } , // a root scoped type
item : & apiservertesting . SimpleRoot { } ,
2015-05-08 04:31:53 +00:00
}
group = & APIGroupVersion {
Storage : map [ string ] rest . Storage {
"simple" : & SimpleRESTStorage { } ,
"simple/sub" : storage ,
} ,
2015-11-12 20:20:20 +00:00
Root : "/" + prefix ,
2015-10-20 17:34:26 +00:00
RequestInfoResolver : newTestRequestInfoResolver ( ) ,
Creater : api . Scheme ,
Convertor : api . Scheme ,
2016-04-29 01:21:35 +00:00
Copier : api . Scheme ,
2015-10-20 17:34:26 +00:00
Typer : api . Scheme ,
Linker : selfLinker ,
2015-05-08 04:31:53 +00:00
Admit : admissionControl ,
Context : requestContextMapper ,
Mapper : namespaceMapper ,
2015-12-08 19:40:23 +00:00
GroupVersion : newGroupVersion ,
OptionsExternalVersion : & newGroupVersion ,
2015-12-21 05:15:35 +00:00
2016-04-20 17:35:09 +00:00
Serializer : api . Codecs ,
ParameterCodec : api . ParameterCodec ,
2015-05-08 04:31:53 +00:00
}
container = restful . NewContainer ( )
2015-06-16 02:39:31 +00:00
if err := group . InstallREST ( container ) ; err != nil {
2015-05-08 04:31:53 +00:00
t . Fatal ( err )
}
// resource is NOT registered in the root scope
w := httptest . NewRecorder ( )
2015-11-12 20:20:20 +00:00
container . ServeHTTP ( w , & http . Request { Method : "GET" , URL : & url . URL { Path : "/" + prefix + "/simple/test/sub" } } )
2015-05-08 04:31:53 +00:00
if w . Code != http . StatusNotFound {
t . Errorf ( "expected not found: %#v" , w )
}
// resource is registered in the namespace scope
w = httptest . NewRecorder ( )
2015-11-12 20:20:20 +00:00
container . ServeHTTP ( w , & http . Request { Method : "GET" , URL : & url . URL { Path : "/" + prefix + "/" + newGroupVersion . Group + "/" + newGroupVersion . Version + "/namespaces/test/simple/test/sub" } } )
2015-05-08 04:31:53 +00:00
if w . Code != http . StatusOK {
t . Fatalf ( "expected OK: %#v" , w )
}
if storage . actualNamespace != "test" {
t . Errorf ( "namespace should be set %#v" , storage )
}
}
2015-05-04 18:38:41 +00:00
func TestCreateWithName ( t * testing . T ) {
pathName := "helloworld"
storage := & NamedCreaterRESTStorage { SimpleRESTStorage : & SimpleRESTStorage { } }
2015-05-08 04:31:53 +00:00
handler := handle ( map [ string ] rest . Storage {
"simple" : & SimpleRESTStorage { } ,
"simple/sub" : storage ,
} )
2015-05-04 18:38:41 +00:00
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2015-05-04 18:38:41 +00:00
client := http . Client { }
2015-10-09 09:07:58 +00:00
simple := & apiservertesting . Simple { Other : "foo" }
2015-12-21 05:15:35 +00:00
data , err := runtime . Encode ( testCodec , simple )
2015-06-20 00:16:25 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
2015-11-12 20:20:20 +00:00
request , err := http . NewRequest ( "POST" , server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/" + pathName + "/sub" , bytes . NewBuffer ( data ) )
2015-05-04 18:38:41 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
response , err := client . Do ( request )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
if response . StatusCode != http . StatusCreated {
t . Errorf ( "Unexpected response %#v" , response )
}
if storage . createdName != pathName {
t . Errorf ( "Did not get expected name in create context. Got: %s, Expected: %s" , storage . createdName , pathName )
}
}
2015-03-04 20:57:05 +00:00
func TestUpdateChecksDecode ( t * testing . T ) {
2015-03-21 16:24:16 +00:00
handler := handle ( map [ string ] rest . Storage { "simple" : & SimpleRESTStorage { } } )
2015-03-04 20:57:05 +00:00
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2015-03-04 20:57:05 +00:00
client := http . Client { }
simple := & api . Pod { }
2016-05-22 21:23:08 +00:00
data , err := runtime . Encode ( testCodec , simple )
2015-06-20 00:16:25 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
2015-11-12 20:20:20 +00:00
request , err := http . NewRequest ( "PUT" , server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/bar" , bytes . NewBuffer ( data ) )
2015-03-04 20:57:05 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
response , err := client . Do ( request )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
if response . StatusCode != http . StatusBadRequest {
2015-12-21 05:15:35 +00:00
t . Errorf ( "Unexpected response %#v\n%s" , response , readBodyOrDie ( response . Body ) )
2015-03-04 20:57:05 +00:00
}
2015-06-20 00:16:25 +00:00
b , err := ioutil . ReadAll ( response . Body )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
} else if ! strings . Contains ( string ( b ) , "cannot be handled as a Simple" ) {
2015-03-04 20:57:05 +00:00
t . Errorf ( "unexpected response: %s" , string ( b ) )
}
}
2014-06-25 20:21:32 +00:00
func TestParseTimeout ( t * testing . T ) {
2015-09-03 17:50:23 +00:00
if d := parseTimeout ( "" ) ; d != 30 * time . Second {
2014-06-25 20:21:32 +00:00
t . Errorf ( "blank timeout produces %v" , d )
}
2015-09-03 17:50:23 +00:00
if d := parseTimeout ( "not a timeout" ) ; d != 30 * time . Second {
2014-06-25 20:21:32 +00:00
t . Errorf ( "bad timeout produces %v" , d )
}
if d := parseTimeout ( "10s" ) ; d != 10 * time . Second {
t . Errorf ( "10s timeout produced: %v" , d )
2014-06-06 23:40:48 +00:00
}
}
2014-06-19 04:04:11 +00:00
2014-09-26 00:20:28 +00:00
type setTestSelfLinker struct {
t * testing . T
expectedSet string
2014-10-23 02:54:34 +00:00
name string
2014-11-24 18:35:24 +00:00
namespace string
2014-09-26 00:20:28 +00:00
called bool
2015-02-12 19:21:47 +00:00
err error
2014-09-26 00:20:28 +00:00
}
2015-02-12 19:21:47 +00:00
func ( s * setTestSelfLinker ) Namespace ( runtime . Object ) ( string , error ) { return s . namespace , s . err }
func ( s * setTestSelfLinker ) Name ( runtime . Object ) ( string , error ) { return s . name , s . err }
func ( s * setTestSelfLinker ) SelfLink ( runtime . Object ) ( string , error ) { return "" , s . err }
2014-09-26 00:20:28 +00:00
func ( s * setTestSelfLinker ) SetSelfLink ( obj runtime . Object , selfLink string ) error {
if e , a := s . expectedSet , selfLink ; e != a {
s . t . Errorf ( "expected '%v', got '%v'" , e , a )
}
s . called = true
2015-02-12 19:21:47 +00:00
return s . err
2014-09-26 00:20:28 +00:00
}
2015-01-22 05:20:57 +00:00
func TestCreate ( t * testing . T ) {
2015-02-12 19:21:47 +00:00
storage := SimpleRESTStorage {
injectedFunction : func ( obj runtime . Object ) ( runtime . Object , error ) {
time . Sleep ( 5 * time . Millisecond )
return obj , nil
} ,
}
selfLinker := & setTestSelfLinker {
t : t ,
name : "bar" ,
namespace : "default" ,
2015-11-12 20:20:20 +00:00
expectedSet : "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/foo/bar" ,
2015-02-12 19:21:47 +00:00
}
2015-03-21 16:24:16 +00:00
handler := handleLinker ( map [ string ] rest . Storage { "foo" : & storage } , selfLinker )
2015-02-12 19:21:47 +00:00
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2015-02-12 19:21:47 +00:00
client := http . Client { }
2015-10-09 09:07:58 +00:00
simple := & apiservertesting . Simple {
2015-02-12 19:21:47 +00:00
Other : "bar" ,
}
2015-12-21 05:15:35 +00:00
data , err := runtime . Encode ( testCodec , simple )
2015-06-20 00:16:25 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
2015-11-12 20:20:20 +00:00
request , err := http . NewRequest ( "POST" , server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/foo" , bytes . NewBuffer ( data ) )
2015-02-12 19:21:47 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
wg := sync . WaitGroup { }
wg . Add ( 1 )
var response * http . Response
go func ( ) {
response , err = client . Do ( request )
wg . Done ( )
} ( )
wg . Wait ( )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
2015-10-09 09:07:58 +00:00
var itemOut apiservertesting . Simple
2015-02-12 19:21:47 +00:00
body , err := extractBody ( response , & itemOut )
if err != nil {
2015-12-21 05:15:35 +00:00
t . Errorf ( "unexpected error: %v %#v" , err , response )
2015-02-12 19:21:47 +00:00
}
2016-07-02 06:46:00 +00:00
itemOut . GetObjectKind ( ) . SetGroupVersionKind ( unversioned . GroupVersionKind { } )
2015-02-12 19:21:47 +00:00
if ! reflect . DeepEqual ( & itemOut , simple ) {
t . Errorf ( "Unexpected data: %#v, expected %#v (%s)" , itemOut , simple , string ( body ) )
}
if response . StatusCode != http . StatusCreated {
t . Errorf ( "Unexpected status: %d, Expected: %d, %#v" , response . StatusCode , http . StatusOK , response )
}
if ! selfLinker . called {
t . Errorf ( "Never set self link" )
}
}
2015-12-21 05:15:35 +00:00
func TestCreateYAML ( t * testing . T ) {
storage := SimpleRESTStorage {
injectedFunction : func ( obj runtime . Object ) ( runtime . Object , error ) {
time . Sleep ( 5 * time . Millisecond )
return obj , nil
} ,
}
selfLinker := & setTestSelfLinker {
t : t ,
name : "bar" ,
namespace : "default" ,
expectedSet : "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/foo/bar" ,
}
handler := handleLinker ( map [ string ] rest . Storage { "foo" : & storage } , selfLinker )
server := httptest . NewServer ( handler )
defer server . Close ( )
client := http . Client { }
// yaml encoder
simple := & apiservertesting . Simple {
Other : "bar" ,
}
2015-12-21 05:21:26 +00:00
serializer , ok := api . Codecs . SerializerForMediaType ( "application/yaml" , nil )
2015-12-21 05:15:35 +00:00
if ! ok {
t . Fatal ( "No yaml serializer" )
}
2015-12-21 05:21:26 +00:00
encoder := api . Codecs . EncoderForVersion ( serializer , testGroupVersion )
decoder := api . Codecs . DecoderToVersion ( serializer , testInternalGroupVersion )
2015-12-21 05:15:35 +00:00
data , err := runtime . Encode ( encoder , simple )
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 ) )
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
}
request . Header . Set ( "Accept" , "application/yaml, application/json" )
request . Header . Set ( "Content-Type" , "application/yaml" )
wg := sync . WaitGroup { }
wg . Add ( 1 )
var response * http . Response
go func ( ) {
response , err = client . Do ( request )
wg . Done ( )
} ( )
wg . Wait ( )
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
}
var itemOut apiservertesting . Simple
body , err := extractBodyDecoder ( response , & itemOut , decoder )
if err != nil {
t . Fatalf ( "unexpected error: %v %#v" , err , response )
}
2016-07-02 06:46:00 +00:00
itemOut . GetObjectKind ( ) . SetGroupVersionKind ( unversioned . GroupVersionKind { } )
2015-12-21 05:15:35 +00:00
if ! reflect . DeepEqual ( & itemOut , simple ) {
t . Errorf ( "Unexpected data: %#v, expected %#v (%s)" , itemOut , simple , string ( body ) )
}
if response . StatusCode != http . StatusCreated {
t . Errorf ( "Unexpected status: %d, Expected: %d, %#v" , response . StatusCode , http . StatusOK , response )
}
if ! selfLinker . called {
t . Errorf ( "Never set self link" )
}
}
2015-02-12 19:21:47 +00:00
func TestCreateInNamespace ( t * testing . T ) {
2014-06-19 04:04:11 +00:00
storage := SimpleRESTStorage {
2014-09-08 04:14:18 +00:00
injectedFunction : func ( obj runtime . Object ) ( runtime . Object , error ) {
2014-07-31 18:16:13 +00:00
time . Sleep ( 5 * time . Millisecond )
2014-06-25 20:21:32 +00:00
return obj , nil
} ,
2014-06-19 04:04:11 +00:00
}
2014-09-26 00:20:28 +00:00
selfLinker := & setTestSelfLinker {
t : t ,
2014-10-23 02:54:34 +00:00
name : "bar" ,
2014-11-24 18:35:24 +00:00
namespace : "other" ,
2015-11-12 20:20:20 +00:00
expectedSet : "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/other/foo/bar" ,
2014-09-26 00:20:28 +00:00
}
2015-03-21 16:24:16 +00:00
handler := handleLinker ( map [ string ] rest . Storage { "foo" : & storage } , selfLinker )
2014-06-19 04:04:11 +00:00
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2014-06-19 04:04:11 +00:00
client := http . Client { }
2015-10-09 09:07:58 +00:00
simple := & apiservertesting . Simple {
2014-10-22 17:02:02 +00:00
Other : "bar" ,
2014-07-16 21:30:28 +00:00
}
2015-12-21 05:15:35 +00:00
data , err := runtime . Encode ( testCodec , simple )
2015-06-20 00:16:25 +00:00
if err != nil {
2015-12-21 05:15:35 +00:00
t . Fatalf ( "unexpected error: %v" , err )
2015-06-20 00:16:25 +00:00
}
2015-11-12 20:20:20 +00:00
request , err := http . NewRequest ( "POST" , server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/other/foo" , bytes . NewBuffer ( data ) )
2014-08-04 00:01:15 +00:00
if err != nil {
2015-12-21 05:15:35 +00:00
t . Fatalf ( "unexpected error: %v" , err )
2014-08-04 00:01:15 +00:00
}
2014-06-19 04:04:11 +00:00
wg := sync . WaitGroup { }
wg . Add ( 1 )
var response * http . Response
go func ( ) {
response , err = client . Do ( request )
wg . Done ( )
} ( )
wg . Wait ( )
2014-08-04 00:01:15 +00:00
if err != nil {
2015-12-21 05:15:35 +00:00
t . Fatalf ( "unexpected error: %v" , err )
2014-08-04 00:01:15 +00:00
}
2015-10-09 09:07:58 +00:00
var itemOut apiservertesting . Simple
2014-06-19 04:04:11 +00:00
body , err := extractBody ( response , & itemOut )
2014-08-04 00:01:15 +00:00
if err != nil {
2015-12-21 05:15:35 +00:00
t . Fatalf ( "unexpected error: %v\n%s" , err , data )
2014-08-04 00:01:15 +00:00
}
2016-07-02 06:46:00 +00:00
itemOut . GetObjectKind ( ) . SetGroupVersionKind ( unversioned . GroupVersionKind { } )
2014-09-08 04:14:18 +00:00
if ! reflect . DeepEqual ( & itemOut , simple ) {
2014-06-19 04:04:11 +00:00
t . Errorf ( "Unexpected data: %#v, expected %#v (%s)" , itemOut , simple , string ( body ) )
}
2015-02-10 14:26:26 +00:00
if response . StatusCode != http . StatusCreated {
2014-06-25 20:21:32 +00:00
t . Errorf ( "Unexpected status: %d, Expected: %d, %#v" , response . StatusCode , http . StatusOK , response )
}
2014-09-26 00:20:28 +00:00
if ! selfLinker . called {
t . Errorf ( "Never set self link" )
}
2014-06-19 04:04:11 +00:00
}
2015-01-22 05:20:57 +00:00
func TestCreateInvokesAdmissionControl ( t * testing . T ) {
storage := SimpleRESTStorage {
injectedFunction : func ( obj runtime . Object ) ( runtime . Object , error ) {
time . Sleep ( 5 * time . Millisecond )
return obj , nil
} ,
}
selfLinker := & setTestSelfLinker {
t : t ,
name : "bar" ,
namespace : "other" ,
2015-11-12 20:20:20 +00:00
expectedSet : "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/other/foo/bar" ,
2015-01-22 05:20:57 +00:00
}
2015-11-13 16:16:26 +00:00
handler := handleInternal ( map [ string ] rest . Storage { "foo" : & storage } , deny . NewAlwaysDeny ( ) , selfLinker )
2015-01-22 05:20:57 +00:00
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2015-01-22 05:20:57 +00:00
client := http . Client { }
2015-10-09 09:07:58 +00:00
simple := & apiservertesting . Simple {
2015-01-22 05:20:57 +00:00
Other : "bar" ,
}
2015-12-21 05:15:35 +00:00
data , err := runtime . Encode ( testCodec , simple )
2015-06-20 00:16:25 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
2015-11-12 20:20:20 +00:00
request , err := http . NewRequest ( "POST" , server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/other/foo" , bytes . NewBuffer ( data ) )
2015-01-22 05:20:57 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
wg := sync . WaitGroup { }
wg . Add ( 1 )
var response * http . Response
go func ( ) {
response , err = client . Do ( request )
wg . Done ( )
} ( )
wg . Wait ( )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
if response . StatusCode != http . StatusForbidden {
t . Errorf ( "Unexpected status: %d, Expected: %d, %#v" , response . StatusCode , http . StatusForbidden , response )
}
}
2015-09-09 21:59:11 +00:00
func expectApiStatus ( t * testing . T , method , url string , data [ ] byte , code int ) * unversioned . Status {
2014-07-31 18:16:13 +00:00
client := http . Client { }
request , err := http . NewRequest ( method , url , bytes . NewBuffer ( data ) )
if err != nil {
t . Fatalf ( "unexpected error %#v" , err )
return nil
}
response , err := client . Do ( request )
if err != nil {
2014-07-31 18:26:34 +00:00
t . Fatalf ( "unexpected error on %s %s: %v" , method , url , err )
2014-07-31 18:16:13 +00:00
return nil
}
2015-09-09 21:59:11 +00:00
var status unversioned . Status
2015-09-18 00:43:05 +00:00
if body , err := extractBody ( response , & status ) ; err != nil {
t . Fatalf ( "unexpected error on %s %s: %v\nbody:\n%s" , method , url , err , body )
2014-07-31 18:16:13 +00:00
return nil
}
if code != response . StatusCode {
2014-07-31 18:26:34 +00:00
t . Fatalf ( "Expected %s %s to return %d, Got %d" , method , url , code , response . StatusCode )
2014-07-31 18:16:13 +00:00
}
return & status
}
2015-01-22 05:20:57 +00:00
func TestDelayReturnsError ( t * testing . T ) {
2014-07-31 18:16:13 +00:00
storage := SimpleRESTStorage {
2014-09-08 04:14:18 +00:00
injectedFunction : func ( obj runtime . Object ) ( runtime . Object , error ) {
2015-12-10 18:32:29 +00:00
return nil , apierrs . NewAlreadyExists ( api . Resource ( "foos" ) , "bar" )
2014-07-31 18:16:13 +00:00
} ,
}
2015-03-21 16:24:16 +00:00
handler := handle ( map [ string ] rest . Storage { "foo" : & storage } )
2014-07-31 18:16:13 +00:00
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2014-07-31 18:16:13 +00:00
2015-11-12 20:20:20 +00:00
status := expectApiStatus ( t , "DELETE" , fmt . Sprintf ( "%s/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/foo/bar" , server . URL ) , nil , http . StatusConflict )
2015-09-09 21:59:11 +00:00
if status . Status != unversioned . StatusFailure || status . Message == "" || status . Details == nil || status . Reason != unversioned . StatusReasonAlreadyExists {
2014-07-31 18:16:13 +00:00
t . Errorf ( "Unexpected status %#v" , status )
}
}
2014-09-08 04:14:18 +00:00
type UnregisteredAPIObject struct {
Value string
}
2015-12-08 03:01:12 +00:00
func ( obj * UnregisteredAPIObject ) GetObjectKind ( ) unversioned . ObjectKind {
return unversioned . EmptyObjectKind
}
2014-09-08 04:14:18 +00:00
2014-07-31 18:16:13 +00:00
func TestWriteJSONDecodeError ( t * testing . T ) {
server := httptest . NewServer ( http . HandlerFunc ( func ( w http . ResponseWriter , req * http . Request ) {
2015-12-21 05:21:26 +00:00
writeNegotiated ( api . Codecs , newGroupVersion , w , req , http . StatusOK , & UnregisteredAPIObject { "Undecodable" } )
2014-07-31 18:16:13 +00:00
} ) )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2015-09-18 00:43:05 +00:00
// We send a 200 status code before we encode the object, so we expect OK, but there will
// still be an error object. This seems ok, the alternative is to validate the object before
// encoding, but this really should never happen, so it's wasted compute for every API request.
status := expectApiStatus ( t , "GET" , server . URL , nil , http . StatusOK )
2015-09-09 21:59:11 +00:00
if status . Reason != unversioned . StatusReasonUnknown {
2014-07-31 18:26:34 +00:00
t . Errorf ( "unexpected reason %#v" , status )
2014-08-04 00:01:15 +00:00
}
2015-12-21 05:15:35 +00:00
if ! strings . Contains ( status . Message , "no kind is registered for the type apiserver.UnregisteredAPIObject" ) {
2014-07-31 18:26:34 +00:00
t . Errorf ( "unexpected message %#v" , status )
2014-07-31 18:16:13 +00:00
}
}
type marshalError struct {
err error
}
func ( m * marshalError ) MarshalJSON ( ) ( [ ] byte , error ) {
return [ ] byte { } , m . err
}
func TestWriteRAWJSONMarshalError ( t * testing . T ) {
server := httptest . NewServer ( http . HandlerFunc ( func ( w http . ResponseWriter , req * http . Request ) {
writeRawJSON ( http . StatusOK , & marshalError { errors . New ( "Undecodable" ) } , w )
} ) )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2014-07-31 18:16:13 +00:00
client := http . Client { }
resp , err := client . Get ( server . URL )
2014-08-04 00:01:15 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
2014-07-31 18:16:13 +00:00
if resp . StatusCode != http . StatusInternalServerError {
t . Errorf ( "unexpected status code %d" , resp . StatusCode )
}
}
2015-01-22 05:20:57 +00:00
func TestCreateTimeout ( t * testing . T ) {
2014-08-12 00:12:53 +00:00
testOver := make ( chan struct { } )
defer close ( testOver )
2014-06-25 20:21:32 +00:00
storage := SimpleRESTStorage {
2014-09-08 04:14:18 +00:00
injectedFunction : func ( obj runtime . Object ) ( runtime . Object , error ) {
2014-08-12 00:12:53 +00:00
// Eliminate flakes by ensuring the create operation takes longer than this test.
<- testOver
2014-06-25 20:21:32 +00:00
return obj , nil
} ,
}
2015-03-21 16:24:16 +00:00
handler := handle ( map [ string ] rest . Storage {
2014-06-25 20:21:32 +00:00
"foo" : & storage ,
2015-03-04 20:57:05 +00:00
} )
2014-06-19 04:04:11 +00:00
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2014-06-19 04:04:11 +00:00
2015-10-09 09:07:58 +00:00
simple := & apiservertesting . Simple { Other : "foo" }
2015-12-21 05:15:35 +00:00
data , err := runtime . Encode ( testCodec , simple )
2015-06-20 00:16:25 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
2015-11-12 20:20:20 +00:00
itemOut := expectApiStatus ( t , "POST" , server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/foo?timeout=4ms" , data , apierrs . StatusServerTimeout )
2015-09-09 21:59:11 +00:00
if itemOut . Status != unversioned . StatusFailure || itemOut . Reason != unversioned . StatusReasonTimeout {
2014-06-25 20:21:32 +00:00
t . Errorf ( "Unexpected status %#v" , itemOut )
}
2014-06-19 04:04:11 +00:00
}
2014-09-02 16:28:24 +00:00
2014-09-09 21:05:18 +00:00
func TestCORSAllowedOrigins ( t * testing . T ) {
table := [ ] struct {
2015-08-05 14:21:47 +00:00
allowedOrigins [ ] string
2014-09-09 21:05:18 +00:00
origin string
allowed bool
} {
{ [ ] string { } , "example.com" , false } ,
{ [ ] string { "example.com" } , "example.com" , true } ,
{ [ ] string { "example.com" } , "not-allowed.com" , false } ,
{ [ ] string { "not-matching.com" , "example.com" } , "example.com" , true } ,
{ [ ] string { ".*" } , "example.com" , true } ,
2014-09-03 18:33:52 +00:00
}
2014-09-09 21:05:18 +00:00
for _ , item := range table {
allowedOriginRegexps , err := util . CompileRegexps ( item . allowedOrigins )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
2014-09-03 18:33:52 +00:00
2014-09-26 00:20:28 +00:00
handler := CORS (
2015-03-21 16:24:16 +00:00
handle ( map [ string ] rest . Storage { } ) ,
2014-09-26 00:20:28 +00:00
allowedOriginRegexps , nil , nil , "true" ,
)
2014-09-09 21:05:18 +00:00
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2014-09-09 21:05:18 +00:00
client := http . Client { }
2014-09-03 18:33:52 +00:00
2014-09-09 21:05:18 +00:00
request , err := http . NewRequest ( "GET" , server . URL + "/version" , nil )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
request . Header . Set ( "Origin" , item . origin )
2014-09-03 18:33:52 +00:00
2014-09-09 21:05:18 +00:00
response , err := client . Do ( request )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
2014-09-03 18:33:52 +00:00
2014-09-09 21:05:18 +00:00
if item . allowed {
if ! reflect . DeepEqual ( item . origin , response . Header . Get ( "Access-Control-Allow-Origin" ) ) {
t . Errorf ( "Expected %#v, Got %#v" , item . origin , response . Header . Get ( "Access-Control-Allow-Origin" ) )
}
if response . Header . Get ( "Access-Control-Allow-Credentials" ) == "" {
t . Errorf ( "Expected Access-Control-Allow-Credentials header to be set" )
}
if response . Header . Get ( "Access-Control-Allow-Headers" ) == "" {
t . Errorf ( "Expected Access-Control-Allow-Headers header to be set" )
}
if response . Header . Get ( "Access-Control-Allow-Methods" ) == "" {
t . Errorf ( "Expected Access-Control-Allow-Methods header to be set" )
}
} else {
if response . Header . Get ( "Access-Control-Allow-Origin" ) != "" {
t . Errorf ( "Expected Access-Control-Allow-Origin header to not be set" )
}
if response . Header . Get ( "Access-Control-Allow-Credentials" ) != "" {
t . Errorf ( "Expected Access-Control-Allow-Credentials header to not be set" )
}
if response . Header . Get ( "Access-Control-Allow-Headers" ) != "" {
t . Errorf ( "Expected Access-Control-Allow-Headers header to not be set" )
}
if response . Header . Get ( "Access-Control-Allow-Methods" ) != "" {
t . Errorf ( "Expected Access-Control-Allow-Methods header to not be set" )
}
}
2014-09-03 18:33:52 +00:00
}
}
2015-06-20 00:16:25 +00:00
func TestCreateChecksAPIVersion ( t * testing . T ) {
handler := handle ( map [ string ] rest . Storage { "simple" : & SimpleRESTStorage { } } )
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2015-06-20 00:16:25 +00:00
client := http . Client { }
2015-10-09 09:07:58 +00:00
simple := & apiservertesting . Simple { }
2015-06-20 00:16:25 +00:00
//using newCodec and send the request to testVersion URL shall cause a discrepancy in apiVersion
2015-12-10 02:15:02 +00:00
data , err := runtime . Encode ( newCodec , simple )
2015-06-20 00:16:25 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
2015-11-13 13:13:55 +00:00
request , err := http . NewRequest ( "POST" , server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple" , bytes . NewBuffer ( data ) )
2015-06-20 00:16:25 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
response , err := client . Do ( request )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
if response . StatusCode != http . StatusBadRequest {
t . Errorf ( "Unexpected response %#v" , response )
}
b , err := ioutil . ReadAll ( response . Body )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
2015-12-21 05:15:35 +00:00
} else if ! strings . Contains ( string ( b ) , "does not match the expected API version" ) {
2015-06-20 00:16:25 +00:00
t . Errorf ( "unexpected response: %s" , string ( b ) )
}
}
func TestCreateDefaultsAPIVersion ( t * testing . T ) {
handler := handle ( map [ string ] rest . Storage { "simple" : & SimpleRESTStorage { } } )
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2015-06-20 00:16:25 +00:00
client := http . Client { }
2015-10-09 09:07:58 +00:00
simple := & apiservertesting . Simple { }
2015-12-10 02:15:02 +00:00
data , err := runtime . Encode ( codec , simple )
2015-06-20 00:16:25 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
m := make ( map [ string ] interface { } )
if err := json . Unmarshal ( data , & m ) ; err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
delete ( m , "apiVersion" )
data , err = json . Marshal ( m )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
2015-11-13 13:13:55 +00:00
request , err := http . NewRequest ( "POST" , server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple" , bytes . NewBuffer ( data ) )
2015-06-20 00:16:25 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
response , err := client . Do ( request )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
if response . StatusCode != http . StatusCreated {
t . Errorf ( "unexpected status: %d, Expected: %d, %#v" , response . StatusCode , http . StatusCreated , response )
}
}
func TestUpdateChecksAPIVersion ( t * testing . T ) {
handler := handle ( map [ string ] rest . Storage { "simple" : & SimpleRESTStorage { } } )
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2015-06-20 00:16:25 +00:00
client := http . Client { }
2015-10-09 09:07:58 +00:00
simple := & apiservertesting . Simple { ObjectMeta : api . ObjectMeta { Name : "bar" } }
2015-12-10 02:15:02 +00:00
data , err := runtime . Encode ( newCodec , simple )
2015-06-20 00:16:25 +00:00
if err != nil {
2015-12-21 05:15:35 +00:00
t . Fatalf ( "unexpected error: %v" , err )
2015-06-20 00:16:25 +00:00
}
2015-11-13 13:13:55 +00:00
request , err := http . NewRequest ( "PUT" , server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/bar" , bytes . NewBuffer ( data ) )
2015-06-20 00:16:25 +00:00
if err != nil {
2015-12-21 05:15:35 +00:00
t . Fatalf ( "unexpected error: %v" , err )
2015-06-20 00:16:25 +00:00
}
response , err := client . Do ( request )
if err != nil {
2015-12-21 05:15:35 +00:00
t . Fatalf ( "unexpected error: %v" , err )
2015-06-20 00:16:25 +00:00
}
if response . StatusCode != http . StatusBadRequest {
t . Errorf ( "Unexpected response %#v" , response )
}
b , err := ioutil . ReadAll ( response . Body )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
2015-12-21 05:15:35 +00:00
} else if ! strings . Contains ( string ( b ) , "does not match the expected API version" ) {
2015-06-20 00:16:25 +00:00
t . Errorf ( "unexpected response: %s" , string ( b ) )
}
}
2015-12-21 05:15:35 +00:00
2016-02-24 19:10:37 +00:00
// SimpleXGSubresource is a cross group subresource, i.e. the subresource does not belong to the
// same group as its parent resource.
type SimpleXGSubresource struct {
unversioned . TypeMeta ` json:",inline" `
api . ObjectMeta ` json:"metadata" `
SubresourceInfo string ` json:"subresourceInfo,omitempty" `
Labels map [ string ] string ` json:"labels,omitempty" `
}
func ( obj * SimpleXGSubresource ) GetObjectKind ( ) unversioned . ObjectKind { return & obj . TypeMeta }
type SimpleXGSubresourceRESTStorage struct {
item SimpleXGSubresource
}
func ( storage * SimpleXGSubresourceRESTStorage ) New ( ) runtime . Object {
return & SimpleXGSubresource { }
}
func ( storage * SimpleXGSubresourceRESTStorage ) Get ( ctx api . Context , id string ) ( runtime . Object , error ) {
copied , err := api . Scheme . Copy ( & storage . item )
if err != nil {
panic ( err )
}
return copied , nil
}
func TestXGSubresource ( t * testing . T ) {
container := restful . NewContainer ( )
container . Router ( restful . CurlyRouter { } )
mux := container . ServeMux
itemID := "theID"
subresourceStorage := & SimpleXGSubresourceRESTStorage {
item : SimpleXGSubresource {
SubresourceInfo : "foo" ,
} ,
}
storage := map [ string ] rest . Storage {
"simple" : & SimpleRESTStorage { } ,
"simple/subsimple" : subresourceStorage ,
}
group := APIGroupVersion {
Storage : storage ,
RequestInfoResolver : newTestRequestInfoResolver ( ) ,
Creater : api . Scheme ,
Convertor : api . Scheme ,
2016-04-29 01:21:35 +00:00
Copier : api . Scheme ,
2016-02-24 19:10:37 +00:00
Typer : api . Scheme ,
Linker : selfLinker ,
Mapper : namespaceMapper ,
ParameterCodec : api . ParameterCodec ,
Admit : admissionControl ,
Context : requestContextMapper ,
Root : "/" + prefix ,
GroupVersion : testGroupVersion ,
OptionsExternalVersion : & testGroupVersion ,
Serializer : api . Codecs ,
SubresourceGroupVersionKind : map [ string ] unversioned . GroupVersionKind {
"simple/subsimple" : testGroup2Version . WithKind ( "SimpleXGSubresource" ) ,
} ,
}
if err := ( & group ) . InstallREST ( container ) ; err != nil {
panic ( fmt . Sprintf ( "unable to install container %s: %v" , group . GroupVersion , err ) )
}
2016-04-27 01:51:37 +00:00
InstallVersionHandler ( mux , container )
2016-02-24 19:10:37 +00:00
handler := defaultAPIServer { mux , container }
server := httptest . NewServer ( handler )
2016-04-21 11:50:55 +00:00
defer server . Close ( )
2016-02-24 19:10:37 +00:00
resp , err := http . Get ( server . URL + "/" + prefix + "/" + testGroupVersion . Group + "/" + testGroupVersion . Version + "/namespaces/default/simple/" + itemID + "/subsimple" )
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
}
if resp . StatusCode != http . StatusOK {
t . Fatalf ( "unexpected response: %#v" , resp )
}
var itemOut SimpleXGSubresource
body , err := extractBody ( resp , & itemOut )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
// Test if the returned object has the expected group, version and kind
// We are directly unmarshaling JSON here because TypeMeta cannot be decoded through the
// installed decoders. TypeMeta cannot be decoded because it is added to the ignored
// conversion type list in API scheme and hence cannot be converted from input type object
// to output type object. So it's values don't appear in the decoded output object.
decoder := json . NewDecoder ( strings . NewReader ( body ) )
var itemFromBody SimpleXGSubresource
err = decoder . Decode ( & itemFromBody )
if err != nil {
t . Errorf ( "unexpected JSON decoding error: %v" , err )
}
if want := fmt . Sprintf ( "%s/%s" , testGroup2Version . Group , testGroup2Version . Version ) ; itemFromBody . APIVersion != want {
t . Errorf ( "unexpected APIVersion got: %+v want: %+v" , itemFromBody . APIVersion , want )
}
if itemFromBody . Kind != "SimpleXGSubresource" {
t . Errorf ( "unexpected Kind got: %+v want: SimpleXGSubresource" , itemFromBody . Kind )
}
if itemOut . Name != subresourceStorage . item . Name {
t . Errorf ( "Unexpected data: %#v, expected %#v (%s)" , itemOut , subresourceStorage . item , string ( body ) )
}
}
2015-12-21 05:15:35 +00:00
func readBodyOrDie ( r io . Reader ) [ ] byte {
body , err := ioutil . ReadAll ( r )
if err != nil {
panic ( err )
}
return body
}
2016-05-22 21:23:08 +00:00
// BenchmarkUpdateProtobuf measures the cost of processing an update on the server in proto
func BenchmarkUpdateProtobuf ( b * testing . B ) {
items := benchmarkItems ( )
simpleStorage := & SimpleRESTStorage { }
handler := handle ( map [ string ] rest . Storage { "simples" : simpleStorage } )
server := httptest . NewServer ( handler )
defer server . Close ( )
client := http . Client { }
dest , _ := url . Parse ( server . URL )
dest . Path = "/" + prefix + "/" + newGroupVersion . Group + "/" + newGroupVersion . Version + "/namespaces/foo/simples/bar"
dest . RawQuery = ""
info , _ := api . Codecs . SerializerForMediaType ( "application/vnd.kubernetes.protobuf" , nil )
e := api . Codecs . EncoderForVersion ( info . Serializer , newGroupVersion )
data , err := runtime . Encode ( e , & items [ 0 ] )
if err != nil {
b . Fatal ( err )
}
b . ResetTimer ( )
for i := 0 ; i < b . N ; i ++ {
request , err := http . NewRequest ( "PUT" , dest . String ( ) , bytes . NewReader ( data ) )
if err != nil {
b . Fatalf ( "unexpected error: %v" , err )
}
request . Header . Set ( "Accept" , "application/vnd.kubernetes.protobuf" )
request . Header . Set ( "Content-Type" , "application/vnd.kubernetes.protobuf" )
response , err := client . Do ( request )
if err != nil {
b . Fatalf ( "unexpected error: %v" , err )
}
if response . StatusCode != http . StatusBadRequest {
body , _ := ioutil . ReadAll ( response . Body )
b . Fatalf ( "Unexpected response %#v\n%s" , response , body )
}
_ , _ = ioutil . ReadAll ( response . Body )
response . Body . Close ( )
}
b . StopTimer ( )
}