Skip to content

OSAC-1210: Add InstanceType servers with CRUD, state lifecycle, and CLI rendering#660

Open
ygalblum wants to merge 8 commits into
osac-project:mainfrom
ygalblum:feat/instancetype-server
Open

OSAC-1210: Add InstanceType servers with CRUD, state lifecycle, and CLI rendering#660
ygalblum wants to merge 8 commits into
osac-project:mainfrom
ygalblum:feat/instancetype-server

Conversation

@ygalblum

@ygalblum ygalblum commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements the InstanceType server layer for the fulfillment-service, providing a catalog of pre-configured compute bundles (cores, memory) that users reference by name when creating VMs.

  • Private InstanceTypes server — full CRUD + Signal with spec immutability enforcement (cores/memory/name cannot change after creation), bidirectional state transitions (ACTIVE ↔ DEPRECATED ↔ OBSOLETE) with auto-populated timestamps, and deletion protection that checks for ComputeInstance references before allowing removal
  • Public InstanceTypes server — wraps the private server via GenericMapper for field mapping; List defaults to showing only ACTIVE+DEPRECATED instance types (OBSOLETE requires explicit filter), following the established host_types_server pattern
  • CLI table rendering — YAML table definitions for both public and private APIs with columns for NAME, CORES, MEMORY, STATE, and DESCRIPTION
  • gRPC and REST registration — both servers registered in the gRPC startup command and REST gateway

Jira

Key Design Decisions

  • id == name: Instance types use their name as the unique identifier, matching cloud-native patterns (e.g., m5.xlarge)
  • Immutable core fields: cores, memory_gib, and name cannot be modified after creation — changing compute specs requires creating a new instance type
  • State lifecycle: Three states with admin-controlled transitions and auto-populated timestamps (deprecated_at, obsoleted_at)
  • Default visibility: Public List hides OBSOLETE instance types unless explicitly filtered, so users see only usable types by default

Test plan

  • ginkgo run -r internal/servers — unit tests for private and public server logic
  • buf lint — proto lint passes
  • go build ./... — clean build
  • ginkgo run it — integration tests pass with new servers registered

Summary by CodeRabbit

Release Notes

  • New Features

    • Added Instance Types API with full CRUD support (create, read, list, update, delete)
    • Instance types now support state management (ACTIVE, DEPRECATED, OBSOLETE)
    • Public API lists only ACTIVE and DEPRECATED instance types by default, with filtering support for other states
    • Deletion protection prevents removing instance types referenced by compute instances
    • Added REST gateway support for instance types endpoints
    • Enhanced CEL filter support for enum field comparisons
  • Tests

    • Added comprehensive integration and unit test coverage for Instance Types API

@openshift-ci-robot

openshift-ci-robot commented Jun 8, 2026

Copy link
Copy Markdown

@ygalblum: This pull request references OSAC-1210 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the task to target the "5.0.0" version, but no target version was set.

Details

In response to this:

Summary

Implements the InstanceType server layer for the fulfillment-service, providing a catalog of pre-configured compute bundles (cores, memory) that users reference by name when creating VMs.

  • Private InstanceTypes server — full CRUD + Signal with spec immutability enforcement (cores/memory/name cannot change after creation), bidirectional state transitions (ACTIVE ↔ DEPRECATED ↔ OBSOLETE) with auto-populated timestamps, and deletion protection that checks for ComputeInstance references before allowing removal
  • Public InstanceTypes server — wraps the private server via GenericMapper for field mapping; List defaults to showing only ACTIVE+DEPRECATED instance types (OBSOLETE requires explicit filter), following the established host_types_server pattern
  • CLI table rendering — YAML table definitions for both public and private APIs with columns for NAME, CORES, MEMORY, STATE, and DESCRIPTION
  • gRPC and REST registration — both servers registered in the gRPC startup command and REST gateway

Jira

