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

MGMT-24213: Add cluster template spec_defaults and server-side default merging - #474

Merged
openshift-merge-bot[bot] merged 2 commits into
osac-project:mainfrom
tzvatot:MGMT-24213/cluster-spec-defaults
Apr 30, 2026
Merged

openshift-merge-bot[bot] merged 2 commits into
osac-project:mainfrom
tzvatot:MGMT-24213/cluster-spec-defaults

Conversation

@tzvatot

@tzvatot tzvatot commented Apr 30, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Add spec_defaults to cluster templates, aligning CaaS with the VMaaS pattern for server-side default resolution.

  • Add ClusterTemplateSpecDefaults message to cluster template proto (public + private) with optional fields: pull_secret, ssh_public_key, release_image, network
  • Apply template defaults to ClusterSpec during cluster creation in the private server (same pattern as ComputeInstance)
  • User-provided values always take precedence; network defaults merge field-by-field
  • Validate CIDR format when provided (net.ParseCIDR)
  • Credentials (pull_secret, ssh_public_key) are not required at API time — the Ansible role falls back to a provider default Secret

Jira

MGMT-24213

Related

Test plan

  • 11 new unit tests for ApplyClusterSpecDefaults (all defaults, user override, partial network merge, clone safety)
  • 5 new unit tests for ValidateClusterSpecFields (nil spec, valid CIDRs, invalid CIDRs)
  • All 51 test suites pass (ginkgo run -r internal)
  • buf lint passes

Summary by CodeRabbit

  • New Features
    • Cluster templates now support default values for cluster configurations. When creating clusters, specified defaults are automatically applied to unspecified fields, while user-provided values take precedence. Enhanced validation ensures configurations are validated early during cluster creation.

…t merging

Add ClusterTemplateSpecDefaults to cluster template proto (public + private)
with optional fields: pull_secret, ssh_public_key, release_image, network.

Apply template defaults to ClusterSpec during cluster creation in the private
server, following the same pattern as ComputeInstance spec_defaults:
- User-provided values always take precedence
- Network defaults merge field-by-field (pod_cidr, service_cidr)
- Cloned to prevent shared state between template and spec

Validate CIDR format when provided (net.ParseCIDR). Credentials
(pull_secret, ssh_public_key) are not required at API time — the Ansible
role falls back to a provider default Secret.
@openshift-ci-robot

openshift-ci-robot commented Apr 30, 2026 •

Copy link
Copy Markdown

@tzvatot: This pull request references MGMT-24213 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

Add spec_defaults to cluster templates, aligning CaaS with the VMaaS pattern for server-side default resolution.

  • Add ClusterTemplateSpecDefaults message to cluster template proto (public + private) with optional fields: pull_secret, ssh_public_key, release_image, network
  • Apply template defaults to ClusterSpec during cluster creation in the private server (same pattern as ComputeInstance)
  • User-provided values always take precedence; network defaults merge field-by-field
  • Validate CIDR format when provided (net.ParseCIDR)
  • Credentials (pull_secret, ssh_public_key) are not required at API time — the Ansible role falls back to a provider default Secret

Jira

MGMT-24213

Related

Test plan

  • 11 new unit tests for ApplyClusterSpecDefaults (all defaults, user override, partial network merge, clone safety)
  • 5 new unit tests for ValidateClusterSpecFields (nil spec, valid CIDRs, invalid CIDRs)
  • All 51 test suites pass (ginkgo run -r internal)
  • buf lint passes

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 jhernand and trewest April 30, 2026 09:36
@coderabbitai

coderabbitai Bot commented Apr 30, 2026 •

Copy link
Copy Markdown

Warning

Rate limit exceeded

@tzvatot has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 39 minutes and 36 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8bc767cd-58a9-4b1c-b890-ae951ffeaffd

📥 Commits

Reviewing files that changed from the base of the PR and between 34dab27 and d4bf46b.

