Unittests
This commit is contained in:
		@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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",
 | 
			
		||||
@@ -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",
 | 
			
		||||
    ],
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
@@ -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"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -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,
 | 
			
		||||
	}
 | 
			
		||||
@@ -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))
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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))
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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")
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -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
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user