Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix kubectl create to create to all resources in a url. #22009

Merged
merged 1 commit into from
Mar 3, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
23 changes: 23 additions & 0 deletions hack/test-cmd.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1499,6 +1499,29 @@ __EOF__
kubectl delete -f "${file}" "${kube_flags[@]}"
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 #
######################
Expand Down
5 changes: 2 additions & 3 deletions pkg/kubectl/resource/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,8 @@ func (b *Builder) FilenameParam(enforceNamespace bool, paths ...string) *Builder
func (b *Builder) URL(urls ...*url.URL) *Builder {
for _, u := range urls {
b.paths = append(b.paths, &URLVisitor{
Mapper: b.mapper,
URL: u,
Schema: b.schema,
URL: u,
StreamVisitor: NewStreamVisitor(nil, b.mapper, u.String(), b.schema),
})
}
return b
Expand Down
16 changes: 11 additions & 5 deletions pkg/kubectl/resource/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -316,25 +316,31 @@ func TestURLBuilder(t *testing.T) {
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
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: "test1"}})))
}))
// TODO: Uncomment when fix #19254
// defer s.Close()

b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
FilenameParam(false, s.URL).
NamespaceParam("test")
NamespaceParam("foo")

test := &testVisitor{}
singular := false

err := b.Do().IntoSingular(&singular).Visit(test.Handle)
if err != nil || !singular || len(test.Infos) != 1 {
t.Fatalf("unexpected response: %v %t %#v", err, singular, test.Infos)
err := b.Do().Visit(test.Handle)
if err != nil || len(test.Infos) != 2 {
t.Fatalf("unexpected response: %v %#v", err, test.Infos)
}
info := test.Infos[0]
if info.Name != "test" || info.Namespace != "foo" || info.Object == nil {
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) {
Expand Down
21 changes: 5 additions & 16 deletions pkg/kubectl/resource/visitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
"bytes"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"os"
Expand Down Expand Up @@ -219,9 +218,8 @@ func ValidateSchema(data []byte, schema validation.Schema) error {
// URLVisitor downloads the contents of a URL, and if successful, returns
// an info object representing the downloaded object.
type URLVisitor struct {
*Mapper
URL *url.URL
Schema validation.Schema
URL *url.URL
*StreamVisitor
}

func (v *URLVisitor) Visit(fn VisitorFunc) error {
Expand All @@ -233,18 +231,9 @@ func (v *URLVisitor) Visit(fn VisitorFunc) error {
if res.StatusCode != 200 {
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 {
return fmt.Errorf("unable to read URL %q: %v\n", v.URL, err)
}
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)

v.StreamVisitor.Reader = res.Body
return v.StreamVisitor.Visit(fn)
}

// DecoratedVisitor will invoke the decorators in order prior to invoking the visitor function
Expand Down