Key Design Decisions

  • id == name: Instance types use their name as the unique identifier, matching cloud-native patterns (e.g., m5.xlarge)
  • Immutable core fields: cores, memory_gib, and name cannot be modified after creation — changing compute specs requires creating a new instance type
  • State lifecycle: Three states with admin-controlled transitions and auto-populated timestamps (deprecated_at, obsoleted_at)
  • Default visibility: Public List hides OBSOLETE instance types unless explicitly filtered, so users see only usable types by default

Test plan

  • ginkgo run -r internal/servers — unit tests for private and public server logic
  • buf lint — proto lint passes
  • go build ./... — clean build
  • ginkgo run it — integration tests pass with new servers registered

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

@openshift-ci openshift-ci Bot requested review from akshaynadkarni and trewest June 8, 2026 22:34
@coderabbitai

coderabbitai Bot commented Jun 8, 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

This PR implements the complete gRPC InstanceTypes service across public and private APIs, including CRUD operations, state-transition management, deletion guards, enum-aware filtering, integration tests, and supporting infrastructure refactoring.

Changes

Instance Types Vertical Slice

Layer / File(s) Summary
Reference checker abstraction and implementations
internal/servers/reference_checker.go, internal/servers/reference_checker_mock.go
New generic interface for reference checking (DAO-backed and SQL-backed implementations) to block deletion when dependent resources exist.
Private server builder and CRUD operations
internal/servers/private_instance_types_server.go
PrivateInstanceTypesServer validates mandatory dependencies, implements List/Get/Create/Update/Delete/Signal with spec validation, field-mask updates, immutability constraints, deprecation/obsolescence timestamps, and reference-guard deletion.
Public server adapter and filtering
internal/servers/instance_types_server.go
Public InstanceTypesServer maps between public/private models, applies default CEL state filter (ACTIVE+DEPRECATED) unless caller references spec.state, and delegates CRUD to private server.
DAO enum-aware filter translation
internal/database/dao/filter_translator.go
Extends CEL→SQL translation to recognize protobuf enum fields in JSON, preserve int64 literals, resolve enum numeric values to names, and emit string comparisons with proper escaping.
gRPC startup, REST gateway, and auth allowlists
internal/cmd/service/start/grpcserver/start_grpc_server_cmd.go, internal/cmd/service/start/restgateway/start_rest_gateway_cmd.go, charts/service/templates/grpc-server/authconfig.yaml, manifests/base/grpc-server/authconfig.yaml
Constructs and registers public/private InstanceTypes servers during startup; registers REST handlers; adds client-permission allowlist entries for Get/List methods.
Table rendering configuration
internal/rendering/tables/osac.private.v1.InstanceType.yaml, internal/rendering/tables/osac.public.v1.InstanceType.yaml
Defines table schemas for NAME, CORES, MEMORY, STATE, DESCRIPTION columns.
Refactor catalog item servers to use generic reference checker
internal/servers/cluster_catalog_items_server.go, internal/servers/compute_instance_catalog_items_server.go, internal/servers/private_cluster_catalog_items_server.go, internal/servers/private_compute_instance_catalog_items_server.go, internal/servers/cluster_catalog_items_server_test.go, internal/servers/compute_instance_catalog_items_server_test.go, internal/servers/private_cluster_catalog_items_server_test.go, internal/servers/private_compute_instance_catalog_items_server_test.go
Updates existing servers to use the new generic referenceChecker abstraction with explicit specField configuration.
Unit tests for server builders and behavior
internal/servers/instance_types_server_test.go, internal/servers/private_instance_types_server_test.go
Validates builder dependencies, CRUD operations, metadata validation, state transitions, immutability, deletion protection, and filtering semantics.
DAO filter translator and generic DAO tests
internal/database/dao/filter_translator_test.go, internal/database/dao/generic_dao_test.go
Tests enum translation success/error cases and DAO filtering by enum fields.
End-to-end integration tests
it/it_private_instance_types_test.go, it/it_public_instance_types_test.go
Full lifecycle testing: create/list/get/update/delete, state transitions, immutability, deletion guards, private filtering, and public API semantics including default filtering and NotFound behavior.
Proto test fixtures
proto/tests/osac/tests/v1/object_type.proto
Adds MyEnum enumeration and spec_enum field to test proto.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes


