Skip to content

#22447: Pre-release QA - #22908

Merged
arthanson merged 2 commits into
featurefrom
22447-cleanup
Aug 12, 2026
Merged

#22447: Pre-release QA#22908
arthanson merged 2 commits into
featurefrom
22447-cleanup

Conversation

@jnovinger

Copy link
Copy Markdown
Member

Closes: #22447

Follow-up QA for the cooling infrastructure feature added in #22517.

Two small fixes found while QA'ing the feature:

Add the missing cooling_outflow GraphQL filter on CoolingIntake

CoolingIntakeFilter did not expose cooling_outflow / cooling_outflow_id, so an intake could not be filtered by its upstream outflow in GraphQL. The reverse direction (CoolingOutflowFilter.cooling_intake) and the REST filterset (cooling_outflow_id) already supported this; the GraphQL intake filter was the only side missing it.

Correct the CoolingIntake docstring

The docstring stated a CoolingIntake is supplied by an upstream CoolingOutflow or CoolingFeed. There is no direct feed relationship: the serving feed is derived from the device's rack, not stored on the intake.

Testing

Covered by the existing CoolingIntakeTestCase (API + auto-generated GraphQL filter tests), which passes with the new filter. Verified live via schema introspection that the two filter fields now appear on CoolingIntakeFilter.

Add the missing `cooling_outflow` GraphQL filter on CoolingIntake, so an
intake can be filtered by its upstream outflow. CoolingOutflow already
exposes the reverse `cooling_intake` filter and the REST filterset already
carries `cooling_outflow_id`; the GraphQL intake filter was the only side
missing it.

Correct the CoolingIntake docstring, which referenced a direct CoolingFeed
relationship that does not exist. The serving feed is derived from the
device's rack, not stored on the intake.
@jnovinger

Copy link
Copy Markdown
Member Author

