Skip to content

⚠️ Rename llmprovider to gateway - #100

Merged
djzager merged 2 commits into
konveyor:mainfrom
djzager:rename-llmprovider-to-gateway
Aug 5, 2026
Merged

djzager merged 2 commits into
konveyor:mainfrom
djzager:rename-llmprovider-to-gateway

Conversation

@djzager

@djzager djzager commented Aug 4, 2026

Copy link
Copy Markdown
Member

Fixes #79
Fixes #97

Summary by CodeRabbit

  • Breaking Changes
    • Replaced LLMProvider resources with Gateway resources, each representing one provider/model endpoint.
    • Agents and workflow runs now reference or select gateways instead of provider/model combinations.
    • Updated resource names, schemas, status fields, and terminology accordingly.
  • Configuration
    • Added canonical KONVEYOR_LLM_* environment variables with backward-compatible legacy fallbacks.
  • Documentation
    • Updated guides, examples, CRD descriptions, and demos for gateway-based configuration.

@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The PR replaces multi-model LLMProvider resources with single-model Gateway resources. Agent and workflow run APIs now select gateways. Controllers, CRDs, tests, E2E resources, and harness variables use the new model.

Changes

Gateway migration

Layer / File(s) Summary
Gateway API and CRD contracts
api/v1alpha1/*, config/crd/*, PROJECT, README.md
Defines Gateway, singular spec.model, gateway references, and gateway-based run selection.
Gateway verification reconciliation
internal/controller/gateway_controller.go, internal/controller/agent_controller.go, cmd/main.go
Reconciles Gateway resources, validates credentials, runs connectivity Jobs, updates status, and tracks Gateway dependencies.
Gateway-based run execution
internal/controller/agentrun_controller.go, internal/controller/agentworkflowrun_controller.go, internal/controller/*_test.go
Validates selected gateways and configures sandbox endpoint, model, and credentials.
Harness and integration updates
harness/*, hack/*, images/*, changes/unreleased/*
Adds canonical KONVEYOR_LLM_* variables with legacy fallbacks and updates deployment, E2E, harness, and release resources.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

Suggested reviewers: fabianvf, savitharaghunathan

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Linked Issues check ❓ Inconclusive The changes satisfy the linked objectives, but api/go.sum is excluded by the !**/*.sum filter and cannot be verified. Review api/go.sum separately to confirm the API submodule dependency checksums and complete verification of issue #97.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the primary breaking change and uses the required warning prefix.
Description check ✅ Passed The description links both relevant issues, and the required breaking-change changelog fragment is present.
Out of Scope Changes check ✅ Passed The documented, API, controller, test, module, and configuration changes align with issues #79 and #97.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

Error: build linters: plugin(logcheck): plugin "logcheck" not found
The command is terminated due to an error: build linters: plugin(logcheck): plugin "logcheck" not found


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.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 8

🧹 Nitpick comments (1)
internal/controller/agent_controller_test.go (1)

43-44: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use Gateway terminology in the test fixture.

gatewayName still contains a provider-based value, and provider stores a Gateway. Rename these identifiers and related fixture strings to use gateway consistently. As per coding guidelines, use the terms defined in CONTEXT.md.

Also applies to: 60-77

