Skip to content

Add nodeimageinfo api endpoint#756

Closed
cverna wants to merge 3 commits intoopenshift:mainfrom
cverna:add-nodeimageinfo-api-endpoint
Closed

Add nodeimageinfo api endpoint#756
cverna wants to merge 3 commits intoopenshift:mainfrom
cverna:add-nodeimageinfo-api-endpoint

Conversation

@cverna
Copy link
Copy Markdown
Contributor

@cverna cverna commented Apr 14, 2026

Add a new JSON API endpoint that exposes RPM package information for release node images, similar to the "Node Image Info" section shown on release pages. This endpoint would particularly be useful for AI Agents to easily access that information.

Endpoint: /api/v1/releasestream/{release}/release/{tag}/nodeimageinfo

Features

  • Returns RPM package list for each CoreOS stream in the release
  • Supports ?from= parameter to get package diff between two releases
  • Returns changed/added/removed packages when comparing releases
  • Supports multi-stream releases (rhel-coreos, rhel-coreos-10) for OCP 4.21+
  • Returns 400 error for releases < 4.19 (Node Image Info not available)
  • Validates that from and to tags are same major.minor version

Example Usage

Get package list for a release:
GET /api/v1/releasestream/4.22.0-0.nightly/release/4.22.0-0.nightly-2026-04-14-053105/nodeimageinfo
Get package diff between two releases:
GET /api/v1/releasestream/4.22.0-0.nightly/release/4.22.0-0.nightly-2026-04-14-053105/nodeimageinfo?from=4.22.0-0.nightly-2026-04-13-120000
Response Format
Without ?from=:

{
  "streams": [
    {
      "name": "rhel-coreos",
      "displayName": "Red Hat Enterprise Linux CoreOS 9.8",
      "packages": {"kernel": "5.14.0-687.5.1.el9_8", ...},
      "extensions": {"kernel-rt-core": "...", ...}
    }
  ]
}

With ?from=:

{
  "from": "4.22.0-0.nightly-2026-04-13-...",
  "to": "4.22.0-0.nightly-2026-04-14-...",
  "streams": [
    {
      "name": "rhel-coreos",
      "displayName": "Red Hat Enterprise Linux CoreOS 9.8",
      "changed": {"kernel": {"old": "5.14.0-570.78.1.el9_6", "new": "5.14.0-570.84.1.el9_6"}},
      "added": {},
      "removed": {}
    }
  ]
}

Summary by CodeRabbit

Release Notes

  • New Features
    • Added API endpoint to query node image RPM package information for specific releases.
    • Added ability to compare RPM packages between two release versions.
    • Implemented standardized JSON error responses for improved API consistency.

cverna added 3 commits April 14, 2026 18:16
Assisted-by: OpenCode (Opus 4.5)
Add types for the nodeimageinfo API endpoint:
- APINodeImageInfo and APINodeImageStream for full package lists
- APINodeImageDiff and APINodeImageStreamDiff for diff responses
- APIError for consistent error responses

These types support both single-release package queries and
two-release diff queries via the ?from= parameter.

Assisted-by: OpenCode (Opus 4.5)
Add new JSON API endpoint for Node Image Info:
  /api/v1/releasestream/{release}/release/{tag}/nodeimageinfo

Features:
- Returns RPM package list for each CoreOS stream in the release
- Supports ?from= parameter for diff between two releases
- Returns 400 for releases < 4.19
- Validates from and to tags are same minor version
- Validates tag belongs to the specified release stream
- Supports multi-stream releases (rhel-coreos, rhel-coreos-10)

Uses FindPublicImagePullSpec for pullspec construction, consistent
with other handlers. Introduces writeAPIResponse helper to reduce
duplication in JSON response writing.

Assisted-by: OpenCode (Opus 4.5)
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 14, 2026

📝 Walkthrough

Walkthrough

A new API endpoint /api/v1/releasestream/{release}/release/{tag}/nodeimageinfo is introduced to retrieve RPM package information from node images within release streams. The endpoint supports optional comparison via a from query parameter. Supporting types for API responses and error handling were added alongside the implementation.

Changes

Cohort / File(s) Summary
API Handler Implementation
cmd/release-controller-api/http.go
Added GET /api/v1/releasestream/{release}/release/{tag}/nodeimageinfo endpoint with apiNodeImageInfo handler. Implemented semver validation, tag resolution, image digest fetching, and machine OS stream discovery. Added conditional logic to return full RPM lists or RPM diffs based on presence of from parameter. Introduced shared JSON helpers writeAPIError and writeAPIResponse for consistent API responses.
Type Definitions
pkg/release-controller/types.go
Added APIError, APINodeImageInfo, APINodeImageStream, APINodeImageDiff, and APINodeImageStreamDiff types to model API responses for node image RPM content. Reformatted VerificationStatus struct field alignment without changing semantics.

