Skip to content

Issues/fix vpc network acl#14

Open
ditahkk wants to merge 4 commits into
mainfrom
issues/fix-vpc-network-acl
Open

Issues/fix vpc network acl#14
ditahkk wants to merge 4 commits into
mainfrom
issues/fix-vpc-network-acl

Conversation

@ditahkk

@ditahkk ditahkk commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features

    • VPC subnet (tier) creation with ACL attach/resolution and network-plan selection; new CLI commands for per-ACL rule CRUD and ACL-name→ID resolution
    • network get for detailed network info and plan network (plan tables now include SLUG)
  • Bug Fixes

    • Fixed request/response field mismatches, blank/decoded network fields, and create-response decoding; improved delete confirmation/polling and “already deleted” handling; expanded 403-not-found recognition
  • Documentation

    • Updated CLI docs, examples, roadmap, release notes, changelog, and smoke-suite guidance

ditahkk added 2 commits June 12, 2026 00:00
…ed replacements

- Added support for creating, updating, and deleting ACL rules with detailed request structures.
- Introduced methods for listing rules and resolving ACL names to IDs.
- Updated ReplaceNetworkACL to use ACL IDs instead of slugs for better accuracy.
- Enhanced ACL data structures to align with the live API response formats.

fix(apierrors): improve resource not found error handling

- Added regex matching for specific error messages indicating invalid resources.
- Updated IsResourceNotFound to handle new error cases and improve clarity.

feat(network): extend network functionality with VPC support

- Added VPC-related fields to Network struct and adjusted JSON unmarshalling for backward compatibility.
- Introduced GetDetail method to fetch detailed network information including CIDR and state.
- Updated CreateRequest to include VPC and billing cycle parameters.

feat(vpc): enhance VPC management with detailed state retrieval

- Implemented detailed VPC retrieval including metadata such as CIDR and network domain.
- Added error handling for not found cases to distinguish between transport errors and missing resources.
@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds v0.0.16 networking features: network detail and plan listing, VPC subnet (tier) creation with post-create ACL attachment, full ACL-list and per-rule CRUD with name→ID resolution, API model updates, CLI command expansions, tests, smoke-suite updates, and release/docs changes.

Changes

v0.0.16 VPC and ACL Workflow Implementation

Layer / File(s) Summary
Release docs and examples
CHANGELOG.md, README.md, RELEASE_NOTES.md, docs/api-inventory.md, docs/command-taxonomy.md, docs/configuration.md, docs/roadmap.md, tests/smoke/README.md, tests/smoke/lib.sh
Changelog, release notes, README, API inventory, command taxonomy, roadmap, and smoke docs updated to describe v0.0.16 networking, VPC tier creation, ACL rule management, plan SLUG usage, and platform limitations.
API models & error handling
pkg/api/apierrors/errors.go, pkg/api/apierrors/errors_test.go, pkg/api/acl/acl.go, pkg/api/network/network.go, pkg/api/plan/plan.go, pkg/api/vpc/vpc.go
API contracts updated: ACL and VPC models include id fields and rule types use snake_case; Network gains VPC/BillingCycle/Detail; Plan adds ServiceNetwork/NetworkType; apierrors recognizes route-model-binding 403 phrasing as not-found.
ACL service & tests
pkg/api/acl/acl.go, pkg/api/acl/acl_test.go
Service adds Delete/ListRules/CreateRule/UpdateRule/DeleteRule and Resolve; rule types refactored; tests verify request/response shapes, routes, and resolution behavior.
ACL CLI and validation tests
internal/commands/acl.go, internal/commands/commands_test.go
CLI adds acl delete, acl rules, acl create-rule, acl update-rule, acl delete-rule; acl replace accepts name or ID with optional --vpc resolution; list output schema and rule-flag validation added along with CLI tests.
Network get, create (VPC subnet) & tests
internal/commands/network.go, pkg/api/network/network.go, pkg/api/network/network_test.go
Adds zcp network get detail command; expands network create to support VPC subnets with required gateway/netmask/billing-cycle and optional --acl attachment; create responses enriched via GetDetail; tests validate request shapes and detail parsing.
VPC detail, create/delete polling & tests
internal/commands/vpc.go, pkg/api/vpc/vpc.go, pkg/api/vpc/vpc_test.go
VPC Service.Get prefers detail endpoint with fallback to list; create fetches full VPC when provider omits state; delete polls until not-found; CIDR canonicalization warning added; tests for detail and fallback added.
Plan command, helpers, auth, profile
internal/commands/plan.go, internal/commands/helpers.go, internal/commands/auth.go, internal/commands/profile.go
Adds plan network and SLUG column to plan outputs; ServiceNetwork and Plan.NetworkType added; looksLikeUUID helper added; auth validate message conditional on ZCP_BEARER_TOKEN; profile delete confirmation refined.
Egress rule parsing & create fallback
pkg/api/egress/egress.go
Flexible UnmarshalJSON for EgressRule to accept numeric-or-string fields and derive status; Create falls back to List when POST lacks an id.
Smoke tests and lifecycles
tests/smoke/cases.sh, tests/smoke/lib.sh
Smoke lifecycles updated to use --network-plan/--billing-cycle, validate via network get, switch ACL lifecycle to VPC-scoped rule CRUD, and adjust teardown and jq slug extraction.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • zsoftly/zcp-cli#10: Related ACL client import/wiring changes touching internal/commands/acl.go.
  • zsoftly/zcp-cli#3: Prior ACL refactor that relates to ACL-list creation and shapes.

Suggested reviewers

  • ClintonChe
  • godsonten
  • ditahm6

Poem

🐰 I hopped through CLI trees tonight,

tiers and ACLs now dancing bright,
Rules named, resolved, created with cheer,
v0.0.16 springs networks near — hop, deploy, and steer.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 47.12% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title "Issues/fix vpc network acl" is vague and generic, using non-descriptive language that doesn't clearly convey what specific changes or fixes are implemented in this comprehensive PR. Provide a more specific title that highlights the main change, such as "Add VPC subnet creation and ACL rule management" or "Implement network detail retrieval and ACL CRUD operations".
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issues/fix-vpc-network-acl

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
tests/smoke/cases.sh (1)

286-288: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

lc_ip still uses the removed category-based gate.

fx_network now provisions through det_network_plan, but lc_ip still skips unless det_network_category is set. That will drop IP lifecycle coverage in environments where plan-based network creation works and category discovery does not. Gate this on the plan-based fixture path instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/smoke/cases.sh` around lines 286 - 288, The lc_ip lifecycle test
currently gates on det_network_category so it is skipped when category discovery
is unavailable; update the gate to check the plan-based fixture path
(det_network_plan) instead so IP tests run when networks are provisioned via
fx_network/det_network_plan. Concretely, in the lc_ip block replace the
det_network_category check with a check that det_network_plan is non-empty (or
the existing fx_network/FX_IP fixture result), and ensure fx_ip is still invoked
to set FX_IP before calling _lc_result and the subsequent "ip in list" run_case
invocation.
pkg/api/network/network.go (1)

275-283: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Update() falls back through a lookup path that can drop VPC subnets.

When the PUT response comes back as data:null, this method calls s.Get(), and Get() still resolves via List(). In this file List() is the isolated-network path, so updating a VPC subnet can succeed remotely and still come back as network "<slug>" not found locally. Re-fetch the resource through /networks/{slug} for the fallback instead of going back through List().

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/api/network/network.go` around lines 275 - 283, The Update() fallback
currently calls s.Get(ctx, slug), which routes through List() and can miss VPC
subnets; change the fallback to re-fetch the single resource via the dedicated
network-by-slug endpoint rather than via List(). Replace the final return
s.Get(ctx, slug) with a call that performs an explicit GET /networks/{slug}
(implement or reuse a method like fetchNetworkBySlug or GetNetworkBySlug) so the
code unmarshals env.Data into Network and, on null, calls that direct-by-slug
fetch to return the accurate Network including VPC subnets.
🧹 Nitpick comments (1)
internal/commands/acl.go (1)

