Skip to content

feat(deployers): implement vcluster factory deduction - #77

Merged
kubernetes-prow[bot] merged 26 commits into
kubernetes-sigs:mainfrom
isadominguez314:feat/vcluster-factory-and-smoke-test
Aug 24, 2026
Merged

feat(deployers): implement vcluster factory deduction#77
kubernetes-prow[bot] merged 26 commits into
kubernetes-sigs:mainfrom
isadominguez314:feat/vcluster-factory-and-smoke-test

Conversation

@isadominguez314

@isadominguez314 isadominguez314 commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements Factory Deduction

Note

Stacked PR: This PR is stacked on top of PR #76 (vcluster provider integration). Please review and merge PR #76 first.

Changes

  • Updates factory to auto-deduct the vcluster provider by inspecting the stack directory name.
  • Adds comprehensive unit tests for the new deduction logic in test_deployers_factory.py.
  • (Note: The dedicated vcluster/smoke-test task was intentionally removed from this PR to keep tasks provider agnostic).

Verification

  • Unit tests added and verified locally.

Summary by CodeRabbit

  • New Features

    • Added support for deploying and managing virtual Kubernetes clusters.
    • Added configurable NodePort or LoadBalancer exposure and generated kubeconfig access.
    • Added host Kubernetes context, kubeconfig, and service CIDR configuration.
    • Added safer cleanup and improved cluster output handling across deployment providers.
  • Bug Fixes

    • Improved relative stack validation, provider detection, and environment-based root resolution.
    • Added more reliable readiness checks, retry handling, and failure reporting during setup.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR adds vCluster provisioning through OpenTofu and Kubernetes, extends provider lifecycle handling, supports configurable Terraform roots, normalizes OpenTofu outputs, persists generated kubeconfigs, and improves OPA remediation readiness checks.

Changes

vCluster integration

