Skip to content

NO-JIRA: Implement -external-certificate flag to edge and re-encrypt route#2256

Open
lunarwhite wants to merge 1 commit intoopenshift:mainfrom
lunarwhite:ext-cert-route-flag
Open

NO-JIRA: Implement -external-certificate flag to edge and re-encrypt route#2256
lunarwhite wants to merge 1 commit intoopenshift:mainfrom
lunarwhite:ext-cert-route-flag

Conversation

@lunarwhite
Copy link
Copy Markdown

@lunarwhite lunarwhite commented Apr 16, 2026

Closes #2254

Summary

Adds support for referencing TLS certificates from a TLS Secret when creating edge and reencrypt routes. The new --external-certificate flag accepts a Secret name and populates route.Spec.TLS.ExternalCertificate as a LocalObjectReference.

This flag is mutually exclusive with --cert and --key, since inline certificates and secret-backed certificates are alternative sources. The --ca-cert flag (and --dest-ca-cert for reencrypt routes) remains compatible with --external-certificate.

E2E Verification

./oc version
Client Version: unknown # local built
Kustomize Version: v5.7.1
Server Version: 4.21.8
Kubernetes Version: v1.34.5
edge route with --external-certificate
./oc create route edge test-edge-extcert \
  --service=nginx \
  --hostname=test-edge-extcert-e2e-extcert-test.apps-crc.testing \
  --external-certificate=my-secret \
  --port 8080 \
  --dry-run=client \
  -o yaml
apiVersion: route.openshift.io/v1
kind: Route
metadata:
  name: test-reencrypt-extcert-destca
spec:
  host: test-edge-extcert-e2e-extcert-test.apps-crc.testing
  port:
    targetPort: 8080
  tls:
    externalCertificate:
      name: my-secret
    termination: edge
  to:
    kind: ""
    name: nginx
    weight: null
status: {}

./oc get route test-edge-extcert
NAME                HOST/PORT                                             PATH   SERVICES   PORT   TERMINATION   WILDCARD
test-edge-extcert   test-edge-extcert-e2e-extcert-test.apps-crc.testing          nginx      8080   edge          None

./oc get route test-edge-extcert -o=jsonpath={.status} | jq 
{
  "ingress": [
    {
      "conditions": [
        {
          "lastTransitionTime": "2026-04-15T09:25:13Z",
          "status": "True",
          "type": "Admitted"
        }
      ],
      "host": "test-edge-extcert-e2e-extcert-test.apps-crc.testing",
      "routerCanonicalHostname": "router-default.apps-crc.testing",
      "routerName": "default",
      "wildcardPolicy": "None"
    }
  ]
}
edge route with --external-certificate + --ca-cert
./oc create route reencrypt test-reencrypt-extcert-destca \
  --service=nginx \
  --hostname=test-reencrypt-extcert-destca-e2e-extcert-test.apps-crc.testing \
  --dest-ca-cert=./dest-ca.crt \
  --external-certificate=my-secret \
  --port 8080 \
  --dry-run=client \
  -o yaml
apiVersion: route.openshift.io/v1
kind: Route
metadata:
  name: test-reencrypt-extcert-destca
spec:
  host: test-reencrypt-extcert-destca-e2e-extcert-test.apps-crc.testing
  port:
    targetPort: 8080
  tls:
    destinationCACertificate: |
      <redacted>
      -----END CERTIFICATE-----
    externalCertificate:
      name: my-secret
    termination: reencrypt
  to:
    kind: ""
    name: nginx
    weight: null
status: {}

./oc get route test-reencrypt-extcert-destca
NAME                            HOST/PORT                                                         PATH   SERVICES   PORT   TERMINATION   WILDCARD
test-reencrypt-extcert-destca   test-reencrypt-extcert-destca-e2e-extcert-test.apps-crc.testing          nginx      8080   reencrypt     None

./oc get route test-reencrypt-extcert-destca -o=jsonpath={.status} | jq
{
  "ingress": [
    {
      "conditions": [
        {
          "lastTransitionTime": "2026-04-15T09:26:27Z",
          "status": "True",
          "type": "Admitted"
        }
      ],
      "host": "test-reencrypt-extcert-destca-e2e-extcert-test.apps-crc.testing",
      "routerCanonicalHostname": "router-default.apps-crc.testing",
      "routerName": "default",
      "wildcardPolicy": "None"
    }
  ]
}
reencrypt route with --external-certificate + --dest-ca-cert
./oc create route edge test-edge-extcert-cacert \
  --service=nginx \
  --hostname=test-edge-extcert-cacert-e2e-extcert-test.apps-crc.testing \
  --ca-cert=./ca.crt \
  --external-certificate=my-secret \
  --port 8080 \
  --dry-run=client \
  -o yaml
apiVersion: route.openshift.io/v1
kind: Route
metadata:
  name: test-edge-extcert-cacert
spec:
  host: test-edge-extcert-cacert-e2e-extcert-test.apps-crc.testing
  port:
    targetPort: 8080
  tls:
    caCertificate: |
      -----BEGIN CERTIFICATE-----
      <redacted>
      -----END CERTIFICATE-----
    externalCertificate:
      name: my-secret
    termination: edge
  to:
    kind: ""
    name: nginx
    weight: null
status: {}

./oc get route test-edge-extcert-cacert
NAME                       HOST/PORT                                                    PATH   SERVICES   PORT   TERMINATION   WILDCARD
test-edge-extcert-cacert   test-edge-extcert-cacert-e2e-extcert-test.apps-crc.testing          nginx      8080   edge          None

./oc get route test-edge-extcert-cacert -o=jsonpath={.status} | jq
{
  "ingress": [
    {
      "conditions": [
        {
          "lastTransitionTime": "2026-04-15T09:26:18Z",
          "status": "True",
          "type": "Admitted"
        }
      ],
      "host": "test-edge-extcert-cacert-e2e-extcert-test.apps-crc.testing",
      "routerCanonicalHostname": "router-default.apps-crc.testing",
      "routerName": "default",
      "wildcardPolicy": "None"
    }
  ]
}
edge route w/o --external-certificate
./oc create route edge test-edge-no-extcert \
  --service=nginx \
  --hostname=test-edge-no-extcert-e2e-extcert-test.apps-crc.testing \
  --port=8080 \
  --dry-run=client \
  -o yaml
apiVersion: route.openshift.io/v1
kind: Route
metadata:
  name: test-edge-no-extcert
spec:
  host: test-edge-no-extcert-e2e-extcert-test.apps-crc.testing
  port:
    targetPort: 8080
  tls:
    termination: edge
  to:
    kind: ""
    name: nginx
    weight: null
status: {}

./oc get route test-edge-no-extcert
NAME                   HOST/PORT                                                PATH   SERVICES   PORT   TERMINATION   WILDCARD
test-edge-no-extcert   test-edge-no-extcert-e2e-extcert-test.apps-crc.testing          nginx      8080   edge          None

./oc get route test-edge-no-extcert -o=jsonpath={.status} | jq
{
  "ingress": [
    {
      "conditions": [
        {
          "lastTransitionTime": "2026-04-15T09:27:00Z",
          "status": "True",
          "type": "Admitted"
        }
      ],
      "host": "test-edge-no-extcert-e2e-extcert-test.apps-crc.testing",
      "routerCanonicalHostname": "router-default.apps-crc.testing",
      "routerName": "default",
      "wildcardPolicy": "None"
    }
  ]
}
[negative] edge route with --cert + --external-certificate
./oc create route edge test-neg --service=nginx --port=8080 --cert=./tls.crt --external-certificate=my-secret
error: --cert and --external-certificate are mutually exclusive
[negative] reencrypt route with --key + --external-certificate
./oc create route reencrypt test-neg --service=nginx --port=8080 --key=./tls.key --external-certificate=my-secret
error: --key and --external-certificate are mutually exclusive

Summary by CodeRabbit

  • New Features

    • Added --external-certificate for edge and reencrypt routes to reference TLS via a Kubernetes secret instead of inline cert/key.
  • Behavior Changes

    • Commands now validate inputs and reject using inline cert/key together with an external certificate to prevent conflicts; validation runs before execution and TLS wiring respects the chosen source.
  • Documentation

    • Help/examples updated to show external-certificate usage.
  • Tests

    • Added tests for mutual-exclusion validation and external-certificate wiring for both route types.

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Apr 16, 2026
@openshift-ci-robot
Copy link
Copy Markdown

@lunarwhite: This pull request explicitly references no jira issue.

Details

In response to this:

Closes #2254

Summary

Adds support for referencing TLS certificates from a TLS Secret when creating edge and reencrypt routes. The new --external-certificate flag accepts a Secret name and populates route.Spec.TLS.ExternalCertificate as a LocalObjectReference.

This flag is mutually exclusive with --cert and --key, since inline certificates and secret-backed certificates are alternative sources. The --ca-cert flag (and --dest-ca-cert for reencrypt routes) remains compatible with --external-certificate.

E2E Verification

./oc version
Client Version: unknown # local built
Kustomize Version: v5.7.1
Server Version: 4.21.8
Kubernetes Version: v1.34.5
edge route with --external-certificate

edge route with --external-certificate + --ca-cert

reencrypt route with --external-certificate + --dest-ca-cert

edge route w/o --external-certificate

[negative] edge route with --cert + --external-certificate

[negative] reencrypt route with --key + --external-certificate

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci openshift-ci Bot requested review from ardaguclu and atiratree April 16, 2026 11:24
@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented Apr 16, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: lunarwhite
Once this PR has been reviewed and has the lgtm label, please assign ardaguclu for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 16, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: ee7a133c-5cf9-41f4-9443-ce9d11aef3bf

📥 Commits

Reviewing files that changed from the base of the PR and between d821dc3 and 34b1b7d.

📒 Files selected for processing (4)
  • pkg/cli/create/routeedge.go
  • pkg/cli/create/routeedge_test.go
  • pkg/cli/create/routereenecrypt.go
  • pkg/cli/create/routereenecrypt_test.go
✅ Files skipped from review due to trivial changes (1)
  • pkg/cli/create/routeedge_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • pkg/cli/create/routereenecrypt.go
  • pkg/cli/create/routereenecrypt_test.go

Walkthrough

Adds a new --external-certificate flag to oc create route edge and oc create route reencrypt, new ExternalCertificate fields and Validate() methods enforcing mutual exclusivity with --cert/--key, and wires spec.tls.externalCertificate when provided. Unit tests validate behavior and wiring.

Changes

