Skip to content

ESD-1614-feat(mcr): add looking-glass ping and traceroute commands#508

Open
Phil-Browne wants to merge 6 commits into
mainfrom
esd-1614-mcr-ping-traceroute
Open

ESD-1614-feat(mcr): add looking-glass ping and traceroute commands#508
Phil-Browne wants to merge 6 commits into
mainfrom
esd-1614-mcr-ping-traceroute

Conversation

@Phil-Browne

Copy link
Copy Markdown
Contributor

Adds mcr looking-glass ping and mcr looking-glass traceroute commands, backed by a megaportgo bump to v1.15.0.

  • Runs ICMP ping or traceroute from an MCR's Looking Glass to a destination, polling until the operation completes.
  • Ping supports optional --source, --packet-count (1-60), and --packet-size (1-9186) flags; traceroute supports --source.
  • Diagnostics waits use a 5 minute timeout to match the SDK's own poll timeout instead of the default 90s.

Bump megaportgo to v1.15.0 and add mcr looking-glass ping/traceroute
subcommands for running ICMP ping and traceroute diagnostics from an MCR.
@codecov

codecov Bot commented Jul 8, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.86364% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 79.06%. Comparing base (f34dc88) to head (c44cad1).
⚠️ Report is 12 commits behind head on main.

Files with missing lines Patch % Lines
internal/commands/mcr/mcr_looking_glass_output.go 96.07% 1 Missing and 1 partial ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #508      +/-   ##
==========================================
+ Coverage   78.57%   79.06%   +0.48%     
==========================================
  Files         192      193       +1     
  Lines       18532    18750     +218     
==========================================
+ Hits        14562    14825     +263     
+ Misses       2904     2858      -46     
- Partials     1066     1067       +1     
Files with missing lines Coverage Δ
internal/commands/mcr/mcr.go 100.00% <100.00%> (ø)
internal/commands/mcr/mcr_looking_glass_actions.go 100.00% <100.00%> (ø)
internal/commands/mcr/mcr_looking_glass_utils.go 100.00% <100.00%> (ø)
internal/validation/helpers.go 100.00% <100.00%> (ø)
internal/commands/mcr/mcr_looking_glass_output.go 94.76% <96.07%> (+0.47%) ⬆️

... and 15 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds MCR Looking Glass diagnostic subcommands (ping and traceroute) to the CLI, wired through the existing cmdbuilder + action pattern and backed by a megaportgo SDK bump to support the new endpoints and polling behavior.

Changes:

  • Add mcr looking-glass ping and mcr looking-glass traceroute commands with destination/source and ping packet options.
  • Implement ping/traceroute actions with SDK-backed async polling and a 5-minute default timeout.
  • Add output shaping and tests (wrappers, action flows, and output conversion), plus generated docs updates.

Reviewed changes

Copilot reviewed 11 out of 12 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
internal/commands/mcr/mcr.go Registers new Looking Glass ping/traceroute cobra commands and flags/examples.
internal/commands/mcr/mcr_looking_glass_actions.go Implements ping/traceroute execution + polling with a 5-minute default timeout and flag validation.
internal/commands/mcr/mcr_looking_glass_output.go Adds output structs and printers for ping results and traceroute hops.
internal/commands/mcr/mcr_looking_glass_utils.go Adds wrapper vars for new SDK calls to simplify mocking in tests.
internal/commands/mcr/mcr_mock.go Extends the Looking Glass mock service to support ping/traceroute methods and results.
internal/commands/mcr/mcr_looking_glass_test.go Adds unit tests for wrappers, ping/traceroute actions, and output conversion helpers.
go.mod Bumps github.com/megaport/megaportgo to v1.15.0.
go.sum Updates sums for the megaportgo v1.15.0 bump.
docs/megaport-cli_mcr_looking-glass.md Links new ping and traceroute subcommand docs from Looking Glass index.
docs/megaport-cli_mcr_looking-glass_ping.md Adds generated documentation for mcr looking-glass ping.
docs/megaport-cli_mcr_looking-glass_traceroute.md Adds generated documentation for mcr looking-glass traceroute.
docs/index.md Regenerates docs index to include new commands and updated generation date.

