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

Pod log location must validate container if provided #17953

Merged
merged 1 commit into from Dec 2, 2015
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
27 changes: 23 additions & 4 deletions pkg/registry/pod/strategy.go
Expand Up @@ -235,13 +235,18 @@ func LogLocation(getter ResourceGetter, connInfo client.ConnectionInfoGetter, ct
}

// Try to figure out a container
// If a container was provided, it must be valid
container := opts.Container
if container == "" {
if len(container) == 0 {
if len(pod.Spec.Containers) == 1 {
container = pod.Spec.Containers[0].Name
} else {
return nil, nil, errors.NewBadRequest(fmt.Sprintf("a container name must be specified for pod %s", name))
}
} else {
if !podHasContainerWithName(pod, container) {
return nil, nil, errors.NewBadRequest(fmt.Sprintf("container %s is not valid for pod %s", container, name))
}
}
nodeHost := pod.Spec.NodeName
if len(nodeHost) == 0 {
Expand Down Expand Up @@ -277,12 +282,21 @@ func LogLocation(getter ResourceGetter, connInfo client.ConnectionInfoGetter, ct
loc := &url.URL{
Scheme: nodeScheme,
Host: fmt.Sprintf("%s:%d", nodeHost, nodePort),
Path: fmt.Sprintf("/containerLogs/%s/%s/%s", pod.Namespace, name, container),
Path: fmt.Sprintf("/containerLogs/%s/%s/%s", pod.Namespace, pod.Name, container),
RawQuery: params.Encode(),
}
return loc, nodeTransport, nil
}

func podHasContainerWithName(pod *api.Pod, containerName string) bool {
for _, c := range pod.Spec.Containers {
if c.Name == containerName {
return true
}
}
return false
}

func streamParams(params url.Values, opts runtime.Object) error {
switch opts := opts.(type) {
case *api.PodExecOptions:
Expand Down Expand Up @@ -339,12 +353,17 @@ func streamLocation(getter ResourceGetter, connInfo client.ConnectionInfoGetter,
}

// Try to figure out a container
// If a container was provided, it must be valid
if container == "" {
if len(pod.Spec.Containers) == 1 {
container = pod.Spec.Containers[0].Name
} else {
return nil, nil, errors.NewBadRequest(fmt.Sprintf("a container name must be specified for pod %s", name))
}
} else {
if !podHasContainerWithName(pod, container) {
return nil, nil, errors.NewBadRequest(fmt.Sprintf("container %s is not valid for pod %s", container, name))
}
}
nodeHost := pod.Spec.NodeName
if len(nodeHost) == 0 {
Expand All @@ -362,7 +381,7 @@ func streamLocation(getter ResourceGetter, connInfo client.ConnectionInfoGetter,
loc := &url.URL{
Scheme: nodeScheme,
Host: fmt.Sprintf("%s:%d", nodeHost, nodePort),
Path: fmt.Sprintf("/%s/%s/%s/%s", path, pod.Namespace, name, container),
Path: fmt.Sprintf("/%s/%s/%s/%s", path, pod.Namespace, pod.Name, container),
RawQuery: params.Encode(),
}
return loc, nodeTransport, nil
Expand All @@ -387,7 +406,7 @@ func PortForwardLocation(getter ResourceGetter, connInfo client.ConnectionInfoGe
loc := &url.URL{
Scheme: nodeScheme,
Host: fmt.Sprintf("%s:%d", nodeHost, nodePort),
Path: fmt.Sprintf("/portForward/%s/%s", pod.Namespace, name),
Path: fmt.Sprintf("/portForward/%s/%s", pod.Namespace, pod.Name),
}
return loc, nodeTransport, nil
}
91 changes: 91 additions & 0 deletions pkg/registry/pod/strategy_test.go
Expand Up @@ -17,9 +17,12 @@ limitations under the License.
package pod

import (
"reflect"
"testing"

"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/runtime"
)

func TestCheckGracefulDelete(t *testing.T) {
Expand Down Expand Up @@ -76,3 +79,91 @@ func TestCheckGracefulDelete(t *testing.T) {
}
}
}

type mockPodGetter struct {
pod *api.Pod
}

func (g mockPodGetter) Get(api.Context, string) (runtime.Object, error) {
return g.pod, nil
}

func TestCheckLogLocation(t *testing.T) {
ctx := api.NewDefaultContext()
tcs := []struct {
in *api.Pod
opts *api.PodLogOptions
expectedErr error
}{
{
in: &api.Pod{
Spec: api.PodSpec{},
Status: api.PodStatus{},
},
opts: &api.PodLogOptions{},
expectedErr: errors.NewBadRequest("a container name must be specified for pod test"),
},
{
in: &api.Pod{
Spec: api.PodSpec{
Containers: []api.Container{
{Name: "mycontainer"},
},
},
Status: api.PodStatus{},
},
opts: &api.PodLogOptions{},
expectedErr: nil,
},
{
in: &api.Pod{
Spec: api.PodSpec{
Containers: []api.Container{
{Name: "container1"},
{Name: "container2"},
},
},
Status: api.PodStatus{},
},
opts: &api.PodLogOptions{},
expectedErr: errors.NewBadRequest("a container name must be specified for pod test"),
},
{
in: &api.Pod{
Spec: api.PodSpec{
Containers: []api.Container{
{Name: "container1"},
{Name: "container2"},
},
},
Status: api.PodStatus{},
},
opts: &api.PodLogOptions{
Container: "unknown",
},
expectedErr: errors.NewBadRequest("container unknown is not valid for pod test"),
},
{
in: &api.Pod{
Spec: api.PodSpec{
Containers: []api.Container{
{Name: "container1"},
{Name: "container2"},
},
},
Status: api.PodStatus{},
},
opts: &api.PodLogOptions{
Container: "container2",
},
expectedErr: nil,
},
}
for _, tc := range tcs {
getter := &mockPodGetter{tc.in}
_, _, err := LogLocation(getter, nil, ctx, "test", tc.opts)
if !reflect.DeepEqual(err, tc.expectedErr) {
t.Errorf("expected %v, got %v", tc.expectedErr, err)
}
}
}