Sequence Diagram

sequenceDiagram
    actor Client
    participant Handler as apiNodeImageInfo<br/>Handler
    participant Tags as Tag Resolution<br/>(findReleaseStreamTags)
    participant Images as Image Discovery<br/>(GetImageInfo)
    participant Streams as Stream Discovery<br/>(ListMachineOSStreams)
    participant RPM as RPM Operations<br/>(RpmListForStream/<br/>RpmDiffForStream)
    
    Client->>Handler: GET /api/v1/releasestream/{release}/release/{tag}/nodeimageinfo?[from=...]
    
    rect rgba(200, 150, 100, 0.5)
    Note over Handler: Parse & Validate
    Handler->>Handler: Parse tag as semver (tolerant)
    Handler->>Handler: Validate tag not <4.19
    alt from parameter present
        Handler->>Handler: Parse from as semver (tolerant)
        Handler->>Handler: Validate both are 4.19+
        Handler->>Handler: Validate same major.minor
    end
    end
    
    rect rgba(100, 150, 200, 0.5)
    Note over Handler,Tags: Resolve Tags
    Handler->>Tags: findReleaseStreamTags(tag, [from])
    Tags-->>Handler: Resolved release tags
    Handler->>Handler: Validate tag in {release} stream
    end
    
    rect rgba(150, 200, 100, 0.5)
    Note over Handler,Images: Fetch Image Info
    Handler->>Images: GetImageInfo(target pullspec)
    Images-->>Handler: Digest pullspec
    alt from parameter present
        Handler->>Images: GetImageInfo(from pullspec)
        Images-->>Handler: From digest pullspec
    end
    end
    
    rect rgba(200, 100, 150, 0.5)
    Note over Handler,Streams: Discover Streams
    Handler->>Streams: ListMachineOSStreams
    Streams-->>Handler: Machine OS streams
    end
    
    rect rgba(150, 100, 200, 0.5)
    Note over Handler,RPM: Process RPM Data
    alt from parameter absent
        Handler->>RPM: RpmListForStream per stream
        RPM-->>Handler: RPM package lists
        Handler->>Handler: Build APINodeImageInfo
    else from parameter present
        Handler->>RPM: RpmDiffForStream per stream
        RPM-->>Handler: RPM diffs
        Handler->>Handler: Build APINodeImageDiff
    end
    end
    
    Handler->>Client: Return JSON response
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 A new endpoint hops into town,
To fetch RPM treasures, both up and down,
Comparing streams with semver care,
Node image info floating through the air!
From lists to diffs, the code runs quick—
This API trick is quite slick! 🎉

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.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 'Add nodeimageinfo api endpoint' directly and accurately summarizes the main change: adding a new API endpoint for node image information.

✏️ 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

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

@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci bot commented Apr 14, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: cverna
Once this PR has been reviewed and has the lgtm label, please assign hoxhaeris for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found 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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

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)
cmd/release-controller-api/http.go (1)

883-923: Unused tag parameter.

The tag parameter is passed to this function but never used. Consider removing it or adding debug logging that includes the tag name for troubleshooting.