🤖 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/controller/agent_controller_test.go` around lines 43 - 44, Update
the test fixture identifiers and related strings around agent_controller tests
to use Gateway terminology consistently: rename gatewayName and the provider
variable that stores a Gateway, along with their provider-based fixture values,
while preserving the existing test behavior and using the terms defined in
CONTEXT.md.

Source: Coding guidelines

🤖 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 `@CONTEXT.md`:
- Around line 28-35: Update the Agent, AgentRun, and relationship sections in
CONTEXT.md to reference Gateway CR names and the controller’s Gateway
Ready-condition validation, not OpenShell Gateway Services. Clearly describe
OpenShell Gateway Services as the future replacement while preserving the
current Gateway CRD contract, so configuration examples and terminology
consistently require Gateway resources.

In `@hack/run-e2e.sh`:
- Around line 46-51: Update the kubectl wait expression in the Gateway readiness
check around the e2e-gateway command to select the status condition whose type
is Ready rather than assuming status.conditions[0] is Ready. Preserve the
existing timeout, success message, failure handling, and diagnostic output.

In `@internal/controller/agentrun_controller.go`:
- Around line 471-479: After fetching the Gateway in the agent-run flow,
validate its current Ready condition before appending the LLM environment
variables or creating the Sandbox. Use the fetched Gateway’s status conditions
and reject or retry when ConditionTypeReady is not true; only continue with
KONVEYOR_LLM_ENDPOINT and KONVEYOR_LLM_MODEL for a currently Ready Gateway.

In `@internal/controller/gateway_controller.go`:
- Around line 155-162: Before setting the current-generation Gateway status to
Ready=False with Reason "Verifying" in both affected branches, clear
gateway.Status.ConnectionVerified and persist that status change before
verification begins. Update the related flow around patchStatus so the CRD and
clients cannot retain the prior generation’s verification result.
- Around line 145-165: Update the verification-job handling in the Gateway
reconciler around createVerificationJob to discover and delete Jobs belonging to
prior Gateway generations before creating the current-generation Job. Ensure
completion events for stale Jobs cannot leave them orphaned, while preserving
the existing current-job lookup and status behavior; add a regression test
covering a Gateway update while verification is queued or running.
- Around line 317-321: Update GatewayReconciler.SetupWithManager to watch
credential Secrets and enqueue the referencing Gateways on Secret changes. Add
the required credential-Secret field index and use a Secret watch with a mapping
based on that index, preserving the existing Gateway and Job watches.
- Around line 169-177: The gateway verification flow around isJobSucceeded must
not mark ConnectionVerified true for unauthenticated or rejected requests. Make
the probe validate credentials for every supported credentialRef type, treat
401/403 as verification failures, and ensure omitted credentialRef.key does not
pass authentication verification; alternatively, report endpoint reachability
separately from credential verification.
- Line 224: Constrain the verification Job’s outbound access before assigning
gateway.Spec.Endpoint to the LLM_ENDPOINT EnvVar in the Gateway reconciliation
flow. Update the logic around verifyJobEndpoint and the Job creation path to
allow only externally reachable Gateway destinations, or apply a default-deny
egress policy, while preserving endpoint verification for valid destinations.

---

Nitpick comments:
In `@internal/controller/agent_controller_test.go`:
- Around line 43-44: Update the test fixture identifiers and related strings
around agent_controller tests to use Gateway terminology consistently: rename
gatewayName and the provider variable that stores a Gateway, along with their
provider-based fixture values, while preserving the existing test behavior and
using the terms defined in CONTEXT.md.
🪄 Autofix

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 Plus

Run ID: 4c53fc25-c496-460b-a5aa-15c5cdf4130b

📥 Commits

Reviewing files that changed from the base of the PR and between 3ee420c and 8998ad6.

📒 Files selected for processing (42)
  • AGENTS.md
  • CONTEXT.md
  • PROJECT
  • README.md
  • api/v1alpha1/agent_types.go
  • api/v1alpha1/agentrun_types.go
  • api/v1alpha1/agentworkflowrun_types.go
  • api/v1alpha1/gateway_types.go
  • api/v1alpha1/groupversion_info.go
  • api/v1alpha1/zz_generated.deepcopy.go
  • changes/unreleased/rename-llmprovider-to-gateway.yaml
  • cmd/main.go
  • config/crd/bases/konveyor.io_agentruns.yaml
  • config/crd/bases/konveyor.io_agents.yaml
  • config/crd/bases/konveyor.io_agentworkflowruns.yaml
  • config/crd/bases/konveyor.io_gateways.yaml
  • config/crd/kustomization.yaml
  • config/rbac/role.yaml
  • docs/slides/demo-2026-07-16.md
  • hack/e2e/resources.yaml
  • hack/harness-test/resources.yaml
  • hack/harness-test/workflow-resources.yaml
  • hack/run-e2e.sh
  • hack/setup-e2e.sh
  • harness/README.md
  • harness/internal/config/config.go
  • harness/internal/config/config_test.go
  • harness/internal/goose/lifecycle.go
  • images/README.md
  • images/agentic-controller-agent/Containerfile
  • images/agentic-controller-agent/entrypoint.sh
  • internal/controller/agent_controller.go
  • internal/controller/agent_controller_test.go
  • internal/controller/agentrun_controller.go
  • internal/controller/agentrun_controller_test.go
  • internal/controller/agentworkflow_controller_test.go
  • internal/controller/agentworkflowrun_controller.go
  • internal/controller/agentworkflowrun_controller_test.go
  • internal/controller/crd_validation_test.go
  • internal/controller/gateway_controller.go
  • internal/controller/gateway_controller_test.go
  • internal/controller/suite_test.go

Comment thread CONTEXT.md Outdated
Comment thread hack/run-e2e.sh Outdated
Comment thread internal/controller/agentrun_controller.go
Comment thread internal/controller/gateway_controller.go Outdated
Comment thread internal/controller/gateway_controller.go
Comment thread internal/controller/gateway_controller.go
// unauthenticated — reachability still verifies (2xx-4xx passes).
env := []corev1.EnvVar{{Name: "LLM_ENDPOINT", Value: provider.Spec.Endpoint}}
if provider.Spec.CredentialRef.Key != "" {
env := []corev1.EnvVar{{Name: "LLM_ENDPOINT", Value: gateway.Spec.Endpoint}}

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.

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== files =="
git ls-files | rg '(^|/)(gateway_controller\.go|rbac|role|rolebinding|networkpolicy|networkpolicies|manifests|config)/|gateway|.*\.yaml$' || true

echo "== gateway_controller relevant sections =="
if [ -f internal/controller/gateway_controller.go ]; then
  wc -l internal/controller/gateway_controller.go
  sed -n '1,80p' internal/controller/gateway_controller.go
  sed -n '200,285p' internal/controller/gateway_controller.go
  sed -n '285,400p' internal/controller/gateway_controller.go
fi

echo "== rbac/search endpoint writers =="
rg -n --hidden -S --glob '*.{go,yaml,yml,md}' 'Gateway|gateway|create.*gateway|update.*gateway|Endpoint|LLM_ENDPOINT|NetworkPolicy|NetworkPolicies|egress|ingress' . || true

echo "== job pod/security policy references =="
rg -n --hidden -S --glob '*.{go,yaml,yml}' 'SecurityContext|runAsNonRoot|NetworkPolicy|egress|AllowDNS|kubectl|namespace|metadata|169\.254|localhost|service account' . || true

Repository: konveyor/agentic-controller

Length of output: 50383


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== network policy files =="
fd -a . config/network-policy -t f | while read -r f; do
  echo "--- $f"
  sed -n '1,200p' "$f"
done

echo "== Gateway CRD relevant block =="
sed -n '1,100p' config/crd/bases/konveyor.io_gateways.yaml
sed -n '21,80p' api/v1alpha1/gateway_types.go || true

echo "== RBAC relevant block =="
sed -n '1,130p' config/rbac/role.yaml

echo "== Job egress/security references exact files =="
rg -n --hidden -S --glob '*.{go,yaml,yml}' 'NetworkPolicy|NetworkPolicies|egress|allow-metrics-traffic|SecurityContext|runAsNonRoot|ServiceAccount|GatewayReconciler|gateways:' .

Repository: konveyor/agentic-controller

Length of output: 10921


SSRF (CWE-918): Server-Side Request Forgery (SSRF)

Reachability: Internal

Reachability path
● Entry
  internal/controller/suite_test.go:131
  GatewayReconciler
│
▼
● Sink
  internal/controller/gateway_controller.go

Constrain verification Job egress for Gateway endpoints.

Gateways can create and update config/crd/bases/konveyor.io_gateways.yaml, and verifyJobEndpoint accepts any non-empty string. That value is passed into a Job that calls "$LLM_ENDPOINT/v1/models". Curl quoting prevents shell injection, but it does not block requests to in-cluster services, control-plane addresses, or metadata endpoints. Restrict egress for these Jobs to externally reachable Gateway destinations, or deny Job egress by default.

🤖 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/controller/gateway_controller.go` at line 224, Constrain the
verification Job’s outbound access before assigning gateway.Spec.Endpoint to the
LLM_ENDPOINT EnvVar in the Gateway reconciliation flow. Update the logic around
verifyJobEndpoint and the Job creation path to allow only externally reachable
Gateway destinations, or apply a default-deny egress policy, while preserving
endpoint verification for valid destinations.

