Skip to content

Commit

Permalink
Unittests
Browse files Browse the repository at this point in the history
  • Loading branch information
bprashanth committed Oct 31, 2016
1 parent aee5b80 commit 11638e9
Show file tree
Hide file tree
Showing 10 changed files with 152 additions and 5 deletions.
5 changes: 5 additions & 0 deletions pkg/kubelet/container/testing/fake_runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ func (f *FakeRuntime) ClearCalls() {
f.StatusErr = nil
}

// UpdatePodCIDR fulfills the cri interface.
func (f *FakeRuntime) UpdatePodCIDR(c string) error {
return nil
}

func (f *FakeRuntime) assertList(expect []string, test []string) error {
if !reflect.DeepEqual(expect, test) {
return fmt.Errorf("expected %#v, got %#v", expect, test)
Expand Down
5 changes: 5 additions & 0 deletions pkg/kubelet/container/testing/runtime_mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,8 @@ func (r *Mock) ImageStats() (*ImageStats, error) {
args := r.Called()
return args.Get(0).(*ImageStats), args.Error(1)
}

// UpdatePodCIDR fulfills the cri interface.
func (r *Mock) UpdatePodCIDR(c string) error {
return nil
}
8 changes: 8 additions & 0 deletions pkg/kubelet/dockershim/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,15 @@ go_library(
tags = ["automanaged"],
deps = [
"//pkg/api:go_default_library",
"//pkg/apis/componentconfig:go_default_library",
"//pkg/kubelet/api:go_default_library",
"//pkg/kubelet/api/v1alpha1/runtime:go_default_library",
"//pkg/kubelet/container:go_default_library",
"//pkg/kubelet/dockertools:go_default_library",
"//pkg/kubelet/leaky:go_default_library",
"//pkg/kubelet/network:go_default_library",
"//pkg/kubelet/network/cni:go_default_library",
"//pkg/kubelet/network/kubenet:go_default_library",
"//pkg/kubelet/qos:go_default_library",
"//pkg/kubelet/server/streaming:go_default_library",
"//pkg/kubelet/types:go_default_library",
Expand Down Expand Up @@ -63,12 +67,16 @@ go_test(
deps = [
"//pkg/api:go_default_library",
"//pkg/kubelet/api/v1alpha1/runtime:go_default_library",
"//pkg/kubelet/container:go_default_library",
"//pkg/kubelet/container/testing:go_default_library",
"//pkg/kubelet/dockertools:go_default_library",
"//pkg/kubelet/network:go_default_library",
"//pkg/kubelet/network/mock_network:go_default_library",
"//pkg/kubelet/types:go_default_library",
"//pkg/security/apparmor:go_default_library",
"//pkg/util/clock:go_default_library",
"//vendor:github.com/docker/engine-api/types",
"//vendor:github.com/golang/mock/gomock",
"//vendor:github.com/stretchr/testify/assert",
],
)
58 changes: 57 additions & 1 deletion pkg/kubelet/dockershim/docker_sandbox_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/stretchr/testify/assert"

runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
"k8s.io/kubernetes/pkg/kubelet/types"
)

Expand Down Expand Up @@ -99,12 +100,13 @@ func TestSandboxStatus(t *testing.T) {

state := runtimeApi.PodSandBoxState_READY
ct := int64(0)
hostNetwork := false
expected := &runtimeApi.PodSandboxStatus{
State: &state,
CreatedAt: &ct,
Metadata: config.Metadata,
Network: &runtimeApi.PodSandboxNetworkStatus{Ip: &fakeIP},
Linux: &runtimeApi.LinuxPodSandboxStatus{Namespaces: &runtimeApi.Namespace{Network: &fakeNS}},
Linux: &runtimeApi.LinuxPodSandboxStatus{Namespaces: &runtimeApi.Namespace{Network: &fakeNS, Options: &runtimeApi.NamespaceOption{HostNetwork: &hostNetwork}}},
Labels: labels,
Annotations: annotations,
}
Expand Down Expand Up @@ -138,3 +140,57 @@ func TestSandboxStatus(t *testing.T) {
status, err = ds.PodSandboxStatus(id)
assert.Error(t, err, fmt.Sprintf("status of sandbox: %+v", status))
}

// TestNetworkPluginInvocation checks that the right SetUpPod and TearDownPod
// calls are made when we run/stop a sandbox.
func TestNetworkPluginInvocation(t *testing.T) {
ds, _, _ := newTestDockerService()
mockPlugin := newTestNetworkPlugin(t)
ds.networkPlugin = mockPlugin
defer mockPlugin.Finish()

name := "foo0"
ns := "bar0"
c := makeSandboxConfigWithLabelsAndAnnotations(
name, ns, "0", 0,
map[string]string{"label": name},
map[string]string{"annotation": ns},
)
cID := kubecontainer.ContainerID{Type: runtimeName, ID: fmt.Sprintf("/%v", makeSandboxName(c))}

setup := mockPlugin.EXPECT().SetUpPod(ns, name, cID)
// StopPodSandbox performs a lookup on status to figure out if the sandbox
// is running with hostnetworking, as all its given is the ID.
mockPlugin.EXPECT().GetPodNetworkStatus(ns, name, cID)
mockPlugin.EXPECT().TearDownPod(ns, name, cID).After(setup)

_, err := ds.RunPodSandbox(c)
assert.NoError(t, err)
err = ds.StopPodSandbox(cID.ID)
assert.NoError(t, err)
}

// TestHostNetworkPluginInvocation checks that *no* SetUp/TearDown calls happen
// for host network sandboxes.
func TestHostNetworkPluginInvocation(t *testing.T) {
ds, _, _ := newTestDockerService()
mockPlugin := newTestNetworkPlugin(t)
ds.networkPlugin = mockPlugin
defer mockPlugin.Finish()

name := "foo0"
ns := "bar0"
c := makeSandboxConfigWithLabelsAndAnnotations(
name, ns, "0", 0,
map[string]string{"label": name},
map[string]string{"annotation": ns},
)
hostNetwork := true
c.Linux = &runtimeApi.LinuxPodSandboxConfig{NamespaceOptions: &runtimeApi.NamespaceOption{HostNetwork: &hostNetwork}}
cID := kubecontainer.ContainerID{Type: runtimeName, ID: fmt.Sprintf("/%v", makeSandboxName(c))}

// No calls to network plugin are expected
_, err := ds.RunPodSandbox(c)
assert.NoError(t, err)
assert.NoError(t, ds.StopPodSandbox(cID.ID))
}
12 changes: 11 additions & 1 deletion pkg/kubelet/dockershim/docker_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,25 @@ limitations under the License.
package dockershim

import (
"github.com/golang/mock/gomock"
"testing"
"time"

containertest "k8s.io/kubernetes/pkg/kubelet/container/testing"
"k8s.io/kubernetes/pkg/kubelet/dockertools"
"k8s.io/kubernetes/pkg/kubelet/network"
"k8s.io/kubernetes/pkg/kubelet/network/mock_network"
"k8s.io/kubernetes/pkg/util/clock"
)

// newTestNetworkPlugin returns a mock plugin that implements network.NetworkPlugin
func newTestNetworkPlugin(t *testing.T) *mock_network.MockNetworkPlugin {
ctrl := gomock.NewController(t)
return mock_network.NewMockNetworkPlugin(ctrl)
}

func newTestDockerService() (*dockerService, *dockertools.FakeDockerClient, *clock.FakeClock) {
fakeClock := clock.NewFakeClock(time.Time{})
c := dockertools.NewFakeDockerClientWithClock(fakeClock)
return &dockerService{client: c, os: &containertest.FakeOS{}}, c, fakeClock
return &dockerService{client: c, os: &containertest.FakeOS{}, networkPlugin: &network.NoopNetworkPlugin{}}, c, fakeClock
}
8 changes: 8 additions & 0 deletions pkg/kubelet/network/cni/cni_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,14 @@ func (fnh *fakeNetworkHost) GetRuntime() kubecontainer.Runtime {
return fnh.runtime
}

func (fnh *fakeNetworkHost) GetNetNS(containerID string) (string, error) {
return fnh.GetRuntime().GetNetNS(kubecontainer.ContainerID{Type: "test", ID: containerID})
}

func (fnh *fakeNetworkHost) SupportsLegacyFeatures() bool {
return true
}

func TestCNIPlugin(t *testing.T) {
// install some random plugin
pluginName := fmt.Sprintf("test%d", rand.Intn(1000))
Expand Down
36 changes: 36 additions & 0 deletions pkg/kubelet/network/kubenet/kubenet_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,4 +229,40 @@ func TestGenerateMacAddress(t *testing.T) {
}
}

// TestInvocationWithoutRuntime invokes the plugin without a runtime.
// This is how kubenet is invoked from the cri.
func TestTearDownWithoutRuntime(t *testing.T) {
fhost := nettest.NewFakeHost(nil)
fhost.Legacy = false
fhost.Runtime = nil
mockcni := &mock_cni.MockCNI{}

fexec := &exec.FakeExec{
CommandScript: []exec.FakeCommandAction{},
LookPathFunc: func(file string) (string, error) {
return fmt.Sprintf("/fake-bin/%s", file), nil
},
}

kubenet := newFakeKubenetPlugin(map[kubecontainer.ContainerID]string{}, fexec, fhost)
kubenet.cniConfig = mockcni
kubenet.iptables = ipttest.NewFake()

details := make(map[string]interface{})
details[network.NET_PLUGIN_EVENT_POD_CIDR_CHANGE_DETAIL_CIDR] = "10.0.0.1/24"
kubenet.Event(network.NET_PLUGIN_EVENT_POD_CIDR_CHANGE, details)

existingContainerID := kubecontainer.BuildContainerID("docker", "123")
kubenet.podIPs[existingContainerID] = "10.0.0.1"

mockcni.On("DelNetwork", mock.AnythingOfType("*libcni.NetworkConfig"), mock.AnythingOfType("*libcni.RuntimeConf")).Return(nil)

if err := kubenet.TearDownPod("namespace", "name", existingContainerID); err != nil {
t.Fatalf("Unexpected error in TearDownPod: %v", err)
}
// Assert that the CNI DelNetwork made it through and we didn't crash
// without a runtime.
mockcni.AssertExpectations(t)
}

//TODO: add unit test for each implementation of network plugin interface
4 changes: 4 additions & 0 deletions pkg/kubelet/network/mock_network/network_plugins.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ func (_m *MockNetworkPlugin) Capabilities() sets.Int {
return ret0
}

func (_m *MockNetworkPlugin) Finish() {
_m.ctrl.Finish()
}

func (_mr *_MockNetworkPluginRecorder) Capabilities() *gomock.Call {
return _mr.mock.ctrl.RecordCall(_mr.mock, "Capabilities")
}
Expand Down
19 changes: 17 additions & 2 deletions pkg/kubelet/network/testing/fake_host.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,14 @@ import (
)

type fakeNetworkHost struct {
fakeNamespaceGetter
kubeClient clientset.Interface
Legacy bool
Runtime *containertest.FakeRuntime
}

func NewFakeHost(kubeClient clientset.Interface) *fakeNetworkHost {
host := &fakeNetworkHost{kubeClient: kubeClient}
host := &fakeNetworkHost{kubeClient: kubeClient, Legacy: true, Runtime: &containertest.FakeRuntime{}}
return host
}

Expand All @@ -44,5 +47,17 @@ func (fnh *fakeNetworkHost) GetKubeClient() clientset.Interface {
}

func (nh *fakeNetworkHost) GetRuntime() kubecontainer.Runtime {
return &containertest.FakeRuntime{}
return nh.Runtime
}

func (nh *fakeNetworkHost) SupportsLegacyFeatures() bool {
return nh.Legacy
}

type fakeNamespaceGetter struct {
ns string
}

func (nh *fakeNamespaceGetter) GetNetNS(containerID string) (string, error) {
return nh.ns, nil
}
2 changes: 1 addition & 1 deletion pkg/kubelet/networks.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ type criNetworkHost struct {
// Any network plugin invoked by a cri must implement NamespaceGetter
// to talk directly to the runtime instead.
func (c *criNetworkHost) GetNetNS(containerID string) (string, error) {
return c.kubelet.GetRuntime().GetNetNS(kubecontainer.ContainerID{"", containerID})
return c.kubelet.GetRuntime().GetNetNS(kubecontainer.ContainerID{Type: "", ID: containerID})
}

// noOpLegacyHost implements the network.LegacyHost interface for the remote
Expand Down

0 comments on commit 11638e9

Please sign in to comment.