Skip to content

33494 optimize os versions response - #33691

Merged
mostlikelee merged 7 commits into
mainfrom
33494-os-versions
Oct 1, 2025
Merged

33494 optimize os versions response#33691
mostlikelee merged 7 commits into
mainfrom
33494-os-versions

Conversation

@mostlikelee

@mostlikelee mostlikelee commented Oct 1, 2025

Copy link
Copy Markdown
Contributor

Related issue: Resolves #33494

  • Pulling in vulnerability data for only the paginated os versions returned. Tested with 800 linux Operating systems (1 kernel each). Response time in localdev went from 52s -> 3s.
  • Updated seed tool to help with this

If some of the following don't apply, delete the relevant line.

  • Changes file added for user-visible changes in changes/, orbit/changes/ or ee/fleetd-chrome/changes.
    See Changes files for more information.

Testing

  • Added/updated automated tests (note: skipped benchmark testing here, no functional changes)

  • QA'd all new/changed functionality manually

Summary by CodeRabbit

  • New Features

    • OS versions view now supports pagination, returns total count/metadata, and lets you sort by host count.
  • Performance

    • Faster OS versions API responses by limiting processing to the current page.
  • Documentation

    • Updated vulnerability seeding guide: clearer steps, optional title review, platform-specific CSVs, added idempotency note.
  • Tools

    • Revamped vulnerability seeder: datastore-driven host/software creation, supports macOS, Windows, Ubuntu cohorts, and optional Linux kernel packages.

@getvictor

getvictor commented Oct 1, 2025

Copy link
Copy Markdown
Member

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Oct 1, 2025

Copy link
Copy Markdown
Contributor

@getvictor: I'll perform a comprehensive review of all the changes in this PR, including the optimization for OS versions response and the seed tool updates.

✅ Actions performed

Full review triggered.

@coderabbitai

coderabbitai Bot commented Oct 1, 2025

Copy link
Copy Markdown
Contributor
✅ Actions performed

Full review triggered.

@coderabbitai

coderabbitai Bot commented Oct 1, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Implements server-side sorting, counting, and pagination for OS versions and restricts vulnerability/kernel loading to the current page. Refactors the vulnerability seeder to use the datastore API (instead of raw SQL), adds CLI flags for platform cohorts, and updates README accordingly.

Changes

Cohort / File(s) Summary
OS versions API pagination and scoped vulnerability loading
server/service/hosts.go
Compute total count before pagination; sort OS versions by hosts_count (default desc, supports asc); paginate OSVersions and load vulnerabilities/kernels only for the paged subset; populate per-item fields (vulns, kernels, GeneratedCPEs) only for paged items; return paged payload with pagination metadata.
Vuln seeder documentation updates
tools/software/vulnerabilities/README.md
Update seeder README: describe inserting hosts/software without a real host, make software-title review optional, add Windows CSV mention, note idempotency, and add CLI flags (--ubuntu, --macos, --windows, --linux-kernels).
Vuln seeder refactor to datastore-driven workflow
tools/software/vulnerabilities/seed_vuln_data.go
Replace raw SQL models/CRUD with datastore (ds) calls; remove local Host/HostSoftware types; add createOrGetHost(ctx, ds, identifier, base); read CSVs into fleet.Software; create macOS/Windows/Ubuntu host cohorts, update OS data, and associate software via datastore APIs; optionally generate kernel-like packages for Ubuntu hosts; remove direct DB driver usage.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Client
  participant Service as Service (hosts.go)
  participant DS as Datastore
  Note over Client,Service: OS versions API request (with order/page params)
  Client->>Service: GET /api/.../os_versions?order=hosts_count&page,per_page
  Service->>DS: Query total count and OS versions (filtered)
  DS-->>Service: total, OS versions (unpaged)
  Note right of Service: sort by hosts_count and slice to requested page
  Service->>DS: Fetch vulnerabilities/kernels for paged OS version IDs only
  DS-->>Service: Vulnerabilities and kernels mapped by os_version_id
  Service-->>Client: Paged OS versions + per-item vulns/kernels + pagination metadata
Loading
sequenceDiagram
  autonumber
  participant User
  participant Seed as seed_vuln_data (CLI)
  participant DS as Datastore
  Note over User,Seed: Run seeder with platform flags
  User->>Seed: go run ... --macos N --windows M --ubuntu K --linux-kernels X
  loop per generated host
    Seed->>DS: createOrGetHost(ctx, ds, identifier, base)
    DS-->>Seed: Host
    alt OS fields to set
      Seed->>DS: UpdateHostOperatingSystem(host, os)
      DS-->>Seed: OK
    end
    Seed->>Seed: Load platform CSV -> []fleet.Software
    Seed->>DS: UpdateHostSoftware(host, softwareList)
    DS-->>Seed: OK
  end
  opt add kernel packages for Ubuntu hosts
    Seed->>DS: UpdateHostSoftware(ubuntuHosts, kernelPackages)
    DS-->>Seed: OK
  end
  Seed-->>User: Done.
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • dantecatalfamo
  • jahzielv
  • iansltx