Comment on lines +317 to +321
func (r *GatewayReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&konveyoriov1alpha1.LLMProvider{}).
For(&konveyoriov1alpha1.Gateway{}).
Owns(&batchv1.Job{}).
Named("llmprovider").
Named("gateway").

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.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Watch credential Secrets so Gateway readiness tracks rotations.

Line 62 grants Secret watch permission, but this controller watches only Gateways and Jobs. A client Get does not subscribe to Secret changes. If a referenced Secret is deleted, rotated, or changed, the Gateway can remain Ready and verified until another event occurs. Add a credential-Secret field index and a Secret watch that maps changes to referencing Gateways.

🤖 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/controller/gateway_controller.go` around lines 317 - 321, Update
GatewayReconciler.SetupWithManager to watch credential Secrets and enqueue the
referencing Gateways on Secret changes. Add the required credential-Secret field
index and use a Secret watch with a mapping based on that index, preserving the
existing Gateway and Job watches.

@ibolton336 ibolton336 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.

Clean, faithful implementation of #79 — the validateGateway delegation to Agent readiness, the preserved keyless/envFrom credential path, and dropping discoveredModels outright all look right. One gap I think is blocking (inline at buildEnvVars), one behavior question (inline at validateGateway), one script nit.

Two housekeeping items: DCO is failing (both commits missing sign-off), and the changelog fragment could note upgrade ordering — the new controller stops emitting KONVEYOR_MODEL_PRIMARY_*, so older harness/agent images fail against a newer controller (the harness fallback only covers the reverse direction). Agent images should upgrade with or before the controller.

Comment thread internal/controller/agentrun_controller.go
Comment thread internal/controller/agentrun_controller.go Outdated
Comment thread hack/run-e2e.sh Outdated
Reshape the LLMProvider CRD to match the OpenShell gateway interaction
model (one gateway = one provider/model combination) so the eventual
flip to real OpenShell Gateways is seamless.

Changes:
- Rename LLMProvider CRD to Gateway (kind, types, controller, tests)
- Flatten Models[] to singular Model field (one CR = one model)
- Rename Agent.spec.providers to Agent.spec.gateways (AgentGatewayRef)
- Replace AgentRun.spec.models (role/provider/model triples) with
  AgentRun.spec.gateway (single string)
- Replace AgentWorkflowRun.spec.models with .spec.gateway
- Simplify buildEnvVars: KONVEYOR_MODEL_{ROLE}_* env vars replaced by
  KONVEYOR_LLM_ENDPOINT, KONVEYOR_LLM_MODEL, KONVEYOR_LLM_API_KEY
- Simplify validateModels -> validateGateway (membership check only)
- Remove DiscoveredModels from status (no longer needed with single model)
- Clean up stale AgentPlaybook/AgentPlaybookRun entries in PROJECT file
- Update CONTEXT.md, sample resources, all tests

Closes konveyor#79

Signed-off-by: David Zager <david.j.zager@gmail.com>
@djzager
djzager force-pushed the rename-llmprovider-to-gateway branch from be12f54 to 0744851 Compare August 4, 2026 20:33

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🧹 Nitpick comments (1)
internal/controller/agentworkflowrun_controller_test.go (1)

168-168: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert Gateway propagation for stage-b.

Line 168 verifies Gateway only on stage-a. A later reconciliation creates stage-b. If that path drops Gateway, this test can still pass because it sets stage-b status directly. Assert stageBRun.Spec.Gateway == gwName.

Proposed test addition
 Expect(k8sClient.Get(ctx, types.NamespacedName{
     Name: stageBRunName, Namespace: testNamespace,
 }, &stageBRun)).To(Succeed())
 Expect(stageBRun.Spec.Instructions).To(Equal("Do stage B"))
+Expect(stageBRun.Spec.Gateway).To(Equal(gwName))
 Expect(stageBRun.Labels).To(HaveKeyWithValue(labelStage, "stage-b"))
🤖 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/controller/agentworkflowrun_controller_test.go` at line 168, Add an
assertion for stage-b’s Gateway propagation in the reconciliation test after
stage-b is retrieved or created, verifying stageBRun.Spec.Gateway equals gwName.
Keep the existing stage-a assertion unchanged and ensure the assertion checks
the reconciled stage-b spec before status is set directly.
🤖 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 `@hack/harness-test/resources.yaml`:
- Line 14: Update the GatewaySpec endpoint value in resources.yaml to use the
complete HTTPS URL, including the https:// scheme, so verification requests
target the secure transport.