Layer / File(s) Summary
Provider selection and lifecycle contracts
devops_bench/deployers/factory.py, devops_bench/providers/*, tests/unit/deployers/test_deployers_factory.py, tests/unit/providers/test_providers.py
Provider deduction supports repository-contained provider directories. Provider interfaces accept OpenTofu outputs and cleanup status. Registry and selection tests cover vCluster and custom Terraform roots.
VCluster provider behavior
devops_bench/providers/vcluster.py, tests/unit/providers/test_vcluster_provider.py
The provider resolves contexts and variables, validates kubeconfig paths, writes secure kubeconfigs, and removes approved temporary resources.
OpenTofu lifecycle and output handling
devops_bench/deployers/tofu.py, tests/unit/deployers/test_deployers_tofu.py
TFDeployer normalizes and caches outputs and always invokes provider cleanup. Tests cover invalid output shapes and teardown paths.
VCluster OpenTofu stack
tf/modules/cluster/*
Terraform resources configure host Kubernetes access, service exposure, quotas, limits, Helm deployment, kubeconfig retrieval, and vCluster outputs.
OPA remediation integration
tf/prebuilt/opa-remediation/*
The remediation stack wires vCluster kubeconfig inputs and outputs. Setup checks Kubernetes, Kyverno, and PolicyReport readiness with bounded retries and stall detection.

Estimated code review effort: 5 (Critical) | ~120 minutes

Merge Risk: 🟡 Moderate · up to 771a7

The vcluster deployment changes can fail during provider initialization or chart rendering because incompatible Terraform provider versions remain allowed and the pinned chart rejects a configured key; an unresolved credential-output validation issue and a small file-descriptor leak also remain. The PR is not merge-ready until the deployment blockers are fixed or explicitly accepted.

Sequence Diagram(s)

sequenceDiagram
  participant TFDeployer
  participant VClusterProvider
  participant OpenTofu
  participant HostKubernetes
  TFDeployer->>VClusterProvider: resolve deployment variables
  VClusterProvider->>HostKubernetes: inspect context and detect Service CIDR
  TFDeployer->>OpenTofu: apply vCluster stack
  OpenTofu-->>TFDeployer: return normalized cluster outputs
  TFDeployer->>VClusterProvider: write generated kubeconfig
  VClusterProvider->>HostKubernetes: clean orphaned volumes and temporary kubeconfig
Loading

Suggested reviewers: janetkuo

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 26.23% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 61 functions across 8 files. (5 skipped: 5 unsupported.) Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: adding vcluster provider deduction to the deployer factory.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@kubernetes-prow kubernetes-prow Bot added the cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. label Aug 6, 2026
@kubernetes-prow
kubernetes-prow Bot requested a review from janetkuo August 6, 2026 20:12
@kubernetes-prow

Copy link
Copy Markdown

Hi @isadominguez314. Thanks for your PR.

I'm waiting for a kubernetes-sigs 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.

Regular contributors should join the org to skip this step.

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.

@kubernetes-prow kubernetes-prow Bot added needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels Aug 6, 2026
@isadominguez314

Copy link
Copy Markdown
Contributor Author

/hold

@kubernetes-prow kubernetes-prow Bot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Aug 6, 2026
@isadominguez314

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@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: 11

🧹 Nitpick comments (8)
tf/prebuilt/vcluster/main.tf (4)

137-158: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Set an explicit timeout for the Helm release.

wait = true and wait_for_jobs = true block until the release is ready, but no timeout is given, so the provider default of 300 seconds applies. A vCluster control plane on a loaded or local host cluster can exceed that. The apply then fails with a partially deployed release still in the namespace.

Add a variable-driven timeout, and consider cleanup_on_fail so a failed release does not leave orphaned objects for the provider cleanup path to find.

♻️ Proposed change
   wait          = true
   wait_for_jobs = true
+  timeout          = var.helm_timeout_seconds
+  cleanup_on_fail  = true

Add to tf/prebuilt/vcluster/variables.tf:

variable "helm_timeout_seconds" {
  description = "Seconds to wait for the vCluster Helm release to become ready."
  type        = number
  default     = 900
}
🤖 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 `@tf/prebuilt/vcluster/main.tf` around lines 137 - 158, Update the
helm_release.vcluster resource to set a variable-driven timeout using a new
helm_timeout_seconds variable in variables.tf, defaulting to 900 seconds with an
appropriate description. Enable cleanup_on_fail for failed releases so partially
deployed objects are removed during provider cleanup.

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

Define the external endpoint expression once. The same non-trivial conditional expression is written in both files. The two copies can drift, and any correction, including the empty-LoadBalancer-address fix, must be applied twice.

  • tf/prebuilt/vcluster/main.tf#L134-L134: keep local.external_endpoint as the single definition, and split the LoadBalancer branch into its own local as proposed in the separate comment on this line.
  • tf/prebuilt/vcluster/outputs.tf#L31-L34: replace the duplicated expression with value = local.external_endpoint.
🤖 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 `@tf/prebuilt/vcluster/main.tf` at line 134, In tf/prebuilt/vcluster/main.tf
lines 134-134, retain local.external_endpoint as the single definition and
extract the LoadBalancer branch into its own local as requested by the related
comment. In tf/prebuilt/vcluster/outputs.tf lines 31-34, remove the duplicated
conditional expression and set the output value to local.external_endpoint.

126-133: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

nodes[0] selection is unstable and can pick a node that does not serve the NodePort.

data.kubernetes_nodes.host_nodes.nodes has no guaranteed ordering. Two consequences follow:

  1. On a multi-node host cluster, nodes[0] may be a control-plane node whose address is not the one the caller can reach.
  2. If the ordering changes between plans, local.host_node_ip changes. That value flows through templatefile into helm_release.vcluster.values, so the release shows a diff and is updated for no functional reason.

Select the node deterministically, for example by sorting the candidate addresses, and prefer a worker node when one exists.

🤖 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 `@tf/prebuilt/vcluster/main.tf` around lines 126 - 133, Update the host_node_ip
expression to avoid relying on nodes[0]: derive candidate addresses from worker
nodes when available, fall back to all host nodes otherwise, and sort the
candidates before selecting one. Preserve the ExternalIP-over-InternalIP
preference and 127.0.0.1 fallback while ensuring stable selection across plans.

86-121: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff

Consider exposing the quota and limit-range sizing as variables.

The CPU, memory, storage, and PVC ceilings are hardcoded. A task that needs a larger or smaller virtual cluster must edit the stack. The values also duplicate the inner policies.resourceQuota values in values.yaml.tftpl (6 CPU, 24Gi), so the two can drift.

Promote the numbers to variables in tf/prebuilt/vcluster/variables.tf with the current values as defaults, and derive the template values from the same variables.

🤖 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 `@tf/prebuilt/vcluster/main.tf` around lines 86 - 121, Promote the hardcoded
CPU, memory, storage, PVC, and limit-range ceilings in the vcluster Terraform
configuration to variables in variables.tf, preserving the current values as
defaults. Update the resource quota and kubernetes_limit_range.vcluster_limits
definitions to reference those variables, and derive the corresponding
policies.resourceQuota values in values.yaml.tftpl from the same variables so
sizing cannot drift.
devops_bench/providers/vcluster.py (3)

286-290: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use get_env instead of os.environ.get for consistency.

This module already imports get_env and uses it at Lines 264, 265, 370, and 401. Lines 286 and 290 read the environment directly. The same pattern repeats in resolve_variables at Lines 373-374 and 379. Use one accessor so environment handling stays uniform.

♻️ Proposed change
-        host_kubeconfig = vars_dict.get("host_kubeconfig_path") or os.environ.get(
-            "HOST_KUBECONFIG", "~/.kube/config"
-        )
+        host_kubeconfig = (
+            vars_dict.get("host_kubeconfig_path")
+            or get_env("HOST_KUBECONFIG")
+            or "~/.kube/config"
+        )
         host_kubeconfig_path = str(Path(host_kubeconfig).expanduser().resolve())
-        host_context = vars_dict.get("host_kubecontext") or os.environ.get("HOST_KUBECONTEXT")
+        host_context = vars_dict.get("host_kubecontext") or get_env("HOST_KUBECONTEXT")
🤖 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 `@devops_bench/providers/vcluster.py` around lines 286 - 290, Replace the
direct os.environ.get calls for HOST_KUBECONFIG and HOST_KUBECONTEXT in the
visible kubeconfig/context resolution logic with the module’s existing get_env
accessor. Apply the same change to the corresponding environment lookups in
resolve_variables, preserving the current defaults and fallback behavior.

384-393: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Guard against a local host context combined with a LoadBalancer override.

The remote gate is clear and the default service_type selection is correct. One gap: service_type uses setdefault, so a task can pass service_type: "LoadBalancer" for a local host context, or "NodePort" for a remote one. The stack then builds a service that never gets a reachable endpoint, and external_endpoint resolves to an empty string. Consider validating the combination, or at least logging a warning when the caller override contradicts the detected host class.

🤖 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 `@devops_bench/providers/vcluster.py` around lines 384 - 393, Validate the
caller-provided service_type in the local/remote classification flow around
_is_allowlisted_context: reject or clearly warn when a local context specifies
LoadBalancer or a remote context specifies NodePort, while preserving the
existing defaults when no override is provided. Ensure contradictory overrides
cannot silently produce an unreachable endpoint.

149-154: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Log the swallowed parse failure before the name-based fallback.

If kubeconfig parsing fails, the function silently falls back to the context-name allowlist. That fallback is weaker than IP inspection, and the operator gets no signal about why. Add a debug or warning log with the exception.

♻️ Proposed change
-        except Exception:
-            pass
+        except Exception as exc:  # noqa: BLE001 - fall back to name allowlist
+            _log.warning(
+                "Failed to inspect kubeconfig %s for context %s; "
+                "falling back to context-name allowlist: %s",
+                kubeconfig_path,
+                context_name,
+                exc,
+            )
🤖 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 `@devops_bench/providers/vcluster.py` around lines 149 - 154, Update the
kubeconfig parsing exception handler in the surrounding context-checking
function to capture the exception and log it at debug or warning level before
continuing to the name-based fallback. Preserve the existing fallback return
logic using _EXACT_LOCAL_CONTEXTS and _LOCAL_CONTEXT_PREFIXES.

Source: Linters/SAST tools

tests/unit/providers/test_vcluster_provider.py (1)

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

Use a unique temp file name and remove it deterministically.

_is_safe_scratch_path requires the parent directory to equal the system temp directory, so tmp_path cannot be used here. The fixed name test-vcluster-clean-vc-config.yaml still collides between concurrent runs on the same machine, for example two CI jobs or pytest-xdist workers. If the assertion fails, the file also stays behind.

Create the file with tempfile.mkstemp and remove it in a finally block.

♻️ Proposed change
 def test_vcluster_cleanup_deletes_scratch_kubeconfig(
     mocker: MockerFixture,
 ) -> None:
     mocker.patch("devops_bench.providers.vcluster.run")
-    scratch_file = Path(tempfile.gettempdir()) / "test-vcluster-clean-vc-config.yaml"
-    scratch_file.write_text("test-kubeconfig", encoding="utf-8")
-
-    info = ClusterInfo(
-        name="test-cluster",
-        location="local",
-        project="local-vcluster",
-        kubeconfig_path=str(scratch_file),
-    )
-    VClusterProvider().cleanup(
-        info,
-        variables={
-            "host_kubeconfig_path": "/fake/host",
-            "host_kubecontext": "kind-host",
-        },
-    )
-
-    assert not scratch_file.exists()
+    fd, raw_path = tempfile.mkstemp(prefix="test-vcluster-clean-", suffix=".yaml")
+    os.close(fd)
+    scratch_file = Path(raw_path)
+    try:
+        scratch_file.write_text("test-kubeconfig", encoding="utf-8")
+
+        info = ClusterInfo(
+            name="test-cluster",
+            location="local",
+            project="local-vcluster",
+            kubeconfig_path=str(scratch_file),
+        )
+        VClusterProvider().cleanup(
+            info,
+            variables={
+                "host_kubeconfig_path": "/fake/host",
+                "host_kubecontext": "kind-host",
+            },
+        )
+
+        assert not scratch_file.exists()
+    finally:
+        scratch_file.unlink(missing_ok=True)

Add import os for this change.

🤖 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/unit/providers/test_vcluster_provider.py` around lines 246 - 267,
Update test_vcluster_cleanup_deletes_scratch_kubeconfig to create a uniquely
named file directly under the system temp directory using tempfile.mkstemp,
adding the required os import and closing the returned descriptor before
writing. Wrap the cleanup invocation and assertion in a finally block that
deterministically removes the temporary file, while preserving the existing
cleanup assertion.
🤖 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 `@devops_bench/deployers/factory.py`:
- Around line 38-44: Update the generic deployer docstrings and ConfigError
message in the factory logic to remove provider-specific “gcp” terminology,
replacing it with neutral wording such as “supported provider” or “supported
in-repository stack.” Apply the change at the referenced sections while
preserving the existing provider deduction and validation behavior.
- Around line 61-63: Update the stack-provider deduction logic around stack_path
so relative candidates are resolved against the repository tf/ root and only
auto-deduced when the resolved path remains within that root; otherwise require
explicit provider selection. Preserve the existing kind, vcluster, and gcp name
matching for valid in-root paths.

In `@devops_bench/deployers/tofu.py`:
- Around line 257-280: The teardown flow around the try/finally block must not
invoke destructive provider cleanup unless both initialization and tofu destroy
complete successfully. Track teardown success after the destroy command, pass
that status through the cleanup contract used by provider.cleanup (including
VClusterProvider.cleanup), and ensure missing directories or failed commands
only perform safe local cleanup without deleting provider resources.

In `@devops_bench/providers/vcluster.py`:
- Around line 263-272: Remove or tighten the TF_DATA_DIR condition in the
path-safety return within the cleanup validation so sibling files are not
treated as deletable. Only allow TF_DATA_DIR-related paths when the TF_DATA_DIR
parent is contained by tmp_dir or BENCH_RUN_STATE_ROOT, or when the candidate
path is already within a known run root; preserve the existing tmp_dir and
BENCH_RUN_STATE_ROOT checks.
- Around line 203-238: Update the kubeconfig write path after parent-directory
creation to open raw_target with os.O_NOFOLLOW, preserving the existing write
flags and file mode so the kernel atomically rejects a final-component symlink.
Convert the resulting OSError into the existing ConfigError behavior/message,
and stop relying on the resolved_target symlink re-check for this protection.
- Around line 213-214: Update the NodePort rewrite condition in
ensure_cluster_credentials to depend on service_type being "NodePort" and
node_port being present, rather than location being "local". Add coverage for a
non-local location with NodePort service_type and node_port, asserting the
kubeconfig server URL is rewritten.

In `@tests/unit/deployers/test_deployers_factory.py`:
- Line 307: Add type annotations to all five specified test functions:
tests/unit/deployers/test_deployers_factory.py lines 307, 327, and 344, and
tests/unit/deployers/test_deployers_tofu.py lines 163-165 and 273. Annotate
every fixture parameter (mocker, base_config, and monkeypatch where present)
using the project’s existing fixture types and add a None return annotation.

In `@tests/unit/providers/test_vcluster_provider.py`:
- Around line 315-320: Update the ClusterInfo construction in the affected test
to pass an empty string for kubeconfig_path instead of None, matching the
field’s declared str type while preserving cleanup behavior.

In `@tf/prebuilt/vcluster/main.tf`:
- Line 134: Add a lifecycle precondition to helm_release.vcluster that rejects
local.external_endpoint when it is empty or ends with “:”, with an error
explaining that the LoadBalancer address is not assigned. Keep the existing
external_endpoint resolution unchanged and ensure the Helm release fails before
rendering an unusable kubeconfig.

In `@tf/prebuilt/vcluster/values.yaml.tftpl`:
- Line 75: Remove the hardcoded serviceCIDR from the vcluster values template so
the chart can discover the host cluster range, or wire it to a new optional
service_cidr variable from the vcluster Terraform configuration with an empty
default. Update the corresponding main.tf Helm values flow and variables.tf
declaration, preserving automatic detection when no value is supplied.
- Around line 77-81: Update the vCluster values configuration around
experimental.syncSettings.syncLabels so virtual PVC/PV objects that claim host
PVs receive the devops-bench/cluster-name label populated from cluster_name.
Preserve the existing syncLabels entries, and ensure the label contract remains
effective when the default cluster_name value is empty so
VClusterProvider.cleanup can select the synced PVs.

---

Nitpick comments:
In `@devops_bench/providers/vcluster.py`:
- Around line 286-290: Replace the direct os.environ.get calls for
HOST_KUBECONFIG and HOST_KUBECONTEXT in the visible kubeconfig/context
resolution logic with the module’s existing get_env accessor. Apply the same
change to the corresponding environment lookups in resolve_variables, preserving
the current defaults and fallback behavior.
- Around line 384-393: Validate the caller-provided service_type in the
local/remote classification flow around _is_allowlisted_context: reject or
clearly warn when a local context specifies LoadBalancer or a remote context
specifies NodePort, while preserving the existing defaults when no override is
provided. Ensure contradictory overrides cannot silently produce an unreachable
endpoint.
- Around line 149-154: Update the kubeconfig parsing exception handler in the
surrounding context-checking function to capture the exception and log it at
debug or warning level before continuing to the name-based fallback. Preserve
the existing fallback return logic using _EXACT_LOCAL_CONTEXTS and
_LOCAL_CONTEXT_PREFIXES.

In `@tests/unit/providers/test_vcluster_provider.py`:
- Around line 246-267: Update test_vcluster_cleanup_deletes_scratch_kubeconfig
to create a uniquely named file directly under the system temp directory using
tempfile.mkstemp, adding the required os import and closing the returned
descriptor before writing. Wrap the cleanup invocation and assertion in a
finally block that deterministically removes the temporary file, while
preserving the existing cleanup assertion.

In `@tf/prebuilt/vcluster/main.tf`:
- Around line 137-158: Update the helm_release.vcluster resource to set a
variable-driven timeout using a new helm_timeout_seconds variable in
variables.tf, defaulting to 900 seconds with an appropriate description. Enable
cleanup_on_fail for failed releases so partially deployed objects are removed
during provider cleanup.
- Line 134: In tf/prebuilt/vcluster/main.tf lines 134-134, retain
local.external_endpoint as the single definition and extract the LoadBalancer
branch into its own local as requested by the related comment. In
tf/prebuilt/vcluster/outputs.tf lines 31-34, remove the duplicated conditional
expression and set the output value to local.external_endpoint.
- Around line 126-133: Update the host_node_ip expression to avoid relying on
nodes[0]: derive candidate addresses from worker nodes when available, fall back
to all host nodes otherwise, and sort the candidates before selecting one.
Preserve the ExternalIP-over-InternalIP preference and 127.0.0.1 fallback while
ensuring stable selection across plans.
- Around line 86-121: Promote the hardcoded CPU, memory, storage, PVC, and
limit-range ceilings in the vcluster Terraform configuration to variables in
variables.tf, preserving the current values as defaults. Update the resource
quota and kubernetes_limit_range.vcluster_limits definitions to reference those
variables, and derive the corresponding policies.resourceQuota values in
values.yaml.tftpl from the same variables so sizing cannot drift.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 9fd4b167-5c0e-46c1-a1c8-5d3d65a53c90

📥 Commits

Reviewing files that changed from the base of the PR and between 4670d76 and 53caf44.

📒 Files selected for processing (17)
  • devops_bench/deployers/factory.py
  • devops_bench/deployers/tofu.py
  • devops_bench/providers/__init__.py
  • devops_bench/providers/base.py
  • devops_bench/providers/gcp.py
  • devops_bench/providers/kind.py
  • devops_bench/providers/vcluster.py
  • tasks/vcluster/smoke-test/task.yaml
  • tests/unit/deployers/test_deployers_factory.py
  • tests/unit/deployers/test_deployers_tofu.py
  • tests/unit/providers/test_providers.py
  • tests/unit/providers/test_vcluster_provider.py
  • tf/prebuilt/vcluster/.terraform.lock.hcl
  • tf/prebuilt/vcluster/main.tf
  • tf/prebuilt/vcluster/outputs.tf
  • tf/prebuilt/vcluster/values.yaml.tftpl
  • tf/prebuilt/vcluster/variables.tf

Comment thread devops_bench/deployers/factory.py Outdated
Comment thread devops_bench/deployers/factory.py Outdated
Comment thread devops_bench/deployers/tofu.py Outdated
Comment thread devops_bench/providers/vcluster.py
Comment thread devops_bench/providers/vcluster.py Outdated
Comment thread tests/unit/deployers/test_deployers_factory.py
Comment thread tests/unit/providers/test_vcluster_provider.py
Comment thread tf/modules/cluster/vcluster/main.tf
Comment thread tf/prebuilt/vcluster/values.yaml.tftpl Outdated
Comment thread tf/modules/cluster/vcluster/values.yaml.tftpl Outdated
@isadominguez314
isadominguez314 force-pushed the feat/vcluster-factory-and-smoke-test branch 2 times, most recently from d1d48bb to 53f65d9 Compare August 9, 2026 21:14
@janetkuo janetkuo added ok-to-test Indicates a non-member PR verified by an org member that is safe to test. and removed needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels Aug 11, 2026
Implement specification for standalone Loft Labs vCluster provisioning:
- Add main.tf with standalone Stage 1 LoadBalancer exposure service and Stage 2 Helm release.
- Validate external endpoint, dynamically discover serviceCIDR, inject devops-bench labels.
- Wire vcluster into generic tf/modules/cluster.
- Update opa-remediation prebuilt to wait for vcluster API server and resolve kubeconfigs dynamically.
@isadominguez314
isadominguez314 force-pushed the feat/vcluster-factory-and-smoke-test branch 2 times, most recently from 1ea4835 to 48e1026 Compare August 12, 2026 20:32
@isadominguez314
isadominguez314 force-pushed the feat/vcluster-factory-and-smoke-test branch from 48e1026 to 49bef7c Compare August 12, 2026 21:45
@isadominguez314 isadominguez314 changed the title feat(deployers): implement vcluster factory deduction and smoke test task feat(deployers): implement vcluster factory deduction Aug 13, 2026
@isadominguez314
isadominguez314 force-pushed the feat/vcluster-factory-and-smoke-test branch from 49bef7c to 35ee429 Compare August 18, 2026 17:46
- Move tf/prebuilt/vcluster to tf/modules/cluster/vcluster to fix inverted dependency.
- Update tf/modules/cluster/main.tf to use the new vcluster submodule path.
- Change default service_type in vcluster/variables.tf to LoadBalancer to match parent module.
- Format opa-remediation main.tf
@isadominguez314
isadominguez314 force-pushed the feat/vcluster-factory-and-smoke-test branch from 35ee429 to 59053d9 Compare August 18, 2026 20:04
@isadominguez314
isadominguez314 force-pushed the feat/vcluster-factory-and-smoke-test branch from 59053d9 to 2f37144 Compare August 19, 2026 21:12
Comment thread devops_bench/deployers/factory.py Outdated
@isadominguez314
isadominguez314 force-pushed the feat/vcluster-factory-and-smoke-test branch from 2f37144 to 5d8ecf0 Compare August 19, 2026 22:36
@isadominguez314
isadominguez314 force-pushed the feat/vcluster-factory-and-smoke-test branch from 4a94d2f to c9dcbc3 Compare August 20, 2026 21:36
@isadominguez314
isadominguez314 force-pushed the feat/vcluster-factory-and-smoke-test branch from b0fd487 to 63e80df Compare August 21, 2026 17:33
@isadominguez314
isadominguez314 force-pushed the feat/vcluster-factory-and-smoke-test branch from 63e80df to 5e4fc3f Compare August 21, 2026 18:59

@janetkuo janetkuo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

/lgtm

@kubernetes-prow kubernetes-prow Bot added lgtm "Looks good to me", indicates that a PR is ready to be merged. approved Indicates a PR has been approved by an approver from all required OWNERS files. labels Aug 21, 2026
…tegration

Implement specification for CL 2:
- Add VClusterProvider with inline no-op account credentials, two-step local allowlist check, and secure kubeconfig writing (0600) / PV cleanup.
- Modify TFDeployer to cache ClusterInfo, pass unwrapped outputs to ensure_cluster_credentials(), and call provider.cleanup() on destroy.
- Update base Provider, GcpProvider, and KindProvider signatures for CL 2 compatibility.
- Add unit tests for VClusterProvider and register provider in PROVIDERS.
Implement specification for CL 3:
- Update _select_provider() in factory.py to match 'vcluster' and 'gcp' by stack directory name and update ConfigError message.
- Add unit tests in test_deployers_factory.py for vcluster stack directory deduction and INFRA_PROVIDER=vcluster override.
…, shared resolve_tf_root, and test assertions
@isadominguez314
isadominguez314 force-pushed the feat/vcluster-factory-and-smoke-test branch from 5e4fc3f to d8415ea Compare August 21, 2026 22:14
@kubernetes-prow kubernetes-prow Bot removed the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Aug 21, 2026
@isadominguez314

Copy link
Copy Markdown
Contributor Author

/unhold

@kubernetes-prow kubernetes-prow Bot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Aug 24, 2026

@janetkuo janetkuo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

/lgtm

@kubernetes-prow kubernetes-prow Bot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Aug 24, 2026
@kubernetes-prow

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: isadominguez314, itssimrank, janetkuo

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

The pull request process is described 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

@kubernetes-prow
kubernetes-prow Bot merged commit d6f27de into kubernetes-sigs:main Aug 24, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. ok-to-test Indicates a non-member PR verified by an org member that is safe to test. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants