Skip to content

refactor: accept expanded deviceInfo fields in v1 devices#1021

Open
ShradhaGupta31 wants to merge 1 commit into
mainfrom
device-discovery-apis
Open

refactor: accept expanded deviceInfo fields in v1 devices#1021
ShradhaGupta31 wants to merge 1 commit into
mainfrom
device-discovery-apis

Conversation

@ShradhaGupta31
Copy link
Copy Markdown
Contributor

@ShradhaGupta31 ShradhaGupta31 commented May 21, 2026

  • Update the v1 devices POST/GET flow to accomodate the full deviceInfo payload

Adresses - #1020

**Step 1: Authorize**
curl --insecure -X POST https://localhost:8181/api/v1/authorize -H "Content-Type:application/json" -d "{\"username\":\"standalone\", \"password\":\"G@ppm0ym\"}" --noproxy "*"
{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3Nzk0NjAzMDd9.EqIrLyN9duk56YscIs7Jhdk3ccH4462YG8YhWK01PmM"}


**Step 2: Execute Post API with dummy values**
$TOKEN='eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3Nzk0NjAzMDd9.EqIrLyN9duk56YscIs7Jhdk3ccH4462YG8YhWK01PmM'
curl --insecure -X POST "https://localhost:8181/api/v1/devices" \
  --noproxy "*" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{
    "guid": "143e4567-e89b-12d3-a456-426614174000",
    "hostname": "hostname",
    "friendlyName": "friendlyName",
    "tags": [],
    "mpsusername": "admin",
    "deviceInfo": {
      "fwVersion": "16.1.30",
      "fwBuild": "3400",
      "fwSku": "11",
      "currentMode": "Admin",
      "features": "SOL,IDER,KVM",
      "ipAddress": "10.0.0.12",
      "lastUpdated": "2026-05-21T00:00:00Z",
      "tlsMode": "TLS 1.2",
      "upid": {
        "oemPlatformIdType": "Not Set (0)",
        "oemId": "",
  }'} "lastDiscovered": "2026-05-14T10:23:00Z"65H",
{"connectionStatus":false,"mpsInstance":"","hostname":"hostname","guid":"143e4567-e89b-12d3-a456-426614174000","mpsusername":"admin","tags":[],"tenantId":"","friendlyName":"friendlyName","dnsSuffix":"","deviceInfo":{"fwVersion":"16.1.30","fwBuild":"3400","fwSku":"11","currentMode":"Admin","features":"SOL,IDER,KVM","ipAddress":"10.0.0.12","lastUpdated":"2026-05-21T00:00:00Z","tlsMode":"TLS 1.2","upid":{"csmeId":"4A45A39C5ED9462082510000","oemId":"","oemPlatformIdType":"Not Set (0)"},"amtEnabledInBIOS":true,"meInterfaceVersion":"16.1.25.2124","dhcpEnabled":true,"certHashes":["a1b2c3","d4e5f6"],"lmsInstalled":true,"lmsVersion":"2410.5.0.0","osName":"linux","osVersion":"6.8.0-51-generic","osDistro":"Ubuntu 24.04 LTS","cpuModel":"Intel(R) Core(TM) Ultra 7 165H","osIpAddress":"10.49.76.163","ethernetAdapterCount":2,"monitorConnected":true,"ieee8021xEnabled":false,"lastDiscovered":"2026-05-14T10:23:00Z"},"username":"","password":"","mpspassword":"","mebxpassword":"","useTLS":false,"allowSelfSigned":false,"certHash":""}

**Step 3: Verify using the same GUID as provided in POST api**
$ curl --insecure -s -X GET "https://localhost:8181/api/v1/devices/143e4567-e89b-12d3-a456-426614174000" \
  --noproxy "*" \
  -H "Authorization: Bearer $TOKEN" | jq '.deviceInfo'
{
  "fwVersion": "16.1.30",
  "fwBuild": "3400",
  "fwSku": "11",
  "currentMode": "Admin",
  "features": "SOL,IDER,KVM",
  "ipAddress": "10.0.0.12",
  "lastUpdated": "2026-05-21T00:00:00Z",
  "tlsMode": "TLS 1.2",
  "upid": {
    "csmeId": "4A45A39C5ED9462082510000",
    "oemId": "",
    "oemPlatformIdType": "Not Set (0)"
  },
  "amtEnabledInBIOS": true,
  "meInterfaceVersion": "16.1.25.2124",
  "dhcpEnabled": true,
  "certHashes": [
    "a1b2c3",
    "d4e5f6"
  ],
  "lmsInstalled": true,
  "lmsVersion": "2410.5.0.0",
  "osName": "linux",
  "osVersion": "6.8.0-51-generic",
  "osDistro": "Ubuntu 24.04 LTS",
  "cpuModel": "Intel(R) Core(TM) Ultra 7 165H",
  "osIpAddress": "10.49.76.163",
  "ethernetAdapterCount": 2,
  "monitorConnected": true,
  "ieee8021xEnabled": false,
  "lastDiscovered": "2026-05-14T10:23:00Z"
}

@ShradhaGupta31 ShradhaGupta31 requested a review from a team as a code owner May 21, 2026 14:43
@codecov
Copy link
Copy Markdown

codecov Bot commented May 21, 2026

Codecov Report

❌ Patch coverage is 79.22078% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 41.67%. Comparing base (51414d2) to head (f54a1fe).

Files with missing lines Patch % Lines
internal/entity/dto/v1/device.go 80.39% 5 Missing and 5 partials ⚠️
internal/usecase/devices/usecase.go 76.92% 3 Missing and 3 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1021      +/-   ##
==========================================
+ Coverage   41.46%   41.67%   +0.20%     
==========================================
  Files         134      135       +1     
  Lines       12332    12403      +71     
==========================================
+ Hits         5114     5169      +55     
- Misses       6672     6680       +8     
- Partials      546      554       +8     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

 - Update the v1 devices POST/GET flow to accomodate the full deviceInfo payload

Adresses - #1020

Signed-off-by: ShradhaGupta31 <shradha.gupta@intel.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the v1 /api/v1/devices DTO/usecase flow to accept and persist an expanded deviceInfo payload (including unknown/extra fields), supporting the Device Discovery requirements in #1020.

Changes:

  • Persist deviceInfo by JSON-marshalling dto.DeviceInfo into entity.Device.DeviceInfo (string) and unmarshalling it back on reads.
  • Expand dto.DeviceInfo with additional fields and custom JSON (un)marshal logic to round-trip unknown fields via ExtraFields.
  • Add/adjust unit tests and update the v1 devices Postman request example to include the expanded deviceInfo.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
internal/usecase/devices/usecase.go Marshals/unmarshals deviceInfo between DTO and entity; allows partial-update setter for deviceInfo.
internal/usecase/devices/repo_test.go Updates partial-update tests to include deviceInfo persistence/round-trip expectations.
internal/entity/dto/v1/device.go Expands DeviceInfo and adds custom JSON round-tripping for unknown fields (ExtraFields).
internal/entity/dto/v1/device_test.go Adds a JSON round-trip test for DeviceInfo, including ExtraFields.
internal/controller/httpapi/v1/devices_test.go Adds controller-level test ensuring POST accepts full deviceInfo payload.
integration-test/collections/console_mps_apis.postman_collection.json Updates Postman sample request body to include full deviceInfo.

Comment on lines +233 to +236
var info dto.DeviceInfo
if err := json.Unmarshal([]byte(raw), &info); err != nil {
return nil
}
Comment on lines 149 to 153
"lastconnected": func(dst, src *dto.Device) { dst.LastConnected = src.LastConnected },
"lastseen": func(dst, src *dto.Device) { dst.LastSeen = src.LastSeen },
"lastdisconnected": func(dst, src *dto.Device) { dst.LastDisconnected = src.LastDisconnected },
"deviceinfo": func(dst, src *dto.Device) { dst.DeviceInfo = src.DeviceInfo },
"username": func(dst, src *dto.Device) { dst.Username = src.Username },
Comment on lines +47 to +56
LastUpdated time.Time `json:"lastUpdated"`
TLSMode string `json:"tlsMode"`
UPID map[string]any `json:"upid,omitempty"`
AMTEnabledInBIOS *bool `json:"amtEnabledInBIOS,omitempty"`
MEInterfaceVersion string `json:"meInterfaceVersion"`
DHCPEnabled *bool `json:"dhcpEnabled,omitempty"`
CertHashes []string `json:"certHashes,omitempty"`
LMSInstalled *bool `json:"lmsInstalled,omitempty"`
LMSVersion string `json:"lmsVersion"`
OSName string `json:"osName"`
return err
}

delete(raw, "fwVersion")
Copy link
Copy Markdown
Member

@rsdmike rsdmike May 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Drop the catch-all entirely. Unknown fields aren't part of the contract — if a field isn't known, it doesn't belong on the wire.

That means this whole UnmarshalJSON (and the matching MarshalJSON below) can be deleted, along with the ExtraFields map. Default encoding/json behavior on the plain struct is exactly what's wanted: declared fields round-trip, undeclared fields are dropped.

Follow-ups in this PR:

  • Remove ExtraFields from the DeviceInfo struct.
  • Remove the custom UnmarshalJSON and MarshalJSON.
  • Drop TestDeviceInfoJSONRoundTrip's ExtraFields assertion.
  • Decide on certProvisioningMode and amtPhase in the Postman sample: either add them as proper typed fields on DeviceInfo, or remove them from the request body.

Net result is roughly -50 lines and removes a class of silent-drift bugs.

}

for key, value := range d.ExtraFields {
raw[key] = value
Copy link
Copy Markdown
Member

@rsdmike rsdmike May 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This concern goes away entirely if ExtraFields and the custom MarshalJSON are removed — see the top-level comment on the deletes. Leaving the thread for visibility only.

IPAddress string `json:"ipAddress"`
LastUpdated time.Time `json:"lastUpdated"`
TLSMode string `json:"tlsMode"`
UPID map[string]any `json:"upid,omitempty"`
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

map[string]any coerces numeric JSON values to float64 on Unmarshal. If any UPID subfield is ever sent as an integer (e.g. "oemPlatformIdType": 0), the re-marshaled value loses type fidelity, and any 64-bit identifier larger than 2^53 loses precision outright.

The Postman sample shows UPID has a knowable shape (oemPlatformIdType, oemId, csmeId) — a typed struct would be safer than map[string]any. If a typed struct isn't practical yet, map[string]json.RawMessage preserves the original bytes for round-trip without coercion.

type alias DeviceInfo

base := alias(d)
base.ExtraFields = nil
Copy link
Copy Markdown
Member

@rsdmike rsdmike May 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moot — the entire MarshalJSON (and UnmarshalJSON) should be deleted along with ExtraFields. See the top-level comment on the deletes.

GUID: "device-guid-123",
TenantID: "tenant-id-456",
Hostname: "new-hostname",
DeviceInfo: `{"fwVersion":"16.1.30","fwBuild":"","fwSku":"","currentMode":"","features":"","ipAddress":"10.0.0.55","lastUpdated":"0001-01-01T00:00:00Z","tlsMode":"","meInterfaceVersion":"","lmsInstalled":true,"lmsVersion":"","osName":"","osVersion":"","osDistro":"","cpuModel":"","osIpAddress":""}`,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pins the expected entity's DeviceInfo to a hand-written JSON string whose key order matches Go's declaration order of DeviceInfo fields. Any future reorder (e.g. grouping OS-related fields together for readability) silently breaks this test even though the behavior is unchanged.

require.JSONEq(t, expectedJSON, actualEntity.DeviceInfo) is order-insensitive, or assert on the unmarshaled DTO instead of the encoded blob.

@rsdmike
Copy link
Copy Markdown
Member

rsdmike commented May 21, 2026

OpenAPI spec is stale. doc/openapi.json only declares the original 7 deviceInfo fields; the 17 new fields added in this PR (tlsMode, upid, amtEnabledInBIOS, meInterfaceVersion, dhcpEnabled, certHashes, lmsInstalled, lmsVersion, osName, osVersion, osDistro, cpuModel, osIpAddress, ethernetAdapterCount, monitorConnected, ieee8021xEnabled, lastDiscovered) are not documented.

CLAUDE.md requires regenerating the spec in the same PR:

go run ./cmd/openapi-gen

Then commit the regenerated doc/openapi.json.

Copy link
Copy Markdown
Member

@rsdmike rsdmike left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great first attack at this, thanks for doing this! Please see my comments. Most important we def need to remove the complexity with the deletes. Thanks!

@sinchubhat
Copy link
Copy Markdown
Contributor

Hi, please take a look at #905 it contains the lmsinstalled part of deviceInfo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants