diff --git a/cli/network_test.go b/cli/network_test.go new file mode 100644 index 0000000000..37a63ea040 --- /dev/null +++ b/cli/network_test.go @@ -0,0 +1,88 @@ +// Copyright (c) 2018 Huawei Corporation. +// +// SPDX-License-Identifier: Apache-2.0 +// + +package main + +import ( + "flag" + "io/ioutil" + "os" + "testing" + + "github.com/kata-containers/agent/protocols/grpc" + vc "github.com/kata-containers/runtime/virtcontainers" + "github.com/stretchr/testify/assert" +) + +var ( + testAddInterfaceFuncReturnNil = func(sandboxID string, inf *grpc.Interface) (*grpc.Interface, error) { + return nil, nil + } + testRemoveInterfaceFuncReturnNil = func(sandboxID string, inf *grpc.Interface) (*grpc.Interface, error) { + return nil, nil + } + testListInterfacesFuncReturnNil = func(sandboxID string) ([]*grpc.Interface, error) { + return nil, nil + } + testUpdateRoutsFuncReturnNil = func(sandboxID string, routes []*grpc.Route) ([]*grpc.Route, error) { + return nil, nil + } + testListRoutesFuncReturnNil = func(sandboxID string) ([]*grpc.Route, error) { + return nil, nil + } +) + +func TestNetworkCliFunction(t *testing.T) { + assert := assert.New(t) + + state := vc.State{ + State: vc.StateRunning, + } + + testingImpl.AddInterfaceFunc = testAddInterfaceFuncReturnNil + testingImpl.RemoveInterfaceFunc = testRemoveInterfaceFuncReturnNil + testingImpl.ListInterfacesFunc = testListInterfacesFuncReturnNil + testingImpl.UpdateRoutesFunc = testUpdateRoutsFuncReturnNil + testingImpl.ListRoutesFunc = testListRoutesFuncReturnNil + + path, err := createTempContainerIDMapping(testContainerID, testSandboxID) + assert.NoError(err) + defer os.RemoveAll(path) + + testingImpl.StatusContainerFunc = func(sandboxID, containerID string) (vc.ContainerStatus, error) { + return newSingleContainerStatus(testContainerID, state, map[string]string{}), nil + } + + defer func() { + testingImpl.AddInterfaceFunc = nil + testingImpl.RemoveInterfaceFunc = nil + testingImpl.ListInterfacesFunc = nil + testingImpl.UpdateRoutesFunc = nil + testingImpl.ListRoutesFunc = nil + testingImpl.StatusContainerFunc = nil + }() + + set := flag.NewFlagSet("", 0) + execCLICommandFunc(assert, addIfaceCommand, set, true) + + set.Parse([]string{testContainerID}) + execCLICommandFunc(assert, listIfacesCommand, set, false) + execCLICommandFunc(assert, listRoutesCommand, set, false) + + f, err := ioutil.TempFile("", "interface") + defer os.Remove(f.Name()) + assert.NoError(err) + assert.NotNil(f) + f.WriteString("{}") + + set.Parse([]string{testContainerID, f.Name()}) + execCLICommandFunc(assert, addIfaceCommand, set, false) + execCLICommandFunc(assert, delIfaceCommand, set, false) + + f.Seek(0, 0) + f.WriteString("[{}]") + f.Close() + execCLICommandFunc(assert, updateRoutesCommand, set, false) +} diff --git a/virtcontainers/api_test.go b/virtcontainers/api_test.go index 0cb1086bf4..11dca61e8a 100644 --- a/virtcontainers/api_test.go +++ b/virtcontainers/api_test.go @@ -16,6 +16,7 @@ import ( "syscall" "testing" + "github.com/kata-containers/agent/protocols/grpc" "github.com/kata-containers/runtime/virtcontainers/pkg/mock" specs "github.com/opencontainers/runtime-spec/specs-go" "github.com/stretchr/testify/assert" @@ -2349,3 +2350,59 @@ func TestPauseResumeContainer(t *testing.T) { err = ResumeContainer(s.ID(), contID) assert.NoError(err) } + +func TestNetworkOperation(t *testing.T) { + if os.Geteuid() != 0 { + t.Skip(testDisabledAsNonRoot) + } + + cleanUp() + + assert := assert.New(t) + inf := &grpc.Interface{ + Name: "eno1", + Mtu: 1500, + HwAddr: "02:00:ca:fe:00:48", + } + ip := grpc.IPAddress{ + Family: 0, + Address: "192.168.0.101", + Mask: "24", + } + inf.IPAddresses = append(inf.IPAddresses, &ip) + + _, err := AddInterface("", inf) + assert.Error(err) + + _, err = AddInterface("abc", inf) + assert.Error(err) + + netNSPath, err := createNetNS() + assert.NoError(err) + defer deleteNetNS(netNSPath) + + config := newTestSandboxConfigNoop() + config.NetworkModel = CNMNetworkModel + config.NetworkConfig = NetworkConfig{ + NetNSPath: netNSPath, + } + + s, _, err := createAndStartSandbox(config) + assert.NoError(err) + assert.NotNil(s) + + _, err = AddInterface(s.ID(), inf) + assert.Error(err) + + _, err = RemoveInterface(s.ID(), inf) + assert.NoError(err) + + _, err = ListInterfaces(s.ID()) + assert.NoError(err) + + _, err = UpdateRoutes(s.ID(), nil) + assert.NoError(err) + + _, err = ListRoutes(s.ID()) + assert.NoError(err) +} diff --git a/virtcontainers/hyperstart_agent_test.go b/virtcontainers/hyperstart_agent_test.go index d0c4ec43c5..41b5faf9e1 100644 --- a/virtcontainers/hyperstart_agent_test.go +++ b/virtcontainers/hyperstart_agent_test.go @@ -206,3 +206,35 @@ func TestHyperReseedAPI(t *testing.T) { err := h.reseedRNG([]byte{}) assert.Nil(err) } + +func TestHyperUpdateInterface(t *testing.T) { + assert := assert.New(t) + + h := &hyper{} + _, err := h.updateInterface(nil) + assert.Nil(err) +} + +func TestHyperListInterfaces(t *testing.T) { + assert := assert.New(t) + + h := &hyper{} + _, err := h.listInterfaces() + assert.Nil(err) +} + +func TestHyperUpdateRoutes(t *testing.T) { + assert := assert.New(t) + + h := &hyper{} + _, err := h.updateRoutes(nil) + assert.Nil(err) +} + +func TestHyperListRoutes(t *testing.T) { + assert := assert.New(t) + + h := &hyper{} + _, err := h.listRoutes() + assert.Nil(err) +} diff --git a/virtcontainers/kata_agent_test.go b/virtcontainers/kata_agent_test.go index 5e9965f743..cc908d9e14 100644 --- a/virtcontainers/kata_agent_test.go +++ b/virtcontainers/kata_agent_test.go @@ -194,11 +194,19 @@ func (p *gRPCProxy) RemoveInterface(ctx context.Context, req *pb.RemoveInterface } func (p *gRPCProxy) UpdateInterface(ctx context.Context, req *pb.UpdateInterfaceRequest) (*pb.Interface, error) { - return nil, nil + return &pb.Interface{}, nil } func (p *gRPCProxy) UpdateRoutes(ctx context.Context, req *pb.UpdateRoutesRequest) (*pb.Routes, error) { - return nil, nil + return &pb.Routes{}, nil +} + +func (p *gRPCProxy) ListInterfaces(ctx context.Context, req *pb.ListInterfacesRequest) (*pb.Interfaces, error) { + return &pb.Interfaces{}, nil +} + +func (p *gRPCProxy) ListRoutes(ctx context.Context, req *pb.ListRoutesRequest) (*pb.Routes, error) { + return &pb.Routes{}, nil } func (p *gRPCProxy) OnlineCPUMem(ctx context.Context, req *pb.OnlineCPUMemRequest) (*gpb.Empty, error) { @@ -839,3 +847,44 @@ func TestAgentCreateContainer(t *testing.T) { _, err = k.createContainer(sandbox, container) assert.Error(err) } + +func TestAgentNetworkOperation(t *testing.T) { + assert := assert.New(t) + + impl := &gRPCProxy{} + + proxy := mock.ProxyGRPCMock{ + GRPCImplementer: impl, + GRPCRegister: gRPCRegister, + } + + sockDir, err := testGenerateKataProxySockDir() + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(sockDir) + + testKataProxyURL := fmt.Sprintf(testKataProxyURLTempl, sockDir) + if err := proxy.Start(testKataProxyURL); err != nil { + t.Fatal(err) + } + defer proxy.Stop() + + k := &kataAgent{ + state: KataAgentState{ + URL: testKataProxyURL, + }, + } + + _, err = k.updateInterface(nil) + assert.Nil(err) + + _, err = k.listInterfaces() + assert.Nil(err) + + _, err = k.updateRoutes([]*pb.Route{}) + assert.Nil(err) + + _, err = k.listRoutes() + assert.Nil(err) +} diff --git a/virtcontainers/network_test.go b/virtcontainers/network_test.go index 75ed18ecfd..ce1ddaf08b 100644 --- a/virtcontainers/network_test.go +++ b/virtcontainers/network_test.go @@ -480,6 +480,60 @@ func TestVhostUserEndpointAttach(t *testing.T) { } } +func TestVhostUserEndpoint_HotAttach(t *testing.T) { + assert := assert.New(t) + v := &VhostUserEndpoint{ + SocketPath: "/tmp/sock", + HardAddr: "mac-addr", + EndpointType: VhostUserEndpointType, + } + + h := &mockHypervisor{} + + err := v.HotAttach(h) + assert.Error(err) +} + +func TestVhostUserEndpoint_HotDetach(t *testing.T) { + assert := assert.New(t) + v := &VhostUserEndpoint{ + SocketPath: "/tmp/sock", + HardAddr: "mac-addr", + EndpointType: VhostUserEndpointType, + } + + h := &mockHypervisor{} + + err := v.HotDetach(h, true, "") + assert.Error(err) +} + +func TestPhysicalEndpoint_HotAttach(t *testing.T) { + assert := assert.New(t) + v := &PhysicalEndpoint{ + IfaceName: "eth0", + HardAddr: net.HardwareAddr{0x02, 0x00, 0xca, 0xfe, 0x00, 0x04}.String(), + } + + h := &mockHypervisor{} + + err := v.HotAttach(h) + assert.Error(err) +} + +func TestPhysicalEndpoint_HotDetach(t *testing.T) { + assert := assert.New(t) + v := &PhysicalEndpoint{ + IfaceName: "eth0", + HardAddr: net.HardwareAddr{0x02, 0x00, 0xca, 0xfe, 0x00, 0x04}.String(), + } + + h := &mockHypervisor{} + + err := v.HotDetach(h, true, "") + assert.Error(err) +} + func TestGetNetNsFromBindMount(t *testing.T) { assert := assert.New(t) diff --git a/virtcontainers/noop_agent_test.go b/virtcontainers/noop_agent_test.go index 847997b202..39b689abb1 100644 --- a/virtcontainers/noop_agent_test.go +++ b/virtcontainers/noop_agent_test.go @@ -217,3 +217,35 @@ func TestNoopAgentReseedRNG(t *testing.T) { t.Fatal("reseedRNG failed") } } + +func TestNoopAgentUpdateInterface(t *testing.T) { + n := &noopAgent{} + _, err := n.updateInterface(nil) + if err != nil { + t.Fatal("updateInterface failed") + } +} + +func TestNoopAgentListInterfaces(t *testing.T) { + n := &noopAgent{} + _, err := n.listInterfaces() + if err != nil { + t.Fatal("listInterfaces failed") + } +} + +func TestNoopAgentUpdateRoutes(t *testing.T) { + n := &noopAgent{} + _, err := n.updateRoutes(nil) + if err != nil { + t.Fatal("updateRoutes failed") + } +} + +func TestNoopAgentListRoutes(t *testing.T) { + n := &noopAgent{} + _, err := n.listRoutes() + if err != nil { + t.Fatal("listRoutes failed") + } +} diff --git a/virtcontainers/pkg/vcmock/mock_test.go b/virtcontainers/pkg/vcmock/mock_test.go index 411bc05541..2dc53a3122 100644 --- a/virtcontainers/pkg/vcmock/mock_test.go +++ b/virtcontainers/pkg/vcmock/mock_test.go @@ -10,6 +10,7 @@ import ( "syscall" "testing" + "github.com/kata-containers/agent/protocols/grpc" vc "github.com/kata-containers/runtime/virtcontainers" "github.com/kata-containers/runtime/virtcontainers/factory" "github.com/sirupsen/logrus" @@ -710,3 +711,133 @@ func TestVCMockSetVMFactory(t *testing.T) { m.SetFactory(f) assert.Equal(factoryTriggered, 1) } + +func TestVCMockAddInterface(t *testing.T) { + assert := assert.New(t) + + m := &VCMock{} + config := &vc.SandboxConfig{} + assert.Nil(m.AddInterfaceFunc) + + _, err := m.AddInterface(config.ID, nil) + assert.Error(err) + assert.True(IsMockError(err)) + + m.AddInterfaceFunc = func(sid string, inf *grpc.Interface) (*grpc.Interface, error) { + return nil, nil + } + + _, err = m.AddInterface(config.ID, nil) + assert.NoError(err) + + // reset + m.AddInterfaceFunc = nil + + _, err = m.AddInterface(config.ID, nil) + assert.Error(err) + assert.True(IsMockError(err)) +} + +func TestVCMockRemoveInterface(t *testing.T) { + assert := assert.New(t) + + m := &VCMock{} + config := &vc.SandboxConfig{} + assert.Nil(m.RemoveInterfaceFunc) + + _, err := m.RemoveInterface(config.ID, nil) + assert.Error(err) + assert.True(IsMockError(err)) + + m.RemoveInterfaceFunc = func(sid string, inf *grpc.Interface) (*grpc.Interface, error) { + return nil, nil + } + + _, err = m.RemoveInterface(config.ID, nil) + assert.NoError(err) + + // reset + m.RemoveInterfaceFunc = nil + + _, err = m.RemoveInterface(config.ID, nil) + assert.Error(err) + assert.True(IsMockError(err)) +} + +func TestVCMockListInterfaces(t *testing.T) { + assert := assert.New(t) + + m := &VCMock{} + config := &vc.SandboxConfig{} + assert.Nil(m.ListInterfacesFunc) + + _, err := m.ListInterfaces(config.ID) + assert.Error(err) + assert.True(IsMockError(err)) + + m.ListInterfacesFunc = func(sid string) ([]*grpc.Interface, error) { + return nil, nil + } + + _, err = m.ListInterfaces(config.ID) + assert.NoError(err) + + // reset + m.ListInterfacesFunc = nil + + _, err = m.ListInterfaces(config.ID) + assert.Error(err) + assert.True(IsMockError(err)) +} + +func TestVCMockUpdateRoutes(t *testing.T) { + assert := assert.New(t) + + m := &VCMock{} + config := &vc.SandboxConfig{} + assert.Nil(m.UpdateRoutesFunc) + + _, err := m.UpdateRoutes(config.ID, nil) + assert.Error(err) + assert.True(IsMockError(err)) + + m.UpdateRoutesFunc = func(sid string, routes []*grpc.Route) ([]*grpc.Route, error) { + return nil, nil + } + + _, err = m.UpdateRoutes(config.ID, nil) + assert.NoError(err) + + // reset + m.UpdateRoutesFunc = nil + + _, err = m.UpdateRoutes(config.ID, nil) + assert.Error(err) + assert.True(IsMockError(err)) +} + +func TestVCMockListRoutes(t *testing.T) { + assert := assert.New(t) + + m := &VCMock{} + config := &vc.SandboxConfig{} + assert.Nil(m.ListRoutesFunc) + + _, err := m.ListRoutes(config.ID) + assert.Error(err) + assert.True(IsMockError(err)) + + m.ListRoutesFunc = func(sid string) ([]*grpc.Route, error) { + return nil, nil + } + + _, err = m.ListRoutes(config.ID) + assert.NoError(err) + + // reset + m.ListRoutesFunc = nil + + _, err = m.ListRoutes(config.ID) + assert.Error(err) + assert.True(IsMockError(err)) +}