)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"3fdb17da96dd68fe8514df9b494c501fc243abf8","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"bbbea051_10f0bb67","updated":"2026-09-03 09:45:14.000000000","message":"https://review.opendev.org/c/openstack/cyborg/+/1003630/3#message-e712ff2478822035ccf55055786e8243a909d192 works with whole nvme series while tested on top of https://review.opendev.org/c/openstack/cyborg/+/999945 nvme driver support","commit_id":"e3c298a45d4d328107ed7e7fbf545753fd61f459"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"56bc6f04ad2f1bbb6ef23fbca306869d3d8190b7","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"d668f756_5d28e35c","updated":"2026-09-03 08:29:23.000000000","message":"rebasing on https://review.opendev.org/c/openstack/cyborg/+/999945/30 to test nvme series","commit_id":"e3c298a45d4d328107ed7e7fbf545753fd61f459"}],"cyborg/tests/unit/api/controllers/v2/test_devices.py":[{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"bb32f7df70670f2d9589f8aa5fd6dbf02872b7de","unresolved":false,"context_lines":[{"line_number":39,"context_line":""},{"line_number":40,"context_line":"    def _validate_device(self, in_device, out_device):"},{"line_number":41,"context_line":"        for field in in_device.keys():"},{"line_number":42,"context_line":"            if field !\u003d \u0027id\u0027 and field in out_device:"},{"line_number":43,"context_line":"                self.assertEqual(in_device[field], out_device[field])"},{"line_number":44,"context_line":"        # Check that the link is properly set up"},{"line_number":45,"context_line":"        self._validate_links(out_device[\u0027links\u0027], in_device[\u0027uuid\u0027])"}],"source_content_type":"text/x-python","patch_set":1,"id":"44dd94ac_65cd29e8","line":42,"updated":"2026-09-03 07:12:25.000000000","message":"The added `and field in out_device` condition makes _validate_device silently skip any input field that does not appear in the serialized API response, instead of failing. The guard was needed because fake devices now carry `device_state`, which the v2 API Device wstype does not declare as a wsattr (like `id`, it is only setattr in Device.__init__ and wsme never serializes it). But the blanket skip applies to every field, not just the known non-exposed ones.\n\n**Severity**: WARNING | **Confidence**: 0.85\n\n**Impact**: A regression that omits any device field from the GET /devices responses would pass all of these controller tests silently, since the loop no longer asserts presence of expected fields. The tests lose their ability to detect response-schema regressions they previously caught (as a KeyError).\n\n**Suggestion**:\nSkip only the fields known not to be exposed by the API response, e.g. `if field in (\u0027id\u0027, \u0027device_state\u0027): continue`, or compare against an explicit list of API-exposed fields so that a missing expected field still fails the assertion.","commit_id":"dba9654fc47275e559a12c41cb0e1a81794d1335"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"7e3711ee77d62b92b45f1bda425b97f4b2a7add1","unresolved":false,"context_lines":[{"line_number":39,"context_line":""},{"line_number":40,"context_line":"    def _validate_device(self, in_device, out_device):"},{"line_number":41,"context_line":"        for field in in_device.keys():"},{"line_number":42,"context_line":"            if field !\u003d \u0027id\u0027 and field in out_device:"},{"line_number":43,"context_line":"                self.assertEqual(in_device[field], out_device[field])"},{"line_number":44,"context_line":"        # Check that the link is properly set up"},{"line_number":45,"context_line":"        self._validate_links(out_device[\u0027links\u0027], in_device[\u0027uuid\u0027])"}],"source_content_type":"text/x-python","patch_set":2,"id":"81abda2d_948d1e80","line":42,"updated":"2026-09-03 07:36:04.000000000","message":"Adding device_state to the fake device fixtures would make _validate_device fail with a KeyError because the v2 API Device wsme type does not declare device_state (only uuid, type, vendor, model, std_board_info, vendor_board_info, hostname, status, links are class-level wsattrs; wsme only serializes declared attributes). Instead of asserting or explicitly skipping device_state, the guard `field !\u003d \u0027id\u0027 and field in out_device` makes the helper silently skip EVERY field that is absent from the response, so the test can no longer detect a regression that drops any field (e.g. hostname or vendor) from GET /devices output.\n\n**Severity**: WARNING | **Confidence**: 0.85\n\n**Impact**: The devices API tests lose their only check that fixture fields actually reach the response body. A future regression that omits any device field from GET /devices or GET /devices/{uuid} output would pass these tests silently. It also hides that device_state, added to the Device object in version 1.5 of this same series, is not exposed to API consumers, so the discrepancy is undocumented.\n\n**Suggestion**:\nMake the skipped fields an explicit, commented decision instead of a blanket skip, e.g. keep `if field \u003d\u003d \u0027id\u0027: continue` and add `if field \u003d\u003d \u0027device_state\u0027: continue  # not yet exposed via the v2 API` (or use assertIn for fields expected to be absent). If exposing device_state to API users is intended in this series, declare it on the API Device wsme type behind a new microversion and assert its value instead.","commit_id":"5ff82f4a951db7137ee637a515106e28438c37e0"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"ef28e859b33bf1d8802826da5acae42d22a9e76d","unresolved":false,"context_lines":[{"line_number":44,"context_line":""},{"line_number":45,"context_line":"    def _validate_device(self, in_device, out_device):"},{"line_number":46,"context_line":"        for field in in_device.keys():"},{"line_number":47,"context_line":"            if field !\u003d \u0027id\u0027 and field in out_device:"},{"line_number":48,"context_line":"                self.assertEqual(in_device[field], out_device[field])"},{"line_number":49,"context_line":"        # Check that the link is properly set up"},{"line_number":50,"context_line":"        self._validate_links(out_device[\u0027links\u0027], in_device[\u0027uuid\u0027])"}],"source_content_type":"text/x-python","patch_set":3,"id":"5982e447_cf2b0ad1","line":47,"updated":"2026-09-03 08:39:57.000000000","message":"The added `field in out_device` guard makes _validate_device() skip the assertion for every field absent from the API response, not just the intended version-gated device_state. The guard exists because the fixture now includes device_state while these tests call get_json() with headers from gen_headers(), which set no OpenStack-API-Version header, so requests run at the base 2.0 microversion and convert_with_links() delattr\u0027s device_state (and status) from responses (cyborg/api/controllers/v2/devices.py:88-93).\n\n**Severity**: SUGGESTION | **Confidence**: 0.9\n\n**Impact**: A future regression that omits or mis-serializes any Device field in v2 API responses would not be caught by these controller tests, since missing keys are silently tolerated instead of failing the assertion.\n\n**Recommendation**:\nNarrow the tolerance to the version-gated fields, e.g. `if field \u003d\u003d \u0027id\u0027: continue; if field \u003d\u003d \u0027device_state\u0027 and \u0027device_state\u0027 not in out_device: continue` (optionally assert presence for all other fields), or better, have these tests send an \u0027OpenStack-API-Version: accelerator 2.4\u0027 header (as _v24_admin_headers() already does) so device_state is returned and its value is actually asserted.","commit_id":"e3c298a45d4d328107ed7e7fbf545753fd61f459"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"8b56701a152cf3f64612e0d403368a782e007e35","unresolved":false,"context_lines":[{"line_number":39,"context_line":""},{"line_number":40,"context_line":"    def _validate_device(self, in_device, out_device):"},{"line_number":41,"context_line":"        for field in in_device.keys():"},{"line_number":42,"context_line":"            if field !\u003d \u0027id\u0027 and field in out_device:"},{"line_number":43,"context_line":"                self.assertEqual(in_device[field], out_device[field])"},{"line_number":44,"context_line":"        # Check that the link is properly set up"},{"line_number":45,"context_line":"        self._validate_links(out_device[\u0027links\u0027], in_device[\u0027uuid\u0027])"}],"source_content_type":"text/x-python","patch_set":4,"id":"998f0f0a_f72a3a1d","line":42,"updated":"2026-09-03 09:57:08.000000000","message":"The added `field in out_device` membership guard makes _validate_device skip every in_device field that is absent from the API response body, instead of exempting only the fields known not to be exposed. These assertions are the only check that the v2 devices response still carries each expected field, so the tests now tolerate the API silently dropping any field.\n\n**Severity**: SUGGESTION | **Confidence**: 0.85\n\n**Impact**: A future regression that removes or renames a field on the Device API class (e.g. hostname or vendor disappearing from the response) will still pass test_devices.py, delaying detection until gate failures, tempest, or API consumers break.\n\n**Recommendation**:\nExempt only the known-unexposed fields explicitly, e.g. `for field in in_device.keys(): if field in (\u0027id\u0027, \u0027device_state\u0027): continue; self.assertEqual(in_device[field], out_device[field])`, or first assert `set(in_device) - {\u0027id\u0027, \u0027device_state\u0027} \u003c\u003d set(out_device)` so unexpected omissions still fail.","commit_id":"ec791647b178ce284e32ba6d02a5a560285a9d79"}]}