In `@internal/controller/gateway_controller.go`:
- Around line 248-257: Update createVerificationJob so credential references are
mounted only after confirming the Gateway writer is authorized to read the
referenced Secret; reject or fail closed when access cannot be verified.
Validate or restrict gateway.Spec.Endpoint before creating the Job, allowing
credentials only for approved verification destinations. Preserve the existing
no-credential path when CredentialRef.Key is empty.

---

Nitpick comments:
In `@internal/controller/agentworkflowrun_controller_test.go`:
- Line 168: Add an assertion for stage-b’s Gateway propagation in the
reconciliation test after stage-b is retrieved or created, verifying
stageBRun.Spec.Gateway equals gwName. Keep the existing stage-a assertion
unchanged and ensure the assertion checks the reconciled stage-b spec before
status is set directly.
🪄 Autofix

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 Plus

Run ID: 90846e17-5c43-4ff7-8ae3-db96fb2c67e4

📥 Commits

Reviewing files that changed from the base of the PR and between 8998ad6 and 0744851.

⛔ Files ignored due to path filters (1)
  • api/go.sum is excluded by !**/*.sum
📒 Files selected for processing (45)
  • AGENTS.md
  • CONTEXT.md
  • Makefile
  • PROJECT
  • README.md
  • api/go.mod
  • api/v1alpha1/agent_types.go
  • api/v1alpha1/agentrun_types.go
  • api/v1alpha1/agentworkflowrun_types.go
  • api/v1alpha1/gateway_types.go
  • api/v1alpha1/groupversion_info.go
  • api/v1alpha1/zz_generated.deepcopy.go
  • changes/unreleased/rename-llmprovider-to-gateway.yaml
  • cmd/main.go
  • config/crd/bases/konveyor.io_agentruns.yaml
  • config/crd/bases/konveyor.io_agents.yaml
  • config/crd/bases/konveyor.io_agentworkflowruns.yaml
  • config/crd/bases/konveyor.io_gateways.yaml
  • config/crd/kustomization.yaml
  • config/rbac/role.yaml
  • docs/slides/demo-2026-07-16.md
  • go.mod
  • hack/e2e/resources.yaml
  • hack/harness-test/resources.yaml
  • hack/harness-test/workflow-resources.yaml
  • hack/run-e2e.sh
  • hack/setup-e2e.sh
  • harness/README.md
  • harness/internal/config/config.go
  • harness/internal/config/config_test.go
  • harness/internal/goose/lifecycle.go
  • images/README.md
  • images/agentic-controller-agent/Containerfile
  • images/agentic-controller-agent/entrypoint.sh
  • internal/controller/agent_controller.go
  • internal/controller/agent_controller_test.go
  • internal/controller/agentrun_controller.go
  • internal/controller/agentrun_controller_test.go
  • internal/controller/agentworkflow_controller_test.go
  • internal/controller/agentworkflowrun_controller.go
  • internal/controller/agentworkflowrun_controller_test.go
  • internal/controller/crd_validation_test.go
  • internal/controller/gateway_controller.go
  • internal/controller/gateway_controller_test.go
  • internal/controller/suite_test.go
🚧 Files skipped from review as they are similar to previous changes (35)
  • internal/controller/agentworkflowrun_controller.go
  • cmd/main.go
  • harness/internal/goose/lifecycle.go
  • images/agentic-controller-agent/entrypoint.sh
  • README.md
  • changes/unreleased/rename-llmprovider-to-gateway.yaml
  • docs/slides/demo-2026-07-16.md
  • harness/README.md
  • api/v1alpha1/agentworkflowrun_types.go
  • hack/run-e2e.sh
  • api/v1alpha1/groupversion_info.go
  • hack/e2e/resources.yaml
  • internal/controller/agent_controller.go
  • api/v1alpha1/agentrun_types.go
  • config/crd/bases/konveyor.io_agents.yaml
  • images/README.md
  • internal/controller/suite_test.go
  • config/crd/bases/konveyor.io_agentruns.yaml
  • AGENTS.md
  • images/agentic-controller-agent/Containerfile
  • config/crd/kustomization.yaml
  • harness/internal/config/config_test.go
  • hack/harness-test/workflow-resources.yaml
  • internal/controller/crd_validation_test.go
  • internal/controller/agentrun_controller.go
  • internal/controller/gateway_controller_test.go
  • api/v1alpha1/gateway_types.go
  • config/rbac/role.yaml
  • config/crd/bases/konveyor.io_agentworkflowruns.yaml
  • config/crd/bases/konveyor.io_gateways.yaml
  • api/v1alpha1/agent_types.go
  • hack/setup-e2e.sh
  • PROJECT
  • harness/internal/config/config.go
  • api/v1alpha1/zz_generated.deepcopy.go

name: gcp-vertex-ai
spec:
provider: gcp-vertex-ai
endpoint: "global-aiplatform.googleapis.com"

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.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== repo files relevant =="
git ls-files | rg '(^|/)(gateway_controller\.go|resources\.yaml)$|hack/harness-test/resources\.yaml$' || true

echo "== target yaml =="
if [ -f hack/harness-test/resources.yaml ]; then
  cat -n hack/harness-test/resources.yaml
fi

echo "== gateway controller references =="
rg -n "LLM_ENDPOINT|GatewaySpec|Endpoint|curl \"$|curl \"\\$LLM_ENDPOINT|v1/models|Accept-Header|reconcile" -S --glob '*.go' . || true

echo "== all endpoint occurrences =="
rg -n 'endpoint:' -S . || true

Repository: konveyor/agentic-controller

Length of output: 979


🌐 Web query:

POSIX curl URL with no scheme defaults to http documentation

💡 Result:

Yes, when a URL provided to curl lacks a scheme (such as http:// or ftp://), curl defaults to using HTTP, but it employs a heuristic "guessing" mechanism based on the hostname prefix before falling back to this default [1][2][3]. If the URL does not start with a recognized scheme, curl examines the first part of the hostname (the subdomain) [4][5]. If the hostname begins with specific prefixes, it assumes a corresponding protocol [6][7]: - ftp. means FTP - dict. means DICT - ldap. means LDAP - imap. means IMAP - smtp. means SMTP - pop3. means POP3 For any hostname that does not match these specific prefixes, curl defaults to HTTP [4][5]. This behavior is a convenience feature mimicking early web browsers and is not defined by standard URL specifications [6][7]. Users can override this behavior in the following ways: - Command-line: Use the --proto-default option to set a different default protocol [4][5]. - libcurl: Use the CURLOPT_DEFAULT_PROTOCOL option in code to specify the protocol to be used when no scheme is present [8][9][10]. When a default protocol is explicitly set, curl bypasses the hostname-based guessing heuristic [8][9][10].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo u

echo "== gateway_controller.go outline/size =="
wc -l internal/controller/gateway_controller.go
ast-grep outline internal/controller/gateway_controller.go --view expanded || true

echo "== gateway_controller.go relevant sections =="
rg -n 'Endpoint|Endpoint|llm|curl|models|2xx|4xx|TLS|Transport|DefaultTransport|scheme|URL' -S internal/controller/gateway_controller.go

echo "== full gateway_controller.go around endpoint and curl =="
python3 - <<'PY'
from pathlib import Path
p=Path('internal/controller/gateway_controller.go')
lines=p.read_text().splitlines()
for name in ['func (r *GatewayReconciler):', 'Endpoint', 'curl', 'GetBaseURL', 'v1/models', 'models']:
    print(f'-- {name} --')
    for i,l in enumerate(lines,1):
        if name.lower() in l.lower():
            start=max(1,i-25); end=min(len(lines),i+35)
            for j in range(start,end+1):
                print(f'{j:4}: {lines[j-1]}')
            print()
PY

Repository: konveyor/agentic-controller

Length of output: 207


🏁 Script executed:

#!/bin/bash
set -u

echo "== gateway_controller.go outline/size =="
wc -l internal/controller/gateway_controller.go
ast-grep outline internal/controller/gateway_controller.go --view expanded || true

echo "== gateway_controller.go relevant terms =="
rg -n 'Endpoint|endpoint|LLM_ENDPOINT|curl|models|2xx|4xx|TLS|Transport|DefaultTransport|scheme|URL' -S internal/controller/gateway_controller.go

echo "== gateway_controller.go around endpoint and curl =="
python3 - <<'PY'
from pathlib import Path
p=Path('internal/controller/gateway_controller.go')
lines=p.read_text().splitlines()
terms = ['Endpoint', 'endpoint', 'LLM_ENDPOINT', 'curl', 'v1/models', 'models', 'models', 'func (r *GatewayReconciler):']
seen=set()
for name in terms:
    print(f'-- {name} --')
    for i,l in enumerate(lines,1):
        if name.lower() in l.lower():
            start=max(1,i-25); end=min(len(lines),i+45)
            for j in range(start,end+1):
                if j not in seen:
                    print(f'{j:4}: {lines[j-1]}')
                    seen.add(j)
            print()
PY

Repository: konveyor/agentic-controller

Length of output: 11620


Use a complete HTTPS URL for spec.endpoint.

GatewaySpec.Endpoint is used as the base URL for the verification curl "$LLM_ENDPOINT/v1/models" request. A scheme-less value makes curl default to HTTP, so this Gateway can verify the wrong transport and report ready from global-aiplatform.googleapis.com:80 instead of HTTPS.

Proposed fix
-  endpoint: "global-aiplatform.googleapis.com"
+  endpoint: "https://global-aiplatform.googleapis.com"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
endpoint: "global-aiplatform.googleapis.com"
endpoint: "https://global-aiplatform.googleapis.com"
🤖 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 `@hack/harness-test/resources.yaml` at line 14, Update the GatewaySpec endpoint
value in resources.yaml to use the complete HTTPS URL, including the https://
scheme, so verification requests target the secure transport.

Source: MCP tools

Comment on lines +248 to +257
env := []corev1.EnvVar{{Name: "LLM_ENDPOINT", Value: gateway.Spec.Endpoint}}
if gateway.Spec.CredentialRef.Key != "" {
env = append(env, corev1.EnvVar{
Name: "LLM_API_KEY",
ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: provider.Spec.CredentialRef.SecretName,
Name: gateway.Spec.CredentialRef.SecretName,
},
Key: provider.Spec.CredentialRef.Key,
Key: gateway.Spec.CredentialRef.Key,

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.

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find repository RBAC and admission-policy definitions that govern Gateway
# writers and Secret readers.
fd -a -t f . | rg -i '(role|rolebinding|clusterrole|clusterrolebinding|policy|constraint|gateway).*\.(yaml|yml|json)$' |
while IFS= read -r file; do
  echo "--- $file"
  rg -n -i -C 4 'gateways|secrets|create|update|get|Gateway|ValidatingAdmission' "$file" || true
done

Repository: konveyor/agentic-controller

Length of output: 7095


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the exact Gateway reconciler credential/env/job construction paths and
# RBAC references that affect Gateway writers and Secret readers.
sed -n '220,290p' internal/controller/gateway_controller.go
printf '\n--- RBAC role binding ---\n'
sed -n '1,140p' config/rbac/role.yaml config/rbac/role_binding.yaml
printf '\n--- Gateway type/schema credential fields ---\n'
sed -n '60,85p' config/crd/bases/konveyor.io_gateways.yaml
sed -n '40,115p' api/v1alpha1/gateway_types.go

# Read-only verifier: identify whether GatewaySpec endpoint is passed directly to
# a Job container env while the referenced SecretKeyRef env source is non-empty.
python3 - <<'PY'
from pathlib import Path
import re, yaml

src = Path('internal/controller/gateway_controller.go').read_text()
crd = yaml.safe_load(Path('config/crd/bases/konveyor.io_gateways.yaml').read_text())
rbac = yaml.safe_load(Path('config/rbac/role.yaml').read_text())

checks = {
    'secret_key_ref_used': 'SecretKeyRef: &corev1.SecretKeySelector{' in src,
    'endpoint_in_env_value': '"LLM_ENDPOINT", Value: gateway.Spec.Endpoint' in src,
    'credential_ref_key_used': 'gateway.Spec.CredentialRef.Key,}' in src,
    'credential_ref_secret_used': 'gateway.Spec.CredentialRef.SecretName,' in src,
    'role_has_gateways_all_verbs': any(
        r.get('resources') == ['secrets','gateways'] and set(r.get('verbs', [])) >= {'create','get','list','watch','patch','update','delete'}
        for r in rbac.get('rules') or []
    ),
    'crd_no_endpoint_pattern': 'pattern' not in str(crd.get('spec', {}).get('versions', [{}])[0].get('schema', {}).get('openAPIV3Schema', {})),
    'crd_allow_any_endpoint': bool(re.search(r'endpoint:.*type:\s*string', str(crd))))
print(repr(checks))
PY

Repository: konveyor/agentic-controller

Length of output: 9059


Sensitive Data Exposure (CWE-200): Exposure of Sensitive Information to an Unauthorized Actor

Reachability: Internal · Exploitability: Moderate

Reachability path
● Entry
  internal/controller/agentrun_controller.go:83
  Reconcile
│
▼
● Sink
  internal/controller/gateway_controller.go

Require Secret read access before mounting selected credentials.

createVerificationJob mounts gateway.Spec.CredentialRef.SecretName/Key as LLM_API_KEY and sends it to gateway.Spec.Endpoint. The controller RBAC allows Secrets, but Gateway writers are not required to have Secret access from this controller path, so a writer-controlled credential reference can expose a Secret value through a Job endpoint. Enforce that Gateway writers can read the referenced Secret and restrict or validate verification destinations before mounting credentials.

🤖 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/controller/gateway_controller.go` around lines 248 - 257, Update
createVerificationJob so credential references are mounted only after confirming
the Gateway writer is authorized to read the referenced Secret; reject or fail
closed when access cannot be verified. Validate or restrict
gateway.Spec.Endpoint before creating the Job, allowing credentials only for
approved verification destinations. Preserve the existing no-credential path
when CredentialRef.Key is empty.

@ibolton336

Copy link
Copy Markdown
Member

The api/ sub-module split is what's failing both red checks: the Dockerfile dep-cache layer copies only the root manifests, so go mod download can't resolve the ./api replace —

go: github.com/konveyor/agentic-controller/api@v0.0.0 (replaced by ./api): reading api/go.mod: open /workspace/api/go.mod: no such file or directory

Copying the sub-module manifests before the download fixes it:

COPY go.mod go.mod
COPY go.sum go.sum
COPY api/go.mod api/go.mod
COPY api/go.sum api/go.sum
RUN go mod download

Make api/ its own Go module so external consumers (e.g. Hub) can
import CRD type definitions without pulling in controller-runtime
and all its transitive dependencies.

The api sub-module depends only on k8s.io/api and k8s.io/apimachinery.
The root module uses a replace directive for local development.

Makefile generate/manifests targets updated to explicitly include
the api path since controller-gen does not descend into separate
Go modules with paths="./...".

Closes konveyor#97
Refs: konveyor#79

Signed-off-by: David Zager <david.j.zager@gmail.com>
@djzager
djzager force-pushed the rename-llmprovider-to-gateway branch from 0744851 to 142cf6e Compare August 5, 2026 00:34
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@coderabbitai coderabbitai Bot 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.

🧹 Nitpick comments (1)
internal/controller/agentworkflowrun_controller_test.go (1)

137-168: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert Gateway propagation for stage-b.

The test checks stageARun.Spec.Gateway at line 168. It does not check stageBRun.Spec.Gateway. Add Expect(stageBRun.Spec.Gateway).To(Equal(gwName)) before simulating stage-b success. This detects regressions that copy the selected Gateway only to the first generated AgentRun.

🤖 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/controller/agentworkflowrun_controller_test.go` around lines 137 -
168, Extend the workflow test’s stage-b verification to assert that
stageBRun.Spec.Gateway equals gwName before simulating stage-b success,
alongside the existing stage-a gateway assertion. Use the existing stageBRun
symbol and preserve the current test flow.
🤖 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 `@internal/controller/agentworkflowrun_controller_test.go`:
- Around line 137-168: Extend the workflow test’s stage-b verification to assert
that stageBRun.Spec.Gateway equals gwName before simulating stage-b success,
alongside the existing stage-a gateway assertion. Use the existing stageBRun
symbol and preserve the current test flow.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0e203e35-cd83-4fe1-b199-aed638b671cb

📥 Commits

Reviewing files that changed from the base of the PR and between 6f22990 and 142cf6e.

⛔ Files ignored due to path filters (1)
  • api/go.sum is excluded by !**/*.sum
📒 Files selected for processing (46)
  • AGENTS.md
  • CONTEXT.md
  • Dockerfile
  • Makefile
  • PROJECT
  • README.md
  • api/go.mod
  • api/v1alpha1/agent_types.go
  • api/v1alpha1/agentrun_types.go
  • api/v1alpha1/agentworkflowrun_types.go
  • api/v1alpha1/gateway_types.go
  • api/v1alpha1/groupversion_info.go
  • api/v1alpha1/zz_generated.deepcopy.go
  • changes/unreleased/rename-llmprovider-to-gateway.yaml
  • cmd/main.go
  • config/crd/bases/konveyor.io_agentruns.yaml
  • config/crd/bases/konveyor.io_agents.yaml
  • config/crd/bases/konveyor.io_agentworkflowruns.yaml
  • config/crd/bases/konveyor.io_gateways.yaml
  • config/crd/kustomization.yaml
  • config/rbac/role.yaml
  • docs/slides/demo-2026-07-16.md
  • go.mod
  • hack/e2e/resources.yaml
  • hack/harness-test/resources.yaml
  • hack/harness-test/workflow-resources.yaml
  • hack/run-e2e.sh
  • hack/setup-e2e.sh
  • harness/README.md
  • harness/internal/config/config.go
  • harness/internal/config/config_test.go
  • harness/internal/goose/lifecycle.go
  • images/README.md
  • images/agentic-controller-agent/Containerfile
  • images/agentic-controller-agent/entrypoint.sh
  • internal/controller/agent_controller.go
  • internal/controller/agent_controller_test.go
  • internal/controller/agentrun_controller.go
  • internal/controller/agentrun_controller_test.go
  • internal/controller/agentworkflow_controller_test.go
  • internal/controller/agentworkflowrun_controller.go
  • internal/controller/agentworkflowrun_controller_test.go
  • internal/controller/crd_validation_test.go
  • internal/controller/gateway_controller.go
  • internal/controller/gateway_controller_test.go
  • internal/controller/suite_test.go
