mirror of https://github.com/k3s-io/k3s
Unittests
parent
aee5b8099c
commit
11638e9ee1
|
@ -118,6 +118,11 @@ func (f *FakeRuntime) ClearCalls() {
|
||||||
f.StatusErr = nil
|
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 {
|
func (f *FakeRuntime) assertList(expect []string, test []string) error {
|
||||||
if !reflect.DeepEqual(expect, test) {
|
if !reflect.DeepEqual(expect, test) {
|
||||||
return fmt.Errorf("expected %#v, got %#v", expect, test)
|
return fmt.Errorf("expected %#v, got %#v", expect, test)
|
||||||
|
|
|
@ -153,3 +153,8 @@ func (r *Mock) ImageStats() (*ImageStats, error) {
|
||||||
args := r.Called()
|
args := r.Called()
|
||||||
return args.Get(0).(*ImageStats), args.Error(1)
|
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"],
|
tags = ["automanaged"],
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/api:go_default_library",
|
"//pkg/api:go_default_library",
|
||||||
|
"//pkg/apis/componentconfig:go_default_library",
|
||||||
"//pkg/kubelet/api:go_default_library",
|
"//pkg/kubelet/api:go_default_library",
|
||||||
"//pkg/kubelet/api/v1alpha1/runtime:go_default_library",
|
"//pkg/kubelet/api/v1alpha1/runtime:go_default_library",
|
||||||
"//pkg/kubelet/container:go_default_library",
|
"//pkg/kubelet/container:go_default_library",
|
||||||
"//pkg/kubelet/dockertools:go_default_library",
|
"//pkg/kubelet/dockertools:go_default_library",
|
||||||
"//pkg/kubelet/leaky: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/qos:go_default_library",
|
||||||
"//pkg/kubelet/server/streaming:go_default_library",
|
"//pkg/kubelet/server/streaming:go_default_library",
|
||||||
"//pkg/kubelet/types:go_default_library",
|
"//pkg/kubelet/types:go_default_library",
|
||||||
|
@ -63,12 +67,16 @@ go_test(
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/api:go_default_library",
|
"//pkg/api:go_default_library",
|
||||||
"//pkg/kubelet/api/v1alpha1/runtime: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/container/testing:go_default_library",
|
||||||
"//pkg/kubelet/dockertools: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/kubelet/types:go_default_library",
|
||||||
"//pkg/security/apparmor:go_default_library",
|
"//pkg/security/apparmor:go_default_library",
|
||||||
"//pkg/util/clock:go_default_library",
|
"//pkg/util/clock:go_default_library",
|
||||||
"//vendor:github.com/docker/engine-api/types",
|
"//vendor:github.com/docker/engine-api/types",
|
||||||
|
"//vendor:github.com/golang/mock/gomock",
|
||||||
"//vendor:github.com/stretchr/testify/assert",
|
"//vendor:github.com/stretchr/testify/assert",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
|
@ -25,6 +25,7 @@ import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
|
runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
|
||||||
|
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/types"
|
"k8s.io/kubernetes/pkg/kubelet/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -99,12 +100,13 @@ func TestSandboxStatus(t *testing.T) {
|
||||||
|
|
||||||
state := runtimeApi.PodSandBoxState_READY
|
state := runtimeApi.PodSandBoxState_READY
|
||||||
ct := int64(0)
|
ct := int64(0)
|
||||||
|
hostNetwork := false
|
||||||
expected := &runtimeApi.PodSandboxStatus{
|
expected := &runtimeApi.PodSandboxStatus{
|
||||||
State: &state,
|
State: &state,
|
||||||
CreatedAt: &ct,
|
CreatedAt: &ct,
|
||||||
Metadata: config.Metadata,
|
Metadata: config.Metadata,
|
||||||
Network: &runtimeApi.PodSandboxNetworkStatus{Ip: &fakeIP},
|
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,
|
Labels: labels,
|
||||||
Annotations: annotations,
|
Annotations: annotations,
|
||||||
}
|
}
|
||||||
|
@ -138,3 +140,57 @@ func TestSandboxStatus(t *testing.T) {
|
||||||
status, err = ds.PodSandboxStatus(id)
|
status, err = ds.PodSandboxStatus(id)
|
||||||
assert.Error(t, err, fmt.Sprintf("status of sandbox: %+v", status))
|
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
|
package dockershim
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/golang/mock/gomock"
|
||||||
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
containertest "k8s.io/kubernetes/pkg/kubelet/container/testing"
|
containertest "k8s.io/kubernetes/pkg/kubelet/container/testing"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/dockertools"
|
"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"
|
"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) {
|
func newTestDockerService() (*dockerService, *dockertools.FakeDockerClient, *clock.FakeClock) {
|
||||||
fakeClock := clock.NewFakeClock(time.Time{})
|
fakeClock := clock.NewFakeClock(time.Time{})
|
||||||
c := dockertools.NewFakeDockerClientWithClock(fakeClock)
|
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
|
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) {
|
func TestCNIPlugin(t *testing.T) {
|
||||||
// install some random plugin
|
// install some random plugin
|
||||||
pluginName := fmt.Sprintf("test%d", rand.Intn(1000))
|
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
|
//TODO: add unit test for each implementation of network plugin interface
|
||||||
|
|
|
@ -55,6 +55,10 @@ func (_m *MockNetworkPlugin) Capabilities() sets.Int {
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (_m *MockNetworkPlugin) Finish() {
|
||||||
|
_m.ctrl.Finish()
|
||||||
|
}
|
||||||
|
|
||||||
func (_mr *_MockNetworkPluginRecorder) Capabilities() *gomock.Call {
|
func (_mr *_MockNetworkPluginRecorder) Capabilities() *gomock.Call {
|
||||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "Capabilities")
|
return _mr.mock.ctrl.RecordCall(_mr.mock, "Capabilities")
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,11 +27,14 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type fakeNetworkHost struct {
|
type fakeNetworkHost struct {
|
||||||
|
fakeNamespaceGetter
|
||||||
kubeClient clientset.Interface
|
kubeClient clientset.Interface
|
||||||
|
Legacy bool
|
||||||
|
Runtime *containertest.FakeRuntime
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFakeHost(kubeClient clientset.Interface) *fakeNetworkHost {
|
func NewFakeHost(kubeClient clientset.Interface) *fakeNetworkHost {
|
||||||
host := &fakeNetworkHost{kubeClient: kubeClient}
|
host := &fakeNetworkHost{kubeClient: kubeClient, Legacy: true, Runtime: &containertest.FakeRuntime{}}
|
||||||
return host
|
return host
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,5 +47,17 @@ func (fnh *fakeNetworkHost) GetKubeClient() clientset.Interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nh *fakeNetworkHost) GetRuntime() kubecontainer.Runtime {
|
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
|
// Any network plugin invoked by a cri must implement NamespaceGetter
|
||||||
// to talk directly to the runtime instead.
|
// to talk directly to the runtime instead.
|
||||||
func (c *criNetworkHost) GetNetNS(containerID string) (string, error) {
|
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
|
// noOpLegacyHost implements the network.LegacyHost interface for the remote
|
||||||
|
|
Loading…
Reference in New Issue