Risk Assessment:

Severity: Medium-High

  1. State Management & Timestamps — The deprecation/obsolescence state-transition logic with timestamp tracking is intricate (lines 317–354 in private_instance_types_server.go). Incorrect timestamp handling could lead to silent data loss or incorrect historical records. Review the conditional timestamp-setting and mask-extension logic carefully.

  2. Deletion Reference Guard — The referenceChecker blocks deletion when compute instances reference an instance type (pre-Phase-4 behavior). Missing or incorrect reference checks could allow orphaning of dependent resources. SQL JSONB queries and DAO CEL filters must be validated thoroughly.

  3. Public Filtering Default — The default CEL filter (ACTIVE+DEPRECATED, excluding OBSOLETE) is automatically composed when the caller's filter doesn't mention spec.state. Incorrect filter composition could expose OBSOLETE/hidden items unintentionally or hide available items. Verify the logic at line 189–204.

  4. Enum Translation in Filtering — New enum-aware SQL generation in filter_translator.go (lines 634–698) converts enum numeric literals to name-based string comparisons. String escaping must prevent SQL injection; edge cases around unspecified/zero enum values require careful handling.

  5. Immutability Enforcement — Updates to spec.cores, spec.memory_gib, and metadata.name are immutable (lines 297–315). Field mask handling must enforce this consistently across all update paths.

Mitigation: All high-risk logic is covered by comprehensive unit and integration tests, including edge cases for state transitions, immutability, and deletion guards. DAO enum translation includes error cases for unknown enum values.

Possibly related PRs

  • osac-project/fulfillment-service#625: Adds referential-integrity delete preconditions using a referenceChecker for catalog items; the main PR reuses and generalizes that pattern for instance types.
  • osac-project/fulfillment-service#372: Adds Prometheus metrics-registerer plumbing that the main PR uses when constructing the new InstanceTypes servers via SetMetricsRegisterer.
  • osac-project/fulfillment-service#634: Adds InstanceType protobuf definitions and GenericServer event payload support that the main PR depends on for the server implementations.

Suggested labels

lgtm

Suggested reviewers

  • trewest
  • akshaynadkarni
  • jhernand

🎯 Instance Types take flight! ✈️
From private core to public face,
Builders wire and mappers trace,
Enums filter, timestamps grace—
CRUD complete in checkout's space. 🚀


🔕 Pre-merge checks override applied

The pre-merge checks have been overridden successfully. You can now proceed with the merge.

Overridden by @ygalblum via checkbox on 2026-06-11T19:34:39.703Z.

❌ Failed checks (2 errors, 2 warnings)