🚧 Files skipped from review as they are similar to previous changes (41)
  • cmd/main.go
  • api/v1alpha1/agent_types.go
  • hack/setup-e2e.sh
  • harness/internal/goose/lifecycle.go
  • api/v1alpha1/agentworkflowrun_types.go
  • docs/slides/demo-2026-07-16.md
  • images/README.md
  • config/crd/kustomization.yaml
  • internal/controller/agentworkflowrun_controller.go
  • Makefile
  • internal/controller/suite_test.go
  • config/crd/bases/konveyor.io_agentruns.yaml
  • api/v1alpha1/groupversion_info.go
  • changes/unreleased/rename-llmprovider-to-gateway.yaml
  • config/rbac/role.yaml
  • config/crd/bases/konveyor.io_agentworkflowruns.yaml
  • images/agentic-controller-agent/Containerfile
  • api/go.mod
  • go.mod
  • AGENTS.md
  • harness/README.md
  • README.md
  • api/v1alpha1/zz_generated.deepcopy.go
  • config/crd/bases/konveyor.io_agents.yaml
  • api/v1alpha1/agentrun_types.go
  • internal/controller/crd_validation_test.go
  • CONTEXT.md
  • harness/internal/config/config_test.go
  • hack/harness-test/workflow-resources.yaml
  • internal/controller/agentrun_controller.go
  • config/crd/bases/konveyor.io_gateways.yaml
  • harness/internal/config/config.go
  • internal/controller/agent_controller.go
  • internal/controller/gateway_controller.go
  • internal/controller/gateway_controller_test.go
  • hack/e2e/resources.yaml
  • PROJECT
  • images/agentic-controller-agent/entrypoint.sh
  • hack/harness-test/resources.yaml
  • hack/run-e2e.sh
  • api/v1alpha1/gateway_types.go

@ibolton336 ibolton336 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.

All three of my earlier points are addressed: spec.provider as a required field injected as KONVEYOR_LLM_PROVIDER, single-gateway defaulting in validateGateway (which retires the client-side model injection workaround), and gateways.konveyor.io in the e2e script. The Dockerfile fix for the api/ sub-module has both builds green.

One non-blocking note: LoadFromEnv no longer treats provider as required, so an empty value falls through to goose's default rather than failing at boot. The CRD's MinLength=1 covers every controller-driven pod, so this only bites hand-rolled ones — fine to leave as is.

@djzager
djzager merged commit 059b6f6 into konveyor:main Aug 5, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants