diff --git a/pkg/registry/pod/etcd/etcd.go b/pkg/registry/pod/etcd/etcd.go index f54ad192891..b1bb13ce0c4 100644 --- a/pkg/registry/pod/etcd/etcd.go +++ b/pkg/registry/pod/etcd/etcd.go @@ -27,7 +27,6 @@ import ( etcderr "k8s.io/kubernetes/pkg/api/errors/etcd" "k8s.io/kubernetes/pkg/api/rest" "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/api/validation" "k8s.io/kubernetes/pkg/capabilities" client "k8s.io/kubernetes/pkg/client/unversioned" "k8s.io/kubernetes/pkg/fields" @@ -36,6 +35,7 @@ import ( etcdgeneric "k8s.io/kubernetes/pkg/registry/generic/etcd" genericrest "k8s.io/kubernetes/pkg/registry/generic/rest" "k8s.io/kubernetes/pkg/registry/pod" + podrest "k8s.io/kubernetes/pkg/registry/pod/rest" "k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/storage" "k8s.io/kubernetes/pkg/util/fielderrors" @@ -46,7 +46,7 @@ type PodStorage struct { Pod *REST Binding *BindingREST Status *StatusREST - Log *LogREST + Log *podrest.LogREST Proxy *ProxyREST Exec *ExecREST Attach *AttachREST @@ -110,7 +110,7 @@ func NewStorage(s storage.Interface, useCacher bool, k client.ConnectionInfoGett Pod: &REST{store, proxyTransport}, Binding: &BindingREST{store: store}, Status: &StatusREST{store: &statusStore}, - Log: &LogREST{store: store, kubeletConn: k}, + Log: &podrest.LogREST{Store: store, KubeletConn: k}, Proxy: &ProxyREST{store: store, proxyTransport: proxyTransport}, Exec: &ExecREST{store: store, kubeletConn: k}, Attach: &AttachREST{store: store, kubeletConn: k}, @@ -212,49 +212,6 @@ func (r *StatusREST) Update(ctx api.Context, obj runtime.Object) (runtime.Object return r.store.Update(ctx, obj) } -// LogREST implements the log endpoint for a Pod -// TODO: move me into pod/rest - I'm generic to store type via ResourceGetter -type LogREST struct { - store *etcdgeneric.Etcd - kubeletConn client.ConnectionInfoGetter -} - -// LogREST implements GetterWithOptions -var _ = rest.GetterWithOptions(&LogREST{}) - -// New creates a new Pod log options object -func (r *LogREST) New() runtime.Object { - // TODO - return a resource that represents a log - return &api.Pod{} -} - -// Get retrieves a runtime.Object that will stream the contents of the pod log -func (r *LogREST) Get(ctx api.Context, name string, opts runtime.Object) (runtime.Object, error) { - logOpts, ok := opts.(*api.PodLogOptions) - if !ok { - return nil, fmt.Errorf("Invalid options object: %#v", opts) - } - if errs := validation.ValidatePodLogOptions(logOpts); len(errs) > 0 { - return nil, errors.NewInvalid("podlogs", name, errs) - } - location, transport, err := pod.LogLocation(r.store, r.kubeletConn, ctx, name, logOpts) - if err != nil { - return nil, err - } - return &genericrest.LocationStreamer{ - Location: location, - Transport: transport, - ContentType: "text/plain", - Flush: logOpts.Follow, - ResponseChecker: genericrest.NewGenericHttpResponseChecker("Pod", name), - }, nil -} - -// NewGetOptions creates a new options object -func (r *LogREST) NewGetOptions() (runtime.Object, bool, string) { - return &api.PodLogOptions{}, false, "" -} - // ProxyREST implements the proxy subresource for a Pod // TODO: move me into pod/rest - I'm generic to store type via ResourceGetter type ProxyREST struct { diff --git a/pkg/registry/pod/etcd/etcd_test.go b/pkg/registry/pod/etcd/etcd_test.go index 19cc073954b..43a8a2340af 100644 --- a/pkg/registry/pod/etcd/etcd_test.go +++ b/pkg/registry/pod/etcd/etcd_test.go @@ -737,21 +737,3 @@ func TestEtcdUpdateStatus(t *testing.T) { t.Errorf("unexpected object: %s", util.ObjectDiff(&expected, podOut)) } } - -func TestPodLogValidates(t *testing.T) { - etcdStorage, _ := registrytest.NewEtcdStorage(t, "") - storage := NewStorage(etcdStorage, false, nil, nil) - - negativeOne := int64(-1) - testCases := []*api.PodLogOptions{ - {SinceSeconds: &negativeOne}, - {TailLines: &negativeOne}, - } - - for _, tc := range testCases { - _, err := storage.Log.Get(api.NewDefaultContext(), "test", tc) - if !errors.IsInvalid(err) { - t.Fatalf("unexpected error: %v", err) - } - } -} diff --git a/pkg/registry/pod/rest/log.go b/pkg/registry/pod/rest/log.go new file mode 100644 index 00000000000..0c2317404dc --- /dev/null +++ b/pkg/registry/pod/rest/log.go @@ -0,0 +1,74 @@ +/* +Copyright 2014 The Kubernetes Authors All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package rest + +import ( + "fmt" + + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/api/errors" + "k8s.io/kubernetes/pkg/api/rest" + "k8s.io/kubernetes/pkg/api/validation" + client "k8s.io/kubernetes/pkg/client/unversioned" + etcdgeneric "k8s.io/kubernetes/pkg/registry/generic/etcd" + genericrest "k8s.io/kubernetes/pkg/registry/generic/rest" + "k8s.io/kubernetes/pkg/registry/pod" + "k8s.io/kubernetes/pkg/runtime" +) + +// LogREST implements the log endpoint for a Pod +// TODO: move me into pod/rest - I'm generic to store type via ResourceGetter +type LogREST struct { + Store *etcdgeneric.Etcd + KubeletConn client.ConnectionInfoGetter +} + +// LogREST implements GetterWithOptions +var _ = rest.GetterWithOptions(&LogREST{}) + +// New creates a new Pod log options object +func (r *LogREST) New() runtime.Object { + // TODO - return a resource that represents a log + return &api.Pod{} +} + +// Get retrieves a runtime.Object that will stream the contents of the pod log +func (r *LogREST) Get(ctx api.Context, name string, opts runtime.Object) (runtime.Object, error) { + logOpts, ok := opts.(*api.PodLogOptions) + if !ok { + return nil, fmt.Errorf("Invalid options object: %#v", opts) + } + if errs := validation.ValidatePodLogOptions(logOpts); len(errs) > 0 { + return nil, errors.NewInvalid("podlogs", name, errs) + } + location, transport, err := pod.LogLocation(r.Store, r.KubeletConn, ctx, name, logOpts) + if err != nil { + return nil, err + } + return &genericrest.LocationStreamer{ + Location: location, + Transport: transport, + ContentType: "text/plain", + Flush: logOpts.Follow, + ResponseChecker: genericrest.NewGenericHttpResponseChecker("Pod", name), + }, nil +} + +// NewGetOptions creates a new options object +func (r *LogREST) NewGetOptions() (runtime.Object, bool, string) { + return &api.PodLogOptions{}, false, "" +} diff --git a/pkg/registry/pod/rest/log_test.go b/pkg/registry/pod/rest/log_test.go new file mode 100644 index 00000000000..013514ed5f5 --- /dev/null +++ b/pkg/registry/pod/rest/log_test.go @@ -0,0 +1,47 @@ +/* +Copyright 2014 The Kubernetes Authors All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package rest + +import ( + "testing" + + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/api/errors" + etcdgeneric "k8s.io/kubernetes/pkg/registry/generic/etcd" + "k8s.io/kubernetes/pkg/registry/registrytest" +) + +func TestPodLogValidates(t *testing.T) { + etcdStorage, _ := registrytest.NewEtcdStorage(t, "") + store := &etcdgeneric.Etcd{ + Storage: etcdStorage, + } + logRest := &LogREST{Store: store, KubeletConn: nil} + + negativeOne := int64(-1) + testCases := []*api.PodLogOptions{ + {SinceSeconds: &negativeOne}, + {TailLines: &negativeOne}, + } + + for _, tc := range testCases { + _, err := logRest.Get(api.NewDefaultContext(), "test", tc) + if !errors.IsInvalid(err) { + t.Fatalf("unexpected error: %v", err) + } + } +}