diff --git a/Makefile b/Makefile index da288b576..b057d9e67 100644 --- a/Makefile +++ b/Makefile @@ -788,3 +788,9 @@ tilt-up: env-vars-for-wl-cluster $(ENVSUBST) $(KUBECTL) $(KUSTOMIZE) $(TILT) clu .PHONY: watch watch: ## Watch CRDs cluster, machines and Events. watch -c -n 2 hack/output-for-watch.sh + +installimageurl := $(shell curl -sL https://api.github.com/repos/syself/hetzner-installimage/releases/latest | jq -r .assets[].browser_download_url) +.PHONY: create-hetzner-installimage-tgz +create-hetzner-installimage-tgz: + rm -rf data/hetzner-installimage* + cd data; curl -sSLO $(installimageurl) diff --git a/Tiltfile b/Tiltfile index a80c45b33..b8d75e674 100644 --- a/Tiltfile +++ b/Tiltfile @@ -137,6 +137,9 @@ def set_env_variables(): tilt_dockerfile_header = """ FROM gcr.io/distroless/base:debug as tilt WORKDIR / + +COPY installimage.tgz . + COPY manager . """ @@ -154,6 +157,10 @@ def caph(): yaml = str(encode_yaml_stream(yaml_dict)) yaml = fixup_yaml_empty_arrays(yaml) + # copy things from data directory to .tiltbuild + if not os.path.exists('.tiltbuild/hetzner-installimage.tgz'): + local("cp data/hetzner-install-image-v1.0.0.tgz .tiltbuild/installimage.tgz") + # Set up a local_resource build of the provider's manager binary. # Forge the build command @@ -183,7 +190,7 @@ def caph(): dockerfile_contents = tilt_dockerfile_header, target = "tilt", entrypoint = entrypoint, - only = "manager", + only = ["manager", "installimage.tgz"], live_update = [ sync(".tiltbuild/manager", "/manager"), ], diff --git a/controllers/hetznerbaremetalhost_controller_test.go b/controllers/hetznerbaremetalhost_controller_test.go index 3c5db670c..927d3543c 100644 --- a/controllers/hetznerbaremetalhost_controller_test.go +++ b/controllers/hetznerbaremetalhost_controller_test.go @@ -829,6 +829,7 @@ name="eth0" model="Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express }) sshClient.On("DownloadImage", mock.Anything, mock.Anything).Return(sshclient.Output{}) sshClient.On("CreateAutoSetup", mock.Anything).Return(sshclient.Output{}) + sshClient.On("UntarTGZ").Return(sshclient.Output{}) sshClient.On("CreatePostInstallScript", mock.Anything).Return(sshclient.Output{}) sshClient.On("ExecuteInstallImage", mock.Anything).Return(sshclient.Output{}) sshClient.On("Reboot").Return(sshclient.Output{}) diff --git a/controllers/hetznerbaremetalremediation_controller_test.go b/controllers/hetznerbaremetalremediation_controller_test.go index 4a63905e4..8a3d4553a 100644 --- a/controllers/hetznerbaremetalremediation_controller_test.go +++ b/controllers/hetznerbaremetalremediation_controller_test.go @@ -213,6 +213,7 @@ var _ = Describe("HetznerBareMetalRemediationReconciler", func() { osSSHClientAfterInstallImage.On("CloudInitStatus").Return(sshclient.Output{StdOut: "status: done"}) osSSHClientAfterInstallImage.On("CheckCloudInitLogsForSigTerm").Return(sshclient.Output{}) osSSHClientAfterInstallImage.On("ResetKubeadm").Return(sshclient.Output{}) + osSSHClientAfterInstallImage.On("GetCloudInitOutput").Return(sshclient.Output{StdOut: "dummy content of /var/log/cloud-init-output.log"}) osSSHClientAfterInstallImage.On("GetHostName").Return(sshclient.Output{ StdOut: infrav1.BareMetalHostNamePrefix + bmMachineName, StdErr: "", @@ -227,6 +228,7 @@ var _ = Describe("HetznerBareMetalRemediationReconciler", 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() { diff --git a/data/hetzner-install-image-v1.0.0.tgz b/data/hetzner-install-image-v1.0.0.tgz new file mode 100644 index 000000000..5b3d0dde1 Binary files /dev/null and b/data/hetzner-install-image-v1.0.0.tgz differ diff --git a/hack/filter-caph-controller-manager-logs.py b/hack/filter-caph-controller-manager-logs.py index ba17869e5..23aa1e789 100755 --- a/hack/filter-caph-controller-manager-logs.py +++ b/hack/filter-caph-controller-manager-logs.py @@ -22,7 +22,7 @@ keys_to_skip = ['controller', 'controllerGroup', 'controllerKind', 'reconcileID', 'HetznerCluster', 'Cluster', - 'namespace', 'name', 'Machine'] + 'namespace', 'name', 'Machine', 'stack', 'stacktrace'] rows_to_skip = [ 'controller-runtime.webhook', 'certwatcher/certwatcher', 'Registering a validating webhook', diff --git a/hack/kind-dev.sh b/hack/kind-dev.sh index de997b256..22ea2952c 100755 --- a/hack/kind-dev.sh +++ b/hack/kind-dev.sh @@ -32,7 +32,7 @@ local CLUSTER_VERSION=$2 cat < /root/install-image-script.sh @@ -365,6 +368,17 @@ func (c *sshClient) ResetKubeadm() Output { return output } +func (c *sshClient) UntarTGZ() Output { + fileName := "/installimage.tgz" + data, err := os.ReadFile(fileName) + if err != nil { + return Output{Err: fmt.Errorf("ReadInstallimageTgzFailed %s: %w", fileName, err)} + } + + return c.runSSH(fmt.Sprintf("echo %s | base64 -d | tar -xzf-", + base64.StdEncoding.EncodeToString(data))) +} + // IsConnectionRefusedError checks whether the ssh error is a connection refused error. func IsConnectionRefusedError(err error) bool { return strings.Contains(err.Error(), ErrConnectionRefused.Error()) diff --git a/pkg/services/baremetal/host/host.go b/pkg/services/baremetal/host/host.go index fb55c19ec..7b896f8e0 100644 --- a/pkg/services/baremetal/host/host.go +++ b/pkg/services/baremetal/host/host.go @@ -950,8 +950,14 @@ func (s *Service) actionImageInstalling() actionResult { } } + out := sshClient.UntarTGZ() + if out.Err != nil { + record.Warnf(s.scope.HetznerBareMetalHost, "UntarInstallimageTgzFailed", "err: %s, stderr: %s", out.Err.Error(), out.StdErr) + return actionError{err: fmt.Errorf("UntarInstallimageTgzFailed: %w", out.Err)} + } + // Execute install image - out := sshClient.ExecuteInstallImage(postInstallScript != "") + 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)}