♻️ Option 1: Remove unused parameter
-func (c *Controller) apiNodeImageInfoList(w http.ResponseWriter, tag, pullspec string, streams []releasecontroller.MachineOSStreamInfo) {
+func (c *Controller) apiNodeImageInfoList(w http.ResponseWriter, pullspec string, streams []releasecontroller.MachineOSStreamInfo) {

And update the call site at line 858:

-		c.apiNodeImageInfoList(w, tag, toDigestPullSpec, streams)
+		c.apiNodeImageInfoList(w, toDigestPullSpec, streams)
♻️ Option 2: Add debug logging
 func (c *Controller) apiNodeImageInfoList(w http.ResponseWriter, tag, pullspec string, streams []releasecontroller.MachineOSStreamInfo) {
 	var response releasecontroller.APINodeImageInfo
+	klog.V(4).Infof("Fetching node image info for tag %s", tag)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/release-controller-api/http.go` around lines 883 - 923, The
apiNodeImageInfoList function has an unused parameter named tag; either remove
the tag parameter from the apiNodeImageInfoList signature and update all call
sites that pass a tag to this function (so callers no longer provide that
argument), or keep the parameter and use it (e.g., add a debug/log line using
tag) so it is not unused; locate the function apiNodeImageInfoList and its
callers to apply the change consistently (update function signature in
Controller and every invocation) or add logging inside apiNodeImageInfoList
referencing tag for troubleshooting.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@cmd/release-controller-api/http.go`:
- Around line 731-745: In writeAPIError, the result of w.Write(data) is not
checked; update writeAPIError to capture and log the error from w.Write (and
also from fmt.Fprintln) using klog.Errorf just like writeAPIResponse does: after
marshalling, assign err = w.Write(data) and if err != nil log it with a clear
message referencing writeAPIError, and likewise check the error returned by
fmt.Fprintln(w) and log it if non-nil so both write calls are consistently
logged on failure.

---

Nitpick comments:
In `@cmd/release-controller-api/http.go`:
- Around line 883-923: The apiNodeImageInfoList function has an unused parameter
named tag; either remove the tag parameter from the apiNodeImageInfoList
signature and update all call sites that pass a tag to this function (so callers
no longer provide that argument), or keep the parameter and use it (e.g., add a
debug/log line using tag) so it is not unused; locate the function
apiNodeImageInfoList and its callers to apply the change consistently (update
function signature in Controller and every invocation) or add logging inside
apiNodeImageInfoList referencing tag for troubleshooting.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 4121b9f2-5ab9-4095-ba87-aa08a08daa38

📥 Commits

Reviewing files that changed from the base of the PR and between b05862e and a8d81a5.

📒 Files selected for processing (2)
  • cmd/release-controller-api/http.go
  • pkg/release-controller/types.go

Comment on lines +731 to +745
func writeAPIError(w http.ResponseWriter, code int, message string) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(code)
response := releasecontroller.APIError{
Code: code,
Message: message,
}
data, err := json.MarshalIndent(&response, "", " ")
if err != nil {
klog.Errorf("Failed to marshal API error response: %v", err)
return
}
w.Write(data)
fmt.Fprintln(w)
}
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.

⚠️ Potential issue | 🟡 Minor

Unchecked w.Write error on line 743.

For consistency with writeAPIResponse (line 753-754), the write error should be logged even though it cannot be recovered from in an error path.

🔧 Proposed fix
-	w.Write(data)
+	if _, err := w.Write(data); err != nil {
+		klog.Errorf("Failed to write API error response: %v", err)
+	}
📝 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
func writeAPIError(w http.ResponseWriter, code int, message string) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(code)
response := releasecontroller.APIError{
Code: code,
Message: message,
}
data, err := json.MarshalIndent(&response, "", " ")
if err != nil {
klog.Errorf("Failed to marshal API error response: %v", err)
return
}
w.Write(data)
fmt.Fprintln(w)
}
func writeAPIError(w http.ResponseWriter, code int, message string) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(code)
response := releasecontroller.APIError{
Code: code,
Message: message,
}
data, err := json.MarshalIndent(&response, "", " ")
if err != nil {
klog.Errorf("Failed to marshal API error response: %v", err)
return
}
if _, err := w.Write(data); err != nil {
klog.Errorf("Failed to write API error response: %v", err)
}
fmt.Fprintln(w)
}
🧰 Tools
🪛 golangci-lint (2.11.4)

[error] 743-743: Error return value of w.Write is not checked

(errcheck)

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

In `@cmd/release-controller-api/http.go` around lines 731 - 745, In writeAPIError,
the result of w.Write(data) is not checked; update writeAPIError to capture and
log the error from w.Write (and also from fmt.Fprintln) using klog.Errorf just
like writeAPIResponse does: after marshalling, assign err = w.Write(data) and if
err != nil log it with a clear message referencing writeAPIError, and likewise
check the error returned by fmt.Fprintln(w) and log it if non-nil so both write
calls are consistently logged on failure.

@bradmwilliams
Copy link
Copy Markdown
Collaborator

/hold
We are currently investigating ways to make the RPMDiff determination not get wedged. This change will only exacerbate the issues we're currently experiencing.

/cc @sdodson

@openshift-ci openshift-ci bot requested a review from sdodson April 14, 2026 19:15
@openshift-ci openshift-ci bot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Apr 14, 2026
@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci bot commented Apr 14, 2026

@cverna: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/lint a8d81a5 link true /test lint

Full PR test history. Your PR dashboard.

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. I understand the commands that are listed here.

@cverna
Copy link
Copy Markdown
Contributor Author

cverna commented Apr 14, 2026

We are currently investigating ways to make the RPMDiff determination not get wedged. This change will only exacerbate the issues we're currently experiencing.

Understood. Still would be super valuable for verifying CVEs and in general getting quick access to the list of packages in RHCOS. It is reusing the same CachingReleaseInfo layer, so repeated requests for the same release won't hit oc. However, I understand first-access load is the concern.

@cverna
Copy link
Copy Markdown
Contributor Author

cverna commented Apr 15, 2026

Closing in favor of #750, will wait to see if I can work with this :-)

@cverna cverna closed this Apr 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants