From b0cd9d9807d03df8e542d09dc53150e90cf950ec Mon Sep 17 00:00:00 2001 From: Kimmo Lehto Date: Fri, 16 Dec 2022 10:06:16 +0200 Subject: [PATCH] Validate MachineID existence & uniqueness (#435) * Validate MachineID existence & uniqueness Signed-off-by: Kimmo Lehto --- configurer/linux.go | 4 ++++ phase/gather_facts.go | 7 +++++++ phase/validate_hosts.go | 15 +++++++++++++-- .../k0sctl.k0sproject.io/v1beta1/cluster/host.go | 2 ++ smoke-test/smoke.common.sh | 8 +++++++- 5 files changed, 33 insertions(+), 3 deletions(-) diff --git a/configurer/linux.go b/configurer/linux.go index cf125d54..6278daa1 100644 --- a/configurer/linux.go +++ b/configurer/linux.go @@ -250,3 +250,7 @@ func (l Linux) UpsertFile(h os.Host, path, content string) error { func (l Linux) DeleteDir(h os.Host, path string, opts ...exec.Option) error { return h.Exec(fmt.Sprintf(`rmdir %s`, shellescape.Quote(path)), opts...) } + +func (l Linux) MachineID(h os.Host) (string, error) { + return h.ExecOutput(`cat /etc/machine-id || cat /var/lib/dbus/machine-id`) +} diff --git a/phase/gather_facts.go b/phase/gather_facts.go index cdc9971d..439f300b 100644 --- a/phase/gather_facts.go +++ b/phase/gather_facts.go @@ -32,6 +32,13 @@ func (p *GatherFacts) investigateHost(h *cluster.Host) error { return err } h.Metadata.Arch = output + + id, err := h.Configurer.MachineID(h) + if err != nil { + return err + } + h.Metadata.MachineID = id + p.IncProp(h.Metadata.Arch) if extra := h.InstallFlags.GetValue("--kubelet-extra-args"); extra != "" { diff --git a/phase/validate_hosts.go b/phase/validate_hosts.go index fe98cf71..5fdf4348 100644 --- a/phase/validate_hosts.go +++ b/phase/validate_hosts.go @@ -9,7 +9,8 @@ import ( // ValidateHosts performs remote OS detection type ValidateHosts struct { GenericPhase - hncount map[string]int + hncount map[string]int + machineidcount map[string]int } // Title for the phase @@ -20,11 +21,13 @@ func (p *ValidateHosts) Title() string { // Run the phase func (p *ValidateHosts) Run() error { p.hncount = make(map[string]int, len(p.Config.Spec.Hosts)) + p.machineidcount = make(map[string]int, len(p.Config.Spec.Hosts)) for _, h := range p.Config.Spec.Hosts { p.hncount[h.Metadata.Hostname]++ + p.machineidcount[h.Metadata.MachineID]++ } - return p.parallelDo(p.Config.Spec.Hosts, p.validateUniqueHostname, p.validateSudo) + return p.parallelDo(p.Config.Spec.Hosts, p.validateUniqueHostname, p.validateUniqueMachineID, p.validateSudo) } func (p *ValidateHosts) validateUniqueHostname(h *cluster.Host) error { @@ -35,6 +38,14 @@ func (p *ValidateHosts) validateUniqueHostname(h *cluster.Host) error { return nil } +func (p *ValidateHosts) validateUniqueMachineID(h *cluster.Host) error { + if p.machineidcount[h.Metadata.MachineID] > 1 { + return fmt.Errorf("machine id %s is not unique: %s", h.Metadata.MachineID, h.Metadata.Hostname) + } + + return nil +} + func (p *ValidateHosts) validateSudo(h *cluster.Host) error { if err := h.Configurer.CheckPrivilege(h); err != nil { return err diff --git a/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/host.go b/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/host.go index 90a680fc..23a99ff2 100644 --- a/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/host.go +++ b/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/host.go @@ -127,6 +127,7 @@ type configurer interface { DeleteDir(os.Host, string, ...exec.Option) error K0sctlLockFilePath(os.Host) string UpsertFile(os.Host, string, string) error + MachineID(os.Host) (string, error) } // HostMetadata resolved metadata for host @@ -138,6 +139,7 @@ type HostMetadata struct { Hostname string Ready bool NeedsUpgrade bool + MachineID string } // UnmarshalYAML sets in some sane defaults when unmarshaling the data from yaml diff --git a/smoke-test/smoke.common.sh b/smoke-test/smoke.common.sh index 939a0f5b..7e1d133a 100644 --- a/smoke-test/smoke.common.sh +++ b/smoke-test/smoke.common.sh @@ -8,6 +8,12 @@ export K0S_VERSION function createCluster() { envsubst < "${FOOTLOOSE_TEMPLATE}" > footloose.yaml footloose create + if [ "${LINUX_IMAGE}" = "quay.io/footloose/debian10" ]; then + for host in $(footloose status -o json|grep hostname|cut -d"\"" -f4); do + footloose ssh root@${host} -- rm -f /etc/machine-id /var/lib/dbus/machine-id + footloose ssh root@${host} -- systemd-machine-id-setup + done + fi } function deleteCluster() { @@ -33,4 +39,4 @@ function downloadKubectl() { esac [ -f kubectl ] || (curl -L https://storage.googleapis.com/kubernetes-release/release/v1.21.3/bin/${OS}/${ARCH}/kubectl > ./kubectl && chmod +x ./kubectl) ./kubectl version --client -} \ No newline at end of file +}