Support subpath on GET for GetterWithOptions

Allows REST consumers to build paths like:

    /api/v1beta3/namespaces/foo/webhookresource/<name>/<encodedsecretinurl>

Also fixes parameter exposure for subresources (was only fixed for
v1beta3).
This commit is contained in:
Clayton Coleman
2015-04-11 11:13:10 -04:00
parent 7ac4a22f18
commit 0225d76b6a
5 changed files with 124 additions and 39 deletions

View File

@@ -239,6 +239,7 @@ type SimpleGetOptions struct {
api.TypeMeta `json:",inline"`
Param1 string `json:"param1"`
Param2 string `json:"param2"`
Path string `json:"atAPath"`
}
func (*SimpleGetOptions) IsAnAPIObject() {}
@@ -459,9 +460,12 @@ func (m *MetadataRESTStorage) ProducesMIMETypes(method string) []string {
return m.types
}
var _ rest.StorageMetadata = &MetadataRESTStorage{}
type GetWithOptionsRESTStorage struct {
*SimpleRESTStorage
optionsReceived runtime.Object
takesPath string
}
func (r *GetWithOptionsRESTStorage) Get(ctx api.Context, name string, options runtime.Object) (runtime.Object, error) {
@@ -472,10 +476,15 @@ func (r *GetWithOptionsRESTStorage) Get(ctx api.Context, name string, options ru
return r.SimpleRESTStorage.Get(ctx, name)
}
func (r *GetWithOptionsRESTStorage) NewGetOptions() runtime.Object {
return &SimpleGetOptions{}
func (r *GetWithOptionsRESTStorage) NewGetOptions() (runtime.Object, bool, string) {
if len(r.takesPath) > 0 {
return &SimpleGetOptions{}, true, r.takesPath
}
return &SimpleGetOptions{}, false, ""
}
var _ rest.GetterWithOptions = &GetWithOptionsRESTStorage{}
func extractBody(response *http.Response, object runtime.Object) (string, error) {
defer response.Body.Close()
body, err := ioutil.ReadAll(response.Body)
@@ -963,6 +972,47 @@ func TestGetWithOptions(t *testing.T) {
}
}
func TestGetWithOptionsAndPath(t *testing.T) {
storage := map[string]rest.Storage{}
simpleStorage := GetWithOptionsRESTStorage{
SimpleRESTStorage: &SimpleRESTStorage{
item: Simple{
Other: "foo",
},
},
takesPath: "atAPath",
}
storage["simple"] = &simpleStorage
handler := handle(storage)
server := httptest.NewServer(handler)
defer server.Close()
resp, err := http.Get(server.URL + "/api/version/simple/id/a/different/path?param1=test1&param2=test2&atAPath=not")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if resp.StatusCode != http.StatusOK {
t.Fatalf("unexpected response: %#v", resp)
}
var itemOut 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))
}
opts, ok := simpleStorage.optionsReceived.(*SimpleGetOptions)
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)
}
}
func TestGetAlternateSelfLink(t *testing.T) {
storage := map[string]rest.Storage{}
simpleStorage := SimpleRESTStorage{