Comment thread internal/commands/mcr/mcr_mock.go Outdated
Comment thread internal/commands/mcr/mcr_mock.go

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 11 out of 12 changed files in this pull request and generated no new comments.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 11 out of 12 changed files in this pull request and generated no new comments.

@penzeliz-megaport

Copy link
Copy Markdown
Collaborator

Small display bug worth fixing before merge: in ToTracerouteHopOutput (internal/commands/mcr/mcr_looking_glass_output.go:264-289), a timed-out probe with a non-nil struct but empty Host still gets formatted with its RTTMs:

host := probe.Host
if host == "" {
    host = "*"
}
probeStrs[i] = fmt.Sprintf("%s (%.3fms)", host, probe.RTTMs)

This renders as "* (0.000ms)", which reads as "responded in 0ms" rather than "no response" — a nil probe correctly renders as a bare "*" with no timing, so this is inconsistent with that case too. The new test TestToTracerouteHopOutput_TimeoutProbe currently asserts "* (0.000ms)" as the expected value, so it's locking in the wrong output rather than catching it.

Suggested fix — treat empty Host the same way as a nil probe (bare "*", no RTT):

host := probe.Host
if host == "" {
    probeStrs[i] = "*"
    continue
}
probeStrs[i] = fmt.Sprintf("%s (%.3fms)", host, probe.RTTMs)

(and update the test's expected value accordingly). Everything else here looked good — context/timeout handling, nil-guarding, and the SDK-only call path (no local shell-out, so no injection surface on --destination/--source).

@Phil-Browne

Copy link
Copy Markdown
Contributor Author

Fixed in ea807b6. An empty Host now renders as a bare * with no timing, matching the nil-probe case, and TestToTracerouteHopOutput_TimeoutProbe asserts * instead of the old * (0.000ms).

…ceroute

# Conflicts:
#	internal/commands/mcr/mcr_mock.go
@penzeliz-megaport

penzeliz-megaport commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

Three findings; the first is worth fixing before merge, the other two are low priority.

1. Error wraps use %v, not %w (mcr_looking_glass_actions.go:250,259,298,307). fmt.Errorf("error starting ping: %v", err) drops the *megaport.ErrorResponse from the chain, so classifyError can't match it: a 401/403 exits General (1) instead of Authentication (3) / API (4). These four commands also won't print MEGAPORT_SESSION_EXPIRED once #490 merges, since its detector needs errors.As to find a *megaport.ErrorResponse. Every other action file (mcr/vxc/ports) returns raw err or wraps with %w. Return the raw error or use %w.

2. Target addresses aren't format-validated (mcr_looking_glass_actions.go:205-215, 270-280). --destination is only checked for empty and --source isn't checked at all; both go straight into DestinationAddress/SourceAddress. It's an HTTP JSON body, so not shell injection, but a client-side IP/hostname check gives a clearer error than a backend rejection and matches the other commands.

3. One nil hop discards the whole traceroute (mcr_looking_glass_output.go:382-385). In printTracerouteResult, a nil element makes ToTracerouteHopOutput return an error that aborts the loop, dropping every valid hop already collected. Nil/blank probes already render as *; a nil hop could do the same. Unlikely the SDK emits nil hops, so low severity.

Wrap ping/traceroute start and wait errors with %w so classifyError can
match megaport.ErrorResponse for correct exit codes. Validate
--destination and --source as IPv4/IPv6 addresses before calling the
API (matches the OpenAPI spec, which requires IP addresses, not
hostnames). Render a nil traceroute hop as a bare "*" instead of
aborting the whole result.
@Phil-Browne

Copy link
Copy Markdown
Contributor Author

Fixed all three in c44cad1:

  1. All four call sites now wrap with %w instead of %v, so errors.As can find the underlying *megaport.ErrorResponse for exit-code classification.
  2. Added validation.ValidateIPAddress (checked the OpenAPI spec: destination_address/source_address are IPv4 or IPv6 only, not hostnames) and wired it into both --destination (required) and --source (when provided) for ping and traceroute.
  3. printTracerouteResult now renders a nil hop as a bare * instead of erroring out and dropping the rest of the hops.

Added test coverage for the address validation, the %w unwrap behavior, and the nil-hop case.

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.

3 participants