⛔ Files ignored due to path filters (2)
  • internal/api/osac/public/v1/cluster_template_type.pb.go is excluded by !**/*.pb.go
  • internal/api/osac/public/v1/cluster_template_type_protoopaque.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (2)
  • internal/utils/cluster_spec_defaults.go
  • proto/public/osac/public/v1/cluster_template_type.proto

Walkthrough

This PR introduces template-level default cluster specification values. It adds proto message types (ClusterTemplateSpecDefaults) to capture default values for pull secret, SSH public key, release image, and network configuration. New utility functions apply these defaults to incoming cluster specs only when fields are unset, while preserving user-provided values. A validation function checks CIDR format for network fields. The private clusters server is updated to apply defaults and validate specs during cluster creation.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Suggested labels

approved, lgtm

Suggested reviewers

  • akshaynadkarni
  • jhernand
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. 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 and specifically describes the main changes: adding spec_defaults to cluster templates and implementing server-side default merging, which aligns with the primary objectives of the PR.
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.

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

✨ 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
Review rate limit: 0/1 reviews remaining, refill in 39 minutes and 36 seconds.

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: 1

🧹 Nitpick comments (1)
internal/utils/cluster_spec_defaults.go (1)

26-104: ⚡ Quick win

Deduplicate the CIDR validation path.

The helper itself looks fine, but the server still has a second net.ParseCIDR block later in validateAndTransformCluster. Routing that path through ValidateClusterSpecFields too would keep the behavior and error text from drifting.

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

In `@internal/utils/cluster_spec_defaults.go` around lines 26 - 104, The CIDR
validation logic is duplicated: move the validation in
validateAndTransformCluster to reuse
ValidateClusterSpecFields/validateClusterNetwork so the behavior and error
messages stay consistent; update validateAndTransformCluster to call
ValidateClusterSpecFields(spec) (or validateClusterNetwork(spec.GetNetwork()))
instead of running its own net.ParseCIDR checks, and remove the redundant
net.ParseCIDR blocks to avoid drift while preserving existing error text from
validateClusterNetwork.
🤖 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/servers/private_clusters_server.go`:
- Around line 525-530: The update path currently skips network/CIDR validation,
so add the same spec defaults+validation used on create into the
ClustersUpdateRequest update flow: after applying template defaults
(template.GetSpecDefaults()) and merging the request into cluster.GetSpec(),
call utils.ValidateClusterSpecFields(cluster.GetSpec()) and return the error if
non-nil. Update the Update (or ClustersUpdateRequest handling) code path to
mirror the create logic that uses utils.ApplyClusterSpecDefaults and
utils.ValidateClusterSpecFields so invalid spec.network/CIDRs cannot be
persisted.

---

Nitpick comments:
In `@internal/utils/cluster_spec_defaults.go`:
- Around line 26-104: The CIDR validation logic is duplicated: move the
validation in validateAndTransformCluster to reuse
ValidateClusterSpecFields/validateClusterNetwork so the behavior and error
messages stay consistent; update validateAndTransformCluster to call
ValidateClusterSpecFields(spec) (or validateClusterNetwork(spec.GetNetwork()))
instead of running its own net.ParseCIDR checks, and remove the redundant
net.ParseCIDR blocks to avoid drift while preserving existing error text from
validateClusterNetwork.
🪄 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: 67923c1b-2584-45c5-b98e-b6d9902739a2

📥 Commits

Reviewing files that changed from the base of the PR and between 6d8d256 and 34dab27.

⛔ Files ignored due to path filters (4)
  • internal/api/osac/private/v1/cluster_template_type.pb.go is excluded by !**/*.pb.go
  • internal/api/osac/private/v1/cluster_template_type_protoopaque.pb.go is excluded by !**/*.pb.go
  • internal/api/osac/public/v1/cluster_template_type.pb.go is excluded by !**/*.pb.go
  • internal/api/osac/public/v1/cluster_template_type_protoopaque.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (5)
  • internal/servers/private_clusters_server.go
  • internal/utils/cluster_spec_defaults.go
  • internal/utils/cluster_spec_defaults_test.go
  • proto/private/osac/private/v1/cluster_template_type.proto
  • proto/public/osac/public/v1/cluster_template_type.proto

Comment on lines +525 to +530
// Apply spec defaults from the template (user values take precedence):
utils.ApplyClusterSpecDefaults(cluster.GetSpec(), template.GetSpecDefaults())

// Validate cluster spec fields (CIDR format, etc.) after defaults have been applied:
if err = utils.ValidateClusterSpecFields(cluster.GetSpec()); err != nil {
return err

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Validate spec.network on update too.

This only protects the create path. If ClustersUpdateRequest can patch spec.network, invalid CIDRs can still be persisted because Update never calls utils.ValidateClusterSpecFields.

🔧 Suggested fix
 func (s *PrivateClustersServer) Update(ctx context.Context,
 	request *privatev1.ClustersUpdateRequest) (response *privatev1.ClustersUpdateResponse, err error) {
 	err = s.validateNoDuplicateConditions(request.GetObject())
 	if err != nil {
 		return
 	}
 	err = s.validateTemplateImmutability(ctx, request)
 	if err != nil {
 		return
 	}
 	err = s.validateNodeSetsUpdate(ctx, request)
 	if err != nil {
 		return
 	}
+	if err = utils.ValidateClusterSpecFields(request.GetObject().GetSpec()); err != nil {
+		return
+	}
 	err = s.generic.Update(ctx, request, &response)
 	return
 }
📝 Committable suggestion

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

Suggested change
// Apply spec defaults from the template (user values take precedence):
utils.ApplyClusterSpecDefaults(cluster.GetSpec(), template.GetSpecDefaults())
// Validate cluster spec fields (CIDR format, etc.) after defaults have been applied:
if err = utils.ValidateClusterSpecFields(cluster.GetSpec()); err != nil {
return err
func (s *PrivateClustersServer) Update(ctx context.Context,
request *privatev1.ClustersUpdateRequest) (response *privatev1.ClustersUpdateResponse, err error) {
err = s.validateNoDuplicateConditions(request.GetObject())
if err != nil {
return
}
err = s.validateTemplateImmutability(ctx, request)
if err != nil {
return
}
err = s.validateNodeSetsUpdate(ctx, request)
if err != nil {
return
}
if err = utils.ValidateClusterSpecFields(request.GetObject().GetSpec()); err != nil {
return
}
err = s.generic.Update(ctx, request, &response)
return
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/servers/private_clusters_server.go` around lines 525 - 530, The
update path currently skips network/CIDR validation, so add the same spec
defaults+validation used on create into the ClustersUpdateRequest update flow:
after applying template defaults (template.GetSpecDefaults()) and merging the
request into cluster.GetSpec(), call
utils.ValidateClusterSpecFields(cluster.GetSpec()) and return the error if
non-nil. Update the Update (or ClustersUpdateRequest handling) code path to
mirror the create logic that uses utils.ApplyClusterSpecDefaults and
utils.ValidateClusterSpecFields so invalid spec.network/CIDRs cannot be
persisted.

- Rename shadowed 'net' variable to 'specNet' in mergeClusterNetworkDefaults
- Remove pull_secret from public ClusterTemplateSpecDefaults (write-only
  field should not be exposed in template GET responses)
@openshift-ci

openshift-ci Bot commented Apr 30, 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-merge-bot
openshift-merge-bot Bot merged commit 3446888 into osac-project:main Apr 30, 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.

3 participants