diff --git a/pkg/hostinfo/hostinfo.go b/pkg/hostinfo/hostinfo.go index 013cff100..aad2db315 100644 --- a/pkg/hostinfo/hostinfo.go +++ b/pkg/hostinfo/hostinfo.go @@ -32,6 +32,8 @@ import ( "github.com/jaypipes/ghw/pkg/net" "github.com/jaypipes/ghw/pkg/product" "github.com/jaypipes/ghw/pkg/topology" + + "github.com/rancher/elemental-operator/pkg/runtime" ) // HostInfo represents all the host info minus the PCI devices @@ -51,6 +53,7 @@ type HostInfo struct { BIOS *bios.Info `json:"bios"` Baseboard *baseboard.Info `json:"baseboard"` Product *product.Info `json:"product"` + Runtime *runtime.Info `json:"runtime"` } // Host returns a pointer to a HostInfo struct that contains fields with @@ -102,6 +105,11 @@ func host(opts ...*ghw.WithOption) (*HostInfo, error) { if err != nil { return nil, err } + runtimeInfo, err := runtime.New() + if err != nil { + return nil, err + } + return &HostInfo{ ctx: ctx, CPU: cpuInfo, @@ -114,6 +122,7 @@ func host(opts ...*ghw.WithOption) (*HostInfo, error) { BIOS: biosInfo, Baseboard: baseboardInfo, Product: productInfo, + Runtime: runtimeInfo, }, nil } @@ -187,6 +196,11 @@ func FillData(data []byte) (map[string]interface{}, error) { } } + runtime := map[string]interface{}{} + if systemData.Runtime != nil { + runtime["Hostname"] = systemData.Runtime.Hostname + } + labels := map[string]interface{}{} labels["System Data"] = map[string]interface{}{ "Memory": memory, @@ -194,6 +208,7 @@ func FillData(data []byte) (map[string]interface{}, error) { "GPU": gpu, "Network": network, "Block Devices": block, + "Runtime": runtime, } // Also available but not used: diff --git a/pkg/runtime/info.go b/pkg/runtime/info.go new file mode 100644 index 000000000..2c477e617 --- /dev/null +++ b/pkg/runtime/info.go @@ -0,0 +1,34 @@ +/* +Copyright © 2022 - 2024 SUSE LLC + +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 runtime + +import "os" + +type Info struct { + Hostname string `json:"hostname"` +} + +func New() (*Info, error) { + name, err := os.Hostname() + if err != nil { + return nil, err + } + + return &Info{ + Hostname: name, + }, nil +} diff --git a/pkg/server/api_registration.go b/pkg/server/api_registration.go index 1a519c4af..e49539c2f 100644 --- a/pkg/server/api_registration.go +++ b/pkg/server/api_registration.go @@ -441,16 +441,17 @@ func updateInventoryFromSMBIOSData(data []byte, mInventory *elementalv1.MachineI // Sanitize any lower dashes into dashes as hostnames cannot have lower dashes, and we use the inventory name // to set the machine hostname. Also set it to lowercase name, err := replaceStringData(smbiosData, mInventory.Name) - if err != nil { + if err == nil { + mInventory.Name = strings.ToLower(sanitizeHostname.ReplaceAllString(name, "-")) + } else { if errors.Is(err, errValueNotFound) { - log.Warningf("Value not found: %v", mInventory.Name) - name = "m" + // value not found, will be set in updateInventoryFromSystemData + log.Warningf("SMBIOS Value not found: %v", mInventory.Name) } else { return err } } - mInventory.Name = strings.ToLower(sanitizeHostname.ReplaceAllString(name, "-")) log.Debugf("Adding labels from registration") // Add extra label info from data coming from smbios and based on the registration data if mInventory.Labels == nil { @@ -489,6 +490,18 @@ func updateInventoryFromSystemData(data []byte, inv *elementalv1.MachineInventor // systemData.Chassis -> asset, serial, vendor,version,product, type. Maybe be useful depending on the provider. // systemData.Topology -> CPU/memory and cache topology. No idea if useful. + name, err := replaceStringData(labels, inv.Name) + if err != nil { + if errors.Is(err, errValueNotFound) { + log.Warningf("System data value not found: %v", inv.Name) + name = "m" + } else { + return err + } + } + + inv.Name = strings.ToLower(sanitizeHostname.ReplaceAllString(name, "-")) + log.Debugf("Parsing labels from System Data") if inv.Labels == nil { diff --git a/pkg/server/api_registration_test.go b/pkg/server/api_registration_test.go index b5544e5af..adb9fe41b 100644 --- a/pkg/server/api_registration_test.go +++ b/pkg/server/api_registration_test.go @@ -47,6 +47,7 @@ import ( elementalv1 "github.com/rancher/elemental-operator/api/v1beta1" "github.com/rancher/elemental-operator/pkg/hostinfo" "github.com/rancher/elemental-operator/pkg/register" + elementalruntime "github.com/rancher/elemental-operator/pkg/runtime" ) func TestUnauthenticatedResponse(t *testing.T) { @@ -264,6 +265,7 @@ func TestUpdateInventoryFromSystemData(t *testing.T) { registration := &elementalv1.MachineRegistration{ Spec: elementalv1.MachineRegistrationSpec{ MachineInventoryLabels: map[string]string{ + "elemental.cattle.io/Hostname": "${System Data/Runtime/Hostname}", "elemental.cattle.io/TotalMemory": "${System Data/Memory/Total Physical Bytes}", "elemental.cattle.io/AvailableMemory": "${System Data/Memory/Total Usable Bytes}", "elemental.cattle.io/CpuTotalCores": "${System Data/CPU/Total Cores}", @@ -321,12 +323,16 @@ func TestUpdateInventoryFromSystemData(t *testing.T) { }, }, }, + Runtime: &elementalruntime.Info{ + Hostname: "machine-1", + }, } encodedData, err := json.Marshal(data) assert.NilError(t, err) err = updateInventoryFromSystemData(encodedData, inventory, registration) assert.NilError(t, err) // Check that the labels we properly added to the inventory + assert.Equal(t, inventory.Labels["elemental.cattle.io/Hostname"], "machine-1") assert.Equal(t, inventory.Labels["elemental.cattle.io/TotalMemory"], "100") assert.Equal(t, inventory.Labels["elemental.cattle.io/TotalMemory"], "100") assert.Equal(t, inventory.Labels["elemental.cattle.io/CpuTotalCores"], "300") @@ -347,6 +353,8 @@ func TestUpdateInventoryFromSystemData(t *testing.T) { func TestUpdateInventoryFromSystemDataSanitized(t *testing.T) { inventory := &elementalv1.MachineInventory{} + inventory.Name = "${System Data/Runtime/Hostname}" + registration := &elementalv1.MachineRegistration{ Spec: elementalv1.MachineRegistrationSpec{ MachineInventoryLabels: map[string]string{ @@ -408,12 +416,16 @@ func TestUpdateInventoryFromSystemDataSanitized(t *testing.T) { }, }, }, + Runtime: &elementalruntime.Info{ + Hostname: "machine-1", + }, } encodedData, err := json.Marshal(data) assert.NilError(t, err) err = updateInventoryFromSystemData(encodedData, inventory, registration) assert.NilError(t, err) // Check that the labels we properly added to the inventory + assert.Equal(t, inventory.Name, "machine-1") assert.Equal(t, inventory.Labels["elemental.cattle.io/TotalMemory"], "100") assert.Equal(t, inventory.Labels["elemental.cattle.io/CpuTotalCores"], "300") assert.Equal(t, inventory.Labels["elemental.cattle.io/CpuTotalThreads"], "300")