Check name Status Explanation Resolution
No-Injection-Vectors ❌ Error [IGNORED] SQL string concatenation found in internal/servers/reference_checker.go lines 65-68 where table and field names are interpolated via fmt.Sprintf into a SELECT query, creating a SQL injection vector... Use PostgreSQL identifier escaping (quote identifiers with double quotes or use pq.QuoteIdentifier) or validate table/specField against an allowlist before SQL construction to prevent injection if these ever become configurable.
No-Sensitive-Data-In-Logs ❌ Error [IGNORED] sqlReferenceChecker exposes internal database errors via fmt.Errorf wrapping at lines 62 and 71 in reference_checker.go. When returned to gRPC clients, these can leak database connection/schema det... Replace fmt.Errorf calls in sqlReferenceChecker.hasReference (lines 62, 71) with grpcstatus.Errorf(grpccodes.Internal, "failed to check resource references") to match daoReferenceChecker error handling pattern.
Docstring Coverage ⚠️ Warning Docstring coverage is 44.44% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Ai-Attribution ⚠️ Warning Commit 85be0d6 uses Co-Authored-By for AI tool (Claude Opus 4.6), violating attribution policy; only Assisted-by/Generated-by should be used for AI. Replace Co-Authored-By: Claude Opus 4.6 with Assisted-by trailer or remove the Co-Authored-By line entirely; keep only Assisted-by.
✅ Passed checks (7 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and concisely describes the main change: adding InstanceType servers with CRUD operations, state lifecycle management, and CLI rendering support.
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.
No-Hardcoded-Secrets ✅ Passed No hardcoded secrets, API keys, tokens, passwords, private keys, long base64 strings, or credential patterns found in PR changes. Only legitimate configuration values (database schema names, error...
No-Weak-Crypto ✅ Passed No weak cryptographic algorithms (MD5, SHA1, DES, RC4, 3DES, Blowfish, ECB), custom crypto implementations, or non-constant-time secret comparisons detected in the PR changes.
Container-Privileges ✅ Passed PR modifies only Authorino AuthConfig resources (policy, not container specs). No deployment/pod security contexts modified; existing deployment maintains strong security posture with allowPrivileg...
✨ 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 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: 3

🤖 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 `@internal/servers/instance_types_server.go`:
- Around line 195-196: Replace the brittle substring check
strings.Contains(filter, "this.spec.state") with AST-level detection: parse the
CEL expression (using the CEL parser/checker used elsewhere in the repo) and
walk the parsed AST to detect a real field selection chain this -> spec -> state
(i.e., FieldSelection/Select nodes or Ident/MemberExpr nodes whose identifiers
are "this", "spec", "state"); only treat the filter as an explicit state filter
when such a field-reference exists (not when the text appears in a string
literal or other token). Update the logic around the existing filter variable to
call the parser, traverse nodes, and return early only on a true AST
field-reference match.
- Around line 316-319: The public Update handler currently builds privateRequest
with SetObject(existingPrivateInstanceType) and SetLock(request.GetLock()) but
does not forward the client's update mask, which risks persisting unintended
fields; modify the code that constructs privateRequest (the variable named
privateRequest used with s.delegate.Update) to also forward the mask from the
incoming request by calling
privateRequest.SetUpdateMask(request.GetUpdateMask()) (or the generated setter
for the update_mask field) so the delegate.Update receives and applies the
caller's update_mask.

In `@internal/servers/private_instance_types_server.go`:
- Around line 208-214: The update currently calls s.generic.Update with the
caller's original update mask so auto-populated fields set by
handleInstanceTypeStateTransition (e.g.,
merged.GetSpec().Deprecation.*_timestamp) can be dropped; change the
request/update mask before calling s.generic.Update to ensure those
auto-populated spec fields are persisted — either expand the mask to include the
specific deprecation timestamp fields you set on merged.GetSpec() or clear the
mask to perform a full-spec write after calling
handleInstanceTypeStateTransition(existing, merged) and
request.GetObject().SetSpec(merged.GetSpec()) so s.generic.Update will persist
the timestamps.
🪄 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: Repository: osac-project/coderabbit/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 34c4be44-e743-4037-a01a-bcf4d5a646cc

📥 Commits

Reviewing files that changed from the base of the PR and between be1a2cd and 033f435.

📒 Files selected for processing (7)
  • internal/cmd/service/start/grpcserver/start_grpc_server_cmd.go
  • internal/cmd/service/start/restgateway/start_rest_gateway_cmd.go
  • internal/rendering/tables/osac.private.v1.InstanceType.yaml
  • internal/rendering/tables/osac.public.v1.InstanceType.yaml
  • internal/servers/instance_type_reference_checker.go
  • internal/servers/instance_types_server.go
  • internal/servers/private_instance_types_server.go

Comment thread internal/servers/instance_types_server.go
Comment thread internal/servers/instance_types_server.go
Comment thread internal/servers/private_instance_types_server.go

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

This needs unit tests.

@ygalblum ygalblum force-pushed the feat/instancetype-server branch from e12d844 to c96cb3b Compare June 10, 2026 18:02
@ygalblum

Copy link
Copy Markdown
Contributor Author

This needs unit tests.

Sorry for that. The ep-to-jira skill split the tests into separate tasks and then the GSD split them into separate phases. I've combined them into the PR. See the additional PRs

@ygalblum ygalblum force-pushed the feat/instancetype-server branch 2 times, most recently from 960a652 to 0e1cbc2 Compare June 10, 2026 20:46

@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

🤖 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 `@internal/database/dao/filter_translator.go`:
- Around line 644-650: The function resolveEnumName currently casts the int64
value to protoreflect.EnumNumber (int32) which can truncate out-of-range values;
add an explicit bounds check on value against the int32 range (min and max of
protoreflect.EnumNumber) before casting in resolveEnumName so any int64 outside
int32 returns "", false instead of being truncated, ensuring callers
(resolveEnum and any uses of resolveEnumName) receive an "unknown enum value"
result for out-of-range integers.

In `@internal/servers/instance_type_reference_checker.go`:
- Around line 36-48: The hasReference method currently swallows all errors from
c.resourceDao.List() which allows deletions on transient failures; update
instanceTypeReferenceChecker.hasReference to inspect the returned error and only
convert the specific "field not found" / CEL unknown-field error into a (false,
nil) result, while returning any other errors unchanged (e.g., return false,
err) so callers can fail safely; locate the call using
c.resourceDao.List().SetFilter(filter).SetLimit(1).Do(ctx) and add error
classification (match on the DAO's sentinel error type or specific error
text/code from the CEL/DAO) to distinguish expected missing-field errors from
real DB/transport errors.
🪄 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: Repository: osac-project/coderabbit/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: c3e92d42-9cae-4ff1-98dd-50fbf9d0c1b7

📥 Commits

Reviewing files that changed from the base of the PR and between c96cb3b and 0e1cbc2.

📒 Files selected for processing (11)
  • internal/cmd/service/start/grpcserver/start_grpc_server_cmd.go
  • internal/cmd/service/start/restgateway/start_rest_gateway_cmd.go
  • internal/database/dao/filter_translator.go
  • internal/rendering/tables/osac.private.v1.InstanceType.yaml
  • internal/rendering/tables/osac.public.v1.InstanceType.yaml
  • internal/servers/instance_type_reference_checker.go
  • internal/servers/instance_types_server.go
  • internal/servers/private_instance_types_server.go
  • internal/servers/private_instance_types_server_test.go
  • it/it_private_instance_types_test.go
  • it/it_public_instance_types_test.go

Comment thread internal/database/dao/filter_translator.go
Comment thread internal/servers/instance_type_reference_checker.go Outdated
@ygalblum ygalblum force-pushed the feat/instancetype-server branch 2 times, most recently from 2bcd987 to f880fbd Compare June 10, 2026 21:44
Comment thread internal/database/dao/filter_translator.go
Comment thread internal/servers/instance_types_server.go
Comment thread it/it_public_instance_types_test.go
@ygalblum ygalblum force-pushed the feat/instancetype-server branch from f880fbd to 9007dfa Compare June 11, 2026 13:31

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

🤖 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 `@internal/database/dao/filter_translator.go`:
- Around line 388-392: The enum comparison handling currently only succeeds when
the numeric side is a literal (checked via hasIntValue), otherwise callers
(e.g., where result, err = t.translateEnumEquals(leftTr, rightTr) and the
similar not-equals path) fall through to assembleBinarySQL producing invalid
text-vs-numeric SQL; update the enum translation functions (translateEnumEquals
and the corresponding not-equals handler used by the code paths around those
calls and the other enum-compare block later) to detect non-literal numeric
expressions and either convert/normalize them safely or return a translator
error/result indicating unsupported non-literal numeric enum comparison so
callers do not fall back to assembleBinarySQL; ensure both equals and not-equals
code paths (and the later enum handling block) are updated to return a non-empty
result.sql or an explicit error when hasIntValue is false.

In `@internal/servers/instance_type_reference_checker.go`:
- Around line 39-43: Replace the full count query with an EXISTS check to avoid
scanning all matches: change the tx.QueryRow call that currently queries `SELECT
count(*) FROM compute_instances WHERE data->'spec'->>'instance_type' = $1` (and
the int64 `count` variable) to query `SELECT EXISTS(SELECT 1 FROM
compute_instances WHERE data->'spec'->>'instance_type' = $1)` and Scan into a
bool (e.g., `exists`). Update the subsequent logic that tests `count > 0` to use
the boolean `exists` instead so the reference check remains semantically
identical but far more efficient.

In `@internal/servers/instance_types_server.go`:
- Around line 77-80: The builder method SetAttributionLogic on
InstanceTypesServerBuilder is documented as optional but Build() and the
downstream delegate creation assume attributionLogic is present, causing runtime
failures; update the builder contract by either making attributionLogic truly
optional (modify Build()/delegate construction to handle a nil/zero
auth.AttributionLogic safely) or require it explicitly (change
SetAttributionLogic to be documented/validated as required and add a Build-time
check that returns an error or panics if attributionLogic is unset). Locate
InstanceTypesServerBuilder, its SetAttributionLogic method, the Build() method
and the delegate construction that reads b.attributionLogic, and implement one
of the two fixes: add nil/zero checks and fallbacks/defaults in Build()/delegate
creation, or add validation in Build() that enforces attributionLogic is set and
returns a clear error message indicating SetAttributionLogic must be called.
🪄 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: Repository: osac-project/coderabbit/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 7b0b23e3-7c77-499d-b035-c088dc2ec428

📥 Commits

Reviewing files that changed from the base of the PR and between 0e1cbc2 and 9007dfa.

⛔ Files ignored due to path filters (2)
  • internal/api/osac/tests/v1/object_type.pb.go is excluded by !**/*.pb.go
  • internal/api/osac/tests/v1/object_type_protoopaque.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (17)
  • charts/service/templates/grpc-server/authconfig.yaml
  • internal/cmd/service/start/grpcserver/start_grpc_server_cmd.go
  • internal/cmd/service/start/restgateway/start_rest_gateway_cmd.go
  • internal/database/dao/filter_translator.go
  • internal/database/dao/filter_translator_test.go
  • internal/database/dao/generic_dao_test.go
  • internal/rendering/tables/osac.private.v1.InstanceType.yaml
  • internal/rendering/tables/osac.public.v1.InstanceType.yaml
  • internal/servers/instance_type_reference_checker.go
  • internal/servers/instance_types_server.go
  • internal/servers/instance_types_server_test.go
  • internal/servers/private_instance_types_server.go
  • internal/servers/private_instance_types_server_test.go
  • it/it_private_instance_types_test.go
  • it/it_public_instance_types_test.go
  • manifests/base/grpc-server/authconfig.yaml
  • proto/tests/osac/tests/v1/object_type.proto
💤 Files with no reviewable changes (6)
  • manifests/base/grpc-server/authconfig.yaml
  • proto/tests/osac/tests/v1/object_type.proto
  • it/it_public_instance_types_test.go
  • it/it_private_instance_types_test.go
  • internal/servers/private_instance_types_server_test.go
  • internal/servers/private_instance_types_server.go

Comment thread internal/database/dao/filter_translator.go
Comment thread internal/servers/instance_type_reference_checker.go Outdated
Comment thread internal/servers/instance_types_server.go Outdated
}
var count int64
err = tx.QueryRow(ctx,
`SELECT count(*) FROM compute_instances WHERE data->'spec'->>'instance_type' = $1`,

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.

This will fail if new compute instances are added that reference the instance type after this check but before what comes next.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

You are correct and it seems like a repeating pattern. In 85be0d6 I consolidate the reference checkers, but it does not solve the issue. However, since the same issue exists in other places, I think I'd rather keep this behaviour and address this holistically.
AFAIK the best way to do so is using FKs. WDYT?

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.

You can address in a follow up patch. The approach I recommend is using a materialized relationship table, as explained here:

https://github.com/osac-project/fulfillment-service/blob/main/AGENTS.md#enforcing-cross-object-constraints

@ygalblum ygalblum Jun 11, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 1462729

@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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/servers/reference_checker.go`:
- Around line 59-73: The sqlReferenceChecker.hasReference function currently
returns wrapped fmt.Errorf values that propagate raw DB errors to callers;
change its error handling to return a generic gRPC internal error consistent
with daoReferenceChecker (e.g., return status.Error(codes.Internal, "failed to
check resource references") or an equivalent package-specific internal error)
whenever tx retrieval or the QueryRow call fails, and log the original error
internally instead of including it in the returned message so no
database-specific details (query, hostnames, schema) are exposed to clients.
🪄 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: Repository: osac-project/coderabbit/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: b8c7695d-6148-4260-af8b-cb8e4c7f3347

📥 Commits

Reviewing files that changed from the base of the PR and between 9007dfa and 85be0d6.

📒 Files selected for processing (12)
  • internal/servers/catalog_item_reference_checker.go
  • internal/servers/cluster_catalog_items_server.go
  • internal/servers/cluster_catalog_items_server_test.go
  • internal/servers/compute_instance_catalog_items_server.go
  • internal/servers/compute_instance_catalog_items_server_test.go
  • internal/servers/private_cluster_catalog_items_server.go
  • internal/servers/private_cluster_catalog_items_server_test.go
  • internal/servers/private_compute_instance_catalog_items_server.go
  • internal/servers/private_compute_instance_catalog_items_server_test.go
  • internal/servers/private_instance_types_server.go
  • internal/servers/reference_checker.go
  • internal/servers/reference_checker_mock.go
💤 Files with no reviewable changes (1)
  • internal/servers/catalog_item_reference_checker.go

Comment thread internal/servers/reference_checker.go Outdated

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.

How is this mock generated? I don't see the go:generate ... line to generate it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

You're right. It was written "manually" by mistake. Fixed in af39ffa

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This file is actually now removed since the consolidation was reverted

@ygalblum ygalblum force-pushed the feat/instancetype-server branch from af39ffa to f21501c Compare June 11, 2026 20:08
@ygalblum

Copy link
Copy Markdown
Contributor Author

@jhernand Since I moved the check to the DB, I reverted the consolidation of the reference checker. To avoid having changes and their reverting commits merged to main, I squashed and reordered the commits in the branch. So, the links might not exist any more.

@openshift-ci openshift-ci Bot added the lgtm label Jun 12, 2026
@jhernand

Copy link
Copy Markdown
Contributor

/retest

2 similar comments
@ygalblum

Copy link
Copy Markdown
Contributor Author

/retest

@ygalblum

Copy link
Copy Markdown
Contributor Author

/retest

ygalblum added 8 commits June 15, 2026 14:16
…state transitions, and deletion protection

- PrivateInstanceTypesServer with full CRUD + Signal gRPC methods
- Create validates spec.cores > 0 and spec.memory_gib > 0, sets id=name, defaults state to ACTIVE
- Update enforces immutability on spec.cores, spec.memory_gib, and name via GetSpec() accessors
- Bidirectional state transitions (ACTIVE/DEPRECATED/OBSOLETE) with auto-populated timestamps per D-01 through D-05
- Delete checks ComputeInstance references via instanceTypeReferenceChecker before allowing deletion (OSAC-1212)
- instanceTypeReferenceChecker queries ComputeInstance DAO with this.spec.instance_type filter (Phase 4 wiring per D-06)

Assisted-by: Claude Code <noreply@anthropic.com>
Signed-off-by: Ygal Blum <ygal.blum@gmail.com>
- Private table (osac.private.v1.InstanceType.yaml): NAME, CORES, MEMORY, STATE, DESCRIPTION columns
- Public table (osac.public.v1.InstanceType.yaml): same column structure with public InstanceTypeState type
- All columns use spec-nested field paths (this.spec.cores, this.spec.memory_gib, this.spec.state) per D-00e
- NAME column uses this.id since id == name per Phase 1 D-01

Assisted-by: Claude Code <noreply@anthropic.com>
Signed-off-by: Ygal Blum <ygal.blum@gmail.com>
…ion and default state filter

- Public server wraps private server via GenericMapper for field mapping
- List defaults to ACTIVE+DEPRECATED via this.spec.state filter, OBSOLETE opt-in via explicit filter
- Get returns any instance type regardless of state
- Create/Update/Delete delegate through inMapper/outMapper following host_types_server pattern
- CEL syntax validation on user-provided filters before composition

Assisted-by: Claude Code <noreply@anthropic.com>
Signed-off-by: Ygal Blum <ygal.blum@gmail.com>
…eway

- Register public InstanceTypesServer via publicv1.RegisterInstanceTypesServer
- Register private InstanceTypesServer via privatev1.RegisterInstanceTypesServer
- Register public REST handler via publicv1.RegisterInstanceTypesHandler
- Register private REST handler via privatev1.RegisterInstanceTypesHandler

Assisted-by: Claude Code <noreply@anthropic.com>
Signed-off-by: Ygal Blum <ygal.blum@gmail.com>
CEL types proto enums as integers, but protojson stores them as string
names in PostgreSQL JSONB. Add enum-aware comparison logic to the filter
translator that resolves numeric enum values to their proto string names
for SQL generation.

Assisted-by: Claude Code <noreply@anthropic.com>
Signed-off-by: Ygal Blum <ygal.blum@gmail.com>
- Builder validation: logger and tenancy logic mandatory checks
- CRUD: create, list, get, update, delete with field mask
- Label/annotation validation via DescribeTable
- State transitions: all 6 bidirectional transitions with timestamp verification
- Same-state update no-op and re-entry timestamp update
- Immutability enforcement: cores, memory_gib, name rejection on update
- Deletion protection: blocks delete when compute instances reference type
- Public server: default state filter hides OBSOLETE, filter override

Assisted-by: Claude Code <noreply@anthropic.com>
Signed-off-by: Ygal Blum <ygal.blum@gmail.com>
…luster

- Happy path CRUD: create, list, get, update description, delete with finalizer
- State transitions: ACTIVE->DEPRECATED, DEPRECATED->OBSOLETE, reactivation with timestamp retention
- Error paths: immutable cores/memory_gib rejection with InvalidArgument
- Deletion protection: documents pre-Phase-4 behavior (succeeds because ComputeInstance lacks instance_type field)
- OBSOLETE filtering: private API returns all states including OBSOLETE

Assisted-by: Claude Code <noreply@anthropic.com>
Signed-off-by: Ygal Blum <ygal.blum@gmail.com>
The wait timeout context was shared between WaitForNotification and
processNotification, so by the time a notification arrived the context
was nearly expired, causing the payload query to time out.

Assisted-by: Claude Code <noreply@anthropic.com>
Signed-off-by: Ygal Blum <ygal.blum@gmail.com>
@ygalblum ygalblum force-pushed the feat/instancetype-server branch from f21501c to 269646b Compare June 15, 2026 18:16
@openshift-ci openshift-ci Bot removed the lgtm label Jun 15, 2026
@openshift-ci openshift-ci Bot added the lgtm label Jun 15, 2026
@openshift-ci

openshift-ci Bot commented Jun 15, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

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

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants