diff --git a/pkg/etcd/etcd_linux_test.go b/pkg/etcd/etcd_linux_test.go index 4fab77b2547..4551f1c08d8 100644 --- a/pkg/etcd/etcd_linux_test.go +++ b/pkg/etcd/etcd_linux_test.go @@ -19,6 +19,7 @@ import ( "github.com/k3s-io/k3s/pkg/daemons/config" "github.com/k3s-io/k3s/pkg/etcd/s3" testutil "github.com/k3s-io/k3s/tests" + "github.com/k3s-io/k3s/tests/mock" "github.com/robfig/cron/v3" "github.com/sirupsen/logrus" "go.etcd.io/etcd/api/v3/etcdserverpb" @@ -137,7 +138,9 @@ func Test_UnitETCD_IsInitialized(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + mock.NewExecutorWithEmbeddedETCD(t) e := NewETCD() + defer tt.teardown(tt.args.config) if err := tt.setup(tt.args.config); err != nil { t.Errorf("Prep for ETCD.IsInitialized() failed = %v", err) @@ -215,6 +218,7 @@ func Test_UnitETCD_Register(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + mock.NewExecutorWithEmbeddedETCD(t) e := NewETCD() defer tt.teardown(tt.args.config) @@ -389,6 +393,7 @@ func Test_UnitETCD_Start(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + mock.NewExecutorWithEmbeddedETCD(t) e := &ETCD{ client: tt.fields.client, config: tt.fields.config, @@ -628,6 +633,7 @@ func Test_UnitETCD_Test(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + mock.NewExecutorWithEmbeddedETCD(t) e := &ETCD{ client: tt.fields.client, config: tt.fields.config, diff --git a/tests/mock/executor.go b/tests/mock/executor.go index 92f612d5c43..80460adef83 100644 --- a/tests/mock/executor.go +++ b/tests/mock/executor.go @@ -1,86 +1,273 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: pkg/daemons/executor/executor.go +// +// Generated by this command: +// +// mockgen --source pkg/daemons/executor/executor.go -self_package github.com/k3s-io/k3s/tests/mock -package mock -mock_names Executor=Executor +// + +// Package mock is a generated GoMock package. package mock import ( - "context" - "errors" - "net/http" + context "context" + http "net/http" + reflect "reflect" - "github.com/k3s-io/k3s/pkg/cli/cmds" - "github.com/k3s-io/k3s/pkg/daemons/config" - "github.com/k3s-io/k3s/pkg/daemons/executor" - "k8s.io/apiserver/pkg/authentication/authenticator" + cmds "github.com/k3s-io/k3s/pkg/cli/cmds" + config "github.com/k3s-io/k3s/pkg/daemons/config" + executor "github.com/k3s-io/k3s/pkg/daemons/executor" + gomock "go.uber.org/mock/gomock" + authenticator "k8s.io/apiserver/pkg/authentication/authenticator" ) -// mock executor that does not actually start anything -type Executor struct{} - -func (e *Executor) Bootstrap(ctx context.Context, nodeConfig *config.Node, cfg cmds.Agent) error { - return errors.New("not implemented") +// Executor is a mock of Executor interface. +type Executor struct { + ctrl *gomock.Controller + recorder *ExecutorMockRecorder + isgomock struct{} } -func (e *Executor) Kubelet(ctx context.Context, args []string) error { - return errors.New("not implemented") +// ExecutorMockRecorder is the mock recorder for Executor. +type ExecutorMockRecorder struct { + mock *Executor } -func (e *Executor) KubeProxy(ctx context.Context, args []string) error { - return errors.New("not implemented") +// NewExecutor creates a new mock instance. +func NewExecutor(ctrl *gomock.Controller) *Executor { + mock := &Executor{ctrl: ctrl} + mock.recorder = &ExecutorMockRecorder{mock} + return mock } -func (e *Executor) APIServerHandlers(ctx context.Context) (authenticator.Request, http.Handler, error) { - return nil, nil, errors.New("not implemented") +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *Executor) EXPECT() *ExecutorMockRecorder { + return m.recorder } -func (e *Executor) APIServer(ctx context.Context, args []string) error { - return errors.New("not implemented") +// APIServer mocks base method. +func (m *Executor) APIServer(ctx context.Context, args []string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "APIServer", ctx, args) + ret0, _ := ret[0].(error) + return ret0 } -func (e *Executor) Scheduler(ctx context.Context, nodeReady <-chan struct{}, args []string) error { - return errors.New("not implemented") +// APIServer indicates an expected call of APIServer. +func (mr *ExecutorMockRecorder) APIServer(ctx, args any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "APIServer", reflect.TypeOf((*Executor)(nil).APIServer), ctx, args) } -func (e *Executor) ControllerManager(ctx context.Context, args []string) error { - return errors.New("not implemented") +// APIServerHandlers mocks base method. +func (m *Executor) APIServerHandlers(ctx context.Context) (authenticator.Request, http.Handler, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "APIServerHandlers", ctx) + ret0, _ := ret[0].(authenticator.Request) + ret1, _ := ret[1].(http.Handler) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 } -func (e *Executor) CurrentETCDOptions() (executor.InitialOptions, error) { - return executor.InitialOptions{}, nil +// APIServerHandlers indicates an expected call of APIServerHandlers. +func (mr *ExecutorMockRecorder) APIServerHandlers(ctx any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "APIServerHandlers", reflect.TypeOf((*Executor)(nil).APIServerHandlers), ctx) } -func (e *Executor) ETCD(ctx context.Context, args *executor.ETCDConfig, extraArgs []string, test executor.TestFunc) error { - embed := &executor.Embedded{} - return embed.ETCD(ctx, args, extraArgs, test) +// APIServerReadyChan mocks base method. +func (m *Executor) APIServerReadyChan() <-chan struct{} { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "APIServerReadyChan") + ret0, _ := ret[0].(<-chan struct{}) + return ret0 } -func (e *Executor) CloudControllerManager(ctx context.Context, ccmRBACReady <-chan struct{}, args []string) error { - return errors.New("not implemented") +// APIServerReadyChan indicates an expected call of APIServerReadyChan. +func (mr *ExecutorMockRecorder) APIServerReadyChan() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "APIServerReadyChan", reflect.TypeOf((*Executor)(nil).APIServerReadyChan)) } -func (e *Executor) Containerd(ctx context.Context, node *config.Node) error { - return errors.New("not implemented") +// Bootstrap mocks base method. +func (m *Executor) Bootstrap(ctx context.Context, nodeConfig *config.Node, cfg cmds.Agent) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Bootstrap", ctx, nodeConfig, cfg) + ret0, _ := ret[0].(error) + return ret0 } -func (e *Executor) Docker(ctx context.Context, node *config.Node) error { - return errors.New("not implemented") +// Bootstrap indicates an expected call of Bootstrap. +func (mr *ExecutorMockRecorder) Bootstrap(ctx, nodeConfig, cfg any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Bootstrap", reflect.TypeOf((*Executor)(nil).Bootstrap), ctx, nodeConfig, cfg) } -func (e *Executor) CRI(ctx context.Context, node *config.Node) error { - return errors.New("not implemented") +// CRI mocks base method. +func (m *Executor) CRI(ctx context.Context, node *config.Node) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CRI", ctx, node) + ret0, _ := ret[0].(error) + return ret0 } -func (e *Executor) APIServerReadyChan() <-chan struct{} { - c := make(chan struct{}) - close(c) - return c +// CRI indicates an expected call of CRI. +func (mr *ExecutorMockRecorder) CRI(ctx, node any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CRI", reflect.TypeOf((*Executor)(nil).CRI), ctx, node) } -func (e *Executor) ETCDReadyChan() <-chan struct{} { - c := make(chan struct{}) - close(c) - return c +// CRIReadyChan mocks base method. +func (m *Executor) CRIReadyChan() <-chan struct{} { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CRIReadyChan") + ret0, _ := ret[0].(<-chan struct{}) + return ret0 } -func (e *Executor) CRIReadyChan() <-chan struct{} { - c := make(chan struct{}) - close(c) - return c +// CRIReadyChan indicates an expected call of CRIReadyChan. +func (mr *ExecutorMockRecorder) CRIReadyChan() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CRIReadyChan", reflect.TypeOf((*Executor)(nil).CRIReadyChan)) +} + +// CloudControllerManager mocks base method. +func (m *Executor) CloudControllerManager(ctx context.Context, ccmRBACReady <-chan struct{}, args []string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CloudControllerManager", ctx, ccmRBACReady, args) + ret0, _ := ret[0].(error) + return ret0 +} + +// CloudControllerManager indicates an expected call of CloudControllerManager. +func (mr *ExecutorMockRecorder) CloudControllerManager(ctx, ccmRBACReady, args any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CloudControllerManager", reflect.TypeOf((*Executor)(nil).CloudControllerManager), ctx, ccmRBACReady, args) +} + +// Containerd mocks base method. +func (m *Executor) Containerd(ctx context.Context, node *config.Node) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Containerd", ctx, node) + ret0, _ := ret[0].(error) + return ret0 +} + +// Containerd indicates an expected call of Containerd. +func (mr *ExecutorMockRecorder) Containerd(ctx, node any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Containerd", reflect.TypeOf((*Executor)(nil).Containerd), ctx, node) +} + +// ControllerManager mocks base method. +func (m *Executor) ControllerManager(ctx context.Context, args []string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ControllerManager", ctx, args) + ret0, _ := ret[0].(error) + return ret0 +} + +// ControllerManager indicates an expected call of ControllerManager. +func (mr *ExecutorMockRecorder) ControllerManager(ctx, args any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ControllerManager", reflect.TypeOf((*Executor)(nil).ControllerManager), ctx, args) +} + +// CurrentETCDOptions mocks base method. +func (m *Executor) CurrentETCDOptions() (executor.InitialOptions, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CurrentETCDOptions") + ret0, _ := ret[0].(executor.InitialOptions) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CurrentETCDOptions indicates an expected call of CurrentETCDOptions. +func (mr *ExecutorMockRecorder) CurrentETCDOptions() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CurrentETCDOptions", reflect.TypeOf((*Executor)(nil).CurrentETCDOptions)) +} + +// Docker mocks base method. +func (m *Executor) Docker(ctx context.Context, node *config.Node) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Docker", ctx, node) + ret0, _ := ret[0].(error) + return ret0 +} + +// Docker indicates an expected call of Docker. +func (mr *ExecutorMockRecorder) Docker(ctx, node any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Docker", reflect.TypeOf((*Executor)(nil).Docker), ctx, node) +} + +// ETCD mocks base method. +func (m *Executor) ETCD(ctx context.Context, args *executor.ETCDConfig, extraArgs []string, test executor.TestFunc) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ETCD", ctx, args, extraArgs, test) + ret0, _ := ret[0].(error) + return ret0 +} + +// ETCD indicates an expected call of ETCD. +func (mr *ExecutorMockRecorder) ETCD(ctx, args, extraArgs, test any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ETCD", reflect.TypeOf((*Executor)(nil).ETCD), ctx, args, extraArgs, test) +} + +// ETCDReadyChan mocks base method. +func (m *Executor) ETCDReadyChan() <-chan struct{} { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ETCDReadyChan") + ret0, _ := ret[0].(<-chan struct{}) + return ret0 +} + +// ETCDReadyChan indicates an expected call of ETCDReadyChan. +func (mr *ExecutorMockRecorder) ETCDReadyChan() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ETCDReadyChan", reflect.TypeOf((*Executor)(nil).ETCDReadyChan)) +} + +// KubeProxy mocks base method. +func (m *Executor) KubeProxy(ctx context.Context, args []string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "KubeProxy", ctx, args) + ret0, _ := ret[0].(error) + return ret0 +} + +// KubeProxy indicates an expected call of KubeProxy. +func (mr *ExecutorMockRecorder) KubeProxy(ctx, args any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "KubeProxy", reflect.TypeOf((*Executor)(nil).KubeProxy), ctx, args) +} + +// Kubelet mocks base method. +func (m *Executor) Kubelet(ctx context.Context, args []string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Kubelet", ctx, args) + ret0, _ := ret[0].(error) + return ret0 +} + +// Kubelet indicates an expected call of Kubelet. +func (mr *ExecutorMockRecorder) Kubelet(ctx, args any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Kubelet", reflect.TypeOf((*Executor)(nil).Kubelet), ctx, args) +} + +// Scheduler mocks base method. +func (m *Executor) Scheduler(ctx context.Context, nodeReady <-chan struct{}, args []string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Scheduler", ctx, nodeReady, args) + ret0, _ := ret[0].(error) + return ret0 +} + +// Scheduler indicates an expected call of Scheduler. +func (mr *ExecutorMockRecorder) Scheduler(ctx, nodeReady, args any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Scheduler", reflect.TypeOf((*Executor)(nil).Scheduler), ctx, nodeReady, args) } diff --git a/tests/mock/executor_helpers.go b/tests/mock/executor_helpers.go new file mode 100644 index 00000000000..df02e0675f9 --- /dev/null +++ b/tests/mock/executor_helpers.go @@ -0,0 +1,33 @@ +package mock + +import ( + "testing" + + executor "github.com/k3s-io/k3s/pkg/daemons/executor" + "go.uber.org/mock/gomock" +) + +// NewExecutorWithEmbeddedETCD creates a new mock executor, and sets it as the current executor. +// The executor exepects calls to ETCD(), and wraps the embedded executor method of the same name. +// The various ready channels are also mocked with immediate channel closure. +func NewExecutorWithEmbeddedETCD(t *testing.T) { + mockController := gomock.NewController(t) + mockExecutor := NewExecutor(mockController) + + embed := &executor.Embedded{} + initialOptions := func() (executor.InitialOptions, error) { + return executor.InitialOptions{}, nil + } + closedChannel := func() <-chan struct{} { + c := make(chan struct{}) + close(c) + return c + } + + mockExecutor.EXPECT().ETCD(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().DoAndReturn(embed.ETCD) + mockExecutor.EXPECT().CurrentETCDOptions().AnyTimes().DoAndReturn(initialOptions) + mockExecutor.EXPECT().CRIReadyChan().AnyTimes().DoAndReturn(closedChannel) + mockExecutor.EXPECT().ETCDReadyChan().AnyTimes().DoAndReturn(closedChannel) + + executor.Set(mockExecutor) +} diff --git a/tests/unit.go b/tests/unit.go index da00b2b06bc..d385815ccc6 100644 --- a/tests/unit.go +++ b/tests/unit.go @@ -7,8 +7,6 @@ import ( "github.com/k3s-io/k3s/pkg/daemons/config" "github.com/k3s-io/k3s/pkg/daemons/control/deps" - "github.com/k3s-io/k3s/pkg/daemons/executor" - "github.com/k3s-io/k3s/tests/mock" ) // GenerateDataDir creates a temporary directory at "/tmp/k3s//". @@ -45,9 +43,6 @@ func CleanupDataDir(cnf *config.Control) { // GenerateRuntime creates a temporary data dir and configures // config.ControlRuntime with all the appropriate certificate keys. func GenerateRuntime(cnf *config.Control) error { - // use mock executor that does not actually start things - executor.Set(&mock.Executor{}) - // reuse ready channel from existing runtime if set cnf.Runtime = config.NewRuntime() if err := GenerateDataDir(cnf); err != nil {