Pre-merge checks and finishing touches

❌ Failed checks (3 warnings)
Check name Status Explanation Resolution
Linked Issues Check ⚠️ Warning The pull request correctly implements the API optimization by restricting vulnerability data loading to the paginated OS versions subset, addressing the core performance issue in linked issue #33494, but it omits the complementary frontend update to use the new vulnerabilities_count field instead of vulnerabilities.length as specified. Please include the necessary UI adjustments to display and leverage the vulnerabilities_count attribute in place of the existing vulnerabilities.length to fully satisfy the linked issue’s requirements.
Out of Scope Changes Check ⚠️ Warning In addition to the OS versions endpoint optimization, the pull request introduces substantial updates to the vulnerability data seeder tool and its README, which are not directly related to the performance fix outlined in linked issue #33494 and therefore fall outside the core scope. Consider moving the seeder tool modifications and documentation updates into a dedicated pull request or clearly justify their inclusion in relation to the OS versions API improvements.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title “33494 optimize os versions response” directly conveys the primary focus of the changeset—improving the performance of the OS versions endpoint—and aligns with the API modifications in the pull request, though the numeric prefix and inconsistent capitalization reduce readability.
Description Check ✅ Passed The pull request description includes the related issue reference, a clear summary of the performance improvement and seed tool update, confirmation of the changes file addition, and testing details aligned with the template’s structure; non-applicable sections such as database migrations and configuration settings were appropriately omitted.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 33494-os-versions

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
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tools/software/vulnerabilities/README.md (1)

16-16: Correct “Comma seperated” to “Comma separated”.

The note should use the standard spelling “Comma separated values…”. Please fix the typo. (dictionary.com)

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between abd558e and 3f9e5e1.

