From d94bab35afb3a3ee4f1ab2af5054ef80288bd07c Mon Sep 17 00:00:00 2001 From: Christopher Nolan Date: Fri, 23 Jan 2026 17:42:49 +0000 Subject: [PATCH 1/6] Extend HW Discovery to report vPRO support --- .../apparmor.d/opt.edge-node.bin.hd-agent | 1 + .../config/sudoers.d/hd-agent | 2 +- .../internal/device/device.go | 45 ++++++++ .../internal/device/device_test.go | 102 ++++++++++++++++++ .../test/data/mock_amtinfo.json | 15 +++ 5 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 hardware-discovery-agent/internal/device/device.go create mode 100644 hardware-discovery-agent/internal/device/device_test.go create mode 100644 hardware-discovery-agent/test/data/mock_amtinfo.json diff --git a/hardware-discovery-agent/config/apparmor.d/opt.edge-node.bin.hd-agent b/hardware-discovery-agent/config/apparmor.d/opt.edge-node.bin.hd-agent index 77c556df..2b57c7f5 100644 --- a/hardware-discovery-agent/config/apparmor.d/opt.edge-node.bin.hd-agent +++ b/hardware-discovery-agent/config/apparmor.d/opt.edge-node.bin.hd-agent @@ -289,6 +289,7 @@ profile hda_sudo { /run/systemd/resolve/stub-resolv.conf r, /usr/bin/ipmitool rPx -> hda_ipmitool, /usr/bin/lshw rPx -> hda_lshw, + /usr/bin/rpc ix /usr/bin/sudo mr, /usr/libexec/sudo/libsudo_util.so.* mr, /usr/sbin/dmidecode rPx -> hda_dmidecode, diff --git a/hardware-discovery-agent/config/sudoers.d/hd-agent b/hardware-discovery-agent/config/sudoers.d/hd-agent index a3492bab..5d7ee359 100644 --- a/hardware-discovery-agent/config/sudoers.d/hd-agent +++ b/hardware-discovery-agent/config/sudoers.d/hd-agent @@ -1 +1 @@ -hd-agent ALL=(root) NOPASSWD:/usr/sbin/dmidecode,/usr/bin/ipmitool,/usr/bin/lshw,/usr/sbin/lshw +hd-agent ALL=(root) NOPASSWD:/usr/sbin/dmidecode,/usr/bin/ipmitool,/usr/bin/lshw,/usr/sbin/lshw,/usr/bin/rpc diff --git a/hardware-discovery-agent/internal/device/device.go b/hardware-discovery-agent/internal/device/device.go new file mode 100644 index 00000000..3026a1a0 --- /dev/null +++ b/hardware-discovery-agent/internal/device/device.go @@ -0,0 +1,45 @@ +// SPDX-FileCopyrightText: (C) 2026 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 + +package device + +import ( + "encoding/json" + "fmt" + + "github.com/open-edge-platform/edge-node-agents/hardware-discovery-agent/internal/utils" +) + +type RASInfo struct { + NetworkStatus string `json:"networkStatus"` + RemoteStatus string `json:"remoteStatus"` + RemoteTrigger string `json:"remoteTrigger"` + MPSHostname string `json:"mpsHostname"` +} + +type AMTInfo struct { + Version string `json:"version"` + BuildNumber string `json:"buildNumber"` + Sku string `json:"sku"` + Features string `json:"features"` + Uuid string `json:"uuid"` + ControlMode string `json:"controlMode"` + DNSSuffix string `json:"dnsSuffix"` + RAS RASInfo `json:"ras"` +} + +func GetDeviceInfo(executor utils.CmdExecutor) (AMTInfo, error) { + var amtInfo AMTInfo + dataBytes, err := utils.ReadFromCommand(executor, "sudo", "rpc", "amtinfo", "-json") + if err != nil { + return amtInfo, fmt.Errorf("failed to read data from command; error: %w", err) + } + + err = json.Unmarshal(dataBytes, &amtInfo) + if err != nil { + return amtInfo, fmt.Errorf("failed to parse data from command; error: %w", err) + } + + return amtInfo, nil +} diff --git a/hardware-discovery-agent/internal/device/device_test.go b/hardware-discovery-agent/internal/device/device_test.go new file mode 100644 index 00000000..56108bd2 --- /dev/null +++ b/hardware-discovery-agent/internal/device/device_test.go @@ -0,0 +1,102 @@ +// SPDX-FileCopyrightText: (C) 2026 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 + +package device_test + +import ( + "fmt" + "os" + "os/exec" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/open-edge-platform/edge-node-agents/hardware-discovery-agent/internal/device" +) + +func Test_GetDeviceInfo(t *testing.T) { + res, err := device.GetDeviceInfo(testSuccess) + expected := device.AMTInfo{ + Version: "16.1.27", + BuildNumber: "2176", + Sku: "16392", + Features: "AMT Pro Corporate", + Uuid: "1234abcd-ef56-7890-abcd-123456ef7890", + ControlMode: "activated in client control mode", + DNSSuffix: "test.com", + RAS: device.RASInfo{ + NetworkStatus: "direct", + RemoteStatus: "not connected", + RemoteTrigger: "user initiated", + MPSHostname: "", + }, + } + assert.NoError(t, err) + assert.Equal(t, expected, res) +} + +func Test_GetDeviceInfoFailed(t *testing.T) { + res, err := device.GetDeviceInfo(testFailure) + var expected device.AMTInfo + assert.Error(t, err) + assert.Equal(t, expected, res) +} + +func Test_GetDeviceInfoFailedUnmarshal(t *testing.T) { + res, err := device.GetDeviceInfo(testFailureUnmarshal) + var expected device.AMTInfo + assert.Error(t, err) + assert.Equal(t, expected, res) +} + +func testSuccess(command string, args ...string) *exec.Cmd { + cs := []string{"-test.run=TestSuccess", "--", command} + cs = append(cs, args...) + cmd := exec.Command(os.Args[0], cs...) + cmd.Env = []string{"GO_TEST_PROCESS=1"} + return cmd +} + +func testFailure(command string, args ...string) *exec.Cmd { + cs := []string{"-test.run=TestFailure", "--", command} + cs = append(cs, args...) + cmd := exec.Command(os.Args[0], cs...) + cmd.Env = []string{"GO_TEST_PROCESS=1"} + return cmd +} + +func testFailureUnmarshal(command string, args ...string) *exec.Cmd { + cs := []string{"-test.run=TestFailureUnmarshal", "--", command} + cs = append(cs, args...) + cmd := exec.Command(os.Args[0], cs...) + cmd.Env = []string{"GO_TEST_PROCESS=1"} + return cmd +} + +func TestSuccess(t *testing.T) { + if os.Getenv("GO_TEST_PROCESS") != "1" { + return + } + testData, err := os.ReadFile("../../test/data/mock_amtinfo.json") + require.NoError(t, err) + fmt.Fprintf(os.Stdout, "%v", string(testData)) + os.Exit(0) +} + +func TestFailure(_ *testing.T) { + if os.Getenv("GO_TEST_PROCESS") != "1" { + return + } + fmt.Fprintf(os.Stderr, "failed to execute command") + os.Exit(1) +} + +func TestFailureUnmarshal(_ *testing.T) { + if os.Getenv("GO_TEST_PROCESS") != "1" { + return + } + fmt.Fprintf(os.Stdout, "%v", string("not a json")) + os.Exit(0) +} diff --git a/hardware-discovery-agent/test/data/mock_amtinfo.json b/hardware-discovery-agent/test/data/mock_amtinfo.json new file mode 100644 index 00000000..4d06390a --- /dev/null +++ b/hardware-discovery-agent/test/data/mock_amtinfo.json @@ -0,0 +1,15 @@ +{ + "version": "16.1.27", + "buildNumber": "2176", + "sku": "16392", + "features": "AMT Pro Corporate", + "uuid": "1234abcd-ef56-7890-abcd-123456ef7890", + "controlMode": "activated in client control mode", + "dnsSuffix": "test.com", + "ras": { + "networkStatus": "direct", + "remoteStatus": "not connected", + "remoteTrigger": "user initiated", + "mpsHostname": "" + } +} \ No newline at end of file From 1685b712fafe5684538e35d9fe25885be7f31076 Mon Sep 17 00:00:00 2001 From: Christopher Nolan Date: Mon, 26 Jan 2026 12:32:11 +0000 Subject: [PATCH 2/6] Add device info call to comms package and update unit tests --- .../internal/comms/comms.go | 6 +++ .../internal/comms/comms_test.go | 42 +++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/hardware-discovery-agent/internal/comms/comms.go b/hardware-discovery-agent/internal/comms/comms.go index 406baf8c..51953c6e 100644 --- a/hardware-discovery-agent/internal/comms/comms.go +++ b/hardware-discovery-agent/internal/comms/comms.go @@ -16,6 +16,7 @@ import ( "google.golang.org/grpc/credentials" "github.com/open-edge-platform/edge-node-agents/hardware-discovery-agent/internal/cpu" + "github.com/open-edge-platform/edge-node-agents/hardware-discovery-agent/internal/device" "github.com/open-edge-platform/edge-node-agents/hardware-discovery-agent/internal/disk" "github.com/open-edge-platform/edge-node-agents/hardware-discovery-agent/internal/gpu" "github.com/open-edge-platform/edge-node-agents/hardware-discovery-agent/internal/logger" @@ -357,5 +358,10 @@ func GenerateSystemInfoRequest(executor utils.CmdExecutor) *proto.SystemInfo { log.Errorf("unable to get usb description : %v", err) } + _, err = device.GetDeviceInfo(executor) + if err != nil { + log.Errorf("unable to get device description : %v", err) + } + return parseSystemInfo(sn, productName, bmcAddr, osInfo, biosInfo, cpu, storage, gpu, mem, networkList, bmType, usbList) } diff --git a/hardware-discovery-agent/internal/comms/comms_test.go b/hardware-discovery-agent/internal/comms/comms_test.go index 344966cb..97378469 100644 --- a/hardware-discovery-agent/internal/comms/comms_test.go +++ b/hardware-discovery-agent/internal/comms/comms_test.go @@ -594,6 +594,24 @@ func TestGenerateUpdateDeviceRequestSuccessUsbInfoOnly(t *testing.T) { assert.Equal(t, expected, json) } +func TestGenerateUpdateDeviceRequestSuccessDeviceInfoOnly(t *testing.T) { + json := comms.GenerateSystemInfoRequest(testCmdExecutorCommandPassedDeviceOnly) + osKern := proto.OsKernel{} + osRelease := proto.OsRelease{} + osInfo := &proto.OsInfo{ + Kernel: &osKern, + Release: &osRelease, + } + cpu := &proto.SystemCPU{} + storage := []*proto.SystemDisk{} + gpu := []*proto.SystemGPU{} + networks := []*proto.SystemNetwork{} + usbInfo := []*proto.SystemUSB{} + expected := expectedSystemInfoResult("", "", "", osInfo, &proto.BiosInfo{}, cpu, storage, gpu, uint64(0), networks, proto.BmInfo_NONE, usbInfo) + require.NotNil(t, json) + assert.Equal(t, expected, json) +} + func testCmd(testFunc string, command string, args ...string) *exec.Cmd { cs := []string{fmt.Sprintf("-test.run=%s", testFunc), "--", command} cs = append(cs, args...) @@ -644,6 +662,8 @@ func testCmdExecutorCommandPassed(command string, args ...string) *exec.Cmd { return testCmd("TestGenerateUpdateDeviceRequestCommandGpuDetails", command, args...) } else if strings.Contains(args[0], "ipmitool") { return testCmd("TestGenerateUpdateDeviceRequestCommandIpmiDetails", command, args...) + } else if strings.Contains(args[0], "rpc") { + return testCmd("TestGenerateUpdateDeviceRequestCommandDeviceDetails", command, args...) } else { if strings.Contains(args[2], "bios-version") { return testCmd("TestGenerateUpdateDeviceRequestCommandBiosVersion", command, args...) @@ -760,6 +780,18 @@ func testCmdExecutorCommandPassedUsbOnly(command string, args ...string) *exec.C } } +func testCmdExecutorCommandPassedDeviceOnly(command string, args ...string) *exec.Cmd { + if strings.Contains(command, "sudo") { + if strings.Contains(args[0], "rpc") { + return testCmd("TestGenerateUpdateDeviceRequestCommandDeviceDetails", command, args...) + } else { + return testCmd("TestGenerateUpdateDeviceRequestCommandFailed", command, args...) + } + } else { + return testCmd("TestGenerateUpdateDeviceRequestCommandFailed", command, args...) + } +} + func testCmdExecutorCommandFailed(command string, args ...string) *exec.Cmd { cs := []string{"-test.run=TestGenerateUpdateDeviceRequestCommandFailed", "--", command} cs = append(cs, args...) @@ -788,6 +820,16 @@ func TestGenerateUpdateDeviceRequestCommandCoreDetails(t *testing.T) { os.Exit(0) } +func TestGenerateUpdateDeviceRequestCommandDeviceDetails(t *testing.T) { + if os.Getenv("GO_TEST_PROCESS") != "1" { + return + } + testData, err := os.ReadFile("../../test/data/mock_amtinfo.json") + require.NoError(t, err) + fmt.Fprintf(os.Stdout, "%v", string(testData)) + os.Exit(0) +} + func TestGenerateUpdateDeviceRequestCommandDiskDetails(t *testing.T) { if os.Getenv("GO_TEST_PROCESS") != "1" { return From eac727f36709e03f0acf4954d3dfad575ad00c4c Mon Sep 17 00:00:00 2001 From: Christopher Nolan Date: Mon, 26 Jan 2026 14:29:02 +0000 Subject: [PATCH 3/6] Add additional comms tests --- .../internal/comms/comms_test.go | 82 ++++++++++++++++--- 1 file changed, 71 insertions(+), 11 deletions(-) diff --git a/hardware-discovery-agent/internal/comms/comms_test.go b/hardware-discovery-agent/internal/comms/comms_test.go index 97378469..dc1bc50b 100644 --- a/hardware-discovery-agent/internal/comms/comms_test.go +++ b/hardware-discovery-agent/internal/comms/comms_test.go @@ -426,6 +426,18 @@ func getUsbInfo() []*proto.SystemUSB { return usbInfo } +func TestGenerateUpdateDeviceRequestSuccessAllInfo(t *testing.T) { + network.ReadFile = mockedReadFile + network.ReadDir = mockedReadDir + network.Readlink = mockedReadlink + network.CollectEthtoolData = mockedCollectEthtoolData + network.Stat = mockedStat + json := comms.GenerateSystemInfoRequest(testCmdExecutorCommandPassed) + expected := expectedSystemInfoResult("12A34B5", "Test Product", "192.168.1.50", getOsInfo(), getBiosInfo(), getCpuInfo(), getStorageInfo(), getGpuInfo(), 17179869184, getNetworkInfo(), proto.BmInfo_IPMI, getUsbInfo()) + require.NotNil(t, json) + assert.Equal(t, expected, json) +} + func TestGenerateUpdateDeviceRequestErr(t *testing.T) { json := comms.GenerateSystemInfoRequest(testCmdExecutorCommandFailed) osKern := proto.OsKernel{} @@ -444,20 +456,25 @@ func TestGenerateUpdateDeviceRequestErr(t *testing.T) { assert.Equal(t, expected, json) } -func TestGenerateUpdateDeviceRequestSuccessAllInfo(t *testing.T) { - network.ReadFile = mockedReadFile - network.ReadDir = mockedReadDir - network.Readlink = mockedReadlink - network.CollectEthtoolData = mockedCollectEthtoolData - network.Stat = mockedStat - json := comms.GenerateSystemInfoRequest(testCmdExecutorCommandPassed) - expected := expectedSystemInfoResult("12A34B5", "Test Product", "192.168.1.50", getOsInfo(), getBiosInfo(), getCpuInfo(), getStorageInfo(), getGpuInfo(), 17179869184, getNetworkInfo(), proto.BmInfo_IPMI, getUsbInfo()) +func TestGenerateUpdateDeviceRequestSuccessStorageOnly(t *testing.T) { + json := comms.GenerateSystemInfoRequest(testCmdExecutorCommandPassedStorageOnly) + osKern := proto.OsKernel{} + osRelease := proto.OsRelease{} + osInfo := &proto.OsInfo{ + Kernel: &osKern, + Release: &osRelease, + } + cpu := &proto.SystemCPU{} + gpu := []*proto.SystemGPU{} + networks := []*proto.SystemNetwork{} + usbInfo := []*proto.SystemUSB{} + expected := expectedSystemInfoResult("", "", "", osInfo, &proto.BiosInfo{}, cpu, getStorageInfo(), gpu, uint64(0), networks, proto.BmInfo_NONE, usbInfo) require.NotNil(t, json) assert.Equal(t, expected, json) } -func TestGenerateUpdateDeviceRequestSuccessStorageOnly(t *testing.T) { - json := comms.GenerateSystemInfoRequest(testCmdExecutorCommandPassedStorageOnly) +func TestGeneraeUpdateDeviceRequestSuccessSerialNumberOnly(t *testing.T) { + json := comms.GenerateSystemInfoRequest(testCmdExecutorCommandPassedSerialNumberOnly) osKern := proto.OsKernel{} osRelease := proto.OsRelease{} osInfo := &proto.OsInfo{ @@ -465,10 +482,29 @@ func TestGenerateUpdateDeviceRequestSuccessStorageOnly(t *testing.T) { Release: &osRelease, } cpu := &proto.SystemCPU{} + storage := []*proto.SystemDisk{} gpu := []*proto.SystemGPU{} networks := []*proto.SystemNetwork{} usbInfo := []*proto.SystemUSB{} - expected := expectedSystemInfoResult("", "", "", osInfo, &proto.BiosInfo{}, cpu, getStorageInfo(), gpu, uint64(0), networks, proto.BmInfo_NONE, usbInfo) + expected := expectedSystemInfoResult("12A34B5", "", "", osInfo, &proto.BiosInfo{}, cpu, storage, gpu, uint64(0), networks, proto.BmInfo_NONE, usbInfo) + require.NotNil(t, json) + assert.Equal(t, expected, json) +} + +func TestGenerateUpdateDeviceRequestSuccessProductNameOnly(t *testing.T) { + json := comms.GenerateSystemInfoRequest(testCmdExecutorCommandPassedProductNameOnly) + osKern := proto.OsKernel{} + osRelease := proto.OsRelease{} + osInfo := &proto.OsInfo{ + Kernel: &osKern, + Release: &osRelease, + } + cpu := &proto.SystemCPU{} + storage := []*proto.SystemDisk{} + gpu := []*proto.SystemGPU{} + networks := []*proto.SystemNetwork{} + usbInfo := []*proto.SystemUSB{} + expected := expectedSystemInfoResult("", "Test Product", "", osInfo, &proto.BiosInfo{}, cpu, storage, gpu, uint64(0), networks, proto.BmInfo_NONE, usbInfo) require.NotNil(t, json) assert.Equal(t, expected, json) } @@ -690,6 +726,30 @@ func testCmdExecutorCommandPassedStorageOnly(command string, args ...string) *ex } } +func testCmdExecutorCommandPassedSerialNumberOnly(command string, args ...string) *exec.Cmd { + if strings.Contains(command, "sudo") && strings.Contains(args[0], "dmidecode") { + if strings.Contains(args[2], "system-serial-number") { + return testCmd("TestGenerateUpdateDeviceRequestCommandSystemSerialNumber", command, args...) + } else { + return testCmd("TestGenerateUpdateDeviceRequestCommandFailed", command, args...) + } + } else { + return testCmd("TestGenerateUpdateDeviceRequestCommandFailed", command, args...) + } +} + +func testCmdExecutorCommandPassedProductNameOnly(command string, args ...string) *exec.Cmd { + if strings.Contains(command, "sudo") && strings.Contains(args[0], "dmidecode") { + if strings.Contains(args[2], "system-product-name") { + return testCmd("TestGenerateUpdateDeviceRequestCommandSystemProductName", command, args...) + } else { + return testCmd("TestGenerateUpdateDeviceRequestCommandFailed", command, args...) + } + } else { + return testCmd("TestGenerateUpdateDeviceRequestCommandFailed", command, args...) + } +} + func testCmdExecutorCommandPassedOsOnly(command string, args ...string) *exec.Cmd { if strings.Contains(command, "uname") { if strings.Contains(args[0], "-r") { From 71bd7407497f6f01a03aa6e02934a0800cfc7f6d Mon Sep 17 00:00:00 2001 From: Christopher Nolan Date: Mon, 26 Jan 2026 18:02:16 +0000 Subject: [PATCH 4/6] Add fallback check for device ID and additional unit tests --- .../internal/device/device.go | 27 +- .../internal/device/device_test.go | 382 ++++++++++++++++-- .../test/data/mock_amtinfo.json | 29 +- .../data/mock_amtinfo_missingbuildnum.json | 35 ++ .../data/mock_amtinfo_missingcontrolmode.json | 35 ++ .../data/mock_amtinfo_missingdnssuffix.json | 35 ++ .../data/mock_amtinfo_missingfeature.json | 35 ++ .../data/mock_amtinfo_missinghostname.json | 35 ++ .../mock_amtinfo_missingnetworkstatus.json | 35 ++ .../data/mock_amtinfo_missingopstate.json | 35 ++ .../data/mock_amtinfo_missingrasinfo.json | 30 ++ .../mock_amtinfo_missingremotestatus.json | 35 ++ .../mock_amtinfo_missingremotetrigger.json | 35 ++ .../test/data/mock_amtinfo_missingsku.json | 35 ++ .../test/data/mock_amtinfo_missinguuid.json | 35 ++ .../data/mock_amtinfo_missingversion.json | 35 ++ 16 files changed, 851 insertions(+), 37 deletions(-) create mode 100644 hardware-discovery-agent/test/data/mock_amtinfo_missingbuildnum.json create mode 100644 hardware-discovery-agent/test/data/mock_amtinfo_missingcontrolmode.json create mode 100644 hardware-discovery-agent/test/data/mock_amtinfo_missingdnssuffix.json create mode 100644 hardware-discovery-agent/test/data/mock_amtinfo_missingfeature.json create mode 100644 hardware-discovery-agent/test/data/mock_amtinfo_missinghostname.json create mode 100644 hardware-discovery-agent/test/data/mock_amtinfo_missingnetworkstatus.json create mode 100644 hardware-discovery-agent/test/data/mock_amtinfo_missingopstate.json create mode 100644 hardware-discovery-agent/test/data/mock_amtinfo_missingrasinfo.json create mode 100644 hardware-discovery-agent/test/data/mock_amtinfo_missingremotestatus.json create mode 100644 hardware-discovery-agent/test/data/mock_amtinfo_missingremotetrigger.json create mode 100644 hardware-discovery-agent/test/data/mock_amtinfo_missingsku.json create mode 100644 hardware-discovery-agent/test/data/mock_amtinfo_missinguuid.json create mode 100644 hardware-discovery-agent/test/data/mock_amtinfo_missingversion.json diff --git a/hardware-discovery-agent/internal/device/device.go b/hardware-discovery-agent/internal/device/device.go index 3026a1a0..22ae6bde 100644 --- a/hardware-discovery-agent/internal/device/device.go +++ b/hardware-discovery-agent/internal/device/device.go @@ -8,6 +8,7 @@ import ( "encoding/json" "fmt" + "github.com/open-edge-platform/edge-node-agents/hardware-discovery-agent/internal/system" "github.com/open-edge-platform/edge-node-agents/hardware-discovery-agent/internal/utils" ) @@ -19,14 +20,16 @@ type RASInfo struct { } type AMTInfo struct { - Version string `json:"version"` - BuildNumber string `json:"buildNumber"` - Sku string `json:"sku"` - Features string `json:"features"` - Uuid string `json:"uuid"` - ControlMode string `json:"controlMode"` - DNSSuffix string `json:"dnsSuffix"` - RAS RASInfo `json:"ras"` + Version string `json:"amt"` + Hostname string `json:"hostnameOS"` + OperationalState string `json:"operationalState"` + BuildNumber string `json:"buildNumber"` + Sku string `json:"sku"` + Features string `json:"features"` + Uuid string `json:"uuid"` + ControlMode string `json:"controlMode"` + DNSSuffix string `json:"dnsSuffix"` + RAS RASInfo `json:"ras"` } func GetDeviceInfo(executor utils.CmdExecutor) (AMTInfo, error) { @@ -41,5 +44,13 @@ func GetDeviceInfo(executor utils.CmdExecutor) (AMTInfo, error) { return amtInfo, fmt.Errorf("failed to parse data from command; error: %w", err) } + if amtInfo.Uuid == "" { + systemId, err := system.GetSystemUUID(executor) + if err != nil { + return AMTInfo{}, fmt.Errorf("failed to retrieve system uuid; error: %w", err) + } + amtInfo.Uuid = systemId + } + return amtInfo, nil } diff --git a/hardware-discovery-agent/internal/device/device_test.go b/hardware-discovery-agent/internal/device/device_test.go index 56108bd2..2674efc2 100644 --- a/hardware-discovery-agent/internal/device/device_test.go +++ b/hardware-discovery-agent/internal/device/device_test.go @@ -8,6 +8,7 @@ import ( "fmt" "os" "os/exec" + "strings" "testing" "github.com/stretchr/testify/assert" @@ -16,23 +17,45 @@ import ( "github.com/open-edge-platform/edge-node-agents/hardware-discovery-agent/internal/device" ) -func Test_GetDeviceInfo(t *testing.T) { - res, err := device.GetDeviceInfo(testSuccess) - expected := device.AMTInfo{ - Version: "16.1.27", - BuildNumber: "2176", - Sku: "16392", - Features: "AMT Pro Corporate", - Uuid: "1234abcd-ef56-7890-abcd-123456ef7890", - ControlMode: "activated in client control mode", - DNSSuffix: "test.com", +var testVersion = "16.1.27" +var testHostname = "testhost" +var testOperationalState = "enabled" +var testBuildNumber = "2176" +var testSku = "16392" +var testFeatures = "AMT Pro Corporate" +var testUuid = "1234abcd-ef56-7890-abcd-123456ef7890" +var testControlMode = "activated in client control mode" +var testDnsSuffix = "test.com" +var testNetworkStatus = "direct" +var testRemoteStatus = "not connected" +var testRemoteTrigger = "user initiated" + +func getExpectedResult(version string, hostname string, opState string, buildNum string, sku string, + features string, uuid string, controlMode string, dnsSuffix string, networkStatus string, + remoteStatus string, remoteTrigger string) device.AMTInfo { + return device.AMTInfo{ + Version: version, + Hostname: hostname, + OperationalState: opState, + BuildNumber: buildNum, + Sku: sku, + Features: features, + Uuid: uuid, + ControlMode: controlMode, + DNSSuffix: dnsSuffix, RAS: device.RASInfo{ - NetworkStatus: "direct", - RemoteStatus: "not connected", - RemoteTrigger: "user initiated", + NetworkStatus: networkStatus, + RemoteStatus: remoteStatus, + RemoteTrigger: remoteTrigger, MPSHostname: "", }, } +} + +func Test_GetDeviceInfo(t *testing.T) { + res, err := device.GetDeviceInfo(testSuccess) + expected := getExpectedResult(testVersion, testHostname, testOperationalState, testBuildNumber, testSku, + testFeatures, testUuid, testControlMode, testDnsSuffix, testNetworkStatus, testRemoteStatus, testRemoteTrigger) assert.NoError(t, err) assert.Equal(t, expected, res) } @@ -44,6 +67,13 @@ func Test_GetDeviceInfoFailed(t *testing.T) { assert.Equal(t, expected, res) } +func Test_GetDeviceInfoSystemUuidFailed(t *testing.T) { + res, err := device.GetDeviceInfo(testFailureSystemUuid) + var expected device.AMTInfo + assert.Error(t, err) + assert.Equal(t, expected, res) +} + func Test_GetDeviceInfoFailedUnmarshal(t *testing.T) { res, err := device.GetDeviceInfo(testFailureUnmarshal) var expected device.AMTInfo @@ -51,28 +81,192 @@ func Test_GetDeviceInfoFailedUnmarshal(t *testing.T) { assert.Equal(t, expected, res) } -func testSuccess(command string, args ...string) *exec.Cmd { - cs := []string{"-test.run=TestSuccess", "--", command} +func Test_GetDeviceInfoMissingVersionNumber(t *testing.T) { + res, err := device.GetDeviceInfo(testMissingVersionNumber) + expected := getExpectedResult("", testHostname, testOperationalState, testBuildNumber, testSku, testFeatures, + testUuid, testControlMode, testDnsSuffix, testNetworkStatus, testRemoteStatus, testRemoteTrigger) + assert.NoError(t, err) + assert.Equal(t, expected, res) +} + +func Test_GetDeviceInfoMissingHostname(t *testing.T) { + res, err := device.GetDeviceInfo(testMissingHostname) + expected := getExpectedResult(testVersion, "", testOperationalState, testBuildNumber, testSku, testFeatures, + testUuid, testControlMode, testDnsSuffix, testNetworkStatus, testRemoteStatus, testRemoteTrigger) + assert.NoError(t, err) + assert.Equal(t, expected, res) +} + +func Test_GetDeviceInfoMissingOperationalState(t *testing.T) { + res, err := device.GetDeviceInfo(testMissingOperationalState) + expected := getExpectedResult(testVersion, testHostname, "", testBuildNumber, testSku, testFeatures, testUuid, + testControlMode, testDnsSuffix, testNetworkStatus, testRemoteStatus, testRemoteTrigger) + assert.NoError(t, err) + assert.Equal(t, expected, res) +} + +func Test_GetDeviceInfoMissingBuildNumber(t *testing.T) { + res, err := device.GetDeviceInfo(testMissingBuildNumber) + expected := getExpectedResult(testVersion, testHostname, testOperationalState, "", testSku, testFeatures, testUuid, + testControlMode, testDnsSuffix, testNetworkStatus, testRemoteStatus, testRemoteTrigger) + assert.NoError(t, err) + assert.Equal(t, expected, res) +} + +func Test_GetDeviceInfoMissingSku(t *testing.T) { + res, err := device.GetDeviceInfo(testMissingSku) + expected := getExpectedResult(testVersion, testHostname, testOperationalState, testBuildNumber, "", testFeatures, + testUuid, testControlMode, testDnsSuffix, testNetworkStatus, testRemoteStatus, testRemoteTrigger) + assert.NoError(t, err) + assert.Equal(t, expected, res) +} + +func Test_GetDeviceInfoMissingFeatures(t *testing.T) { + res, err := device.GetDeviceInfo(testMissingFeatures) + expected := getExpectedResult(testVersion, testHostname, testOperationalState, testBuildNumber, testSku, "", + testUuid, testControlMode, testDnsSuffix, testNetworkStatus, testRemoteStatus, testRemoteTrigger) + assert.NoError(t, err) + assert.Equal(t, expected, res) +} + +func Test_GetDeviceInfoMissingUuid(t *testing.T) { + res, err := device.GetDeviceInfo(testMissingUuid) + expected := getExpectedResult(testVersion, testHostname, testOperationalState, testBuildNumber, testSku, + testFeatures, testUuid, testControlMode, testDnsSuffix, testNetworkStatus, testRemoteStatus, testRemoteTrigger) + assert.NoError(t, err) + assert.Equal(t, expected, res) +} + +func Test_GetDeviceInfoMissingControlMode(t *testing.T) { + res, err := device.GetDeviceInfo(testMissingControlMode) + expected := getExpectedResult(testVersion, testHostname, testOperationalState, testBuildNumber, testSku, + testFeatures, testUuid, "", testDnsSuffix, testNetworkStatus, testRemoteStatus, testRemoteTrigger) + assert.NoError(t, err) + assert.Equal(t, expected, res) +} + +func Test_GetDeviceInfoMissingDnsSuffix(t *testing.T) { + res, err := device.GetDeviceInfo(testMissingDnsSuffix) + expected := getExpectedResult(testVersion, testHostname, testOperationalState, testBuildNumber, testSku, + testFeatures, testUuid, testControlMode, "", testNetworkStatus, testRemoteStatus, testRemoteTrigger) + assert.NoError(t, err) + assert.Equal(t, expected, res) +} + +func Test_GetDeviceInfoMissingRasInfo(t *testing.T) { + res, err := device.GetDeviceInfo(testMissingRasInfo) + expected := getExpectedResult(testVersion, testHostname, testOperationalState, testBuildNumber, testSku, + testFeatures, testUuid, testControlMode, testDnsSuffix, "", "", "") + assert.NoError(t, err) + assert.Equal(t, expected, res) +} + +func Test_GetDeviceInfoMissingNetworkStatus(t *testing.T) { + res, err := device.GetDeviceInfo(testMissingNetworkStatus) + expected := getExpectedResult(testVersion, testHostname, testOperationalState, testBuildNumber, testSku, + testFeatures, testUuid, testControlMode, testDnsSuffix, "", testRemoteStatus, testRemoteTrigger) + assert.NoError(t, err) + assert.Equal(t, expected, res) +} + +func Test_GetDeviceInfoMissingRemoteStatus(t *testing.T) { + res, err := device.GetDeviceInfo(testMissingRemoteStatus) + expected := getExpectedResult(testVersion, testHostname, testOperationalState, testBuildNumber, testSku, + testFeatures, testUuid, testControlMode, testDnsSuffix, testNetworkStatus, "", testRemoteTrigger) + assert.NoError(t, err) + assert.Equal(t, expected, res) +} + +func Test_GetDeviceInfoMissingRemoteTrigger(t *testing.T) { + res, err := device.GetDeviceInfo(testMissingRemoteTrigger) + expected := getExpectedResult(testVersion, testHostname, testOperationalState, testBuildNumber, testSku, + testFeatures, testUuid, testControlMode, testDnsSuffix, testNetworkStatus, testRemoteStatus, "") + assert.NoError(t, err) + assert.Equal(t, expected, res) +} + +func testCmd(testFunc string, command string, args ...string) *exec.Cmd { + cs := []string{fmt.Sprintf("-test.run=%s", testFunc), "--", command} cs = append(cs, args...) cmd := exec.Command(os.Args[0], cs...) cmd.Env = []string{"GO_TEST_PROCESS=1"} return cmd } +func testSuccess(command string, args ...string) *exec.Cmd { + return testCmd("TestSuccess", command, args...) +} + func testFailure(command string, args ...string) *exec.Cmd { - cs := []string{"-test.run=TestFailure", "--", command} - cs = append(cs, args...) - cmd := exec.Command(os.Args[0], cs...) - cmd.Env = []string{"GO_TEST_PROCESS=1"} - return cmd + return testCmd("TestFailure", command, args...) +} + +func testFailureSystemUuid(command string, args ...string) *exec.Cmd { + if strings.Contains(args[0], "rpc") { + return testCmd("TestMissingUuid", command, args...) + } else { + return testCmd("TestFailure", command, args...) + } } func testFailureUnmarshal(command string, args ...string) *exec.Cmd { - cs := []string{"-test.run=TestFailureUnmarshal", "--", command} - cs = append(cs, args...) - cmd := exec.Command(os.Args[0], cs...) - cmd.Env = []string{"GO_TEST_PROCESS=1"} - return cmd + return testCmd("TestFailureUnmarshal", command, args...) +} + +func testMissingVersionNumber(command string, args ...string) *exec.Cmd { + return testCmd("TestMissingVersionNumber", command, args...) +} + +func testMissingHostname(command string, args ...string) *exec.Cmd { + return testCmd("TestMissingHostname", command, args...) +} + +func testMissingOperationalState(command string, args ...string) *exec.Cmd { + return testCmd("TestMissingOperationalState", command, args...) +} + +func testMissingBuildNumber(command string, args ...string) *exec.Cmd { + return testCmd("TestMissingBuildNumber", command, args...) +} + +func testMissingSku(command string, args ...string) *exec.Cmd { + return testCmd("TestMissingSku", command, args...) +} + +func testMissingFeatures(command string, args ...string) *exec.Cmd { + return testCmd("TestMissingFeatures", command, args...) +} + +func testMissingUuid(command string, args ...string) *exec.Cmd { + if strings.Contains(args[0], "rpc") { + return testCmd("TestMissingUuid", command, args...) + } else { + return testCmd("TestSystemUuid", command, args...) + } +} + +func testMissingControlMode(command string, args ...string) *exec.Cmd { + return testCmd("TestMissingControlMode", command, args...) +} + +func testMissingDnsSuffix(command string, args ...string) *exec.Cmd { + return testCmd("TestMissingDnsSuffix", command, args...) +} + +func testMissingRasInfo(command string, args ...string) *exec.Cmd { + return testCmd("TestMissingRasInfo", command, args...) +} + +func testMissingNetworkStatus(command string, args ...string) *exec.Cmd { + return testCmd("TestMissingNetworkStatus", command, args...) +} + +func testMissingRemoteStatus(command string, args ...string) *exec.Cmd { + return testCmd("TestMissingRemoteStatus", command, args...) +} + +func testMissingRemoteTrigger(command string, args ...string) *exec.Cmd { + return testCmd("TestMissingRemoteTrigger", command, args...) } func TestSuccess(t *testing.T) { @@ -100,3 +294,141 @@ func TestFailureUnmarshal(_ *testing.T) { fmt.Fprintf(os.Stdout, "%v", string("not a json")) os.Exit(0) } + +func TestMissingVersionNumber(t *testing.T) { + if os.Getenv("GO_TEST_PROCESS") != "1" { + return + } + testData, err := os.ReadFile("../../test/data/mock_amtinfo_missingversion.json") + require.NoError(t, err) + fmt.Fprintf(os.Stdout, "%v", string(testData)) + os.Exit(0) +} + +func TestMissingHostname(t *testing.T) { + if os.Getenv("GO_TEST_PROCESS") != "1" { + return + } + testData, err := os.ReadFile("../../test/data/mock_amtinfo_missinghostname.json") + require.NoError(t, err) + fmt.Fprintf(os.Stdout, "%v", string(testData)) + os.Exit(0) +} + +func TestMissingOperationalState(t *testing.T) { + if os.Getenv("GO_TEST_PROCESS") != "1" { + return + } + testData, err := os.ReadFile("../../test/data/mock_amtinfo_missingopstate.json") + require.NoError(t, err) + fmt.Fprintf(os.Stdout, "%v", string(testData)) + os.Exit(0) +} + +func TestMissingBuildNumber(t *testing.T) { + if os.Getenv("GO_TEST_PROCESS") != "1" { + return + } + testData, err := os.ReadFile("../../test/data/mock_amtinfo_missingbuildnum.json") + require.NoError(t, err) + fmt.Fprintf(os.Stdout, "%v", string(testData)) + os.Exit(0) +} + +func TestMissingSku(t *testing.T) { + if os.Getenv("GO_TEST_PROCESS") != "1" { + return + } + testData, err := os.ReadFile("../../test/data/mock_amtinfo_missingsku.json") + require.NoError(t, err) + fmt.Fprintf(os.Stdout, "%v", string(testData)) + os.Exit(0) +} + +func TestMissingFeatures(t *testing.T) { + if os.Getenv("GO_TEST_PROCESS") != "1" { + return + } + testData, err := os.ReadFile("../../test/data/mock_amtinfo_missingfeature.json") + require.NoError(t, err) + fmt.Fprintf(os.Stdout, "%v", string(testData)) + os.Exit(0) +} + +func TestMissingUuid(t *testing.T) { + if os.Getenv("GO_TEST_PROCESS") != "1" { + return + } + testData, err := os.ReadFile("../../test/data/mock_amtinfo_missinguuid.json") + require.NoError(t, err) + fmt.Fprintf(os.Stdout, "%v", string(testData)) + os.Exit(0) +} + +func TestSystemUuid(_ *testing.T) { + if os.Getenv("GO_TEST_PROCESS") != "1" { + return + } + fmt.Fprintf(os.Stdout, "%v", testUuid) + os.Exit(0) +} + +func TestMissingControlMode(t *testing.T) { + if os.Getenv("GO_TEST_PROCESS") != "1" { + return + } + testData, err := os.ReadFile("../../test/data/mock_amtinfo_missingcontrolmode.json") + require.NoError(t, err) + fmt.Fprintf(os.Stdout, "%v", string(testData)) + os.Exit(0) +} + +func TestMissingDnsSuffix(t *testing.T) { + if os.Getenv("GO_TEST_PROCESS") != "1" { + return + } + testData, err := os.ReadFile("../../test/data/mock_amtinfo_missingdnssuffix.json") + require.NoError(t, err) + fmt.Fprintf(os.Stdout, "%v", string(testData)) + os.Exit(0) +} + +func TestMissingRasInfo(t *testing.T) { + if os.Getenv("GO_TEST_PROCESS") != "1" { + return + } + testData, err := os.ReadFile("../../test/data/mock_amtinfo_missingrasinfo.json") + require.NoError(t, err) + fmt.Fprintf(os.Stdout, "%v", string(testData)) + os.Exit(0) +} + +func TestMissingNetworkStatus(t *testing.T) { + if os.Getenv("GO_TEST_PROCESS") != "1" { + return + } + testData, err := os.ReadFile("../../test/data/mock_amtinfo_missingnetworkstatus.json") + require.NoError(t, err) + fmt.Fprintf(os.Stdout, "%v", string(testData)) + os.Exit(0) +} + +func TestMissingRemoteStatus(t *testing.T) { + if os.Getenv("GO_TEST_PROCESS") != "1" { + return + } + testData, err := os.ReadFile("../../test/data/mock_amtinfo_missingremotestatus.json") + require.NoError(t, err) + fmt.Fprintf(os.Stdout, "%v", string(testData)) + os.Exit(0) +} + +func TestMissingRemoteTrigger(t *testing.T) { + if os.Getenv("GO_TEST_PROCESS") != "1" { + return + } + testData, err := os.ReadFile("../../test/data/mock_amtinfo_missingremotetrigger.json") + require.NoError(t, err) + fmt.Fprintf(os.Stdout, "%v", string(testData)) + os.Exit(0) +} diff --git a/hardware-discovery-agent/test/data/mock_amtinfo.json b/hardware-discovery-agent/test/data/mock_amtinfo.json index 4d06390a..5724ca75 100644 --- a/hardware-discovery-agent/test/data/mock_amtinfo.json +++ b/hardware-discovery-agent/test/data/mock_amtinfo.json @@ -1,15 +1,36 @@ { - "version": "16.1.27", + "amt": "16.1.27", "buildNumber": "2176", - "sku": "16392", - "features": "AMT Pro Corporate", - "uuid": "1234abcd-ef56-7890-abcd-123456ef7890", "controlMode": "activated in client control mode", "dnsSuffix": "test.com", + "dnsSuffixOS": "localhost", + "features": "AMT Pro Corporate", + "hostnameOS": "testhost", + "operationalState": "enabled", "ras": { "networkStatus": "direct", "remoteStatus": "not connected", "remoteTrigger": "user initiated", "mpsHostname": "" + }, + "sku": "16392", + "uuid": "1234abcd-ef56-7890-abcd-123456ef7890", + "wiredAdapter": { + "isEnable": false, + "linkStatus": "down", + "dhcpEnabled": false, + "dhcpMode": "passive", + "ipAddress": "0.0.0.0", + "osIpAddress": "0.0.0.0", + "macAddress": "1a:b2:3c:d4:5e:f6" + }, + "wirelessAddress": { + "isEnable": false, + "linkStatus": "down", + "dhcpEnabled": false, + "dhcpMode": "passive", + "ipAddress": "0.0.0.0", + "osIpAddress": "0.0.0.0", + "macAddress": "a1:2b:c3:4d:e5:6f" } } \ No newline at end of file diff --git a/hardware-discovery-agent/test/data/mock_amtinfo_missingbuildnum.json b/hardware-discovery-agent/test/data/mock_amtinfo_missingbuildnum.json new file mode 100644 index 00000000..0b8138a4 --- /dev/null +++ b/hardware-discovery-agent/test/data/mock_amtinfo_missingbuildnum.json @@ -0,0 +1,35 @@ +{ + "amt": "16.1.27", + "controlMode": "activated in client control mode", + "dnsSuffix": "test.com", + "dnsSuffixOS": "localhost", + "features": "AMT Pro Corporate", + "hostnameOS": "testhost", + "operationalState": "enabled", + "ras": { + "networkStatus": "direct", + "remoteStatus": "not connected", + "remoteTrigger": "user initiated", + "mpsHostname": "" + }, + "sku": "16392", + "uuid": "1234abcd-ef56-7890-abcd-123456ef7890", + "wiredAdapter": { + "isEnable": false, + "linkStatus": "down", + "dhcpEnabled": false, + "dhcpMode": "passive", + "ipAddress": "0.0.0.0", + "osIpAddress": "0.0.0.0", + "macAddress": "1a:b2:3c:d4:5e:f6" + }, + "wirelessAddress": { + "isEnable": false, + "linkStatus": "down", + "dhcpEnabled": false, + "dhcpMode": "passive", + "ipAddress": "0.0.0.0", + "osIpAddress": "0.0.0.0", + "macAddress": "a1:2b:c3:4d:e5:6f" + } +} \ No newline at end of file diff --git a/hardware-discovery-agent/test/data/mock_amtinfo_missingcontrolmode.json b/hardware-discovery-agent/test/data/mock_amtinfo_missingcontrolmode.json new file mode 100644 index 00000000..e38d101f --- /dev/null +++ b/hardware-discovery-agent/test/data/mock_amtinfo_missingcontrolmode.json @@ -0,0 +1,35 @@ +{ + "amt": "16.1.27", + "buildNumber": "2176", + "dnsSuffix": "test.com", + "dnsSuffixOS": "localhost", + "features": "AMT Pro Corporate", + "hostnameOS": "testhost", + "operationalState": "enabled", + "ras": { + "networkStatus": "direct", + "remoteStatus": "not connected", + "remoteTrigger": "user initiated", + "mpsHostname": "" + }, + "sku": "16392", + "uuid": "1234abcd-ef56-7890-abcd-123456ef7890", + "wiredAdapter": { + "isEnable": false, + "linkStatus": "down", + "dhcpEnabled": false, + "dhcpMode": "passive", + "ipAddress": "0.0.0.0", + "osIpAddress": "0.0.0.0", + "macAddress": "1a:b2:3c:d4:5e:f6" + }, + "wirelessAddress": { + "isEnable": false, + "linkStatus": "down", + "dhcpEnabled": false, + "dhcpMode": "passive", + "ipAddress": "0.0.0.0", + "osIpAddress": "0.0.0.0", + "macAddress": "a1:2b:c3:4d:e5:6f" + } +} \ No newline at end of file diff --git a/hardware-discovery-agent/test/data/mock_amtinfo_missingdnssuffix.json b/hardware-discovery-agent/test/data/mock_amtinfo_missingdnssuffix.json new file mode 100644 index 00000000..ce7b0426 --- /dev/null +++ b/hardware-discovery-agent/test/data/mock_amtinfo_missingdnssuffix.json @@ -0,0 +1,35 @@ +{ + "amt": "16.1.27", + "buildNumber": "2176", + "controlMode": "activated in client control mode", + "dnsSuffixOS": "localhost", + "features": "AMT Pro Corporate", + "hostnameOS": "testhost", + "operationalState": "enabled", + "ras": { + "networkStatus": "direct", + "remoteStatus": "not connected", + "remoteTrigger": "user initiated", + "mpsHostname": "" + }, + "sku": "16392", + "uuid": "1234abcd-ef56-7890-abcd-123456ef7890", + "wiredAdapter": { + "isEnable": false, + "linkStatus": "down", + "dhcpEnabled": false, + "dhcpMode": "passive", + "ipAddress": "0.0.0.0", + "osIpAddress": "0.0.0.0", + "macAddress": "1a:b2:3c:d4:5e:f6" + }, + "wirelessAddress": { + "isEnable": false, + "linkStatus": "down", + "dhcpEnabled": false, + "dhcpMode": "passive", + "ipAddress": "0.0.0.0", + "osIpAddress": "0.0.0.0", + "macAddress": "a1:2b:c3:4d:e5:6f" + } +} \ No newline at end of file diff --git a/hardware-discovery-agent/test/data/mock_amtinfo_missingfeature.json b/hardware-discovery-agent/test/data/mock_amtinfo_missingfeature.json new file mode 100644 index 00000000..148c1380 --- /dev/null +++ b/hardware-discovery-agent/test/data/mock_amtinfo_missingfeature.json @@ -0,0 +1,35 @@ +{ + "amt": "16.1.27", + "buildNumber": "2176", + "controlMode": "activated in client control mode", + "dnsSuffix": "test.com", + "dnsSuffixOS": "localhost", + "hostnameOS": "testhost", + "operationalState": "enabled", + "ras": { + "networkStatus": "direct", + "remoteStatus": "not connected", + "remoteTrigger": "user initiated", + "mpsHostname": "" + }, + "sku": "16392", + "uuid": "1234abcd-ef56-7890-abcd-123456ef7890", + "wiredAdapter": { + "isEnable": false, + "linkStatus": "down", + "dhcpEnabled": false, + "dhcpMode": "passive", + "ipAddress": "0.0.0.0", + "osIpAddress": "0.0.0.0", + "macAddress": "1a:b2:3c:d4:5e:f6" + }, + "wirelessAddress": { + "isEnable": false, + "linkStatus": "down", + "dhcpEnabled": false, + "dhcpMode": "passive", + "ipAddress": "0.0.0.0", + "osIpAddress": "0.0.0.0", + "macAddress": "a1:2b:c3:4d:e5:6f" + } +} \ No newline at end of file diff --git a/hardware-discovery-agent/test/data/mock_amtinfo_missinghostname.json b/hardware-discovery-agent/test/data/mock_amtinfo_missinghostname.json new file mode 100644 index 00000000..3649eab8 --- /dev/null +++ b/hardware-discovery-agent/test/data/mock_amtinfo_missinghostname.json @@ -0,0 +1,35 @@ +{ + "amt": "16.1.27", + "buildNumber": "2176", + "controlMode": "activated in client control mode", + "dnsSuffix": "test.com", + "dnsSuffixOS": "localhost", + "features": "AMT Pro Corporate", + "operationalState": "enabled", + "ras": { + "networkStatus": "direct", + "remoteStatus": "not connected", + "remoteTrigger": "user initiated", + "mpsHostname": "" + }, + "sku": "16392", + "uuid": "1234abcd-ef56-7890-abcd-123456ef7890", + "wiredAdapter": { + "isEnable": false, + "linkStatus": "down", + "dhcpEnabled": false, + "dhcpMode": "passive", + "ipAddress": "0.0.0.0", + "osIpAddress": "0.0.0.0", + "macAddress": "1a:b2:3c:d4:5e:f6" + }, + "wirelessAddress": { + "isEnable": false, + "linkStatus": "down", + "dhcpEnabled": false, + "dhcpMode": "passive", + "ipAddress": "0.0.0.0", + "osIpAddress": "0.0.0.0", + "macAddress": "a1:2b:c3:4d:e5:6f" + } +} \ No newline at end of file diff --git a/hardware-discovery-agent/test/data/mock_amtinfo_missingnetworkstatus.json b/hardware-discovery-agent/test/data/mock_amtinfo_missingnetworkstatus.json new file mode 100644 index 00000000..82213266 --- /dev/null +++ b/hardware-discovery-agent/test/data/mock_amtinfo_missingnetworkstatus.json @@ -0,0 +1,35 @@ +{ + "amt": "16.1.27", + "buildNumber": "2176", + "controlMode": "activated in client control mode", + "dnsSuffix": "test.com", + "dnsSuffixOS": "localhost", + "features": "AMT Pro Corporate", + "hostnameOS": "testhost", + "operationalState": "enabled", + "ras": { + "remoteStatus": "not connected", + "remoteTrigger": "user initiated", + "mpsHostname": "" + }, + "sku": "16392", + "uuid": "1234abcd-ef56-7890-abcd-123456ef7890", + "wiredAdapter": { + "isEnable": false, + "linkStatus": "down", + "dhcpEnabled": false, + "dhcpMode": "passive", + "ipAddress": "0.0.0.0", + "osIpAddress": "0.0.0.0", + "macAddress": "1a:b2:3c:d4:5e:f6" + }, + "wirelessAddress": { + "isEnable": false, + "linkStatus": "down", + "dhcpEnabled": false, + "dhcpMode": "passive", + "ipAddress": "0.0.0.0", + "osIpAddress": "0.0.0.0", + "macAddress": "a1:2b:c3:4d:e5:6f" + } +} \ No newline at end of file diff --git a/hardware-discovery-agent/test/data/mock_amtinfo_missingopstate.json b/hardware-discovery-agent/test/data/mock_amtinfo_missingopstate.json new file mode 100644 index 00000000..36047d9b --- /dev/null +++ b/hardware-discovery-agent/test/data/mock_amtinfo_missingopstate.json @@ -0,0 +1,35 @@ +{ + "amt": "16.1.27", + "buildNumber": "2176", + "controlMode": "activated in client control mode", + "dnsSuffix": "test.com", + "dnsSuffixOS": "localhost", + "features": "AMT Pro Corporate", + "hostnameOS": "testhost", + "ras": { + "networkStatus": "direct", + "remoteStatus": "not connected", + "remoteTrigger": "user initiated", + "mpsHostname": "" + }, + "sku": "16392", + "uuid": "1234abcd-ef56-7890-abcd-123456ef7890", + "wiredAdapter": { + "isEnable": false, + "linkStatus": "down", + "dhcpEnabled": false, + "dhcpMode": "passive", + "ipAddress": "0.0.0.0", + "osIpAddress": "0.0.0.0", + "macAddress": "1a:b2:3c:d4:5e:f6" + }, + "wirelessAddress": { + "isEnable": false, + "linkStatus": "down", + "dhcpEnabled": false, + "dhcpMode": "passive", + "ipAddress": "0.0.0.0", + "osIpAddress": "0.0.0.0", + "macAddress": "a1:2b:c3:4d:e5:6f" + } +} \ No newline at end of file diff --git a/hardware-discovery-agent/test/data/mock_amtinfo_missingrasinfo.json b/hardware-discovery-agent/test/data/mock_amtinfo_missingrasinfo.json new file mode 100644 index 00000000..d8027ae2 --- /dev/null +++ b/hardware-discovery-agent/test/data/mock_amtinfo_missingrasinfo.json @@ -0,0 +1,30 @@ +{ + "amt": "16.1.27", + "buildNumber": "2176", + "controlMode": "activated in client control mode", + "dnsSuffix": "test.com", + "dnsSuffixOS": "localhost", + "features": "AMT Pro Corporate", + "hostnameOS": "testhost", + "operationalState": "enabled", + "sku": "16392", + "uuid": "1234abcd-ef56-7890-abcd-123456ef7890", + "wiredAdapter": { + "isEnable": false, + "linkStatus": "down", + "dhcpEnabled": false, + "dhcpMode": "passive", + "ipAddress": "0.0.0.0", + "osIpAddress": "0.0.0.0", + "macAddress": "1a:b2:3c:d4:5e:f6" + }, + "wirelessAddress": { + "isEnable": false, + "linkStatus": "down", + "dhcpEnabled": false, + "dhcpMode": "passive", + "ipAddress": "0.0.0.0", + "osIpAddress": "0.0.0.0", + "macAddress": "a1:2b:c3:4d:e5:6f" + } +} \ No newline at end of file diff --git a/hardware-discovery-agent/test/data/mock_amtinfo_missingremotestatus.json b/hardware-discovery-agent/test/data/mock_amtinfo_missingremotestatus.json new file mode 100644 index 00000000..1bd8eea7 --- /dev/null +++ b/hardware-discovery-agent/test/data/mock_amtinfo_missingremotestatus.json @@ -0,0 +1,35 @@ +{ + "amt": "16.1.27", + "buildNumber": "2176", + "controlMode": "activated in client control mode", + "dnsSuffix": "test.com", + "dnsSuffixOS": "localhost", + "features": "AMT Pro Corporate", + "hostnameOS": "testhost", + "operationalState": "enabled", + "ras": { + "networkStatus": "direct", + "remoteTrigger": "user initiated", + "mpsHostname": "" + }, + "sku": "16392", + "uuid": "1234abcd-ef56-7890-abcd-123456ef7890", + "wiredAdapter": { + "isEnable": false, + "linkStatus": "down", + "dhcpEnabled": false, + "dhcpMode": "passive", + "ipAddress": "0.0.0.0", + "osIpAddress": "0.0.0.0", + "macAddress": "1a:b2:3c:d4:5e:f6" + }, + "wirelessAddress": { + "isEnable": false, + "linkStatus": "down", + "dhcpEnabled": false, + "dhcpMode": "passive", + "ipAddress": "0.0.0.0", + "osIpAddress": "0.0.0.0", + "macAddress": "a1:2b:c3:4d:e5:6f" + } +} \ No newline at end of file diff --git a/hardware-discovery-agent/test/data/mock_amtinfo_missingremotetrigger.json b/hardware-discovery-agent/test/data/mock_amtinfo_missingremotetrigger.json new file mode 100644 index 00000000..241cc07c --- /dev/null +++ b/hardware-discovery-agent/test/data/mock_amtinfo_missingremotetrigger.json @@ -0,0 +1,35 @@ +{ + "amt": "16.1.27", + "buildNumber": "2176", + "controlMode": "activated in client control mode", + "dnsSuffix": "test.com", + "dnsSuffixOS": "localhost", + "features": "AMT Pro Corporate", + "hostnameOS": "testhost", + "operationalState": "enabled", + "ras": { + "networkStatus": "direct", + "remoteStatus": "not connected", + "mpsHostname": "" + }, + "sku": "16392", + "uuid": "1234abcd-ef56-7890-abcd-123456ef7890", + "wiredAdapter": { + "isEnable": false, + "linkStatus": "down", + "dhcpEnabled": false, + "dhcpMode": "passive", + "ipAddress": "0.0.0.0", + "osIpAddress": "0.0.0.0", + "macAddress": "1a:b2:3c:d4:5e:f6" + }, + "wirelessAddress": { + "isEnable": false, + "linkStatus": "down", + "dhcpEnabled": false, + "dhcpMode": "passive", + "ipAddress": "0.0.0.0", + "osIpAddress": "0.0.0.0", + "macAddress": "a1:2b:c3:4d:e5:6f" + } +} \ No newline at end of file diff --git a/hardware-discovery-agent/test/data/mock_amtinfo_missingsku.json b/hardware-discovery-agent/test/data/mock_amtinfo_missingsku.json new file mode 100644 index 00000000..520be320 --- /dev/null +++ b/hardware-discovery-agent/test/data/mock_amtinfo_missingsku.json @@ -0,0 +1,35 @@ +{ + "amt": "16.1.27", + "buildNumber": "2176", + "controlMode": "activated in client control mode", + "dnsSuffix": "test.com", + "dnsSuffixOS": "localhost", + "features": "AMT Pro Corporate", + "hostnameOS": "testhost", + "operationalState": "enabled", + "ras": { + "networkStatus": "direct", + "remoteStatus": "not connected", + "remoteTrigger": "user initiated", + "mpsHostname": "" + }, + "uuid": "1234abcd-ef56-7890-abcd-123456ef7890", + "wiredAdapter": { + "isEnable": false, + "linkStatus": "down", + "dhcpEnabled": false, + "dhcpMode": "passive", + "ipAddress": "0.0.0.0", + "osIpAddress": "0.0.0.0", + "macAddress": "1a:b2:3c:d4:5e:f6" + }, + "wirelessAddress": { + "isEnable": false, + "linkStatus": "down", + "dhcpEnabled": false, + "dhcpMode": "passive", + "ipAddress": "0.0.0.0", + "osIpAddress": "0.0.0.0", + "macAddress": "a1:2b:c3:4d:e5:6f" + } +} \ No newline at end of file diff --git a/hardware-discovery-agent/test/data/mock_amtinfo_missinguuid.json b/hardware-discovery-agent/test/data/mock_amtinfo_missinguuid.json new file mode 100644 index 00000000..d2aaf5d8 --- /dev/null +++ b/hardware-discovery-agent/test/data/mock_amtinfo_missinguuid.json @@ -0,0 +1,35 @@ +{ + "amt": "16.1.27", + "buildNumber": "2176", + "controlMode": "activated in client control mode", + "dnsSuffix": "test.com", + "dnsSuffixOS": "localhost", + "features": "AMT Pro Corporate", + "hostnameOS": "testhost", + "operationalState": "enabled", + "ras": { + "networkStatus": "direct", + "remoteStatus": "not connected", + "remoteTrigger": "user initiated", + "mpsHostname": "" + }, + "sku": "16392", + "wiredAdapter": { + "isEnable": false, + "linkStatus": "down", + "dhcpEnabled": false, + "dhcpMode": "passive", + "ipAddress": "0.0.0.0", + "osIpAddress": "0.0.0.0", + "macAddress": "1a:b2:3c:d4:5e:f6" + }, + "wirelessAddress": { + "isEnable": false, + "linkStatus": "down", + "dhcpEnabled": false, + "dhcpMode": "passive", + "ipAddress": "0.0.0.0", + "osIpAddress": "0.0.0.0", + "macAddress": "a1:2b:c3:4d:e5:6f" + } +} \ No newline at end of file diff --git a/hardware-discovery-agent/test/data/mock_amtinfo_missingversion.json b/hardware-discovery-agent/test/data/mock_amtinfo_missingversion.json new file mode 100644 index 00000000..02248dc9 --- /dev/null +++ b/hardware-discovery-agent/test/data/mock_amtinfo_missingversion.json @@ -0,0 +1,35 @@ +{ + "buildNumber": "2176", + "controlMode": "activated in client control mode", + "dnsSuffix": "test.com", + "dnsSuffixOS": "localhost", + "features": "AMT Pro Corporate", + "hostnameOS": "testhost", + "operationalState": "enabled", + "ras": { + "networkStatus": "direct", + "remoteStatus": "not connected", + "remoteTrigger": "user initiated", + "mpsHostname": "" + }, + "sku": "16392", + "uuid": "1234abcd-ef56-7890-abcd-123456ef7890", + "wiredAdapter": { + "isEnable": false, + "linkStatus": "down", + "dhcpEnabled": false, + "dhcpMode": "passive", + "ipAddress": "0.0.0.0", + "osIpAddress": "0.0.0.0", + "macAddress": "1a:b2:3c:d4:5e:f6" + }, + "wirelessAddress": { + "isEnable": false, + "linkStatus": "down", + "dhcpEnabled": false, + "dhcpMode": "passive", + "ipAddress": "0.0.0.0", + "osIpAddress": "0.0.0.0", + "macAddress": "a1:2b:c3:4d:e5:6f" + } +} \ No newline at end of file From 194e9033c6aca9b4d540910df53e7a3607083800 Mon Sep 17 00:00:00 2001 From: Christopher Nolan Date: Wed, 28 Jan 2026 12:19:00 +0000 Subject: [PATCH 5/6] Fix apparmor typo --- .../config/apparmor.d/opt.edge-node.bin.hd-agent | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hardware-discovery-agent/config/apparmor.d/opt.edge-node.bin.hd-agent b/hardware-discovery-agent/config/apparmor.d/opt.edge-node.bin.hd-agent index 2b57c7f5..52fa3211 100644 --- a/hardware-discovery-agent/config/apparmor.d/opt.edge-node.bin.hd-agent +++ b/hardware-discovery-agent/config/apparmor.d/opt.edge-node.bin.hd-agent @@ -289,7 +289,7 @@ profile hda_sudo { /run/systemd/resolve/stub-resolv.conf r, /usr/bin/ipmitool rPx -> hda_ipmitool, /usr/bin/lshw rPx -> hda_lshw, - /usr/bin/rpc ix + /usr/bin/rpc ix, /usr/bin/sudo mr, /usr/libexec/sudo/libsudo_util.so.* mr, /usr/sbin/dmidecode rPx -> hda_dmidecode, From 2c6a03551d4a484ea07841309b19a16a0dcba938 Mon Sep 17 00:00:00 2001 From: Christopher Nolan Date: Wed, 28 Jan 2026 12:19:35 +0000 Subject: [PATCH 6/6] Update license headers --- hardware-discovery-agent/internal/comms/comms.go | 2 +- hardware-discovery-agent/internal/comms/comms_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hardware-discovery-agent/internal/comms/comms.go b/hardware-discovery-agent/internal/comms/comms.go index 51953c6e..74839844 100644 --- a/hardware-discovery-agent/internal/comms/comms.go +++ b/hardware-discovery-agent/internal/comms/comms.go @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: (C) 2025 Intel Corporation +// SPDX-FileCopyrightText: (C) 2026 Intel Corporation // SPDX-License-Identifier: Apache-2.0 package comms diff --git a/hardware-discovery-agent/internal/comms/comms_test.go b/hardware-discovery-agent/internal/comms/comms_test.go index dc1bc50b..2b10e3be 100644 --- a/hardware-discovery-agent/internal/comms/comms_test.go +++ b/hardware-discovery-agent/internal/comms/comms_test.go @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: (C) 2025 Intel Corporation +// SPDX-FileCopyrightText: (C) 2026 Intel Corporation // SPDX-License-Identifier: Apache-2.0 package comms_test