@claude /review Only report on issues of potential concern; we don't need commentary on anything that doesn't require further consideration. Keep the review tight, we're not looking to expand scope, we're looking to identify and fix gaps in the original FR (#22447) as part of the pre-beta QA work.

@github-actions

github-actions Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Claude finished @jnovinger's task in 5m 31s —— View job


Review: #22447 Pre-release QA

  • Gather PR diff and context
  • Audit GraphQL filter parity for cooling models
  • Verify docstring correctness against model relationships
  • Sweep the rest of the cooling surface for the same class of gap
  • Post review findings

On the diff itself

Both changes are correct, no objections.

  • CoolingIntake.cooling_outflow is a real forward FK (device_components.py:717), so cooling_outflow_id: ID resolves to an actual column — no reverse-relation FieldError risk. The mutual recursion now created between CoolingOutflowFilterCoolingIntakeFilter is fine (same shape as InterfaceFilter.parent, filters.py:570).
  • The docstring is accurate and consistent with CoolingFeed's own docstring (cooling.py:106-107) — the feed→intake relationship really is derived via CoolingFeed.rack, not stored.

Gaps of the same class still open in the FR

These are all the mirror image of what this PR just fixed — one side of the intake/outflow relationship wired up, the other side missed. Flagging since this is the pre-beta pass.

1. UI filter form is missing cooling_intake_id on both outflow forms — the exact inverse of the GraphQL gap fixed here.

CoolingIntakeFilterForm exposes cooling_outflow_id (dcim/forms/filtersets.py:1863, :1895), but neither CoolingOutflowFilterForm (:1938-1966) nor CoolingOutflowTemplateFilterForm (:1969-1989) exposes cooling_intake_id — despite CoolingOutflowFilterSet.cooling_intake_id (filtersets.py:2220) and CoolingOutflowTemplateFilterSet.cooling_intake_id (filtersets.py:1112) both existing, and GraphQL supporting it. So the filter is reachable via REST/GraphQL but not from the list view's filter panel. Fix this →

2. cooling_outflow is not a default column on the intake tables, but cooling_intake is on the outflow tables.

dcim/tables/cooling.py: CoolingOutflowTable.default_columns (:207-209) and DeviceCoolingOutflowTable.default_columns (:301-303) both include cooling_intake, but CoolingIntakeTable.default_columns (:166-169) and DeviceCoolingIntakeTable.default_columns (:283-286) omit cooling_outflow — it's in fields but hidden by default. Arguably the upstream outflow is the more useful of the two to surface. Inconsistent defaults for the same relationship. Fix this →

3. The device-type YAML JSON schema knows nothing about cooling — this one is worth catching before beta, since the devicetype-library validates against it.

DeviceType.to_yaml() (dcim/models/devices.py:270) emits cooling_method unconditionally on every export, plus cooling-intakes / cooling-outflows blocks (:294-301), and DeviceTypeImportView.related_object_forms accepts both keys (dcim/views.py:1696-1697). But templates/extras/schema/devicetype_schema.jinja2 has zero cooling definitions, and CHOICES_MAP in dcim/management/commands/buildschema.py:15-30 omits CoolingMethodChoices, CoolingConnectorTypeChoices, DiameterUnitChoices, and FlowRateUnitChoices.

Note the release checklist's "regenerate contrib/generated_schema.json" step will not close this — the Jinja template is the source and needs the new definitions first. Compare airflow and subdevice-role, which are DeviceType-level enums that are exported. Fix this →

One thing to confirm rather than change

CoolingIntakeTemplate has no cooling_outflow counterpart to CoolingOutflowTemplate.cooling_intake, so an intake's upstream outflow can never be templated. This looks deliberate — CoolingOutflow.clean() enforces same-device for cooling_intake (device_components.py:775-780) while CoolingIntake.clean() intentionally has no such check, i.e. an intake's upstream outflow normally lives on a different device (a CDU), which a device-type template can't express. Worth a one-line note in the docstring you're already touching if you agree, since the asymmetry reads like an omission otherwise.

Nothing else found

Model, serializer, REST filterset, filter form, table fields, GraphQL type, and docs (docs/models/dcim/coolingintake.md) all cover cooling_outflow. Filterset tests cover cooling_outflow_id (test_filtersets.py:4923-4925) and cooling_intake_id (:5188-5190). No contrib/openapi.json impact — the REST filter already existed.

--- • branch 22447-cleanup

Address the same-class gaps surfaced in review, all mirror images of the
intake/outflow filter parity already fixed:

Add the `cooling_intake_id` filter to CoolingOutflowFilterForm and
CoolingOutflowTemplateFilterForm. The underlying filtersets already carried
`cooling_intake_id` and GraphQL supported it, but the list-view filter panel
did not expose it, so an outflow could not be filtered by its downstream
intake from the UI.

Add `cooling_outflow` to the default columns on CoolingIntakeTable and
DeviceCoolingIntakeTable. The outflow tables already default-show
`cooling_intake`; the intake tables hid the reverse, so the same relationship
displayed inconsistently between the two sides.

Note in the CoolingIntake docstring why CoolingIntakeTemplate has no
upstream-outflow field: an intake's outflow normally lives on a different
device (a CDU), which a device-type template cannot express.
@jnovinger

Copy link
Copy Markdown
Member Author

1. UI filter form is missing cooling_intake_id on both outflow forms

Fixed in af3c7cf. Added cooling_intake_id to CoolingOutflowFilterForm and CoolingOutflowTemplateFilterForm, mirroring the intake form.

2. cooling_outflow is not a default column on the intake tables

Fixed in af3c7cf. Added cooling_outflow to default_columns on CoolingIntakeTable and DeviceCoolingIntakeTable.

3. The device-type YAML JSON schema knows nothing about cooling

Real and worth catching before beta, but it's a larger change (schema template + buildschema.py CHOICES_MAP + regen) that touches the devicetype-library contract, so it's out of scope for this pass.

One thing to confirm rather than change (CoolingIntakeTemplate has no cooling_outflow counterpart)

Confirmed deliberate. Added a note to the CoolingIntake docstring in af3c7cf: an intake's upstream outflow normally lives on a different device (a CDU), which a device-type template can't express.

@jnovinger
jnovinger requested review from a team and arthanson and removed request for a team August 11, 2026 19:14
@arthanson
arthanson merged commit feffda9 into feature Aug 12, 2026
19 checks passed
@arthanson
arthanson deleted the 22447-cleanup branch August 12, 2026 16:57
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.

2 participants