244-247: 💤 Low value

Port display for non-TCP/UDP protocols shows empty string.

When the protocol is icmp, all, or protocol_number, both StartPort and EndPort are typically empty strings. The ports variable will be empty, which displays as a blank cell. Consider displaying - or N/A for clarity.

💡 Suggested improvement
 			ports := ""
 			if r.StartPort != "" {
 				ports = r.StartPort + "-" + r.EndPort
+			} else {
+				ports = "-"
 			}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/commands/acl.go` around lines 244 - 247, The ports string logic
leaves a blank when StartPort/EndPort are empty (e.g., for
ICMP/all/protocol_number). Update the code that builds ports (using
variables/fields r.StartPort, r.EndPort, r.Protocol and the local ports
variable) to provide a fallback like "-" or "N/A" when both StartPort and
EndPort are empty or when r.Protocol is "icmp", "all", or "protocol_number";
otherwise keep the existing StartPort+"-"+EndPort formatting. Ensure you only
change the ports assignment logic so display cells are never empty.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/configuration.md`:
- Around line 105-112: Replace the insecure inline token insertion that uses
printf with a method that does not expose the token on the command line or shell
history; update the instructions around creating ~/.secrets/zcp.zsh and setting
ZCP_BEARER_TOKEN to tell users to either (a) open and edit ~/.secrets/zcp.zsh
with their editor and add the export line, or (b) use an interactive stdin
prompt to capture the token and write it to ~/.secrets/zcp.zsh so the token
never appears in shell history, ensuring the file remains chmod 600 and that
~/.zshrc sources ~/.secrets/zcp.zsh.

In `@internal/commands/auth.go`:
- Around line 68-70: The validation message printed in the auth flow incorrectly
shows 'overrides profile ""' when an env-only token is used; update the
fmt.Fprintf call inside the os.Getenv("ZCP_BEARER_TOKEN") branch (the block near
the check for ZCP_BEARER_TOKEN) to conditionally include "overrides profile %q"
only when profile.Name is non-empty and otherwise print a message that indicates
an environment-provided token is being validated (reference ResolveProfile and
the existing fmt.Fprintf usage to locate the code).

In `@pkg/api/acl/acl.go`:
- Around line 169-179: The Resolve function currently returns a.ID on name match
even if a.ID is empty; update Resolve(ctx, vpcSlug, nameOrID string) to only
consider a match successful when a.ID is non-empty (i.e., require a.ID != ""
before returning), and in addition accept the legacy slug field by treating
a.Slug (or similar legacy identifier) as an alias when present (check a.Slug ==
nameOrID and ensure a.ID is non-empty before returning a.ID); keep using
List(ctx, vpcSlug) to enumerate ACLs and return a clear error if no valid id is
found.

In `@README.md`:
- Around line 308-309: The docs show the "zcp network create" example without
the required --type flag; update all "network create" examples and the command
description to include the required --type (e.g., --type isolated or the L2
value your CLI expects) and mark it as required in the prose so the command
surface is accurate; specifically, modify the example line "zcp network create
--name my-net --network-plan inet-yow --billing-cycle hourly --cloud-provider
zcp --region yow-1 --project my-project" to include the required "--type
<value>" and add a short note in the command taxonomy/description stating that
--type is mandatory for the isolated/L2 network create flow.