📒 Files selected for processing (4)
  • changes/33494-os-version-response-time (1 hunks)
  • server/service/hosts.go (3 hunks)
  • tools/software/vulnerabilities/README.md (2 hunks)
  • tools/software/vulnerabilities/seed_vuln_data.go (3 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.go

⚙️ CodeRabbit configuration file

When reviewing SQL queries that are added or modified, ensure that appropriate filtering criteria are applied—especially when a query is intended to return data for a specific entity (e.g., a single host). Check for missing WHERE clauses or incorrect filtering that could lead to incorrect or non-deterministic results (e.g., returning the first row instead of the correct one). Flag any queries that may return unintended results due to lack of precise scoping.

Files:

  • tools/software/vulnerabilities/seed_vuln_data.go
  • server/service/hosts.go

Comment thread server/service/hosts.go Outdated
Comment on lines +2245 to +2246
// Return only the page, but with total count
return &fleet.OSVersions{OSVersions: paged}, count, meta, nil

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 | 🟠 Major

Preserve CountsUpdatedAt when returning the paged slice

By constructing a brand-new fleet.OSVersions here, you drop the CountsUpdatedAt field that came back from the datastore. The endpoint then emits a zero timestamp in counts_updated_at, regressing the API contract/UI display. Reuse the original struct (or copy the field) before returning.

-	// Return only the page, but with total count
-	return &fleet.OSVersions{OSVersions: paged}, count, meta, nil
+	// Return only the page while preserving metadata from the datastore
+	osVersions.OSVersions = paged
+	return osVersions, count, meta, nil
🤖 Prompt for AI Agents
In server/service/hosts.go around lines 2245-2246, the code constructs a new
fleet.OSVersions for the paged results which drops the CountsUpdatedAt timestamp
returned from the datastore; copy the CountsUpdatedAt field from the original
datastore result (or return the original struct with OSVersions replaced by the
paged slice) so the returned object preserves CountsUpdatedAt before returning
the value, count, meta, nil.

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.

great catch, added tests to catch countUpdatedAt zero values


## Usage

1. Ensure your local development enviornment is running using `docker-compose up` and `fleet serve`

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

Fix spelling of “environment”.

The instructions should read “Ensure your local development environment…”. Please correct the misspelling. (difference.wiki)

🤖 Prompt for AI Agents
In tools/software/vulnerabilities/README.md at line 8, the word "enviornment" is
misspelled; update the sentence to read "Ensure your local development
environment is running using `docker-compose up` and `fleet serve`" replacing
"enviornment" with "environment".

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

♻️ Duplicate comments (2)
tools/software/vulnerabilities/README.md (1)

8-8: Fix spelling of "environment".

The word "enviornment" is misspelled; it should be "environment".

server/service/hosts.go (1)

2245-2246: Preserve CountsUpdatedAt when returning the paged slice.

Constructing a new fleet.OSVersions here drops the CountsUpdatedAt field from the original datastore result. The endpoint will emit a zero timestamp in counts_updated_at, regressing the API contract. Reuse the original struct (or copy the field) before returning.

Apply this diff to preserve the metadata:

-	// Return only the page, but with total count
-	return &fleet.OSVersions{OSVersions: paged}, count, meta, nil
+	// Return only the page while preserving metadata from the datastore
+	osVersions.OSVersions = paged
+	return osVersions, count, meta, nil
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between abd558e and 3f9e5e1.

📒 Files selected for processing (4)
  • changes/33494-os-version-response-time (1 hunks)
  • server/service/hosts.go (3 hunks)
  • tools/software/vulnerabilities/README.md (2 hunks)
  • tools/software/vulnerabilities/seed_vuln_data.go (3 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.go

⚙️ CodeRabbit configuration file

When reviewing SQL queries that are added or modified, ensure that appropriate filtering criteria are applied—especially when a query is intended to return data for a specific entity (e.g., a single host). Check for missing WHERE clauses or incorrect filtering that could lead to incorrect or non-deterministic results (e.g., returning the first row instead of the correct one). Flag any queries that may return unintended results due to lack of precise scoping.

Files:

  • server/service/hosts.go
  • tools/software/vulnerabilities/seed_vuln_data.go
🔇 Additional comments (21)
tools/software/vulnerabilities/seed_vuln_data.go (10)

33-60: LGTM!

CSV reading logic is correct: properly handles file operations, defers close, skips header, and maps columns to fleet.Software fields.


62-71: LGTM!

The createOrGetHost helper correctly implements idempotent host creation: it retrieves existing hosts by identifier and only creates new ones if not found, aligning with the README's claim that the tool won't create duplicates.


73-82: LGTM!

CLI flags are correctly declared with descriptive names and sensible defaults (0 = no action), matching the usage documented in the README.


83-96: LGTM!

Datastore initialization correctly uses the Fleet datastore API and hardcoded local dev credentials (appropriate for a seed tool), replacing the old raw SQL approach.


100-125: LGTM!

macOS host creation logic is correct: uses idempotent helper, handles errors gracefully (logs and continues), and sets appropriate platform/OS metadata.


127-152: LGTM!

Windows host creation follows the same correct pattern as macOS: idempotent, error-tolerant, and sets appropriate metadata.


154-187: LGTM!

Ubuntu host creation correctly varies the OS version per host (20.04.1, 20.04.2, etc.), calls UpdateHostOperatingSystem to populate detailed OS metadata, and handles errors gracefully.


189-201: LGTM!

macOS software loading correctly uses the datastore UpdateHostSoftware API, reads from the expected CSV path, and handles errors gracefully.


203-215: LGTM!

Windows software loading mirrors the macOS approach and correctly uses the datastore API with the expected CSV path.


217-234: LGTM!

Linux kernel package generation correctly creates kernel software entries with IsKernel=true, varying the version per package, and uses the datastore API to insert them.

changes/33494-os-version-response-time (1)

1-1: LGTM!

Change file correctly documents the optimization for the os_versions API response time.

tools/software/vulnerabilities/README.md (3)

3-4: LGTM!

Updated description accurately reflects the tool's purpose: seeding hosts and software without requiring real hosts or osquery-perf.


10-10: LGTM!

Marking the CSV review step as "Optional" is appropriate and clarifies usage.


24-26: LGTM!

The idempotent behavior note accurately describes the tool's functionality and clarifies that removed CSV entries are not deleted.

server/service/hosts.go (7)

2134-2142: LGTM!

Function signature reformatted to multi-line for readability; no semantic changes to parameters or return types.


2181-2193: LGTM!

Loading all OS versions unpaged is necessary for sorting and counting before pagination, which is the correct approach for this optimization.


2195-2204: LGTM!

Sorting by hosts_count with default descending order preserves existing behavior while supporting explicit ascending sort when requested.


2206-2207: LGTM!

Total count is correctly calculated before pagination, ensuring the API returns the full count of matching OS versions.


2209-2211: LGTM!

Pagination is correctly applied before loading vulnerabilities, which is the core optimization that reduces response time by limiting vulnerability queries to the current page.


2213-2243: LGTM!

Vulnerability loading is correctly restricted to the paginated slice, which is the critical optimization that improves response time from 52s to 3s (as noted in PR objectives). The implementation properly generates CPEs for Darwin, maps vulnerabilities, and initializes collections.


2249-2271: LGTM!

The paginateOSVersions helper correctly implements slice-based pagination with proper edge-case handling (empty results, last page, no pagination).


```bash
go run ./tools/seed_data/seed_vuln_data.go
go run ./tools/seed_data/seed_vuln_data.go --ubuntu 1 --macos 1 --windows 1 --linux-kernels 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.

⚠️ Potential issue | 🟡 Minor

Incorrect file path in command example.

The command references ./tools/seed_data/seed_vuln_data.go, but based on the file structure, the correct path should be ./tools/software/vulnerabilities/seed_vuln_data.go.

Apply this diff to fix the path:

-go run ./tools/seed_data/seed_vuln_data.go --ubuntu 1 --macos 1 --windows 1 --linux-kernels 1
+go run ./tools/software/vulnerabilities/seed_vuln_data.go --ubuntu 1 --macos 1 --windows 1 --linux-kernels 1
📝 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
go run ./tools/seed_data/seed_vuln_data.go --ubuntu 1 --macos 1 --windows 1 --linux-kernels 1
go run ./tools/software/vulnerabilities/seed_vuln_data.go --ubuntu 1 --macos 1 --windows 1 --linux-kernels 1
🤖 Prompt for AI Agents
In tools/software/vulnerabilities/README.md around line 21, the example command
uses an incorrect path ./tools/seed_data/seed_vuln_data.go; update the command
to reference the correct file path
./tools/software/vulnerabilities/seed_vuln_data.go so the example runs against
the actual script in this directory.

Comment on lines +21 to +31
var (
// MySQL config
mysqlAddr = "localhost:3306"
mysqlUser = "fleet"
mysqlPass = "insecure"
mysqlDB = "fleet"

type HostSoftware struct {
HostID int64 `db:"host_id"`
SoftwareID int64 `db:"software_id"`
}
// CSV paths
macCSVPath = "./tools/software/vulnerabilities/software-macos.csv"
winCSVPath = "./tools/software/vulnerabilities/software-win.csv"
)

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

Remove unused global variables.

These package-level variables (mysqlAddr, mysqlUser, mysqlPass, mysqlDB, macCSVPath, winCSVPath) are declared but never referenced. The new implementation uses CLI flags and hardcoded paths within main(). Clean up by removing these unused globals.

🤖 Prompt for AI Agents
In tools/software/vulnerabilities/seed_vuln_data.go around lines 21 to 31 the
package declares unused global variables (mysqlAddr, mysqlUser, mysqlPass,
mysqlDB, macCSVPath, winCSVPath) that are not referenced because the program now
uses CLI flags and local paths in main; remove these unused globals from the
file to clean up dead code and ensure no unused-variable compile warnings
remain, leaving any necessary configuration handled via flags or local variables
in main.

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

Looks good overall. I made a couple nit comments and I see Code Rabbit made some as well.

I did not do a detail review of the tool update.

Also, we should change the default for osquery-perf to randomize between at least 50 OS versions. (800 would be nice, but I don't how easy/maintainable that is) That way our load test would be closer to customer environment. But that can be done in a later PR.

Comment thread server/service/hosts.go Outdated
count = len(osVersions.OSVersions)

// Paginate first
var meta *fleet.PaginationMetadata

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.

Nit. Can this line be removed since it is initialized below?

Comment thread server/service/hosts.go Outdated

// Pull vulnerabilities ONLY for the paginated slice, as the full list slows
// response times down significantly with many CVEs.
if len(paged) > 0 {

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.

Nit. If len(paged) == 0, return right away. This is a general Go best practice to return early for special conditions. This will eliminate the indentation of the code below.

@codecov

codecov Bot commented Oct 1, 2025

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.50000% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 64.01%. Comparing base (662f3f5) to head (e05e365).
⚠️ Report is 16 commits behind head on main.

Files with missing lines Patch % Lines
server/service/hosts.go 92.50% 2 Missing and 1 partial ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main   #33691   +/-   ##
=======================================
  Coverage   64.00%   64.01%           
=======================================
  Files        2067     2067           
  Lines      207195   207214   +19     
  Branches     6725     6725           
=======================================
+ Hits       132625   132642   +17     
- Misses      64140    64143    +3     
+ Partials    10430    10429    -1     
Flag Coverage Δ
backend 65.11% <92.50%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@getvictor getvictor 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

@mostlikelee
mostlikelee merged commit 651a4f3 into main Oct 1, 2025
43 checks passed
@mostlikelee
mostlikelee deleted the 33494-os-versions branch October 1, 2025 18:11
mostlikelee pushed a commit that referenced this pull request Oct 1, 2025
iansltx pushed a commit that referenced this pull request Oct 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OS versions: 502s after upgrading v4.73.1 -> v4.73.2

3 participants