Cohort / File(s) Summary
Edge Route Implementation
pkg/cli/create/routeedge.go
Added ExternalCertificate field and --external-certificate flag; new Validate() invoked before Run() to enforce mutual exclusivity with --cert/--key; Run() conditionally sets route.Spec.TLS.ExternalCertificate vs. embedding cert/key.
Edge Route Tests
pkg/cli/create/routeedge_test.go
New unit tests validating mutual-exclusivity rules and that a created edge Route uses Spec.TLS.ExternalCertificate (and leaves inline Certificate/Key empty).
Reencrypt Route Implementation
pkg/cli/create/routereenecrypt.go
Added ExternalCertificate field and --external-certificate flag; new Validate() called before Run() to enforce mutual exclusivity; Run() conditionally assigns Spec.TLS.ExternalCertificate or loads inline cert/key; examples updated.
Reencrypt Route Tests
pkg/cli/create/routereenecrypt_test.go
New unit tests validating mutual-exclusivity rules and that a created reencrypt Route sets Spec.TLS.ExternalCertificate with termination: reencrypt while inline Certificate/Key remain unset.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 10 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.18% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Test Structure And Quality ❓ Inconclusive Custom check instructions specify Ginkgo BDD test patterns, but added tests use standard Go testing with table-driven subtests. Clarify whether custom check applies only to Ginkgo tests or all unit tests, and provide adapted assessment criteria for standard Go tests.
✅ Passed checks (10 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: implementing a --external-certificate flag for edge and re-encrypt routes, which matches the primary objective of the PR.
Linked Issues check ✅ Passed The PR fully implements the coding requirements from issue #2254: adds --external-certificate flag to edge and reencrypt routes, enforces mutual exclusivity with --cert/--key, allows compatibility with CA flags, and sets route.spec.tls.externalCertificate as a LocalObjectReference.
Out of Scope Changes check ✅ Passed All changes are within scope: additions to edge and reencrypt route creation commands, validation logic, and comprehensive unit tests. No passthrough routes are modified, and CA-flag compatibility is preserved.
Stable And Deterministic Test Names ✅ Passed Test names (TestCreateEdgeRoute_MutualExclusivity, TestCreateEdgeRoute_ExternalCertificateWiring, TestCreateReencryptRoute_MutualExclusivity, TestCreateReencryptRoute_ExternalCertificateWiring) are static, descriptive, and follow Go conventions without dynamic elements.
Microshift Test Compatibility ✅ Passed The added test files are standard Go unit tests, not Ginkgo e2e tests, so the custom check targeting Ginkgo patterns is not applicable.
Single Node Openshift (Sno) Test Compatibility ✅ Passed The test files are standard Go unit tests using the testing package with fake Kubernetes clients, not Ginkgo e2e tests, so SNO compatibility check is not applicable.
Topology-Aware Scheduling Compatibility ✅ Passed PR modifies only CLI command code without deployment manifests, operator code, or controllers, so topology-aware scheduling check is not applicable.
Ote Binary Stdout Contract ✅ Passed The OTE Binary Stdout Contract is not violated by this pull request. The modified CLI command implementations have no process-level stdout writes, only explicit IOStreams output writes.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed Tests are standard Go unit tests using mock Kubernetes clients with no hardcoded IPs or external connectivity requirements, compatible with IPv6 and disconnected networks.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@openshift-ci openshift-ci Bot added the needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. label Apr 16, 2026
@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented Apr 16, 2026

Hi @lunarwhite. Thanks for your PR.

I'm waiting for a openshift member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work.

Tip

We noticed you've done this a few times! Consider joining the org to skip this step and gain /lgtm and other bot rights. We recommend asking approvers on your previous PRs to sponsor you.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
pkg/cli/create/routeedge.go (1)

100-106: Extract shared TLS external-certificate validation/wiring logic.

The mutual-exclusivity checks and ExternalCertificate assignment here are duplicated with pkg/cli/create/routereenecrypt.go, which risks behavioral drift over time. Consider moving this into shared helpers used by both commands.

Refactor sketch
+// pkg/cli/create/route_tls_helpers.go
+func validateExternalCertMutualExclusion(certPath, keyPath, externalName string) error {
+	if len(externalName) == 0 {
+		return nil
+	}
+	if len(certPath) > 0 {
+		return fmt.Errorf("--cert and --external-certificate are mutually exclusive")
+	}
+	if len(keyPath) > 0 {
+		return fmt.Errorf("--key and --external-certificate are mutually exclusive")
+	}
+	return nil
+}
+
+func setExternalCertificate(tls *routev1.TLSConfig, externalName string) {
+	if len(externalName) == 0 {
+		return
+	}
+	tls.ExternalCertificate = &routev1.LocalObjectReference{Name: externalName}
+}
-	if len(o.Cert) > 0 && len(o.ExternalCertificate) > 0 { ... }
-	if len(o.Key) > 0 && len(o.ExternalCertificate) > 0 { ... }
+	if err := validateExternalCertMutualExclusion(o.Cert, o.Key, o.ExternalCertificate); err != nil {
+		return err
+	}
...
-	if len(o.ExternalCertificate) > 0 {
-		route.Spec.TLS.ExternalCertificate = &routev1.LocalObjectReference{
-			Name: o.ExternalCertificate,
-		}
-	}
+	setExternalCertificate(route.Spec.TLS, o.ExternalCertificate)

Also applies to: 142-146

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/cli/create/routeedge.go` around lines 100 - 106, The mutual-exclusivity
TLS checks and ExternalCertificate assignment duplicated in
CreateEdgeRouteOptions.Run (and the similar block in routereenecrypt.go) should
be extracted into a shared helper (e.g., ValidateAndWireExternalCertificate or
WireExternalCert) in a common package (pkg/cli/create or
pkg/cli/create/internal); implement the helper to accept the options struct
fields (Cert, Key, ExternalCertificate) or the options pointer, perform the
mutual-exclusion checks, return a wired ExternalCertificate value or an error,
and replace the duplicated logic in CreateEdgeRouteOptions.Run and the
corresponding routereenecrypt.Run by calling this helper and using its returned
value; ensure tests and callers preserve existing error messages ("--cert and
--external-certificate are mutually exclusive", "--key and
--external-certificate are mutually exclusive").
pkg/cli/create/routeedge_test.go (1)

48-77: Consider consolidating duplicated test harness between edge/reencrypt suites.

newTestEdgeRouteOptions, setup, and many assertions mirror pkg/cli/create/routereenecrypt_test.go. A shared helper would reduce maintenance overhead.

Also applies to: 79-262

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/cli/create/routeedge_test.go` around lines 48 - 77, Tests duplicate the
route options setup in newTestEdgeRouteOptions and the reencrypt suite; extract
the common setup into a single helper (e.g., newTestRouteOptions) that performs
genericiooptions.NewTestIOStreams, fakekubernetes.NewClientset(service),
routefake.NewClientset(), meta.NewDefaultRESTMapper(nil),
genericclioptions.NewPrintFlags(...).ToPrinter(), and returns the shared
CreateRouteSubcommandOptions (with Mapper, Client from
fakeRouteClientset.RouteV1(), CoreClient, Printer, IOStreams), the
fakeRouteClientset, and the output buffer; then rewrite newTestEdgeRouteOptions
to call newTestRouteOptions and wrap/augment its result into a
CreateEdgeRouteOptions (setting Service, Name, Namespace or TLS-specific fields)
so both edge and reencrypt tests reuse the same setup.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@pkg/cli/create/routeedge_test.go`:
- Around line 48-77: Tests duplicate the route options setup in
newTestEdgeRouteOptions and the reencrypt suite; extract the common setup into a
single helper (e.g., newTestRouteOptions) that performs
genericiooptions.NewTestIOStreams, fakekubernetes.NewClientset(service),
routefake.NewClientset(), meta.NewDefaultRESTMapper(nil),
genericclioptions.NewPrintFlags(...).ToPrinter(), and returns the shared
CreateRouteSubcommandOptions (with Mapper, Client from
fakeRouteClientset.RouteV1(), CoreClient, Printer, IOStreams), the
fakeRouteClientset, and the output buffer; then rewrite newTestEdgeRouteOptions
to call newTestRouteOptions and wrap/augment its result into a
CreateEdgeRouteOptions (setting Service, Name, Namespace or TLS-specific fields)
so both edge and reencrypt tests reuse the same setup.

In `@pkg/cli/create/routeedge.go`:
- Around line 100-106: The mutual-exclusivity TLS checks and ExternalCertificate
assignment duplicated in CreateEdgeRouteOptions.Run (and the similar block in
routereenecrypt.go) should be extracted into a shared helper (e.g.,
ValidateAndWireExternalCertificate or WireExternalCert) in a common package
(pkg/cli/create or pkg/cli/create/internal); implement the helper to accept the
options struct fields (Cert, Key, ExternalCertificate) or the options pointer,
perform the mutual-exclusion checks, return a wired ExternalCertificate value or
an error, and replace the duplicated logic in CreateEdgeRouteOptions.Run and the
corresponding routereenecrypt.Run by calling this helper and using its returned
value; ensure tests and callers preserve existing error messages ("--cert and
--external-certificate are mutually exclusive", "--key and
--external-certificate are mutually exclusive").

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: c10a931c-5e0b-498d-92e6-592877a11d7e

📥 Commits

Reviewing files that changed from the base of the PR and between 66dee73 and 9225a5f.

📒 Files selected for processing (4)
  • pkg/cli/create/routeedge.go
  • pkg/cli/create/routeedge_test.go
  • pkg/cli/create/routereenecrypt.go
  • pkg/cli/create/routereenecrypt_test.go

@lunarwhite lunarwhite marked this pull request as draft April 16, 2026 11:41
@openshift-ci openshift-ci Bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Apr 16, 2026
@lunarwhite lunarwhite force-pushed the ext-cert-route-flag branch from 9225a5f to e0ac307 Compare April 17, 2026 06:21
@lunarwhite lunarwhite marked this pull request as ready for review April 17, 2026 06:22
@openshift-ci openshift-ci Bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Apr 17, 2026
@openshift-ci openshift-ci Bot requested review from ingvagabund and tchap April 17, 2026 06:22
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
pkg/cli/create/routeedge_test.go (2)

86-87: Use filepath.Join for OS-safe test paths.

These paths are currently string-concatenated; filepath.Join is safer and idiomatic across platforms.

Proposed diff
 import (
 	"bytes"
 	"context"
 	"os"
+	"path/filepath"
 	"strings"
 	"testing"
@@
-	certFile := tmpDir + "/tls.crt"
-	keyFile := tmpDir + "/tls.key"
+	certFile := filepath.Join(tmpDir, "tls.crt")
+	keyFile := filepath.Join(tmpDir, "tls.key")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/cli/create/routeedge_test.go` around lines 86 - 87, The test builds file
paths by string-concatenating tmpDir with "/tls.crt" and "/tls.key" (variables
certFile and keyFile); replace those concatenations with filepath.Join(tmpDir,
"tls.crt") and filepath.Join(tmpDir, "tls.key") to make the paths OS-safe and
idiomatic (ensure you add/import "path/filepath" if not already present).

122-124: Consider adding tt := tt for explicit loop variable capture clarity.

This is optional defensive coding. Go 1.22+ (required by go.mod 1.25.0) fixed range-loop variable capture semantics in closures, so this change is not needed for correctness—only for code readability if preferred.

Proposed diff
 for _, tt := range tests {
+	tt := tt
 	t.Run(tt.name, func(t *testing.T) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/cli/create/routeedge_test.go` around lines 122 - 124, In the table-driven
test loop over "tests" before launching the subtest with t.Run, shadow the loop
variable by adding "tt := tt" so the closure captures the per-iteration value
explicitly; update the range loop in pkg/cli/create/routeedge_test.go (the block
that calls newTestEdgeRouteOptions and t.Run) to introduce this local assignment
immediately before t.Run.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@pkg/cli/create/routeedge_test.go`:
- Around line 86-87: The test builds file paths by string-concatenating tmpDir
with "/tls.crt" and "/tls.key" (variables certFile and keyFile); replace those
concatenations with filepath.Join(tmpDir, "tls.crt") and filepath.Join(tmpDir,
"tls.key") to make the paths OS-safe and idiomatic (ensure you add/import
"path/filepath" if not already present).
- Around line 122-124: In the table-driven test loop over "tests" before
launching the subtest with t.Run, shadow the loop variable by adding "tt := tt"
so the closure captures the per-iteration value explicitly; update the range
loop in pkg/cli/create/routeedge_test.go (the block that calls
newTestEdgeRouteOptions and t.Run) to introduce this local assignment
immediately before t.Run.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: d51fb9d4-775c-4649-b669-6e4834eae93d

📥 Commits

Reviewing files that changed from the base of the PR and between 9225a5f and e0ac307.

📒 Files selected for processing (4)
  • pkg/cli/create/routeedge.go
  • pkg/cli/create/routeedge_test.go
  • pkg/cli/create/routereenecrypt.go
  • pkg/cli/create/routereenecrypt_test.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • pkg/cli/create/routereenecrypt_test.go
  • pkg/cli/create/routereenecrypt.go
  • pkg/cli/create/routeedge.go

@lunarwhite lunarwhite force-pushed the ext-cert-route-flag branch from e0ac307 to d821dc3 Compare April 17, 2026 06:49
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
pkg/cli/create/routereenecrypt_test.go (2)

26-30: Temp file setup is unnecessary in this unit test.

Validate() only checks whether strings are non-empty, so creating real cert/key files adds noise and I/O without increasing confidence.

♻️ Simplify test setup
-	tmpDir := t.TempDir()
-	certFile := filepath.Join(tmpDir, "tls.crt")
-	keyFile := filepath.Join(tmpDir, "tls.key")
-	writeTestFile(t, certFile, "test-cert-data")
-	writeTestFile(t, keyFile, "test-key-data")
+	certFile := "dummy-cert"
+	keyFile := "dummy-key"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/cli/create/routereenecrypt_test.go` around lines 26 - 30, The test
currently creates real temp files and writes cert/key data even though
Validate() only checks non-empty strings; remove the tmpDir, filepath.Join and
writeTestFile calls and instead set certFile and keyFile to simple non-empty
string literals (e.g., "test-cert-data", "test-key-data") so the test avoids
unnecessary I/O; update the variables used by the Validate() call in the test in
routereenecrypt_test.go accordingly.

122-123: Prefer typed termination constant over string literal.

The test at lines 122-123 uses string literal "reencrypt" instead of the available typed constant. Replace with routev1.TLSTerminationReencrypt (already used in the same package at routereenecrypt.go:139) to avoid literal drift and align with the existing codebase pattern.

Import routev1 from github.com/openshift/api/route/v1 if not already present.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/cli/create/routereenecrypt_test.go` around lines 122 - 123, The test
checks route.Spec.TLS.Termination against the string literal "reencrypt"—replace
that literal with the typed constant routev1.TLSTerminationReencrypt and
add/import routev1 from github.com/openshift/api/route/v1 if missing; update the
assertion in the test (the comparison of route.Spec.TLS.Termination) to use
routev1.TLSTerminationReencrypt to match the usage in routereenecrypt.go (where
TLSTerminationReencrypt is already used).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@pkg/cli/create/routereenecrypt_test.go`:
- Around line 26-30: The test currently creates real temp files and writes
cert/key data even though Validate() only checks non-empty strings; remove the
tmpDir, filepath.Join and writeTestFile calls and instead set certFile and
keyFile to simple non-empty string literals (e.g., "test-cert-data",
"test-key-data") so the test avoids unnecessary I/O; update the variables used
by the Validate() call in the test in routereenecrypt_test.go accordingly.
- Around line 122-123: The test checks route.Spec.TLS.Termination against the
string literal "reencrypt"—replace that literal with the typed constant
routev1.TLSTerminationReencrypt and add/import routev1 from
github.com/openshift/api/route/v1 if missing; update the assertion in the test
(the comparison of route.Spec.TLS.Termination) to use
routev1.TLSTerminationReencrypt to match the usage in routereenecrypt.go (where
TLSTerminationReencrypt is already used).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 91b6ed89-c258-4dd1-ba99-49ed399362a6

📥 Commits

Reviewing files that changed from the base of the PR and between e0ac307 and d821dc3.

📒 Files selected for processing (4)
  • pkg/cli/create/routeedge.go
  • pkg/cli/create/routeedge_test.go
  • pkg/cli/create/routereenecrypt.go
  • pkg/cli/create/routereenecrypt_test.go
✅ Files skipped from review due to trivial changes (1)
  • pkg/cli/create/routeedge_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • pkg/cli/create/routereenecrypt.go
  • pkg/cli/create/routeedge.go

Adds support for referencing TLS certificates from a TLS Secret when creating
edge and reencrypt routes. The new '--external-certificate' flag accepts a Secret
name and populates 'route.Spec.TLS.ExternalCertificate' as a LocalObjectReference.

This flag is mutually exclusive with '--cert' and '--key', since inline certificates and
secret-backed certificates are alternative sources. The '--ca-cert' flag (and
'--dest-ca-cert' for reencrypt routes) remains compatible with '--external-certificate'.
@lunarwhite lunarwhite force-pushed the ext-cert-route-flag branch from d821dc3 to 34b1b7d Compare April 17, 2026 07:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature Request] Support creating Routes with external certificate ref in oc create route

2 participants