Skip to content
This repository was archived by the owner on Sep 9, 2026. It is now read-only.

Add compute instance scenario, mock server, and e2e test - #385

Merged
openshift-merge-bot[bot] merged 5 commits into
osac-project:mainfrom
tzvatot:feature/ci-test-server-scenario
Apr 15, 2026
Merged

openshift-merge-bot[bot] merged 5 commits into
osac-project:mainfrom
tzvatot:feature/ci-test-server-scenario

Conversation

@tzvatot

@tzvatot tzvatot commented Apr 9, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Add ComputeInstanceScenario with YAML loader for test data
  • Add MockComputeInstancesServer and MockComputeInstanceTemplatesServer with basic filter support
  • Add e2e test validating full CRUD lifecycle (list templates, create/get/list/delete instances)
  • Add standalone test server binary (cmd/test-server) for manual CLI testing

Ported from archived fulfillment-cli repo (PR #100).

Test plan

  • All 35 unit test suites pass (ginkgo run -r internal)
  • E2e test passes: in-process gRPC server with mock scenario
  • Manual CLI lifecycle verified against test server: list templates, create, list, describe, delete, verify deleted

Generated with Claude Code

Summary by CodeRabbit

  • Tests

    • Added end-to-end tests validating compute instance create/list/get/delete workflows.
    • Added in-process mock gRPC servers to simulate compute instance and template behavior for deterministic test runs.
    • Added a test suite entrypoint to run the new specs.
  • Chores

    • Added a local test-server tool to run a mock fulfillment service for development/CI.
    • Added scenario-driven test fixtures, test helpers/models, and YAML testdata to seed templates and instances for testing.

tzvatot added 2 commits April 9, 2026 15:48
Port from archived fulfillment-cli repo (PR osac-project#100):
- Add ComputeInstanceScenario with YAML loader for test data
- Add MockComputeInstancesServer and MockComputeInstanceTemplatesServer
- Add e2e test validating full CRUD lifecycle (list templates, list/create/get/delete instances)

Generated with [Claude Code](https://claude.com/claude-code)
Standalone gRPC server that registers mock compute instance and template
servers with scenario data, enabling manual CLI lifecycle testing.

Generated with [Claude Code](https://claude.com/claude-code)
@coderabbitai

coderabbitai Bot commented Apr 9, 2026 •

Copy link
Copy Markdown

Walkthrough

Adds testing infrastructure for compute instances: a new gRPC test-server CLI at cmd/test-server/main.go that loads a YAML scenario; test scenario types and a YAML loader in internal/testing/compute_instance_scenario.go; in-memory mock gRPC servers for compute instances and templates in internal/testing/mock_compute_instances_server.go; a YAML testdata file internal/testing/testdata/compute-instance-scenario.yaml; and a Ginkgo/Gomega end-to-end test plus suite in internal/cmd/cli/create/computeinstance/ exercising create/list/get/delete flows.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

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.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: adding compute instance scenario, mock server, and e2e test, which are the primary components introduced across all modified files.

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

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

Warning

Review ran into problems

🔥 Problems

Timed out fetching pipeline failures after 30000ms


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

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (2)
internal/testing/compute_instance_scenario.go (1)

79-82: Use strict YAML decoding to catch misspelled fields early.

yaml.Unmarshal ignores unknown keys, so fixture typos can slip through silently.

♻️ Proposed fix
 import (
+	"bytes"
 	"fmt"
 	"os"
@@
 	var file computeInstanceScenarioFile
-	if err := yaml.Unmarshal(data, &file); err != nil {
+	decoder := yaml.NewDecoder(bytes.NewReader(data))
+	decoder.KnownFields(true)
+	if err := decoder.Decode(&file); err != nil {
 		return nil, fmt.Errorf("failed to parse scenario YAML: %w", err)
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/testing/compute_instance_scenario.go` around lines 79 - 82, Replace
the permissive yaml.Unmarshal call with a strict decoder so unknown/misspelled
fields fail fast: create a yaml.NewDecoder over the input data, call
decoder.KnownFields(true), then Decode into the computeInstanceScenarioFile
variable (file) and propagate the returned error; update the error message to
reflect strict YAML decoding failure where the function currently uses
yaml.Unmarshal and the computeInstanceScenarioFile type is being populated.
cmd/test-server/main.go (1)

31-37: Make the default scenario path resilient for standalone execution.

Using a repo-relative default path is brittle when running the compiled binary from another working directory.

♻️ Proposed fix
 import (
 	"flag"
 	"fmt"
 	"log"
 	"net"
+	"path/filepath"
+	"runtime"
@@
 const (
 	serverPort            = "8080"
-	defaultCIScenarioFile = "internal/testing/testdata/compute-instance-scenario.yaml"
 )
+
+func defaultScenarioPath() string {
+	_, thisFile, _, ok := runtime.Caller(0)
+	if !ok {
+		return "internal/testing/testdata/compute-instance-scenario.yaml"
+	}
+	return filepath.Clean(filepath.Join(filepath.Dir(thisFile), "..", "..", "internal", "testing", "testdata", "compute-instance-scenario.yaml"))
+}
 
 func main() {
-	ciScenarioFile := flag.String("ci-scenario", defaultCIScenarioFile, "Path to compute instance scenario YAML file")
+	ciScenarioFile := flag.String("ci-scenario", defaultScenarioPath(), "Path to compute instance scenario YAML file")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/test-server/main.go` around lines 31 - 37, The defaultCIScenarioFile
constant is repo-relative and brittle when the binary is run from another CWD;
update main to compute the default at runtime: in main (where ciScenarioFile is
created) determine the executable's directory via os.Executable(), resolve the
default path with filepath.Join(execDir,
"internal/testing/testdata/compute-instance-scenario.yaml"), and use that as the
default for the -ci-scenario flag (falling back to the existing repo-relative
constant if os.Executable() fails); update references to
defaultCIScenarioFile/serverPort only as needed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/cmd/cli/create/computeinstance/computeinstance_e2e_test.go`:
- Around line 149-153: The test currently checks only that an error occurred
after calling instanceClient.Get(ctx, &publicv1.ComputeInstancesGetRequest{Id:
createdID}), which can hide unrelated failures; replace the generic
Expect(err).To(HaveOccurred()) with an assertion that the gRPC status code is
codes.NotFound by extracting the status from err (using status.FromError or
status.Code) and comparing to grpc codes.NotFound; update imports to include
"google.golang.org/grpc/status" and "google.golang.org/grpc/codes" and assert
the specific NotFound code for the Get call on createdID.

In `@internal/testing/compute_instance_scenario.go`:
- Around line 84-85: file.toScenario() (and any helper used in the 87-116 block
that maps the `state` string to the proto enum) currently lets unknown state
strings fall through to COMPUTE_INSTANCE_STATE_UNSPECIFIED; change the
conversion so you validate the input string against the enum's allowed values
and return a clear error instead of returning an unspecified value. Locate the
mapping logic inside toScenario() (or the helper that maps `state` strings to
the ComputeInstance_State enum) and replace the blind conversion with a lookup
that fails on unknown keys (use the proto enum name/value map or a switch that
returns an error for default cases) so invalid scenario data is surfaced rather
than masked.

In `@internal/testing/mock_compute_instances_server.go`:
- Around line 159-163: The current substring filter on templateData.ID and
templateData.Name is too loose; change the logic in the template-listing code
that applies the "filter" (where templateData.ID and templateData.Name are
checked) to require exact matches instead of substrings: treat filter as either
the full ID or the full name (use strings.EqualFold for name to be
case-insensitive) and skip the template only when neither exact ID nor exact
name matches; optionally support simple "id:<value>" or "name:<value>" prefixes
by parsing the filter before comparison if you want explicit field scoping.
- Around line 53-79: In Create on MockComputeInstancesServer validate that the
incoming instance has a non-nil Spec and Spec.Template with a non-empty Id and
that the Template Id exists in the mock's known templates (e.g., check
s.templates or whatever map stores valid templates); if missing or unknown
return status.Error(codes.InvalidArgument, "spec.template is required/unknown
template id") so tests fail fast and mock behavior matches real validation.
Ensure this check happens before assigning IDs/state and storing in s.instances.

---

Nitpick comments:
In `@cmd/test-server/main.go`:
- Around line 31-37: The defaultCIScenarioFile constant is repo-relative and
brittle when the binary is run from another CWD; update main to compute the
default at runtime: in main (where ciScenarioFile is created) determine the
executable's directory via os.Executable(), resolve the default path with
filepath.Join(execDir,
"internal/testing/testdata/compute-instance-scenario.yaml"), and use that as the
default for the -ci-scenario flag (falling back to the existing repo-relative
constant if os.Executable() fails); update references to
defaultCIScenarioFile/serverPort only as needed.

In `@internal/testing/compute_instance_scenario.go`:
- Around line 79-82: Replace the permissive yaml.Unmarshal call with a strict
decoder so unknown/misspelled fields fail fast: create a yaml.NewDecoder over
the input data, call decoder.KnownFields(true), then Decode into the
computeInstanceScenarioFile variable (file) and propagate the returned error;
update the error message to reflect strict YAML decoding failure where the
function currently uses yaml.Unmarshal and the computeInstanceScenarioFile type
is being populated.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 67ce3abe-6822-4498-ade8-35e0fe9f2a66

📥 Commits

Reviewing files that changed from the base of the PR and between 50cc23e and fee5b23.

📒 Files selected for processing (6)
  • cmd/test-server/main.go
  • internal/cmd/cli/create/computeinstance/computeinstance_e2e_test.go
  • internal/cmd/cli/create/computeinstance/computeinstance_suite_test.go
  • internal/testing/compute_instance_scenario.go
  • internal/testing/mock_compute_instances_server.go
  • internal/testing/testdata/compute-instance-scenario.yaml

Comment thread internal/cmd/cli/create/computeinstance/computeinstance_e2e_test.go
Comment thread internal/testing/compute_instance_scenario.go Outdated
Comment thread internal/testing/mock_compute_instances_server.go
Comment thread internal/testing/mock_compute_instances_server.go
@openshift-ci

openshift-ci Bot commented Apr 9, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: jhernand, tzvatot

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

@openshift-ci openshift-ci Bot removed the lgtm label Apr 12, 2026
@openshift-ci

openshift-ci Bot commented Apr 12, 2026

Copy link
Copy Markdown

New changes are detected. LGTM label has been removed.

- Assert NotFound status code in e2e test after delete
- Validate enum strings in scenario loader, return error on unknown state
- Use quoted literal matching in template filter to avoid partial matches

Generated with [Claude Code](https://claude.com/claude-code)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/testing/compute_instance_scenario.go`:
- Around line 96-103: The loop over f.Templates (and similarly f.Instances)
dereferences potential nil YAML entries causing a panic; add a nil-check inside
the loops (for i, t := range f.Templates and for i, inst := range f.Instances)
and if an element is nil return a descriptive error (e.g. "nil template entry at
index %d" or "nil instance entry at index %d") instead of assigning into
scenario.Templates or scenario.Instances; perform these checks before
constructing TemplateData/InstanceData to ensure safe dereference and consistent
structured error handling.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8871c59b-e739-4594-b682-4cf4c5bc42f5

📥 Commits

Reviewing files that changed from the base of the PR and between 7247738 and 6fa6acb.

📒 Files selected for processing (3)
  • internal/cmd/cli/create/computeinstance/computeinstance_e2e_test.go
  • internal/testing/compute_instance_scenario.go
  • internal/testing/mock_compute_instances_server.go
✅ Files skipped from review due to trivial changes (1)
  • internal/cmd/cli/create/computeinstance/computeinstance_e2e_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/testing/mock_compute_instances_server.go

Comment thread internal/testing/compute_instance_scenario.go
The mock server now validates that the template ID exists in the
scenario's known templates before accepting a create request,
matching real server behavior.

Generated with [Claude Code](https://claude.com/claude-code)

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

🧹 Nitpick comments (1)
internal/testing/mock_compute_instances_server.go (1)

109-116: Consider deterministic ordering for instance List output.

Map iteration order is random, so response order may vary run-to-run. Sorting before returning helps keep CLI/e2e assertions stable.

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

In `@internal/testing/mock_compute_instances_server.go` around lines 109 - 116,
The List method on MockComputeInstancesServer builds a slice from the
s.instances map which iterates in random order; make the response deterministic
by sorting the instances slice before returning (e.g., use sort.Slice on the
local instances slice and compare a stable key such as
publicv1.ComputeInstance.GetId() or .GetName()). Update the List function to
import "sort" if needed and perform the sort on instances after the append loop
so CLI/e2e assertions are stable.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/testing/mock_compute_instances_server.go`:
- Around line 37-47: The constructor NewMockComputeInstancesServer dereferences
scenario.Instances unconditionally which panics if scenario is nil; update
NewMockComputeInstancesServer to guard against a nil scenario by checking if
scenario == nil and either initialize scenario = &ComputeInstanceScenario{} or
return a server with an empty instances map, then safely iterate over
scenario.Instances (nil-safe) to pre-populate server.instances; refer to
NewMockComputeInstancesServer and ComputeInstanceScenario and the
scenario.Instances loop when applying the change.
- Around line 75-90: The Create handler currently always writes to
s.instances[instance.Id] which silently overwrites on ID collision; update the
logic in Create (mock server method that manipulates s.nextID and s.instances)
to first check whether an entry exists for instance.Id and if so return an error
(e.g., AlreadyExists) instead of replacing it; if using auto-generated IDs
(s.nextID path), loop/generate until a non-colliding ID is found (or fail after
N attempts) before assigning instance.Id and storing into s.instances to avoid
races/overwrites.

---

Nitpick comments:
In `@internal/testing/mock_compute_instances_server.go`:
- Around line 109-116: The List method on MockComputeInstancesServer builds a
slice from the s.instances map which iterates in random order; make the response
deterministic by sorting the instances slice before returning (e.g., use
sort.Slice on the local instances slice and compare a stable key such as
publicv1.ComputeInstance.GetId() or .GetName()). Update the List function to
import "sort" if needed and perform the sort on instances after the append loop
so CLI/e2e assertions are stable.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 16ba1836-ea3f-4fd8-b519-379e3fe9f301

📥 Commits

Reviewing files that changed from the base of the PR and between 6fa6acb and fbc9fbb.

📒 Files selected for processing (1)
  • internal/testing/mock_compute_instances_server.go

Comment thread internal/testing/mock_compute_instances_server.go
Comment thread internal/testing/mock_compute_instances_server.go
@tzvatot tzvatot added the lgtm label Apr 15, 2026
@openshift-merge-bot
openshift-merge-bot Bot merged commit e3b00d3 into osac-project:main Apr 15, 2026
12 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants