Skip to content

Commit

Permalink
add UTs for runtime handler (#125)
Browse files Browse the repository at this point in the history
Signed-off-by: saintube <saintube@foxmail.com>
  • Loading branch information
saintube committed May 7, 2022
1 parent ee19dce commit 23b491b
Show file tree
Hide file tree
Showing 142 changed files with 2,046 additions and 2,431 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ require (
github.com/golang/mock v1.6.0
github.com/google/uuid v1.2.0
github.com/jinzhu/copier v0.3.5
github.com/moby/moby v20.10.14+incompatible
github.com/onsi/ginkgo v1.16.4
github.com/onsi/gomega v1.15.0
github.com/prashantv/gostub v1.1.0
github.com/prometheus/client_golang v1.11.0
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.7.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -442,8 +442,6 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/moby/ipvs v1.0.1/go.mod h1:2pngiyseZbIKXNv7hsKj3O9UEz30c53MT9005gt2hxQ=
github.com/moby/moby v20.10.14+incompatible h1:J47P0p+O49F3au8QyE34dE/qXz571kcVmsbx8bvEuS0=
github.com/moby/moby v20.10.14+incompatible/go.mod h1:fDXVQ6+S340veQPv35CzDahGBmHsiclFwfEygB/TWMc=
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc=
Expand Down Expand Up @@ -512,6 +510,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
Expand Down
2 changes: 1 addition & 1 deletion pkg/koordlet/metriccache/mockmetriccache/mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pkg/koordlet/statesinformer/mockstatesinformer/mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 14 additions & 4 deletions pkg/runtime/handler/containerd_runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,21 @@ import (
"net"
"net/url"
"os"
"path/filepath"
"strings"
"time"

"google.golang.org/grpc"
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"

"github.com/koordinator-sh/koordinator/pkg/util/system"
)

var (
ContainerdEndpoint1 = filepath.Join(system.Conf.VarRunRootDir, "containerd.sock")
ContainerdEndpoint2 = filepath.Join(system.Conf.VarRunRootDir, "containerd/containerd.sock")

GrpcDial = grpc.DialContext //for test
)

type ContainerdRuntimeHandler struct {
Expand Down Expand Up @@ -55,7 +65,7 @@ func NewContainerdRuntimeHandler(endpoint string) (ContainerRuntimeHandler, erro

func (c *ContainerdRuntimeHandler) StopContainer(containerID string, timeout int64) error {
if containerID == "" {
return fmt.Errorf("ID cannot be empty")
return fmt.Errorf("containerID cannot be empty")
}
t := c.timeout + time.Duration(timeout)
ctx, cancel := context.WithTimeout(context.Background(), t)
Expand All @@ -71,7 +81,7 @@ func (c *ContainerdRuntimeHandler) StopContainer(containerID string, timeout int

func (c *ContainerdRuntimeHandler) UpdateContainerResources(containerID string, opts UpdateOptions) error {
if containerID == "" {
return fmt.Errorf("ID cannot be empty")
return fmt.Errorf("containerID cannot be empty")
}
ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
defer cancel()
Expand Down Expand Up @@ -109,7 +119,7 @@ func getClientConnection(endpoint string) (*grpc.ClientConn, error) {
ctx, cancel := context.WithTimeout(context.Background(), defaultConnectionTimeout)
defer cancel()

conn, err := grpc.DialContext(ctx, addr, grpc.WithInsecure(), grpc.WithBlock(), grpc.WithContextDialer(dialer))
conn, err := GrpcDial(ctx, addr, grpc.WithInsecure(), grpc.WithBlock(), grpc.WithContextDialer(dialer))
if err != nil {
return nil, fmt.Errorf("failed to connect, make sure you are running as root and the runtime has been started: %v", err)
}
Expand Down Expand Up @@ -138,7 +148,7 @@ func parseEndpoint(endpoint string) (string, string, error) {
case unixProtocol:
return unixProtocol, u.Path, nil
default:
return u.Scheme, "", fmt.Errorf("protocol %q not supported", u.Scheme)
return u.Scheme, "", fmt.Errorf("protocol %q is not supported", u.Scheme)
}
}

Expand Down
105 changes: 104 additions & 1 deletion pkg/runtime/handler/containerd_runtime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,107 @@

package handler

// TODO
import (
"context"
"fmt"
"path/filepath"
"testing"

"github.com/golang/mock/gomock"
"github.com/prashantv/gostub"
"github.com/stretchr/testify/assert"
"google.golang.org/grpc"

mockclient "github.com/koordinator-sh/koordinator/pkg/runtime/handler/mockclient"
"github.com/koordinator-sh/koordinator/pkg/util/system"
)

func Test_NewContainerdRuntimeHandler(t *testing.T) {
stubs := gostub.Stub(&GrpcDial, func(context context.Context, target string, opts ...grpc.DialOption) (*grpc.ClientConn, error) {
return &grpc.ClientConn{}, nil
})
defer stubs.Reset()

helper := system.NewFileTestUtil(t)
defer helper.Cleanup()
helper.MkDirAll("/var/run")
helper.WriteFileContents("/var/run/containerd.sock", "test")
system.Conf.VarRunRootDir = filepath.Join(helper.TempDir, "/var/run")
ContainerdEndpoint1 = filepath.Join(system.Conf.VarRunRootDir, "containerd.sock")

unixEndPoint := fmt.Sprintf("unix://%s", ContainerdEndpoint1)
containerdRuntime, err := NewContainerdRuntimeHandler(unixEndPoint)
assert.NoError(t, err)
assert.NotNil(t, containerdRuntime)
}

func Test_Containerd_StopContainer(t *testing.T) {
type args struct {
name string
containerId string
runtimeError error
expectError bool
}
tests := []args{
{
name: "test_stopContainer_success",
containerId: "test_container_id",
runtimeError: nil,
expectError: false,
},
{
name: "test_stopContainer_fail",
containerId: "test_container_id",
runtimeError: fmt.Errorf("stopContainer error"),
expectError: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctl := gomock.NewController(t)
defer ctl.Finish()
mockRuntimeClient := mockclient.NewMockRuntimeServiceClient(ctl)
mockRuntimeClient.EXPECT().StopContainer(gomock.Any(), gomock.Any()).Return(nil, tt.runtimeError)

runtimeHandler := ContainerdRuntimeHandler{runtimeServiceClient: mockRuntimeClient, timeout: 1, endpoint: ContainerdEndpoint1}
gotErr := runtimeHandler.StopContainer(tt.containerId, 1)
assert.Equal(t, gotErr != nil, tt.expectError)

})
}
}

func Test_Containerd_UpdateContainerResources(t *testing.T) {
type args struct {
name string
containerId string
runtimeError error
expectError bool
}
tests := []args{
{
name: "test_UpdateContainerResources_success",
containerId: "test_container_id",
runtimeError: nil,
expectError: false,
},
{
name: "test_UpdateContainerResources_fail",
containerId: "test_container_id",
runtimeError: fmt.Errorf("UpdateContainerResources error"),
expectError: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctl := gomock.NewController(t)
defer ctl.Finish()
mockRuntimeClient := mockclient.NewMockRuntimeServiceClient(ctl)
mockRuntimeClient.EXPECT().UpdateContainerResources(gomock.Any(), gomock.Any()).Return(nil, tt.runtimeError)

runtimeHandler := ContainerdRuntimeHandler{runtimeServiceClient: mockRuntimeClient, timeout: 1, endpoint: ContainerdEndpoint1}
gotErr := runtimeHandler.UpdateContainerResources(tt.containerId, UpdateOptions{})
assert.Equal(t, tt.expectError, gotErr != nil)
})
}
}
54 changes: 37 additions & 17 deletions pkg/runtime/handler/docker_runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,66 +19,86 @@ package handler
import (
"context"
"fmt"
"net/http"
"os"
"path/filepath"
"strings"
"time"

"github.com/docker/docker/api/types/container"
"github.com/moby/moby/client"
dclient "github.com/docker/docker/client"

"github.com/koordinator-sh/koordinator/pkg/util/system"
)

var (
DockerEndpoint = filepath.Join(system.Conf.VarRunRootDir, "docker.sock")
)

var GetDockerClient = createDockerClient // for test

type DockerRuntimeHandler struct {
dockerClient *client.Client
dockerClient *dclient.Client
endpoint string
}

func NewDockerRuntimeHandler(endpoint string) (ContainerRuntimeHandler, error) {
dockerClient, err := createDockerClient(endpoint)
var (
client *dclient.Client
httpClient *http.Client
err error
)

client, err = GetDockerClient(httpClient, endpoint)
if err != nil {
return nil, err
}

ctx, cancel := context.WithTimeout(context.Background(), defaultConnectionTimeout)
defer cancel()
dockerClient.NegotiateAPIVersion(ctx)

client.NegotiateAPIVersion(ctx)

return &DockerRuntimeHandler{
dockerClient: dockerClient,
dockerClient: client,
endpoint: endpoint,
}, err
}

func createDockerClient(endpoint string) (*client.Client, error) {
ep := strings.TrimPrefix(endpoint, "unix://")
func createDockerClient(httpClient *http.Client, endPoint string) (*dclient.Client, error) {
ep := strings.TrimPrefix(endPoint, "unix://")

if _, err := os.Stat(ep); err != nil {
return nil, err
}
return client.NewClientWithOpts(client.WithHost(endpoint))

return dclient.NewClientWithOpts(dclient.WithHost(endPoint), dclient.WithHTTPClient(httpClient))
}

func (d *DockerRuntimeHandler) StopContainer(containerID string, timeout int64) error {
if containerID == "" {
return fmt.Errorf("container ID cannot be empty")
if d == nil || d.dockerClient == nil {
return fmt.Errorf("stop container fail! docker client is nil! containerID=%v", containerID)
}

if d == nil || d.dockerClient == nil {
return fmt.Errorf("failed to stop container %v, docker client is nil", containerID)
if containerID == "" {
return fmt.Errorf("containerID cannot be empty")
}

ctx, cancel := context.WithTimeout(context.Background(), defaultConnectionTimeout)
defer cancel()

stopTimeout := time.Duration(timeout) * time.Second

return d.dockerClient.ContainerStop(ctx, containerID, &stopTimeout)
}

func (d *DockerRuntimeHandler) UpdateContainerResources(containerID string, opts UpdateOptions) error {
if containerID == "" {
return fmt.Errorf("container ID cannot be empty")
if d == nil || d.dockerClient == nil {
return fmt.Errorf("UpdateContainerResources fail! docker client is nil! containerID=%v", containerID)
}

if d == nil || d.dockerClient == nil {
return fmt.Errorf("failed to stop container %v, docker client is nil", containerID)
if containerID == "" {
return fmt.Errorf("containerID cannot be empty")
}

updateConfig := container.UpdateConfig{
Expand All @@ -94,7 +114,7 @@ func (d *DockerRuntimeHandler) UpdateContainerResources(containerID string, opts

ctx, cancel := context.WithTimeout(context.Background(), defaultConnectionTimeout)
defer cancel()
_, err := d.dockerClient.ContainerUpdate(ctx, containerID, updateConfig)

_, err := d.dockerClient.ContainerUpdate(ctx, containerID, updateConfig)
return err
}
Loading

0 comments on commit 23b491b

Please sign in to comment.