From 81cb605eaa9b3c09b814ceac1203aaa4eaa63290 Mon Sep 17 00:00:00 2001 From: Thomas Guettler Date: Mon, 9 Oct 2023 11:14:56 +0200 Subject: [PATCH] :seedling: Installimage: create event containing debug.txt --- .gitignore | 2 + Makefile | 8 +- api/v1beta1/hetznerbaremetalhost_types.go | 2 +- .../hetznerbaremetalhost_controller_test.go | 7 +- ...hetznerbaremetalmachine_controller_test.go | 2 + docs/topics/quickstart.md | 2 +- pkg/services/baremetal/client/.mockery.yaml | 16 + .../baremetal/client/mocks/robot/Client.go | 376 ++++++++- .../baremetal/client/mocks/robot/Factory.go | 45 +- .../baremetal/client/mocks/ssh/Client.go | 713 +++++++++++++++++- .../baremetal/client/mocks/ssh/Factory.go | 45 +- .../baremetal/client/ssh/ssh_client.go | 100 ++- .../baremetal/client/ssh/ssh_client_test.go | 51 ++ pkg/services/baremetal/host/host.go | 51 +- pkg/services/baremetal/host/host_test.go | 1 + pkg/services/hcloud/server/server.go | 2 +- test/e2e/data/ccm/hcloud-ccm-hetzner.yaml | 20 +- test/e2e/data/ccm/hcloud-ccm-network.yaml | 22 +- test/helpers/defaults.go | 7 +- 19 files changed, 1399 insertions(+), 73 deletions(-) create mode 100644 pkg/services/baremetal/client/.mockery.yaml create mode 100644 pkg/services/baremetal/client/ssh/ssh_client_test.go diff --git a/.gitignore b/.gitignore index a3b634a9c..f11c2f5d0 100644 --- a/.gitignore +++ b/.gitignore @@ -73,3 +73,5 @@ __pycache__/ /_output tmp_* +# baremetal hosts +baremetalhosts*yaml \ No newline at end of file diff --git a/Makefile b/Makefile index 4d5e72e1d..8e377084a 100644 --- a/Makefile +++ b/Makefile @@ -191,7 +191,7 @@ install-cilium-in-wl-cluster: install-ccm-in-wl-cluster: helm repo add syself https://charts.syself.com helm repo update syself - KUBECONFIG=$(WORKER_CLUSTER_KUBECONFIG) helm upgrade --install ccm syself/ccm-hetzner --version 1.1.8 \ + KUBECONFIG=$(WORKER_CLUSTER_KUBECONFIG) helm upgrade --install ccm syself/ccm-hetzner --version 1.1.10 \ --namespace kube-system \ --set privateNetwork.enabled=$(PRIVATE_NETWORK) @echo 'run "kubectl --kubeconfig=$(WORKER_CLUSTER_KUBECONFIG) ..." to work with the new target cluster' @@ -749,8 +749,12 @@ lint: lint-golang lint-yaml lint-dockerfile lint-links ## Lint Codebase .PHONY: format format: format-starlark format-golang format-yaml ## Format Codebase +.PHONY: generate-mocks +generate-mocks: ## Generate Mocks + cd pkg/services/baremetal/client; go run github.com/vektra/mockery/v2@v2.35.3 + .PHONY: generate -generate: generate-manifests generate-go-deepcopy generate-boilerplate generate-modules ## Generate Files +generate: generate-manifests generate-go-deepcopy generate-boilerplate generate-modules generate-mocks ## Generate Files ALL_VERIFY_CHECKS = boilerplate shellcheck starlark .PHONY: verify diff --git a/api/v1beta1/hetznerbaremetalhost_types.go b/api/v1beta1/hetznerbaremetalhost_types.go index 501d0d79b..5764e4b9f 100644 --- a/api/v1beta1/hetznerbaremetalhost_types.go +++ b/api/v1beta1/hetznerbaremetalhost_types.go @@ -137,7 +137,7 @@ const ( // StateProvisioning means we are sending userData to the host and boot the machine. StateProvisioning ProvisioningState = "provisioning" - // StateEnsureProvisioned means we are ensuring the reboot worked and cloud init is installed. + // StateEnsureProvisioned means we are ensuring the reboot worked and cloud init was executed successfully. StateEnsureProvisioned ProvisioningState = "ensure-provisioned" // StateProvisioned means we have sent userData to the host and booted the machine. diff --git a/controllers/hetznerbaremetalhost_controller_test.go b/controllers/hetznerbaremetalhost_controller_test.go index 89055913c..3c5db670c 100644 --- a/controllers/hetznerbaremetalhost_controller_test.go +++ b/controllers/hetznerbaremetalhost_controller_test.go @@ -173,6 +173,8 @@ var _ = Describe("HetznerBareMetalHostReconciler", func() { StdErr: "", Err: nil, }) + osSSHClientAfterInstallImage.On("GetCloudInitOutput").Return(sshclient.Output{StdOut: "dummy content of /var/log/cloud-init-output.log"}) + osSSHClientAfterCloudInit.On("Reboot").Return(sshclient.Output{}) osSSHClientAfterCloudInit.On("GetHostName").Return(sshclient.Output{ StdOut: infrav1.BareMetalHostNamePrefix + bmMachineName, @@ -182,6 +184,7 @@ var _ = Describe("HetznerBareMetalHostReconciler", func() { osSSHClientAfterCloudInit.On("CloudInitStatus").Return(sshclient.Output{StdOut: "status: done"}) osSSHClientAfterCloudInit.On("CheckCloudInitLogsForSigTerm").Return(sshclient.Output{}) osSSHClientAfterCloudInit.On("ResetKubeadm").Return(sshclient.Output{}) + osSSHClientAfterCloudInit.On("GetCloudInitOutput").Return(sshclient.Output{StdOut: "dummy content of /var/log/cloud-init-output.log"}) }) AfterEach(func() { @@ -333,6 +336,7 @@ var _ = Describe("HetznerBareMetalHostReconciler", func() { }, timeout, time.Second).Should(BeNil()) Eventually(func() bool { + // TODO: Add logging to trace flaky unit-test. if err := testEnv.Get(ctx, key, host); err != nil { return false } @@ -693,7 +697,7 @@ var _ = Describe("HetznerBareMetalHostReconciler - missing secrets", func() { }, timeout).Should(BeTrue()) }) - It("gives the right error if secret is invalid", func() { + It("gives the right error if secret if rescue-ssh is invalid", func() { rescueSSHSecret = &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: "rescue-ssh-secret", @@ -828,4 +832,5 @@ name="eth0" model="Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express sshClient.On("CreatePostInstallScript", mock.Anything).Return(sshclient.Output{}) sshClient.On("ExecuteInstallImage", mock.Anything).Return(sshclient.Output{}) sshClient.On("Reboot").Return(sshclient.Output{}) + sshClient.On("GetCloudInitOutput").Return(sshclient.Output{StdOut: "dummy content of /var/log/cloud-init-output.log"}) } diff --git a/controllers/hetznerbaremetalmachine_controller_test.go b/controllers/hetznerbaremetalmachine_controller_test.go index b34fe0f17..0a18b0dea 100644 --- a/controllers/hetznerbaremetalmachine_controller_test.go +++ b/controllers/hetznerbaremetalmachine_controller_test.go @@ -159,6 +159,8 @@ var _ = Describe("HetznerBareMetalMachineReconciler", func() { StdErr: "", Err: nil, }) + osSSHClient.On("GetCloudInitOutput").Return(sshclient.Output{StdOut: "dummy content of /var/log/cloud-init-output.log"}) + }) AfterEach(func() { diff --git a/docs/topics/quickstart.md b/docs/topics/quickstart.md index ea84de69c..e1b3b9b2e 100644 --- a/docs/topics/quickstart.md +++ b/docs/topics/quickstart.md @@ -127,7 +127,7 @@ KUBECONFIG=$CAPH_WORKER_CLUSTER_KUBECONFIG helm upgrade --install ccm syself/ccm helm repo add syself https://charts.syself.com helm repo update syself -KUBECONFIG=$CAPH_WORKER_CLUSTER_KUBECONFIG helm upgrade --install ccm syself/ccm-hetzner --version 1.1.8 \ +KUBECONFIG=$CAPH_WORKER_CLUSTER_KUBECONFIG helm upgrade --install ccm syself/ccm-hetzner --version 1.1.10 \ --namespace kube-system \ --set privateNetwork.enabled=false ``` diff --git a/pkg/services/baremetal/client/.mockery.yaml b/pkg/services/baremetal/client/.mockery.yaml new file mode 100644 index 000000000..3b8149814 --- /dev/null +++ b/pkg/services/baremetal/client/.mockery.yaml @@ -0,0 +1,16 @@ +# This config was choosen, so that the output matches to old structure (pre config file .mockery.yaml). +# If you are here to copy this config to a new project, then it might +# make sense to choose a structure which needs less config by using +# the default values of Mockery. +all: True +filename: "{{.InterfaceName}}.go" +mockname: "{{.InterfaceName}}" +outpkg: mocks +packages: + github.com/syself/cluster-api-provider-hetzner/pkg/services/baremetal/client/ssh: + config: + dir: mocks/ssh + + github.com/syself/cluster-api-provider-hetzner/pkg/services/baremetal/client/robot: + config: + dir: mocks/robot diff --git a/pkg/services/baremetal/client/mocks/robot/Client.go b/pkg/services/baremetal/client/mocks/robot/Client.go index 8ed9382c3..e10937d10 100644 --- a/pkg/services/baremetal/client/mocks/robot/Client.go +++ b/pkg/services/baremetal/client/mocks/robot/Client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.14.0. DO NOT EDIT. +// Code generated by mockery v2.35.3. DO NOT EDIT. package mocks @@ -14,11 +14,23 @@ type Client struct { mock.Mock } +type Client_Expecter struct { + mock *mock.Mock +} + +func (_m *Client) EXPECT() *Client_Expecter { + return &Client_Expecter{mock: &_m.Mock} +} + // DeleteBootRescue provides a mock function with given fields: id func (_m *Client) DeleteBootRescue(id int) (*models.Rescue, error) { ret := _m.Called(id) var r0 *models.Rescue + var r1 error + if rf, ok := ret.Get(0).(func(int) (*models.Rescue, error)); ok { + return rf(id) + } if rf, ok := ret.Get(0).(func(int) *models.Rescue); ok { r0 = rf(id) } else { @@ -27,7 +39,6 @@ func (_m *Client) DeleteBootRescue(id int) (*models.Rescue, error) { } } - var r1 error if rf, ok := ret.Get(1).(func(int) error); ok { r1 = rf(id) } else { @@ -37,11 +48,43 @@ func (_m *Client) DeleteBootRescue(id int) (*models.Rescue, error) { return r0, r1 } +// Client_DeleteBootRescue_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteBootRescue' +type Client_DeleteBootRescue_Call struct { + *mock.Call +} + +// DeleteBootRescue is a helper method to define mock.On call +// - id int +func (_e *Client_Expecter) DeleteBootRescue(id interface{}) *Client_DeleteBootRescue_Call { + return &Client_DeleteBootRescue_Call{Call: _e.mock.On("DeleteBootRescue", id)} +} + +func (_c *Client_DeleteBootRescue_Call) Run(run func(id int)) *Client_DeleteBootRescue_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(int)) + }) + return _c +} + +func (_c *Client_DeleteBootRescue_Call) Return(_a0 *models.Rescue, _a1 error) *Client_DeleteBootRescue_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_DeleteBootRescue_Call) RunAndReturn(run func(int) (*models.Rescue, error)) *Client_DeleteBootRescue_Call { + _c.Call.Return(run) + return _c +} + // GetBMServer provides a mock function with given fields: _a0 func (_m *Client) GetBMServer(_a0 int) (*models.Server, error) { ret := _m.Called(_a0) var r0 *models.Server + var r1 error + if rf, ok := ret.Get(0).(func(int) (*models.Server, error)); ok { + return rf(_a0) + } if rf, ok := ret.Get(0).(func(int) *models.Server); ok { r0 = rf(_a0) } else { @@ -50,7 +93,6 @@ func (_m *Client) GetBMServer(_a0 int) (*models.Server, error) { } } - var r1 error if rf, ok := ret.Get(1).(func(int) error); ok { r1 = rf(_a0) } else { @@ -60,11 +102,43 @@ func (_m *Client) GetBMServer(_a0 int) (*models.Server, error) { return r0, r1 } +// Client_GetBMServer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetBMServer' +type Client_GetBMServer_Call struct { + *mock.Call +} + +// GetBMServer is a helper method to define mock.On call +// - _a0 int +func (_e *Client_Expecter) GetBMServer(_a0 interface{}) *Client_GetBMServer_Call { + return &Client_GetBMServer_Call{Call: _e.mock.On("GetBMServer", _a0)} +} + +func (_c *Client_GetBMServer_Call) Run(run func(_a0 int)) *Client_GetBMServer_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(int)) + }) + return _c +} + +func (_c *Client_GetBMServer_Call) Return(_a0 *models.Server, _a1 error) *Client_GetBMServer_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_GetBMServer_Call) RunAndReturn(run func(int) (*models.Server, error)) *Client_GetBMServer_Call { + _c.Call.Return(run) + return _c +} + // GetBootRescue provides a mock function with given fields: id func (_m *Client) GetBootRescue(id int) (*models.Rescue, error) { ret := _m.Called(id) var r0 *models.Rescue + var r1 error + if rf, ok := ret.Get(0).(func(int) (*models.Rescue, error)); ok { + return rf(id) + } if rf, ok := ret.Get(0).(func(int) *models.Rescue); ok { r0 = rf(id) } else { @@ -73,7 +147,6 @@ func (_m *Client) GetBootRescue(id int) (*models.Rescue, error) { } } - var r1 error if rf, ok := ret.Get(1).(func(int) error); ok { r1 = rf(id) } else { @@ -83,11 +156,43 @@ func (_m *Client) GetBootRescue(id int) (*models.Rescue, error) { return r0, r1 } +// Client_GetBootRescue_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetBootRescue' +type Client_GetBootRescue_Call struct { + *mock.Call +} + +// GetBootRescue is a helper method to define mock.On call +// - id int +func (_e *Client_Expecter) GetBootRescue(id interface{}) *Client_GetBootRescue_Call { + return &Client_GetBootRescue_Call{Call: _e.mock.On("GetBootRescue", id)} +} + +func (_c *Client_GetBootRescue_Call) Run(run func(id int)) *Client_GetBootRescue_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(int)) + }) + return _c +} + +func (_c *Client_GetBootRescue_Call) Return(_a0 *models.Rescue, _a1 error) *Client_GetBootRescue_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_GetBootRescue_Call) RunAndReturn(run func(int) (*models.Rescue, error)) *Client_GetBootRescue_Call { + _c.Call.Return(run) + return _c +} + // GetReboot provides a mock function with given fields: _a0 func (_m *Client) GetReboot(_a0 int) (*models.Reset, error) { ret := _m.Called(_a0) var r0 *models.Reset + var r1 error + if rf, ok := ret.Get(0).(func(int) (*models.Reset, error)); ok { + return rf(_a0) + } if rf, ok := ret.Get(0).(func(int) *models.Reset); ok { r0 = rf(_a0) } else { @@ -96,7 +201,6 @@ func (_m *Client) GetReboot(_a0 int) (*models.Reset, error) { } } - var r1 error if rf, ok := ret.Get(1).(func(int) error); ok { r1 = rf(_a0) } else { @@ -106,11 +210,43 @@ func (_m *Client) GetReboot(_a0 int) (*models.Reset, error) { return r0, r1 } +// Client_GetReboot_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetReboot' +type Client_GetReboot_Call struct { + *mock.Call +} + +// GetReboot is a helper method to define mock.On call +// - _a0 int +func (_e *Client_Expecter) GetReboot(_a0 interface{}) *Client_GetReboot_Call { + return &Client_GetReboot_Call{Call: _e.mock.On("GetReboot", _a0)} +} + +func (_c *Client_GetReboot_Call) Run(run func(_a0 int)) *Client_GetReboot_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(int)) + }) + return _c +} + +func (_c *Client_GetReboot_Call) Return(_a0 *models.Reset, _a1 error) *Client_GetReboot_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_GetReboot_Call) RunAndReturn(run func(int) (*models.Reset, error)) *Client_GetReboot_Call { + _c.Call.Return(run) + return _c +} + // ListBMServers provides a mock function with given fields: func (_m *Client) ListBMServers() ([]models.Server, error) { ret := _m.Called() var r0 []models.Server + var r1 error + if rf, ok := ret.Get(0).(func() ([]models.Server, error)); ok { + return rf() + } if rf, ok := ret.Get(0).(func() []models.Server); ok { r0 = rf() } else { @@ -119,7 +255,6 @@ func (_m *Client) ListBMServers() ([]models.Server, error) { } } - var r1 error if rf, ok := ret.Get(1).(func() error); ok { r1 = rf() } else { @@ -129,11 +264,42 @@ func (_m *Client) ListBMServers() ([]models.Server, error) { return r0, r1 } +// Client_ListBMServers_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListBMServers' +type Client_ListBMServers_Call struct { + *mock.Call +} + +// ListBMServers is a helper method to define mock.On call +func (_e *Client_Expecter) ListBMServers() *Client_ListBMServers_Call { + return &Client_ListBMServers_Call{Call: _e.mock.On("ListBMServers")} +} + +func (_c *Client_ListBMServers_Call) Run(run func()) *Client_ListBMServers_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Client_ListBMServers_Call) Return(_a0 []models.Server, _a1 error) *Client_ListBMServers_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_ListBMServers_Call) RunAndReturn(run func() ([]models.Server, error)) *Client_ListBMServers_Call { + _c.Call.Return(run) + return _c +} + // ListSSHKeys provides a mock function with given fields: func (_m *Client) ListSSHKeys() ([]models.Key, error) { ret := _m.Called() var r0 []models.Key + var r1 error + if rf, ok := ret.Get(0).(func() ([]models.Key, error)); ok { + return rf() + } if rf, ok := ret.Get(0).(func() []models.Key); ok { r0 = rf() } else { @@ -142,7 +308,6 @@ func (_m *Client) ListSSHKeys() ([]models.Key, error) { } } - var r1 error if rf, ok := ret.Get(1).(func() error); ok { r1 = rf() } else { @@ -152,11 +317,42 @@ func (_m *Client) ListSSHKeys() ([]models.Key, error) { return r0, r1 } +// Client_ListSSHKeys_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListSSHKeys' +type Client_ListSSHKeys_Call struct { + *mock.Call +} + +// ListSSHKeys is a helper method to define mock.On call +func (_e *Client_Expecter) ListSSHKeys() *Client_ListSSHKeys_Call { + return &Client_ListSSHKeys_Call{Call: _e.mock.On("ListSSHKeys")} +} + +func (_c *Client_ListSSHKeys_Call) Run(run func()) *Client_ListSSHKeys_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Client_ListSSHKeys_Call) Return(_a0 []models.Key, _a1 error) *Client_ListSSHKeys_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_ListSSHKeys_Call) RunAndReturn(run func() ([]models.Key, error)) *Client_ListSSHKeys_Call { + _c.Call.Return(run) + return _c +} + // RebootBMServer provides a mock function with given fields: _a0, _a1 func (_m *Client) RebootBMServer(_a0 int, _a1 v1beta1.RebootType) (*models.ResetPost, error) { ret := _m.Called(_a0, _a1) var r0 *models.ResetPost + var r1 error + if rf, ok := ret.Get(0).(func(int, v1beta1.RebootType) (*models.ResetPost, error)); ok { + return rf(_a0, _a1) + } if rf, ok := ret.Get(0).(func(int, v1beta1.RebootType) *models.ResetPost); ok { r0 = rf(_a0, _a1) } else { @@ -165,7 +361,6 @@ func (_m *Client) RebootBMServer(_a0 int, _a1 v1beta1.RebootType) (*models.Reset } } - var r1 error if rf, ok := ret.Get(1).(func(int, v1beta1.RebootType) error); ok { r1 = rf(_a0, _a1) } else { @@ -175,11 +370,44 @@ func (_m *Client) RebootBMServer(_a0 int, _a1 v1beta1.RebootType) (*models.Reset return r0, r1 } +// Client_RebootBMServer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RebootBMServer' +type Client_RebootBMServer_Call struct { + *mock.Call +} + +// RebootBMServer is a helper method to define mock.On call +// - _a0 int +// - _a1 v1beta1.RebootType +func (_e *Client_Expecter) RebootBMServer(_a0 interface{}, _a1 interface{}) *Client_RebootBMServer_Call { + return &Client_RebootBMServer_Call{Call: _e.mock.On("RebootBMServer", _a0, _a1)} +} + +func (_c *Client_RebootBMServer_Call) Run(run func(_a0 int, _a1 v1beta1.RebootType)) *Client_RebootBMServer_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(int), args[1].(v1beta1.RebootType)) + }) + return _c +} + +func (_c *Client_RebootBMServer_Call) Return(_a0 *models.ResetPost, _a1 error) *Client_RebootBMServer_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_RebootBMServer_Call) RunAndReturn(run func(int, v1beta1.RebootType) (*models.ResetPost, error)) *Client_RebootBMServer_Call { + _c.Call.Return(run) + return _c +} + // SetBMServerName provides a mock function with given fields: _a0, _a1 func (_m *Client) SetBMServerName(_a0 int, _a1 string) (*models.Server, error) { ret := _m.Called(_a0, _a1) var r0 *models.Server + var r1 error + if rf, ok := ret.Get(0).(func(int, string) (*models.Server, error)); ok { + return rf(_a0, _a1) + } if rf, ok := ret.Get(0).(func(int, string) *models.Server); ok { r0 = rf(_a0, _a1) } else { @@ -188,7 +416,6 @@ func (_m *Client) SetBMServerName(_a0 int, _a1 string) (*models.Server, error) { } } - var r1 error if rf, ok := ret.Get(1).(func(int, string) error); ok { r1 = rf(_a0, _a1) } else { @@ -198,11 +425,44 @@ func (_m *Client) SetBMServerName(_a0 int, _a1 string) (*models.Server, error) { return r0, r1 } +// Client_SetBMServerName_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetBMServerName' +type Client_SetBMServerName_Call struct { + *mock.Call +} + +// SetBMServerName is a helper method to define mock.On call +// - _a0 int +// - _a1 string +func (_e *Client_Expecter) SetBMServerName(_a0 interface{}, _a1 interface{}) *Client_SetBMServerName_Call { + return &Client_SetBMServerName_Call{Call: _e.mock.On("SetBMServerName", _a0, _a1)} +} + +func (_c *Client_SetBMServerName_Call) Run(run func(_a0 int, _a1 string)) *Client_SetBMServerName_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(int), args[1].(string)) + }) + return _c +} + +func (_c *Client_SetBMServerName_Call) Return(_a0 *models.Server, _a1 error) *Client_SetBMServerName_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_SetBMServerName_Call) RunAndReturn(run func(int, string) (*models.Server, error)) *Client_SetBMServerName_Call { + _c.Call.Return(run) + return _c +} + // SetBootRescue provides a mock function with given fields: id, fingerprint func (_m *Client) SetBootRescue(id int, fingerprint string) (*models.Rescue, error) { ret := _m.Called(id, fingerprint) var r0 *models.Rescue + var r1 error + if rf, ok := ret.Get(0).(func(int, string) (*models.Rescue, error)); ok { + return rf(id, fingerprint) + } if rf, ok := ret.Get(0).(func(int, string) *models.Rescue); ok { r0 = rf(id, fingerprint) } else { @@ -211,7 +471,6 @@ func (_m *Client) SetBootRescue(id int, fingerprint string) (*models.Rescue, err } } - var r1 error if rf, ok := ret.Get(1).(func(int, string) error); ok { r1 = rf(id, fingerprint) } else { @@ -221,11 +480,44 @@ func (_m *Client) SetBootRescue(id int, fingerprint string) (*models.Rescue, err return r0, r1 } +// Client_SetBootRescue_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetBootRescue' +type Client_SetBootRescue_Call struct { + *mock.Call +} + +// SetBootRescue is a helper method to define mock.On call +// - id int +// - fingerprint string +func (_e *Client_Expecter) SetBootRescue(id interface{}, fingerprint interface{}) *Client_SetBootRescue_Call { + return &Client_SetBootRescue_Call{Call: _e.mock.On("SetBootRescue", id, fingerprint)} +} + +func (_c *Client_SetBootRescue_Call) Run(run func(id int, fingerprint string)) *Client_SetBootRescue_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(int), args[1].(string)) + }) + return _c +} + +func (_c *Client_SetBootRescue_Call) Return(_a0 *models.Rescue, _a1 error) *Client_SetBootRescue_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_SetBootRescue_Call) RunAndReturn(run func(int, string) (*models.Rescue, error)) *Client_SetBootRescue_Call { + _c.Call.Return(run) + return _c +} + // SetSSHKey provides a mock function with given fields: name, publickey func (_m *Client) SetSSHKey(name string, publickey string) (*models.Key, error) { ret := _m.Called(name, publickey) var r0 *models.Key + var r1 error + if rf, ok := ret.Get(0).(func(string, string) (*models.Key, error)); ok { + return rf(name, publickey) + } if rf, ok := ret.Get(0).(func(string, string) *models.Key); ok { r0 = rf(name, publickey) } else { @@ -234,7 +526,6 @@ func (_m *Client) SetSSHKey(name string, publickey string) (*models.Key, error) } } - var r1 error if rf, ok := ret.Get(1).(func(string, string) error); ok { r1 = rf(name, publickey) } else { @@ -244,6 +535,35 @@ func (_m *Client) SetSSHKey(name string, publickey string) (*models.Key, error) return r0, r1 } +// Client_SetSSHKey_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetSSHKey' +type Client_SetSSHKey_Call struct { + *mock.Call +} + +// SetSSHKey is a helper method to define mock.On call +// - name string +// - publickey string +func (_e *Client_Expecter) SetSSHKey(name interface{}, publickey interface{}) *Client_SetSSHKey_Call { + return &Client_SetSSHKey_Call{Call: _e.mock.On("SetSSHKey", name, publickey)} +} + +func (_c *Client_SetSSHKey_Call) Run(run func(name string, publickey string)) *Client_SetSSHKey_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string), args[1].(string)) + }) + return _c +} + +func (_c *Client_SetSSHKey_Call) Return(_a0 *models.Key, _a1 error) *Client_SetSSHKey_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_SetSSHKey_Call) RunAndReturn(run func(string, string) (*models.Key, error)) *Client_SetSSHKey_Call { + _c.Call.Return(run) + return _c +} + // ValidateCredentials provides a mock function with given fields: func (_m *Client) ValidateCredentials() error { ret := _m.Called() @@ -258,13 +578,39 @@ func (_m *Client) ValidateCredentials() error { return r0 } -type mockConstructorTestingTNewClient interface { - mock.TestingT - Cleanup(func()) +// Client_ValidateCredentials_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ValidateCredentials' +type Client_ValidateCredentials_Call struct { + *mock.Call +} + +// ValidateCredentials is a helper method to define mock.On call +func (_e *Client_Expecter) ValidateCredentials() *Client_ValidateCredentials_Call { + return &Client_ValidateCredentials_Call{Call: _e.mock.On("ValidateCredentials")} +} + +func (_c *Client_ValidateCredentials_Call) Run(run func()) *Client_ValidateCredentials_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Client_ValidateCredentials_Call) Return(_a0 error) *Client_ValidateCredentials_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_ValidateCredentials_Call) RunAndReturn(run func() error) *Client_ValidateCredentials_Call { + _c.Call.Return(run) + return _c } // NewClient creates a new instance of Client. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewClient(t mockConstructorTestingTNewClient) *Client { +// The first argument is typically a *testing.T value. +func NewClient(t interface { + mock.TestingT + Cleanup(func()) +}) *Client { mock := &Client{} mock.Mock.Test(t) diff --git a/pkg/services/baremetal/client/mocks/robot/Factory.go b/pkg/services/baremetal/client/mocks/robot/Factory.go index 6d9f92db7..dae6304a0 100644 --- a/pkg/services/baremetal/client/mocks/robot/Factory.go +++ b/pkg/services/baremetal/client/mocks/robot/Factory.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.14.0. DO NOT EDIT. +// Code generated by mockery v2.35.3. DO NOT EDIT. package mocks @@ -12,6 +12,14 @@ type Factory struct { mock.Mock } +type Factory_Expecter struct { + mock *mock.Mock +} + +func (_m *Factory) EXPECT() *Factory_Expecter { + return &Factory_Expecter{mock: &_m.Mock} +} + // NewClient provides a mock function with given fields: _a0 func (_m *Factory) NewClient(_a0 robotclient.Credentials) robotclient.Client { ret := _m.Called(_a0) @@ -28,13 +36,40 @@ func (_m *Factory) NewClient(_a0 robotclient.Credentials) robotclient.Client { return r0 } -type mockConstructorTestingTNewFactory interface { - mock.TestingT - Cleanup(func()) +// Factory_NewClient_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'NewClient' +type Factory_NewClient_Call struct { + *mock.Call +} + +// NewClient is a helper method to define mock.On call +// - _a0 robotclient.Credentials +func (_e *Factory_Expecter) NewClient(_a0 interface{}) *Factory_NewClient_Call { + return &Factory_NewClient_Call{Call: _e.mock.On("NewClient", _a0)} +} + +func (_c *Factory_NewClient_Call) Run(run func(_a0 robotclient.Credentials)) *Factory_NewClient_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(robotclient.Credentials)) + }) + return _c +} + +func (_c *Factory_NewClient_Call) Return(_a0 robotclient.Client) *Factory_NewClient_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Factory_NewClient_Call) RunAndReturn(run func(robotclient.Credentials) robotclient.Client) *Factory_NewClient_Call { + _c.Call.Return(run) + return _c } // NewFactory creates a new instance of Factory. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewFactory(t mockConstructorTestingTNewFactory) *Factory { +// The first argument is typically a *testing.T value. +func NewFactory(t interface { + mock.TestingT + Cleanup(func()) +}) *Factory { mock := &Factory{} mock.Mock.Test(t) diff --git a/pkg/services/baremetal/client/mocks/ssh/Client.go b/pkg/services/baremetal/client/mocks/ssh/Client.go index 916ec556a..fc25239d5 100644 --- a/pkg/services/baremetal/client/mocks/ssh/Client.go +++ b/pkg/services/baremetal/client/mocks/ssh/Client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.14.0. DO NOT EDIT. +// Code generated by mockery v2.35.3. DO NOT EDIT. package mocks @@ -12,6 +12,14 @@ type Client struct { mock.Mock } +type Client_Expecter struct { + mock *mock.Mock +} + +func (_m *Client) EXPECT() *Client_Expecter { + return &Client_Expecter{mock: &_m.Mock} +} + // CheckCloudInitLogsForSigTerm provides a mock function with given fields: func (_m *Client) CheckCloudInitLogsForSigTerm() sshclient.Output { ret := _m.Called() @@ -26,6 +34,33 @@ func (_m *Client) CheckCloudInitLogsForSigTerm() sshclient.Output { return r0 } +// Client_CheckCloudInitLogsForSigTerm_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CheckCloudInitLogsForSigTerm' +type Client_CheckCloudInitLogsForSigTerm_Call struct { + *mock.Call +} + +// CheckCloudInitLogsForSigTerm is a helper method to define mock.On call +func (_e *Client_Expecter) CheckCloudInitLogsForSigTerm() *Client_CheckCloudInitLogsForSigTerm_Call { + return &Client_CheckCloudInitLogsForSigTerm_Call{Call: _e.mock.On("CheckCloudInitLogsForSigTerm")} +} + +func (_c *Client_CheckCloudInitLogsForSigTerm_Call) Run(run func()) *Client_CheckCloudInitLogsForSigTerm_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Client_CheckCloudInitLogsForSigTerm_Call) Return(_a0 sshclient.Output) *Client_CheckCloudInitLogsForSigTerm_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_CheckCloudInitLogsForSigTerm_Call) RunAndReturn(run func() sshclient.Output) *Client_CheckCloudInitLogsForSigTerm_Call { + _c.Call.Return(run) + return _c +} + // CleanCloudInitInstances provides a mock function with given fields: func (_m *Client) CleanCloudInitInstances() sshclient.Output { ret := _m.Called() @@ -40,6 +75,33 @@ func (_m *Client) CleanCloudInitInstances() sshclient.Output { return r0 } +// Client_CleanCloudInitInstances_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CleanCloudInitInstances' +type Client_CleanCloudInitInstances_Call struct { + *mock.Call +} + +// CleanCloudInitInstances is a helper method to define mock.On call +func (_e *Client_Expecter) CleanCloudInitInstances() *Client_CleanCloudInitInstances_Call { + return &Client_CleanCloudInitInstances_Call{Call: _e.mock.On("CleanCloudInitInstances")} +} + +func (_c *Client_CleanCloudInitInstances_Call) Run(run func()) *Client_CleanCloudInitInstances_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Client_CleanCloudInitInstances_Call) Return(_a0 sshclient.Output) *Client_CleanCloudInitInstances_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_CleanCloudInitInstances_Call) RunAndReturn(run func() sshclient.Output) *Client_CleanCloudInitInstances_Call { + _c.Call.Return(run) + return _c +} + // CleanCloudInitLogs provides a mock function with given fields: func (_m *Client) CleanCloudInitLogs() sshclient.Output { ret := _m.Called() @@ -54,6 +116,33 @@ func (_m *Client) CleanCloudInitLogs() sshclient.Output { return r0 } +// Client_CleanCloudInitLogs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CleanCloudInitLogs' +type Client_CleanCloudInitLogs_Call struct { + *mock.Call +} + +// CleanCloudInitLogs is a helper method to define mock.On call +func (_e *Client_Expecter) CleanCloudInitLogs() *Client_CleanCloudInitLogs_Call { + return &Client_CleanCloudInitLogs_Call{Call: _e.mock.On("CleanCloudInitLogs")} +} + +func (_c *Client_CleanCloudInitLogs_Call) Run(run func()) *Client_CleanCloudInitLogs_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Client_CleanCloudInitLogs_Call) Return(_a0 sshclient.Output) *Client_CleanCloudInitLogs_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_CleanCloudInitLogs_Call) RunAndReturn(run func() sshclient.Output) *Client_CleanCloudInitLogs_Call { + _c.Call.Return(run) + return _c +} + // CloudInitStatus provides a mock function with given fields: func (_m *Client) CloudInitStatus() sshclient.Output { ret := _m.Called() @@ -68,6 +157,33 @@ func (_m *Client) CloudInitStatus() sshclient.Output { return r0 } +// Client_CloudInitStatus_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CloudInitStatus' +type Client_CloudInitStatus_Call struct { + *mock.Call +} + +// CloudInitStatus is a helper method to define mock.On call +func (_e *Client_Expecter) CloudInitStatus() *Client_CloudInitStatus_Call { + return &Client_CloudInitStatus_Call{Call: _e.mock.On("CloudInitStatus")} +} + +func (_c *Client_CloudInitStatus_Call) Run(run func()) *Client_CloudInitStatus_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Client_CloudInitStatus_Call) Return(_a0 sshclient.Output) *Client_CloudInitStatus_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_CloudInitStatus_Call) RunAndReturn(run func() sshclient.Output) *Client_CloudInitStatus_Call { + _c.Call.Return(run) + return _c +} + // CreateAutoSetup provides a mock function with given fields: data func (_m *Client) CreateAutoSetup(data string) sshclient.Output { ret := _m.Called(data) @@ -82,6 +198,34 @@ func (_m *Client) CreateAutoSetup(data string) sshclient.Output { return r0 } +// Client_CreateAutoSetup_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateAutoSetup' +type Client_CreateAutoSetup_Call struct { + *mock.Call +} + +// CreateAutoSetup is a helper method to define mock.On call +// - data string +func (_e *Client_Expecter) CreateAutoSetup(data interface{}) *Client_CreateAutoSetup_Call { + return &Client_CreateAutoSetup_Call{Call: _e.mock.On("CreateAutoSetup", data)} +} + +func (_c *Client_CreateAutoSetup_Call) Run(run func(data string)) *Client_CreateAutoSetup_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string)) + }) + return _c +} + +func (_c *Client_CreateAutoSetup_Call) Return(_a0 sshclient.Output) *Client_CreateAutoSetup_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_CreateAutoSetup_Call) RunAndReturn(run func(string) sshclient.Output) *Client_CreateAutoSetup_Call { + _c.Call.Return(run) + return _c +} + // CreateMetaData provides a mock function with given fields: hostName func (_m *Client) CreateMetaData(hostName string) sshclient.Output { ret := _m.Called(hostName) @@ -96,6 +240,34 @@ func (_m *Client) CreateMetaData(hostName string) sshclient.Output { return r0 } +// Client_CreateMetaData_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateMetaData' +type Client_CreateMetaData_Call struct { + *mock.Call +} + +// CreateMetaData is a helper method to define mock.On call +// - hostName string +func (_e *Client_Expecter) CreateMetaData(hostName interface{}) *Client_CreateMetaData_Call { + return &Client_CreateMetaData_Call{Call: _e.mock.On("CreateMetaData", hostName)} +} + +func (_c *Client_CreateMetaData_Call) Run(run func(hostName string)) *Client_CreateMetaData_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string)) + }) + return _c +} + +func (_c *Client_CreateMetaData_Call) Return(_a0 sshclient.Output) *Client_CreateMetaData_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_CreateMetaData_Call) RunAndReturn(run func(string) sshclient.Output) *Client_CreateMetaData_Call { + _c.Call.Return(run) + return _c +} + // CreateNoCloudDirectory provides a mock function with given fields: func (_m *Client) CreateNoCloudDirectory() sshclient.Output { ret := _m.Called() @@ -110,6 +282,33 @@ func (_m *Client) CreateNoCloudDirectory() sshclient.Output { return r0 } +// Client_CreateNoCloudDirectory_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateNoCloudDirectory' +type Client_CreateNoCloudDirectory_Call struct { + *mock.Call +} + +// CreateNoCloudDirectory is a helper method to define mock.On call +func (_e *Client_Expecter) CreateNoCloudDirectory() *Client_CreateNoCloudDirectory_Call { + return &Client_CreateNoCloudDirectory_Call{Call: _e.mock.On("CreateNoCloudDirectory")} +} + +func (_c *Client_CreateNoCloudDirectory_Call) Run(run func()) *Client_CreateNoCloudDirectory_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Client_CreateNoCloudDirectory_Call) Return(_a0 sshclient.Output) *Client_CreateNoCloudDirectory_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_CreateNoCloudDirectory_Call) RunAndReturn(run func() sshclient.Output) *Client_CreateNoCloudDirectory_Call { + _c.Call.Return(run) + return _c +} + // CreatePostInstallScript provides a mock function with given fields: data func (_m *Client) CreatePostInstallScript(data string) sshclient.Output { ret := _m.Called(data) @@ -124,6 +323,34 @@ func (_m *Client) CreatePostInstallScript(data string) sshclient.Output { return r0 } +// Client_CreatePostInstallScript_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreatePostInstallScript' +type Client_CreatePostInstallScript_Call struct { + *mock.Call +} + +// CreatePostInstallScript is a helper method to define mock.On call +// - data string +func (_e *Client_Expecter) CreatePostInstallScript(data interface{}) *Client_CreatePostInstallScript_Call { + return &Client_CreatePostInstallScript_Call{Call: _e.mock.On("CreatePostInstallScript", data)} +} + +func (_c *Client_CreatePostInstallScript_Call) Run(run func(data string)) *Client_CreatePostInstallScript_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string)) + }) + return _c +} + +func (_c *Client_CreatePostInstallScript_Call) Return(_a0 sshclient.Output) *Client_CreatePostInstallScript_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_CreatePostInstallScript_Call) RunAndReturn(run func(string) sshclient.Output) *Client_CreatePostInstallScript_Call { + _c.Call.Return(run) + return _c +} + // CreateUserData provides a mock function with given fields: userData func (_m *Client) CreateUserData(userData string) sshclient.Output { ret := _m.Called(userData) @@ -138,6 +365,34 @@ func (_m *Client) CreateUserData(userData string) sshclient.Output { return r0 } +// Client_CreateUserData_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateUserData' +type Client_CreateUserData_Call struct { + *mock.Call +} + +// CreateUserData is a helper method to define mock.On call +// - userData string +func (_e *Client_Expecter) CreateUserData(userData interface{}) *Client_CreateUserData_Call { + return &Client_CreateUserData_Call{Call: _e.mock.On("CreateUserData", userData)} +} + +func (_c *Client_CreateUserData_Call) Run(run func(userData string)) *Client_CreateUserData_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string)) + }) + return _c +} + +func (_c *Client_CreateUserData_Call) Return(_a0 sshclient.Output) *Client_CreateUserData_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_CreateUserData_Call) RunAndReturn(run func(string) sshclient.Output) *Client_CreateUserData_Call { + _c.Call.Return(run) + return _c +} + // DownloadImage provides a mock function with given fields: path, url func (_m *Client) DownloadImage(path string, url string) sshclient.Output { ret := _m.Called(path, url) @@ -152,6 +407,35 @@ func (_m *Client) DownloadImage(path string, url string) sshclient.Output { return r0 } +// Client_DownloadImage_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DownloadImage' +type Client_DownloadImage_Call struct { + *mock.Call +} + +// DownloadImage is a helper method to define mock.On call +// - path string +// - url string +func (_e *Client_Expecter) DownloadImage(path interface{}, url interface{}) *Client_DownloadImage_Call { + return &Client_DownloadImage_Call{Call: _e.mock.On("DownloadImage", path, url)} +} + +func (_c *Client_DownloadImage_Call) Run(run func(path string, url string)) *Client_DownloadImage_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string), args[1].(string)) + }) + return _c +} + +func (_c *Client_DownloadImage_Call) Return(_a0 sshclient.Output) *Client_DownloadImage_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_DownloadImage_Call) RunAndReturn(run func(string, string) sshclient.Output) *Client_DownloadImage_Call { + _c.Call.Return(run) + return _c +} + // EnsureCloudInit provides a mock function with given fields: func (_m *Client) EnsureCloudInit() sshclient.Output { ret := _m.Called() @@ -166,6 +450,33 @@ func (_m *Client) EnsureCloudInit() sshclient.Output { return r0 } +// Client_EnsureCloudInit_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EnsureCloudInit' +type Client_EnsureCloudInit_Call struct { + *mock.Call +} + +// EnsureCloudInit is a helper method to define mock.On call +func (_e *Client_Expecter) EnsureCloudInit() *Client_EnsureCloudInit_Call { + return &Client_EnsureCloudInit_Call{Call: _e.mock.On("EnsureCloudInit")} +} + +func (_c *Client_EnsureCloudInit_Call) Run(run func()) *Client_EnsureCloudInit_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Client_EnsureCloudInit_Call) Return(_a0 sshclient.Output) *Client_EnsureCloudInit_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_EnsureCloudInit_Call) RunAndReturn(run func() sshclient.Output) *Client_EnsureCloudInit_Call { + _c.Call.Return(run) + return _c +} + // ExecuteInstallImage provides a mock function with given fields: hasPostInstallScript func (_m *Client) ExecuteInstallImage(hasPostInstallScript bool) sshclient.Output { ret := _m.Called(hasPostInstallScript) @@ -180,6 +491,75 @@ func (_m *Client) ExecuteInstallImage(hasPostInstallScript bool) sshclient.Outpu return r0 } +// Client_ExecuteInstallImage_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ExecuteInstallImage' +type Client_ExecuteInstallImage_Call struct { + *mock.Call +} + +// ExecuteInstallImage is a helper method to define mock.On call +// - hasPostInstallScript bool +func (_e *Client_Expecter) ExecuteInstallImage(hasPostInstallScript interface{}) *Client_ExecuteInstallImage_Call { + return &Client_ExecuteInstallImage_Call{Call: _e.mock.On("ExecuteInstallImage", hasPostInstallScript)} +} + +func (_c *Client_ExecuteInstallImage_Call) Run(run func(hasPostInstallScript bool)) *Client_ExecuteInstallImage_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(bool)) + }) + return _c +} + +func (_c *Client_ExecuteInstallImage_Call) Return(_a0 sshclient.Output) *Client_ExecuteInstallImage_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_ExecuteInstallImage_Call) RunAndReturn(run func(bool) sshclient.Output) *Client_ExecuteInstallImage_Call { + _c.Call.Return(run) + return _c +} + +// GetCloudInitOutput provides a mock function with given fields: +func (_m *Client) GetCloudInitOutput() sshclient.Output { + ret := _m.Called() + + var r0 sshclient.Output + if rf, ok := ret.Get(0).(func() sshclient.Output); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(sshclient.Output) + } + + return r0 +} + +// Client_GetCloudInitOutput_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetCloudInitOutput' +type Client_GetCloudInitOutput_Call struct { + *mock.Call +} + +// GetCloudInitOutput is a helper method to define mock.On call +func (_e *Client_Expecter) GetCloudInitOutput() *Client_GetCloudInitOutput_Call { + return &Client_GetCloudInitOutput_Call{Call: _e.mock.On("GetCloudInitOutput")} +} + +func (_c *Client_GetCloudInitOutput_Call) Run(run func()) *Client_GetCloudInitOutput_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Client_GetCloudInitOutput_Call) Return(_a0 sshclient.Output) *Client_GetCloudInitOutput_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_GetCloudInitOutput_Call) RunAndReturn(run func() sshclient.Output) *Client_GetCloudInitOutput_Call { + _c.Call.Return(run) + return _c +} + // GetHardwareDetailsCPUArch provides a mock function with given fields: func (_m *Client) GetHardwareDetailsCPUArch() sshclient.Output { ret := _m.Called() @@ -194,6 +574,33 @@ func (_m *Client) GetHardwareDetailsCPUArch() sshclient.Output { return r0 } +// Client_GetHardwareDetailsCPUArch_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetHardwareDetailsCPUArch' +type Client_GetHardwareDetailsCPUArch_Call struct { + *mock.Call +} + +// GetHardwareDetailsCPUArch is a helper method to define mock.On call +func (_e *Client_Expecter) GetHardwareDetailsCPUArch() *Client_GetHardwareDetailsCPUArch_Call { + return &Client_GetHardwareDetailsCPUArch_Call{Call: _e.mock.On("GetHardwareDetailsCPUArch")} +} + +func (_c *Client_GetHardwareDetailsCPUArch_Call) Run(run func()) *Client_GetHardwareDetailsCPUArch_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Client_GetHardwareDetailsCPUArch_Call) Return(_a0 sshclient.Output) *Client_GetHardwareDetailsCPUArch_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_GetHardwareDetailsCPUArch_Call) RunAndReturn(run func() sshclient.Output) *Client_GetHardwareDetailsCPUArch_Call { + _c.Call.Return(run) + return _c +} + // GetHardwareDetailsCPUClockGigahertz provides a mock function with given fields: func (_m *Client) GetHardwareDetailsCPUClockGigahertz() sshclient.Output { ret := _m.Called() @@ -208,6 +615,33 @@ func (_m *Client) GetHardwareDetailsCPUClockGigahertz() sshclient.Output { return r0 } +// Client_GetHardwareDetailsCPUClockGigahertz_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetHardwareDetailsCPUClockGigahertz' +type Client_GetHardwareDetailsCPUClockGigahertz_Call struct { + *mock.Call +} + +// GetHardwareDetailsCPUClockGigahertz is a helper method to define mock.On call +func (_e *Client_Expecter) GetHardwareDetailsCPUClockGigahertz() *Client_GetHardwareDetailsCPUClockGigahertz_Call { + return &Client_GetHardwareDetailsCPUClockGigahertz_Call{Call: _e.mock.On("GetHardwareDetailsCPUClockGigahertz")} +} + +func (_c *Client_GetHardwareDetailsCPUClockGigahertz_Call) Run(run func()) *Client_GetHardwareDetailsCPUClockGigahertz_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Client_GetHardwareDetailsCPUClockGigahertz_Call) Return(_a0 sshclient.Output) *Client_GetHardwareDetailsCPUClockGigahertz_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_GetHardwareDetailsCPUClockGigahertz_Call) RunAndReturn(run func() sshclient.Output) *Client_GetHardwareDetailsCPUClockGigahertz_Call { + _c.Call.Return(run) + return _c +} + // GetHardwareDetailsCPUCores provides a mock function with given fields: func (_m *Client) GetHardwareDetailsCPUCores() sshclient.Output { ret := _m.Called() @@ -222,6 +656,33 @@ func (_m *Client) GetHardwareDetailsCPUCores() sshclient.Output { return r0 } +// Client_GetHardwareDetailsCPUCores_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetHardwareDetailsCPUCores' +type Client_GetHardwareDetailsCPUCores_Call struct { + *mock.Call +} + +// GetHardwareDetailsCPUCores is a helper method to define mock.On call +func (_e *Client_Expecter) GetHardwareDetailsCPUCores() *Client_GetHardwareDetailsCPUCores_Call { + return &Client_GetHardwareDetailsCPUCores_Call{Call: _e.mock.On("GetHardwareDetailsCPUCores")} +} + +func (_c *Client_GetHardwareDetailsCPUCores_Call) Run(run func()) *Client_GetHardwareDetailsCPUCores_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Client_GetHardwareDetailsCPUCores_Call) Return(_a0 sshclient.Output) *Client_GetHardwareDetailsCPUCores_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_GetHardwareDetailsCPUCores_Call) RunAndReturn(run func() sshclient.Output) *Client_GetHardwareDetailsCPUCores_Call { + _c.Call.Return(run) + return _c +} + // GetHardwareDetailsCPUFlags provides a mock function with given fields: func (_m *Client) GetHardwareDetailsCPUFlags() sshclient.Output { ret := _m.Called() @@ -236,6 +697,33 @@ func (_m *Client) GetHardwareDetailsCPUFlags() sshclient.Output { return r0 } +// Client_GetHardwareDetailsCPUFlags_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetHardwareDetailsCPUFlags' +type Client_GetHardwareDetailsCPUFlags_Call struct { + *mock.Call +} + +// GetHardwareDetailsCPUFlags is a helper method to define mock.On call +func (_e *Client_Expecter) GetHardwareDetailsCPUFlags() *Client_GetHardwareDetailsCPUFlags_Call { + return &Client_GetHardwareDetailsCPUFlags_Call{Call: _e.mock.On("GetHardwareDetailsCPUFlags")} +} + +func (_c *Client_GetHardwareDetailsCPUFlags_Call) Run(run func()) *Client_GetHardwareDetailsCPUFlags_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Client_GetHardwareDetailsCPUFlags_Call) Return(_a0 sshclient.Output) *Client_GetHardwareDetailsCPUFlags_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_GetHardwareDetailsCPUFlags_Call) RunAndReturn(run func() sshclient.Output) *Client_GetHardwareDetailsCPUFlags_Call { + _c.Call.Return(run) + return _c +} + // GetHardwareDetailsCPUModel provides a mock function with given fields: func (_m *Client) GetHardwareDetailsCPUModel() sshclient.Output { ret := _m.Called() @@ -250,6 +738,33 @@ func (_m *Client) GetHardwareDetailsCPUModel() sshclient.Output { return r0 } +// Client_GetHardwareDetailsCPUModel_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetHardwareDetailsCPUModel' +type Client_GetHardwareDetailsCPUModel_Call struct { + *mock.Call +} + +// GetHardwareDetailsCPUModel is a helper method to define mock.On call +func (_e *Client_Expecter) GetHardwareDetailsCPUModel() *Client_GetHardwareDetailsCPUModel_Call { + return &Client_GetHardwareDetailsCPUModel_Call{Call: _e.mock.On("GetHardwareDetailsCPUModel")} +} + +func (_c *Client_GetHardwareDetailsCPUModel_Call) Run(run func()) *Client_GetHardwareDetailsCPUModel_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Client_GetHardwareDetailsCPUModel_Call) Return(_a0 sshclient.Output) *Client_GetHardwareDetailsCPUModel_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_GetHardwareDetailsCPUModel_Call) RunAndReturn(run func() sshclient.Output) *Client_GetHardwareDetailsCPUModel_Call { + _c.Call.Return(run) + return _c +} + // GetHardwareDetailsCPUThreads provides a mock function with given fields: func (_m *Client) GetHardwareDetailsCPUThreads() sshclient.Output { ret := _m.Called() @@ -264,6 +779,33 @@ func (_m *Client) GetHardwareDetailsCPUThreads() sshclient.Output { return r0 } +// Client_GetHardwareDetailsCPUThreads_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetHardwareDetailsCPUThreads' +type Client_GetHardwareDetailsCPUThreads_Call struct { + *mock.Call +} + +// GetHardwareDetailsCPUThreads is a helper method to define mock.On call +func (_e *Client_Expecter) GetHardwareDetailsCPUThreads() *Client_GetHardwareDetailsCPUThreads_Call { + return &Client_GetHardwareDetailsCPUThreads_Call{Call: _e.mock.On("GetHardwareDetailsCPUThreads")} +} + +func (_c *Client_GetHardwareDetailsCPUThreads_Call) Run(run func()) *Client_GetHardwareDetailsCPUThreads_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Client_GetHardwareDetailsCPUThreads_Call) Return(_a0 sshclient.Output) *Client_GetHardwareDetailsCPUThreads_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_GetHardwareDetailsCPUThreads_Call) RunAndReturn(run func() sshclient.Output) *Client_GetHardwareDetailsCPUThreads_Call { + _c.Call.Return(run) + return _c +} + // GetHardwareDetailsNics provides a mock function with given fields: func (_m *Client) GetHardwareDetailsNics() sshclient.Output { ret := _m.Called() @@ -278,6 +820,33 @@ func (_m *Client) GetHardwareDetailsNics() sshclient.Output { return r0 } +// Client_GetHardwareDetailsNics_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetHardwareDetailsNics' +type Client_GetHardwareDetailsNics_Call struct { + *mock.Call +} + +// GetHardwareDetailsNics is a helper method to define mock.On call +func (_e *Client_Expecter) GetHardwareDetailsNics() *Client_GetHardwareDetailsNics_Call { + return &Client_GetHardwareDetailsNics_Call{Call: _e.mock.On("GetHardwareDetailsNics")} +} + +func (_c *Client_GetHardwareDetailsNics_Call) Run(run func()) *Client_GetHardwareDetailsNics_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Client_GetHardwareDetailsNics_Call) Return(_a0 sshclient.Output) *Client_GetHardwareDetailsNics_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_GetHardwareDetailsNics_Call) RunAndReturn(run func() sshclient.Output) *Client_GetHardwareDetailsNics_Call { + _c.Call.Return(run) + return _c +} + // GetHardwareDetailsRAM provides a mock function with given fields: func (_m *Client) GetHardwareDetailsRAM() sshclient.Output { ret := _m.Called() @@ -292,6 +861,33 @@ func (_m *Client) GetHardwareDetailsRAM() sshclient.Output { return r0 } +// Client_GetHardwareDetailsRAM_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetHardwareDetailsRAM' +type Client_GetHardwareDetailsRAM_Call struct { + *mock.Call +} + +// GetHardwareDetailsRAM is a helper method to define mock.On call +func (_e *Client_Expecter) GetHardwareDetailsRAM() *Client_GetHardwareDetailsRAM_Call { + return &Client_GetHardwareDetailsRAM_Call{Call: _e.mock.On("GetHardwareDetailsRAM")} +} + +func (_c *Client_GetHardwareDetailsRAM_Call) Run(run func()) *Client_GetHardwareDetailsRAM_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Client_GetHardwareDetailsRAM_Call) Return(_a0 sshclient.Output) *Client_GetHardwareDetailsRAM_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_GetHardwareDetailsRAM_Call) RunAndReturn(run func() sshclient.Output) *Client_GetHardwareDetailsRAM_Call { + _c.Call.Return(run) + return _c +} + // GetHardwareDetailsStorage provides a mock function with given fields: func (_m *Client) GetHardwareDetailsStorage() sshclient.Output { ret := _m.Called() @@ -306,6 +902,33 @@ func (_m *Client) GetHardwareDetailsStorage() sshclient.Output { return r0 } +// Client_GetHardwareDetailsStorage_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetHardwareDetailsStorage' +type Client_GetHardwareDetailsStorage_Call struct { + *mock.Call +} + +// GetHardwareDetailsStorage is a helper method to define mock.On call +func (_e *Client_Expecter) GetHardwareDetailsStorage() *Client_GetHardwareDetailsStorage_Call { + return &Client_GetHardwareDetailsStorage_Call{Call: _e.mock.On("GetHardwareDetailsStorage")} +} + +func (_c *Client_GetHardwareDetailsStorage_Call) Run(run func()) *Client_GetHardwareDetailsStorage_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Client_GetHardwareDetailsStorage_Call) Return(_a0 sshclient.Output) *Client_GetHardwareDetailsStorage_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_GetHardwareDetailsStorage_Call) RunAndReturn(run func() sshclient.Output) *Client_GetHardwareDetailsStorage_Call { + _c.Call.Return(run) + return _c +} + // GetHostName provides a mock function with given fields: func (_m *Client) GetHostName() sshclient.Output { ret := _m.Called() @@ -320,6 +943,33 @@ func (_m *Client) GetHostName() sshclient.Output { return r0 } +// Client_GetHostName_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetHostName' +type Client_GetHostName_Call struct { + *mock.Call +} + +// GetHostName is a helper method to define mock.On call +func (_e *Client_Expecter) GetHostName() *Client_GetHostName_Call { + return &Client_GetHostName_Call{Call: _e.mock.On("GetHostName")} +} + +func (_c *Client_GetHostName_Call) Run(run func()) *Client_GetHostName_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Client_GetHostName_Call) Return(_a0 sshclient.Output) *Client_GetHostName_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_GetHostName_Call) RunAndReturn(run func() sshclient.Output) *Client_GetHostName_Call { + _c.Call.Return(run) + return _c +} + // Reboot provides a mock function with given fields: func (_m *Client) Reboot() sshclient.Output { ret := _m.Called() @@ -334,6 +984,33 @@ func (_m *Client) Reboot() sshclient.Output { return r0 } +// Client_Reboot_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Reboot' +type Client_Reboot_Call struct { + *mock.Call +} + +// Reboot is a helper method to define mock.On call +func (_e *Client_Expecter) Reboot() *Client_Reboot_Call { + return &Client_Reboot_Call{Call: _e.mock.On("Reboot")} +} + +func (_c *Client_Reboot_Call) Run(run func()) *Client_Reboot_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Client_Reboot_Call) Return(_a0 sshclient.Output) *Client_Reboot_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_Reboot_Call) RunAndReturn(run func() sshclient.Output) *Client_Reboot_Call { + _c.Call.Return(run) + return _c +} + // ResetKubeadm provides a mock function with given fields: func (_m *Client) ResetKubeadm() sshclient.Output { ret := _m.Called() @@ -348,13 +1025,39 @@ func (_m *Client) ResetKubeadm() sshclient.Output { return r0 } -type mockConstructorTestingTNewClient interface { - mock.TestingT - Cleanup(func()) +// Client_ResetKubeadm_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ResetKubeadm' +type Client_ResetKubeadm_Call struct { + *mock.Call +} + +// ResetKubeadm is a helper method to define mock.On call +func (_e *Client_Expecter) ResetKubeadm() *Client_ResetKubeadm_Call { + return &Client_ResetKubeadm_Call{Call: _e.mock.On("ResetKubeadm")} +} + +func (_c *Client_ResetKubeadm_Call) Run(run func()) *Client_ResetKubeadm_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Client_ResetKubeadm_Call) Return(_a0 sshclient.Output) *Client_ResetKubeadm_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_ResetKubeadm_Call) RunAndReturn(run func() sshclient.Output) *Client_ResetKubeadm_Call { + _c.Call.Return(run) + return _c } // NewClient creates a new instance of Client. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewClient(t mockConstructorTestingTNewClient) *Client { +// The first argument is typically a *testing.T value. +func NewClient(t interface { + mock.TestingT + Cleanup(func()) +}) *Client { mock := &Client{} mock.Mock.Test(t) diff --git a/pkg/services/baremetal/client/mocks/ssh/Factory.go b/pkg/services/baremetal/client/mocks/ssh/Factory.go index 90e67439a..259f34c89 100644 --- a/pkg/services/baremetal/client/mocks/ssh/Factory.go +++ b/pkg/services/baremetal/client/mocks/ssh/Factory.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.14.0. DO NOT EDIT. +// Code generated by mockery v2.35.3. DO NOT EDIT. package mocks @@ -12,6 +12,14 @@ type Factory struct { mock.Mock } +type Factory_Expecter struct { + mock *mock.Mock +} + +func (_m *Factory) EXPECT() *Factory_Expecter { + return &Factory_Expecter{mock: &_m.Mock} +} + // NewClient provides a mock function with given fields: _a0 func (_m *Factory) NewClient(_a0 sshclient.Input) sshclient.Client { ret := _m.Called(_a0) @@ -28,13 +36,40 @@ func (_m *Factory) NewClient(_a0 sshclient.Input) sshclient.Client { return r0 } -type mockConstructorTestingTNewFactory interface { - mock.TestingT - Cleanup(func()) +// Factory_NewClient_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'NewClient' +type Factory_NewClient_Call struct { + *mock.Call +} + +// NewClient is a helper method to define mock.On call +// - _a0 sshclient.Input +func (_e *Factory_Expecter) NewClient(_a0 interface{}) *Factory_NewClient_Call { + return &Factory_NewClient_Call{Call: _e.mock.On("NewClient", _a0)} +} + +func (_c *Factory_NewClient_Call) Run(run func(_a0 sshclient.Input)) *Factory_NewClient_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(sshclient.Input)) + }) + return _c +} + +func (_c *Factory_NewClient_Call) Return(_a0 sshclient.Client) *Factory_NewClient_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Factory_NewClient_Call) RunAndReturn(run func(sshclient.Input) sshclient.Client) *Factory_NewClient_Call { + _c.Call.Return(run) + return _c } // NewFactory creates a new instance of Factory. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewFactory(t mockConstructorTestingTNewFactory) *Factory { +// The first argument is typically a *testing.T value. +func NewFactory(t interface { + mock.TestingT + Cleanup(func()) +}) *Factory { mock := &Factory{} mock.Mock.Test(t) diff --git a/pkg/services/baremetal/client/ssh/ssh_client.go b/pkg/services/baremetal/client/ssh/ssh_client.go index 32c73e1a5..c79a6af57 100644 --- a/pkg/services/baremetal/client/ssh/ssh_client.go +++ b/pkg/services/baremetal/client/ssh/ssh_client.go @@ -18,9 +18,11 @@ limitations under the License. package sshclient import ( + "bufio" "bytes" "errors" "fmt" + "regexp" "strings" "time" @@ -75,6 +77,7 @@ type Client interface { GetHardwareDetailsCPUFlags() Output GetHardwareDetailsCPUThreads() Output GetHardwareDetailsCPUCores() Output + GetCloudInitOutput() Output CreateAutoSetup(data string) Output DownloadImage(path, url string) Output CreatePostInstallScript(data string) Output @@ -150,7 +153,7 @@ if test -n $IP_V4; then fi if test -n $IP_V6; then - echo "name=\""$iname\""" "model=$MODEL" "mac=$MAC" "ip=$IP_V6" "speedMbps=$SPEED" + echo "name=\""$iname\""" "model=$MODEL" "mac=$MAC" "ip=$IP_V6" "speedMbps=$SPEED" fi done @@ -187,6 +190,15 @@ func (c *sshClient) GetHardwareDetailsCPUFlags() Output { return c.runSSH(`lscpu | grep "Flags:" | awk '{ $1=""; print $0}' | sed "s/^[ \t]*//"`) } +// GetCloudInitOutput implements the GetCloudInitOutput method of the SSHClient interface. +func (c *sshClient) GetCloudInitOutput() Output { + out := c.runSSH(`cat /var/log/cloud-init-output.log`) + if out.Err == nil { + out.StdOut = removeUselessLinesFromCloudInitOutput(out.StdOut) + } + return out +} + // GetHardwareDetailsCPUThreads implements the GetHardwareDetailsCPUThreads method of the SSHClient interface. func (c *sshClient) GetHardwareDetailsCPUThreads() Output { return c.runSSH(`lscpu | grep "CPU(s):" | head -1 | awk '{ print $2}'`) @@ -199,7 +211,7 @@ func (c *sshClient) GetHardwareDetailsCPUCores() Output { // CreateAutoSetup implements the CreateAutoSetup method of the SSHClient interface. func (c *sshClient) CreateAutoSetup(data string) Output { - return c.runSSH(fmt.Sprintf(`cat << 'EOF' > /autosetup + return c.runSSH(fmt.Sprintf(`cat << 'EOF' > /autosetup %s EOF`, data)) } @@ -211,7 +223,7 @@ func (c *sshClient) DownloadImage(path, url string) Output { // CreatePostInstallScript implements the CreatePostInstallScript method of the SSHClient interface. func (c *sshClient) CreatePostInstallScript(data string) Output { - out := c.runSSH(fmt.Sprintf(`cat << 'EOF' > /root/post-install.sh + out := c.runSSH(fmt.Sprintf(`cat << 'EOF' > /root/post-install.sh %sEOF`, data)) if out.Err != nil || out.StdErr != "" { @@ -229,10 +241,12 @@ func (c *sshClient) ExecuteInstallImage(hasPostInstallScript bool) Output { cmd = `/root/.oldroot/nfs/install/installimage -a -c /autosetup` } - out := c.runSSH(fmt.Sprintf(`cat << 'EOF' > /root/install-image-script.sh + out := c.runSSH(fmt.Sprintf(`cat << 'EOF' > /root/install-image-script.sh #!/bin/bash export TERM=xterm -%s + +# don't wait 20 seconds before starting: echo "x" +echo "x" | %s EOF`, cmd)) if out.Err != nil || out.StdErr != "" { return out @@ -243,12 +257,32 @@ EOF`, cmd)) return out } - out = c.runSSH(`sh /root/install-image-script.sh`) - if out.Err != nil { - return out + installImageOut := c.runSSH(`sh /root/install-image-script.sh`) + + debugTxtOut := c.runSSH(`cat /root/debug.txt`) + installImageOut.StdOut = fmt.Sprintf(`debug.txt: +%s +%s +###################################### + +/root/install-image-script.sh stdout: +%s +###################################### + +stderr: +%s`, + debugTxtOut.StdOut, debugTxtOut.StdErr, installImageOut.StdOut, installImageOut.StdErr) + + if installImageOut.Err != nil { + return installImageOut + } + + if debugTxtOut.Err != nil { + installImageOut.StdOut += fmt.Sprintf("\nfailed to get /root/debug.txt:\n%s", debugTxtOut.Err.Error()) } + // Ignore StdErr in this command - return Output{StdOut: out.StdOut} + return Output{StdOut: installImageOut.StdOut} } // Reboot implements the Reboot method of the SSHClient interface. @@ -395,3 +429,51 @@ func (c *sshClient) runSSH(command string) Output { Err: err, } } + +func removeUselessLinesFromCloudInitOutput(s string) string { + regexes := []string{ + `^\s*\d+K [. ]+ \d+%.*\ds$`, // 10000K .......... .......... .......... .......... .......... 6%!M(MISSING) 1s + `^Get:\d+ https?://.* [kM]B.*`, // Get:17 http://archive.ubuntu.com/ubuntu focal/universe Translation-en [5,124 kB[]` + `^Preparing to unpack \.\.\..*`, // Preparing to unpack .../04-libx11-6_2%!a(MISSING)1.6.9-2ubuntu1.6_amd64.deb ...\r + `^Selecting previously unselected package.*`, // Selecting previously unselected package kubeadm.\r + `^Setting up .* \.\.\..*`, // Setting up hicolor-icon-theme (0.17-2) ...\r + `^Unpacking .* \.\.\..*`, // Unpacking libatk1.0-0:amd64 (2.35.1-1ubuntu2) ...\r + } + + // Compile the regexes + compiledRegexes := make([]*regexp.Regexp, 0, len(regexes)) + for _, re := range regexes { + compiled, err := regexp.Compile(re) + if err != nil { + return fmt.Sprintf("removeUselessLinesFromCloudInitOutput: Failed to compile regex %s: %v\n%s", + re, err, s) + } + compiledRegexes = append(compiledRegexes, compiled) + } + + var output []string + + scanner := bufio.NewScanner(strings.NewReader(s)) + for scanner.Scan() { + line := scanner.Text() + + // Check if the line matches any of the regexes + matches := false + for _, re := range compiledRegexes { + if re.MatchString(line) { + matches = true + break + } + } + + if matches { + continue + } + output = append(output, line) + } + + if err := scanner.Err(); err != nil { + return fmt.Sprintf("Error reading string: %v\n%s", err, s) + } + return strings.Join(output, "\n") +} diff --git a/pkg/services/baremetal/client/ssh/ssh_client_test.go b/pkg/services/baremetal/client/ssh/ssh_client_test.go new file mode 100644 index 000000000..5aebd2171 --- /dev/null +++ b/pkg/services/baremetal/client/ssh/ssh_client_test.go @@ -0,0 +1,51 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package sshclient contains the interface to speak to bare metal servers with ssh. +package sshclient + +import "testing" + +func Test_removeUselessLinesFromCloudInitOutput(t *testing.T) { + tests := []struct { + name string + s string + want string + }{ + { + name: "ignore: 10000K .......... .......... .......... .......... .......... 6%!M(MISSING) 1s", + s: "foo\n 10000K .......... .......... .......... .......... .......... 6%!M(MISSING) 1s\nbar", + want: "foo\nbar", + }, + { + name: "ignore: ^10000K .......... .......... .......... .......... .......... 6%!M(MISSING) 1s", + s: "foo\n10000K .......... .......... .......... .......... .......... 6%!M(MISSING) 1s\nbar", + want: "foo\nbar", + }, + { + name: "ignore: Get:17 http://archive.ubuntu.com/ubuntu focal/universe Translation-en [5,124 kB[]", + s: "foo\nGet:17 http://archive.ubuntu.com/ubuntu focal/universe Translation-en [5,124 kB[]\nbar", + want: "foo\nbar", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := removeUselessLinesFromCloudInitOutput(tt.s); got != tt.want { + t.Errorf("removeUselessLinesFromCloudInitOutput() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/services/baremetal/host/host.go b/pkg/services/baremetal/host/host.go index ee85b14f9..f33f0a5b2 100644 --- a/pkg/services/baremetal/host/host.go +++ b/pkg/services/baremetal/host/host.go @@ -20,6 +20,7 @@ package host import ( "context" "encoding/json" + "errors" "fmt" "os" "reflect" @@ -943,9 +944,12 @@ func (s *Service) actionImageInstalling() actionResult { } // Execute install image - if err := handleSSHError(sshClient.ExecuteInstallImage(postInstallScript != "")); err != nil { - return actionError{err: fmt.Errorf("failed to execute installimage: %w", err)} + out := sshClient.ExecuteInstallImage(postInstallScript != "") + if out.Err != nil { + record.Warnf(s.scope.HetznerBareMetalHost, "ExecuteInstallImageFailed", out.StdOut) + return actionError{err: fmt.Errorf("failed to execute installimage: %w", out.Err)} } + record.Eventf(s.scope.HetznerBareMetalHost, "ExecuteInstallImageSucceeded", out.StdOut) // Update name in robot API if _, err := s.scope.RobotClient.SetBMServerName(s.scope.HetznerBareMetalHost.Spec.ServerID, autoSetupInput.hostName); err != nil { @@ -1053,6 +1057,10 @@ func (s *Service) actionProvisioning() actionResult { isSSHTimeoutError, isSSHConnectionRefusedError, err := analyzeSSHOutputInstallImage(out, rescueSSHClient, portAfterInstallImage) if err != nil { + if errors.Is(err, errUnexpectedHostName) { + // One possible reason: The machine gets used by a second wl-cluster + record.Warn(host, "UnexpectedHostName", err.Error()) + } return actionError{err: fmt.Errorf("failed to handle incomplete boot - installImage: %w", err)} } failed, err := s.handleIncompleteBoot(false, isSSHTimeoutError, isSSHConnectionRefusedError) @@ -1181,13 +1189,42 @@ func verifyConnectionRefused(sshClient sshclient.Client, port int) bool { return true } -func (s *Service) actionEnsureProvisioned() actionResult { +func (s *Service) actionEnsureProvisioned() (ar actionResult) { sshClient := s.scope.SSHClientFactory.NewClient(sshclient.Input{ PrivateKey: sshclient.CredentialsFromSecret(s.scope.OSSSHSecret, s.scope.HetznerBareMetalHost.Spec.Status.SSHSpec.SecretRef).PrivateKey, Port: s.scope.HetznerBareMetalHost.Spec.Status.SSHSpec.PortAfterCloudInit, IP: s.scope.HetznerBareMetalHost.Spec.Status.GetIPAddress(), }) + defer func() { + // Create an Event which contains the content of /var/log/cloud-init-output.log + + if _, ok := ar.(actionContinue); ok { + // don't create an event + return + } + out := sshClient.GetCloudInitOutput() + if out.Err != nil || out.StdErr != "" { + record.Warnf(s.scope.HetznerBareMetalHost, "GetCloudInitOutputFailed", + fmt.Sprintf("GetCloudInitOutput failed to get /var/log/cloud-init-output.log: stdout %q, stderr %q, err %q", + out.StdOut, out.StdErr, out.Err.Error())) + return + } + _, ok := ar.(actionComplete) + if ok { + record.Eventf(s.scope.HetznerBareMetalHost, "CloudInitOutput", + "/var/log/cloud-init-output.log: "+out.StdOut) + } else { + _, err := ar.Result() + errString := "" + if err != nil { + errString = err.Error() + } + record.Warnf(s.scope.HetznerBareMetalHost, "CloudInitOutput", fmt.Sprintf("cloud init output (%s):\n%s", + errString, + out.StdOut)) + } + }() // Check hostname with sshClient wantHostName := infrav1.BareMetalHostNamePrefix + s.scope.HetznerBareMetalHost.Spec.ConsumerRef.Name @@ -1200,6 +1237,10 @@ func (s *Service) actionEnsureProvisioned() actionResult { isTimeout, isSSHConnectionRefusedError, err := analyzeSSHOutputProvisioned(out) if err != nil { + if errors.Is(err, errUnexpectedHostName) { + // One possible reason: The machine gets used by a second wl-cluster + record.Warn(s.scope.HetznerBareMetalHost, "UnexpectedHostName", err.Error()) + } return actionError{err: fmt.Errorf("failed to handle incomplete boot - provisioning: %w", err)} } // A connection failed error could mean that cloud init is still running (if cloudInit introduces a new port) @@ -1405,6 +1446,10 @@ func (s *Service) actionProvisioned() actionResult { // Reboot has been ongoing isTimeout, isSSHConnectionRefusedError, err := analyzeSSHOutputProvisioned(out) if err != nil { + if errors.Is(err, errUnexpectedHostName) { + // One possible reason: The machine gets used by a second wl-cluster + record.Warn(s.scope.HetznerBareMetalHost, "UnexpectedHostName", err.Error()) + } return actionError{err: fmt.Errorf("failed to handle incomplete boot - provisioning: %w", err)} } failed, err := s.handleIncompleteBoot(false, isTimeout, isSSHConnectionRefusedError) diff --git a/pkg/services/baremetal/host/host_test.go b/pkg/services/baremetal/host/host_test.go index 57a8b953b..032ceb73d 100644 --- a/pkg/services/baremetal/host/host_test.go +++ b/pkg/services/baremetal/host/host_test.go @@ -1303,6 +1303,7 @@ var _ = Describe("actionEnsureProvisioned", func() { sshMock.On("CleanCloudInitLogs").Return(sshclient.Output{}) sshMock.On("CleanCloudInitInstances").Return(sshclient.Output{}) sshMock.On("Reboot").Return(sshclient.Output{}) + sshMock.On("GetCloudInitOutput").Return(sshclient.Output{StdOut: "dummy content of /var/log/cloud-init-output.log"}) oldSSHMock := &sshmock.Client{} oldSSHMock.On("CloudInitStatus").Return(in.outOldSSHClientCloudInitStatus) diff --git a/pkg/services/hcloud/server/server.go b/pkg/services/hcloud/server/server.go index fd54aba80..4a836d0c9 100644 --- a/pkg/services/hcloud/server/server.go +++ b/pkg/services/hcloud/server/server.go @@ -742,7 +742,7 @@ func filterHCloudSSHKeys(sshKeysAPI []*hcloud.SSHKey, sshKeysSpec []infrav1.SSHK for i, sshKeySpec := range sshKeysSpec { sshKey, ok := sshKeysAPIMap[sshKeySpec.Name] if !ok { - return nil, fmt.Errorf("ssh key not found. SSH key name: %s", sshKeySpec.Name) + return nil, fmt.Errorf("ssh key not found in HCloud. SSH key name: %s", sshKeySpec.Name) } sshKeys[i] = sshKey } diff --git a/test/e2e/data/ccm/hcloud-ccm-hetzner.yaml b/test/e2e/data/ccm/hcloud-ccm-hetzner.yaml index c8faa5c32..7274b5ab5 100644 --- a/test/e2e/data/ccm/hcloud-ccm-hetzner.yaml +++ b/test/e2e/data/ccm/hcloud-ccm-hetzner.yaml @@ -6,11 +6,11 @@ metadata: name: ccm-ccm-hetzner namespace: kube-system labels: - helm.sh/chart: ccm-hetzner-1.1.8 + helm.sh/chart: ccm-hetzner-1.1.10 app: ccm app.kubernetes.io/name: ccm-hetzner app.kubernetes.io/instance: ccm - app.kubernetes.io/version: "v1.18.0-0.0.4" + app.kubernetes.io/version: "v1.18.0-0.0.5" app.kubernetes.io/managed-by: Helm --- # Source: ccm-hetzner/templates/serviceaccount.yaml @@ -20,11 +20,11 @@ metadata: name: ccm-ccm-hetzner namespace: kube-system labels: - helm.sh/chart: ccm-hetzner-1.1.8 + helm.sh/chart: ccm-hetzner-1.1.10 app: ccm app.kubernetes.io/name: ccm-hetzner app.kubernetes.io/instance: ccm - app.kubernetes.io/version: "v1.18.0-0.0.4" + app.kubernetes.io/version: "v1.18.0-0.0.5" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -42,11 +42,11 @@ metadata: name: ccm-ccm-hetzner namespace: kube-system labels: - helm.sh/chart: ccm-hetzner-1.1.8 + helm.sh/chart: ccm-hetzner-1.1.10 app: ccm app.kubernetes.io/name: ccm-hetzner app.kubernetes.io/instance: ccm - app.kubernetes.io/version: "v1.18.0-0.0.4" + app.kubernetes.io/version: "v1.18.0-0.0.5" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -63,8 +63,7 @@ spec: spec: dnsPolicy: Default serviceAccountName: ccm-ccm-hetzner - securityContext: - {} + securityContext: {} tolerations: # Introduced with CAPI v1.4, more info: https://cluster-api.sigs.k8s.io/developer/providers/bootstrap.html#taint-nodes-at-creation - key: "node.cluster.x-k8s.io/uninitialized" @@ -86,9 +85,8 @@ spec: effect: "NoSchedule" containers: - name: ccm-hetzner - securityContext: - {} - image: "ghcr.io/syself/hetzner-cloud-controller-manager:v1.18.0-0.0.4" + securityContext: {} + image: "ghcr.io/syself/hetzner-cloud-controller-manager:v1.18.0-0.0.5" imagePullPolicy: Always command: - "/bin/hetzner-cloud-controller-manager" diff --git a/test/e2e/data/ccm/hcloud-ccm-network.yaml b/test/e2e/data/ccm/hcloud-ccm-network.yaml index e08e58c8b..3302181de 100644 --- a/test/e2e/data/ccm/hcloud-ccm-network.yaml +++ b/test/e2e/data/ccm/hcloud-ccm-network.yaml @@ -6,11 +6,11 @@ metadata: name: ccm-ccm-hcloud namespace: kube-system labels: - helm.sh/chart: ccm-hetzner-1.1.8 + helm.sh/chart: ccm-hetzner-1.1.10 app: ccm app.kubernetes.io/name: ccm-hcloud app.kubernetes.io/instance: ccm - app.kubernetes.io/version: "v1.18.0-0.0.4" + app.kubernetes.io/version: "v1.18.0-0.0.5" app.kubernetes.io/managed-by: Helm --- # Source: ccm-hcloud/templates/serviceaccount.yaml @@ -20,11 +20,11 @@ metadata: name: ccm-ccm-hcloud namespace: kube-system labels: - helm.sh/chart: ccm-hetzner-1.1.8 + helm.sh/chart: ccm-hetzner-1.1.10 app: ccm app.kubernetes.io/name: ccm-hcloud app.kubernetes.io/instance: ccm - app.kubernetes.io/version: "v1.18.0-0.0.4" + app.kubernetes.io/version: "v1.18.0-0.0.5" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -42,11 +42,11 @@ metadata: name: ccm-ccm-hcloud namespace: kube-system labels: - helm.sh/chart: ccm-hetzner-1.1.8 + helm.sh/chart: ccm-hetzner-1.1.10 app: ccm app.kubernetes.io/name: ccm-hcloud app.kubernetes.io/instance: ccm - app.kubernetes.io/version: "v1.18.0-0.0.4" + app.kubernetes.io/version: "v1.18.0-0.0.5" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -63,8 +63,7 @@ spec: spec: dnsPolicy: Default serviceAccountName: ccm-ccm-hcloud - securityContext: - {} + securityContext: {} tolerations: # this taint is set by all kubelets running `--cloud-provider=external` # so we should tolerate it to schedule the cloud controller manager @@ -85,12 +84,11 @@ spec: hostNetwork: true containers: - name: ccm-hcloud - securityContext: - {} - image: "ghcr.io/syself/hetzner-cloud-controller-manager:v1.18.0-0.0.4" + securityContext: {} + image: "ghcr.io/syself/hetzner-cloud-controller-manager:v1.18.0-0.0.5" imagePullPolicy: Always command: - - "/bin/hcloud-cloud-controller-manager" + - "/bin/hetzner-cloud-controller-manager" - "--cloud-provider=hcloud" - "--leader-elect=true" - "--allow-untagged-cloud" diff --git a/test/helpers/defaults.go b/test/helpers/defaults.go index 5bc1a8222..6e5b5baca 100644 --- a/test/helpers/defaults.go +++ b/test/helpers/defaults.go @@ -18,11 +18,11 @@ package helpers import ( "fmt" + "sync/atomic" infrav1 "github.com/syself/cluster-api-provider-hetzner/api/v1beta1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - kuberand "k8s.io/apimachinery/pkg/util/rand" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" ) @@ -40,15 +40,18 @@ const ( var defaultPlacementGroupName = "caph-placement-group" +var globalServerIdCounter int32 + // BareMetalHost returns a bare metal host given options. func BareMetalHost(name, namespace string, opts ...HostOpts) *infrav1.HetznerBareMetalHost { + serverID := atomic.AddInt32(&globalServerIdCounter, 1) host := &infrav1.HetznerBareMetalHost{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: namespace, }, Spec: infrav1.HetznerBareMetalHostSpec{ - ServerID: kuberand.Intn(1000), + ServerID: int(serverID), }, } for _, o := range opts {