Merge pull request #22009 from aveshagarwal/master-create-urls-issue

Fix kubectl create to create to all resources in a url.
This commit is contained in:
Jeff Lowdermilk 2016-03-03 15:21:35 -08:00
commit afa7816c38
4 changed files with 41 additions and 24 deletions

View File

@ -1502,6 +1502,29 @@ __EOF__
kubectl delete -f "${file}" "${kube_flags[@]}" kubectl delete -f "${file}" "${kube_flags[@]}"
done done
#############################
# Multiple Resources via URL#
#############################
# Pre-condition: no service (other than default kubernetes services) or replication controller exists
kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:'
kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" ''
# Command
kubectl create -f https://raw.githubusercontent.com/kubernetes/kubernetes/master/hack/testdata/multi-resource-yaml.yaml "${kube_flags[@]}"
# Post-condition: service(mock) and rc(mock) exist
kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:mock:'
kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" 'mock:'
# Clean up
kubectl delete -f https://raw.githubusercontent.com/kubernetes/kubernetes/master/hack/testdata/multi-resource-yaml.yaml "${kube_flags[@]}"
# Post-condition: no service (other than default kubernetes services) or replication controller exists
kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:'
kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" ''
###################### ######################
# Persistent Volumes # # Persistent Volumes #
###################### ######################

View File

@ -126,9 +126,8 @@ func (b *Builder) FilenameParam(enforceNamespace bool, paths ...string) *Builder
func (b *Builder) URL(urls ...*url.URL) *Builder { func (b *Builder) URL(urls ...*url.URL) *Builder {
for _, u := range urls { for _, u := range urls {
b.paths = append(b.paths, &URLVisitor{ b.paths = append(b.paths, &URLVisitor{
Mapper: b.mapper, URL: u,
URL: u, StreamVisitor: NewStreamVisitor(nil, b.mapper, u.String(), b.schema),
Schema: b.schema,
}) })
} }
return b return b

View File

@ -316,25 +316,31 @@ func TestURLBuilder(t *testing.T) {
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
w.Write([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), &api.Pod{ObjectMeta: api.ObjectMeta{Namespace: "foo", Name: "test"}}))) w.Write([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), &api.Pod{ObjectMeta: api.ObjectMeta{Namespace: "foo", Name: "test"}})))
w.Write([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), &api.Pod{ObjectMeta: api.ObjectMeta{Namespace: "foo", Name: "test1"}})))
})) }))
// TODO: Uncomment when fix #19254 // TODO: Uncomment when fix #19254
// defer s.Close() // defer s.Close()
b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()). b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
FilenameParam(false, s.URL). FilenameParam(false, s.URL).
NamespaceParam("test") NamespaceParam("foo")
test := &testVisitor{} test := &testVisitor{}
singular := false
err := b.Do().IntoSingular(&singular).Visit(test.Handle) err := b.Do().Visit(test.Handle)
if err != nil || !singular || len(test.Infos) != 1 { if err != nil || len(test.Infos) != 2 {
t.Fatalf("unexpected response: %v %t %#v", err, singular, test.Infos) t.Fatalf("unexpected response: %v %#v", err, test.Infos)
} }
info := test.Infos[0] info := test.Infos[0]
if info.Name != "test" || info.Namespace != "foo" || info.Object == nil { if info.Name != "test" || info.Namespace != "foo" || info.Object == nil {
t.Errorf("unexpected info: %#v", info) t.Errorf("unexpected info: %#v", info)
} }
info = test.Infos[1]
if info.Name != "test1" || info.Namespace != "foo" || info.Object == nil {
t.Errorf("unexpected info: %#v", info)
}
} }
func TestURLBuilderRequireNamespace(t *testing.T) { func TestURLBuilderRequireNamespace(t *testing.T) {

View File

@ -20,7 +20,6 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"net/http" "net/http"
"net/url" "net/url"
"os" "os"
@ -219,9 +218,8 @@ func ValidateSchema(data []byte, schema validation.Schema) error {
// URLVisitor downloads the contents of a URL, and if successful, returns // URLVisitor downloads the contents of a URL, and if successful, returns
// an info object representing the downloaded object. // an info object representing the downloaded object.
type URLVisitor struct { type URLVisitor struct {
*Mapper URL *url.URL
URL *url.URL *StreamVisitor
Schema validation.Schema
} }
func (v *URLVisitor) Visit(fn VisitorFunc) error { func (v *URLVisitor) Visit(fn VisitorFunc) error {
@ -233,18 +231,9 @@ func (v *URLVisitor) Visit(fn VisitorFunc) error {
if res.StatusCode != 200 { if res.StatusCode != 200 {
return fmt.Errorf("unable to read URL %q, server reported %d %s", v.URL, res.StatusCode, res.Status) return fmt.Errorf("unable to read URL %q, server reported %d %s", v.URL, res.StatusCode, res.Status)
} }
data, err := ioutil.ReadAll(res.Body)
if err != nil { v.StreamVisitor.Reader = res.Body
return fmt.Errorf("unable to read URL %q: %v\n", v.URL, err) return v.StreamVisitor.Visit(fn)
}
if err := ValidateSchema(data, v.Schema); err != nil {
return fmt.Errorf("error validating %q: %v", v.URL, err)
}
info, err := v.Mapper.InfoForData(data, v.URL.String())
if err != nil {
return err
}
return fn(info, nil)
} }
// DecoratedVisitor will invoke the decorators in order prior to invoking the visitor function // DecoratedVisitor will invoke the decorators in order prior to invoking the visitor function