Skip to content

feat(service-catalog): split printer-device access and LAN discovery lane (closes #67)#201

Open
clubanderson wants to merge 2 commits into
projectbluefin:mainfrom
clubanderson:feat/service-catalog/print-device-discovery-lane
Open

feat(service-catalog): split printer-device access and LAN discovery lane (closes #67)#201
clubanderson wants to merge 2 commits into
projectbluefin:mainfrom
clubanderson:feat/service-catalog/print-device-discovery-lane

Conversation

@clubanderson

Copy link
Copy Markdown
Contributor

Summary

Defines the printer-device access and LAN mDNS discovery validation lane as a standalone split from the base print-service lane (#64). Closes #67.

Dependency chain (made explicit by this PR)

#54 substrate (USB device passthrough + LAN network policy on ghost)
    → #67 this lane (USB access + mDNS discovery contract proven)
    → #64 base print lane (already unblocked; this lane extends it)

Acceptance criteria check

What's in this PR

tests/service_catalog/print_device/test_print_device_discovery.py

Two independent test classes with separate skip gates:

TestPrinterDeviceAccessLane (gate: TEST_USB_PRINTER_DEVICE env var)

Test What it proves
test_usb_device_node_exists_in_container hostPath device node visible in CUPS container
test_usb_device_node_is_character_device node is a real character device, not a placeholder
test_cups_can_detect_local_usb_printer CUPS lpinfo -v reports USB URI
test_cups_accepts_test_print_job lp submits job without error (cancelled immediately)
test_usb_device_permissions_allow_cups_user CUPS user can r/w device node
test_kubevirt_usb_passthrough_is_out_of_scope pytest.skip#54

TestLanDiscoveryLane (gate: TEST_AVAHI_ENABLED=true)

Test What it proves
test_ipp_service_exposed_outside_cluster service type is NodePort or LoadBalancer
test_nodeport_is_reachable_on_node_ip NodePort reachable from inside cluster using host IP
test_avahi_sidecar_container_is_running avahi sidecar container is Ready
test_avahi_daemon_process_is_active avahi-daemon process is alive inside sidecar
test_avahi_daemon_advertises_ipp_service avahi-browse _ipp._tcp finds the record
test_avahi_service_file_is_present_in_config .service file present in /etc/avahi/services/
test_auth_gated_cups_ui_is_out_of_scope pytest.skip → deferred
test_split_horizon_dns_for_cups_is_out_of_scope pytest.skip → bluespeed

Both classes skip cleanly when their gate condition is not met — non-hardware CI is not broken.

argo/workflow-templates/homelab-print-device.yaml

WorkflowTemplate with parameterized hardware paths:

  • usb-device-path: if set, adds hostPath volume + enables USB tests
  • avahi-enabled: true: adds avahi sidecar + NodePort service + enables mDNS tests
  • check-prerequisites guard step emits informative epic: homelab cluster substrate and fleet-client model #54 instructions without failing the workflow
  • Fixture uses lscr.io/linuxserver/cups:latest (real CUPS, not nginx stub — USB tests need lpinfo/lp)
  • Avahi sidecar: ubuntu:22.04 + avahi-daemon + ConfigMap-mounted _ipp._tcp service file

docs/homelab-contracts.md

Dependencies

…lane (closes projectbluefin#67)

Defines the printer-device access and LAN mDNS discovery validation lane as
a standalone split from the base print-service lane (projectbluefin#64).  Makes the
substrate dependencies (projectbluefin#54) explicit and keeps them out of the base lane.

## Dependency chain

  projectbluefin#54 substrate (USB device passthrough + LAN network policy on ghost)
      → projectbluefin#67 this lane (USB access + mDNS discovery contract proven)
      → projectbluefin#64 base print lane (already unblocked; this lane extends it)

## New files

### tests/service_catalog/print_device/test_print_device_discovery.py
Two test classes with independent skip gates:

TestPrinterDeviceAccessLane (gate: TEST_USB_PRINTER_DEVICE env var)
- test_usb_device_node_exists_in_container
- test_usb_device_node_is_character_device
- test_cups_can_detect_local_usb_printer (lpinfo -v)
- test_cups_accepts_test_print_job (lp + cancel)
- test_usb_device_permissions_allow_cups_user
- test_kubevirt_usb_passthrough_is_out_of_scope → pytest.skip → projectbluefin#54

TestLanDiscoveryLane (gate: TEST_AVAHI_ENABLED=true)
- test_ipp_service_exposed_outside_cluster (NodePort/LB)
- test_nodeport_is_reachable_on_node_ip
- test_avahi_sidecar_container_is_running
- test_avahi_daemon_process_is_active
- test_avahi_daemon_advertises_ipp_service (avahi-browse _ipp._tcp)
- test_avahi_service_file_is_present_in_config
- test_auth_gated_cups_ui_is_out_of_scope → pytest.skip → deferred
- test_split_horizon_dns_for_cups_is_out_of_scope → pytest.skip → bluespeed

Both classes skip cleanly when their gate condition is not met so non-hardware
CI is not broken.

### argo/workflow-templates/homelab-print-device.yaml
WorkflowTemplate with three parameters controlling hardware paths:
- usb-device-path: set to /dev/usb/lp0 to enable USB tests (hostPath volume)
- avahi-enabled: set to 'true' to enable mDNS tests (NodePort svc + avahi sidecar)
- ipp-nodeport: default 30631

check-prerequisites guard step emits informative messages about projectbluefin#54 requirements
but does not fail — tests self-skip when conditions are absent.

Fixture uses lscr.io/linuxserver/cups:latest (real CUPS image, not nginx stub)
because USB tests require actual CUPS commands (lpinfo, lp, lpstat).

Avahi sidecar uses ubuntu:22.04 + avahi-daemon + ConfigMap service definition
for the _ipp._tcp record.

### argo/homelab-print-device.yaml
Workflow submit trigger.

## Updated files

### docs/homelab-contracts.md
- §6 known-blockers: projectbluefin#67 → ✅ defined
- §7 Printer-Device Access and LAN Discovery Lane added:
  boundary table (base vs this lane), substrate assumptions tables,
  behavior tables for both test classes, WorkflowTemplate parameters table

Closes projectbluefin#67
Child of projectbluefin#51
Depends on projectbluefin#54 (substrate), projectbluefin#64 (base print lane)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

@hanthor hanthor left a comment

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.

LGTM — well-structured test/infra addition, clean code.

@hanthor hanthor left a comment

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.

Service-catalog lane addition. Merge after foundational #202. LGTM.

@hanthor hanthor left a comment

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.

Approved via org-wide review.

@hanthor hanthor left a comment

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.

Approved via org-wide review.

hanthor
hanthor previously approved these changes Jul 1, 2026

@hanthor hanthor left a comment

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.

Review: Approved ✅

Part of the structured service-catalog project build-up. Conventional Commits format, referenced issues, consistent with related PRs in the series.

@castrojo castrojo added needs-triage Auto-applied when required labels missing — human must fix queue/agent-ready Has a spec, ready to claim — comment /claim. and removed needs-triage Auto-applied when required labels missing — human must fix labels Jul 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent/blocked queue/agent-ready Has a spec, ready to claim — comment /claim.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: split printer-device access and LAN discovery from the base non-media lane

4 participants