In `@RELEASE_NOTES.md`:
- Around line 16-20: The fenced code blocks containing the zcp CLI examples
(e.g., the block starting with "zcp network create --name web-tier ..." and the
other example around lines later in the file) need a language tag to satisfy
markdownlint MD040; edit RELEASE_NOTES.md and change the opening triple-backtick
markers to include "bash" (```bash) for both fenced examples so they are
recognized as Bash code blocks.

---

Outside diff comments:
In `@pkg/api/network/network.go`:
- Around line 275-283: The Update() fallback currently calls s.Get(ctx, slug),
which routes through List() and can miss VPC subnets; change the fallback to
re-fetch the single resource via the dedicated network-by-slug endpoint rather
than via List(). Replace the final return s.Get(ctx, slug) with a call that
performs an explicit GET /networks/{slug} (implement or reuse a method like
fetchNetworkBySlug or GetNetworkBySlug) so the code unmarshals env.Data into
Network and, on null, calls that direct-by-slug fetch to return the accurate
Network including VPC subnets.

In `@tests/smoke/cases.sh`:
- Around line 286-288: The lc_ip lifecycle test currently gates on
det_network_category so it is skipped when category discovery is unavailable;
update the gate to check the plan-based fixture path (det_network_plan) instead
so IP tests run when networks are provisioned via fx_network/det_network_plan.
Concretely, in the lc_ip block replace the det_network_category check with a
check that det_network_plan is non-empty (or the existing fx_network/FX_IP
fixture result), and ensure fx_ip is still invoked to set FX_IP before calling
_lc_result and the subsequent "ip in list" run_case invocation.

---

Nitpick comments:
In `@internal/commands/acl.go`:
- Around line 244-247: The ports string logic leaves a blank when
StartPort/EndPort are empty (e.g., for ICMP/all/protocol_number). Update the
code that builds ports (using variables/fields r.StartPort, r.EndPort,
r.Protocol and the local ports variable) to provide a fallback like "-" or "N/A"
when both StartPort and EndPort are empty or when r.Protocol is "icmp", "all",
or "protocol_number"; otherwise keep the existing StartPort+"-"+EndPort
formatting. Ensure you only change the ports assignment logic so display cells
are never empty.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b4ca184e-8baf-487f-9973-52e22e267a34

📥 Commits

Reviewing files that changed from the base of the PR and between b250cc9 and 2113018.

📒 Files selected for processing (27)
  • CHANGELOG.md
  • README.md
  • RELEASE_NOTES.md
  • docs/api-inventory.md
  • docs/command-taxonomy.md
  • docs/configuration.md
  • docs/roadmap.md
  • internal/commands/acl.go
  • internal/commands/auth.go
  • internal/commands/commands_test.go
  • internal/commands/helpers.go
  • internal/commands/network.go
  • internal/commands/plan.go
  • internal/commands/profile.go
  • internal/commands/vpc.go
  • pkg/api/acl/acl.go
  • pkg/api/acl/acl_test.go
  • pkg/api/apierrors/errors.go
  • pkg/api/apierrors/errors_test.go
  • pkg/api/network/network.go
  • pkg/api/network/network_test.go
  • pkg/api/plan/plan.go
  • pkg/api/vpc/vpc.go
  • pkg/api/vpc/vpc_test.go
  • tests/smoke/README.md
  • tests/smoke/cases.sh
  • tests/smoke/lib.sh

Comment thread docs/configuration.md
Comment thread internal/commands/auth.go Outdated
Comment thread pkg/api/acl/acl.go
Comment thread README.md
Comment thread RELEASE_NOTES.md Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tests/smoke/cases.sh (1)

337-353: ⚠️ Potential issue | 🟡 Minor

Filter lc_acl’s VPC selection to the test region.
tests/smoke/cases.sh selects the first VPC via zcp vpc list -o json ... | head -1 with no det_region (or usable-state) filtering; since other smoke resources are region-scoped, this can pick a cross-region/otherwise-incompatible VPC and make ACL tests flaky. Select a VPC scoped to det_region and limited to usable states (e.g., Running/Stopped), or reuse an existing region-scoped VPC fixture if present.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/smoke/cases.sh` around lines 337 - 353, lc_acl currently picks the
first VPC unscoped, causing cross-region flakiness; update the VPC selection in
the lc_acl function to restrict results to the test region and usable states by
passing/adding the det_region filter and usable-state constraints to the zcp vpc
list invocation (e.g., use --region "$det_region" and/or a usable-state filter)
and then pipe to jq to only select entries where .region == env DET_REGION (or
.region == "$det_region") and .state is one of the usable values (e.g.,
"Running","Stopped") before taking head -1; ensure the variable name vpc and
subsequent calls (zcp acl create/update/delete-rule) remain unchanged so the
rest of lc_acl works with the filtered VPC.
🧹 Nitpick comments (1)
tests/smoke/cases.sh (1)

318-326: 💤 Low value

Consider the async creation workaround.

Line 324 introduces a 5-second sleep before the List fallback to account for asynchronous egress rule creation in CloudStack. While this pattern is common in integration tests, fixed sleep durations are inherently brittle—too short and the test becomes flaky; too long and the suite slows down unnecessarily.

♻️ More robust retry pattern

Replace the fixed sleep with a retry loop:

 s="$(jq -r '[.[]?|select(.field=="ID")|.value|select(.!="")][0] // empty' <<<"$out" 2>/dev/null)"
-# rule creation is async — give CloudStack a moment before the list fallback
-[[ -z "$s" ]] && { sleep 5; s="$(zcp egress list --network "$net" -o json 2>/dev/null | jq -r '.[0].id // empty')"; }
+if [[ -z "$s" ]]; then
+  # rule creation is async — retry with exponential backoff
+  for i in 1 2 4; do
+    sleep "$i"
+    s="$(zcp egress list --network "$net" -o json 2>/dev/null | jq -r '.[0].id // empty')"
+    [[ -n "$s" ]] && break
+  done
+fi
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/smoke/cases.sh` around lines 318 - 326, The current lc_egress function
uses a fixed sleep (sleep 5) before falling back to zcp egress list, which is
brittle; replace that single sleep+one-list attempt with a short retry loop that
repeatedly calls zcp egress list and parses the id into s (using the same jq
expression currently used: '.[0].id // empty') until a non-empty s or a max
timeout/attempt count is reached (e.g., 10 attempts with 1s sleep or exponential
backoff), breaking early when s is found and preserving the existing _lc_result
"egress rule" "$s" && defer egress "$s" "$net" behavior; implement the loop
inside lc_egress around the fallback logic so you no longer rely on the single
sleep.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/api/egress/egress.go`:
- Around line 128-138: In Create, don’t swallow errors from s.List and make the
fallback match deterministic: if resp.Data.ID is empty and you call s.List(ctx,
req.NetworkSlug), propagate and return the list error (don’t return &resp.Data,
nil on lerr); when scanning rules (rules[i]), include CIDR in the equality check
(e.g., match Protocol, StartPort, EndPort and, when req.CIDR is non-empty, match
CIDR as well) so you don’t return the wrong rule, and if no matching rule is
found return an explicit error instead of returning &resp.Data with empty ID.

---

Outside diff comments:
In `@tests/smoke/cases.sh`:
- Around line 337-353: lc_acl currently picks the first VPC unscoped, causing
cross-region flakiness; update the VPC selection in the lc_acl function to
restrict results to the test region and usable states by passing/adding the
det_region filter and usable-state constraints to the zcp vpc list invocation
(e.g., use --region "$det_region" and/or a usable-state filter) and then pipe to
jq to only select entries where .region == env DET_REGION (or .region ==
"$det_region") and .state is one of the usable values (e.g.,
"Running","Stopped") before taking head -1; ensure the variable name vpc and
subsequent calls (zcp acl create/update/delete-rule) remain unchanged so the
rest of lc_acl works with the filtered VPC.

---

Nitpick comments:
In `@tests/smoke/cases.sh`:
- Around line 318-326: The current lc_egress function uses a fixed sleep (sleep
5) before falling back to zcp egress list, which is brittle; replace that single
sleep+one-list attempt with a short retry loop that repeatedly calls zcp egress
list and parses the id into s (using the same jq expression currently used:
'.[0].id // empty') until a non-empty s or a max timeout/attempt count is
reached (e.g., 10 attempts with 1s sleep or exponential backoff), breaking early
when s is found and preserving the existing _lc_result "egress rule" "$s" &&
defer egress "$s" "$net" behavior; implement the loop inside lc_egress around
the fallback logic so you no longer rely on the single sleep.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: dc0ccbce-0338-4597-bddc-056d26d79100

📥 Commits

Reviewing files that changed from the base of the PR and between 2113018 and 8e481aa.

📒 Files selected for processing (11)
  • CHANGELOG.md
  • RELEASE_NOTES.md
  • docs/configuration.md
  • internal/commands/acl.go
  • internal/commands/auth.go
  • internal/commands/network.go
  • pkg/api/acl/acl.go
  • pkg/api/acl/acl_test.go
  • pkg/api/egress/egress.go
  • tests/smoke/cases.sh
  • tests/smoke/lib.sh
✅ Files skipped from review due to trivial changes (3)
  • CHANGELOG.md
  • docs/configuration.md
  • RELEASE_NOTES.md
🚧 Files skipped from review as they are similar to previous changes (4)
  • internal/commands/auth.go
  • pkg/api/acl/acl_test.go
  • internal/commands/acl.go
  • internal/commands/network.go

Comment thread pkg/api/egress/egress.go Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
pkg/api/egress/egress_test.go (1)

160-181: 📐 Maintainability & Code Quality | ⚡ Quick win

Add a regression test for the POST-success + LIST-failure fallback branch.

Current additions cover fallback match and no-match, but not the List failure path that previously regressed. A dedicated test here would lock in the new error-propagation behavior.

📌 Proposed test addition
 import (
 	"context"
 	"encoding/json"
 	"fmt"
 	"net/http"
 	"net/http/httptest"
+	"strings"
 	"testing"
 	"time"
@@
 func TestCreateFallbackNoMatchErrors(t *testing.T) {
@@
 }
+
+func TestCreateFallbackListFailureErrors(t *testing.T) {
+	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Set("Content-Type", "application/json")
+		if r.Method == http.MethodPost {
+			fmt.Fprint(w, `{"status":"Success","data":null}`)
+			return
+		}
+		w.WriteHeader(http.StatusInternalServerError)
+		fmt.Fprint(w, `{"status":"Error","message":"backend unavailable"}`)
+	}))
+	defer srv.Close()
+
+	svc := egress.NewService(newClient(srv.URL))
+	_, err := svc.Create(context.Background(), egress.CreateRequest{
+		NetworkSlug: "my-net", Protocol: "tcp", StartPort: "80", EndPort: "80", CIDR: "0.0.0.0/0",
+	})
+	if err == nil {
+		t.Fatal("Create() = nil error, want list failure error")
+	}
+	if !strings.Contains(err.Error(), "fetching it back failed") {
+		t.Fatalf("Create() error = %v, want wrapped list failure context", err)
+	}
+}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/api/egress/egress_test.go` around lines 160 - 181, Add a new unit test
that covers the POST-success + LIST-failure fallback branch: create a
TestCreateFallbackListErrors function modeled after
TestCreateFallbackNoMatchErrors where the httptest server returns
{"status":"Success","data":null} for the POST but returns an HTTP error or
non-success JSON for the subsequent LIST request; instantiate the service with
egress.NewService(newClient(srv.URL)) and call svc.Create(...), then assert that
the call returns a non-nil error (i.e., the List error is propagated) rather
than a silent success; reference TestCreateFallbackNoMatchErrors,
egress.NewService, newClient, and svc.Create when adding the test.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@pkg/api/egress/egress_test.go`:
- Around line 160-181: Add a new unit test that covers the POST-success +
LIST-failure fallback branch: create a TestCreateFallbackListErrors function
modeled after TestCreateFallbackNoMatchErrors where the httptest server returns
{"status":"Success","data":null} for the POST but returns an HTTP error or
non-success JSON for the subsequent LIST request; instantiate the service with
egress.NewService(newClient(srv.URL)) and call svc.Create(...), then assert that
the call returns a non-nil error (i.e., the List error is propagated) rather
than a silent success; reference TestCreateFallbackNoMatchErrors,
egress.NewService, newClient, and svc.Create when adding the test.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b7ab28c2-c996-4751-bf73-cd187d6ed7ce

📥 Commits

Reviewing files that changed from the base of the PR and between 8e481aa and 57c79f2.

📒 Files selected for processing (2)
  • pkg/api/egress/egress.go
  • pkg/api/egress/egress_test.go

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.

1 participant