Skip to content

Add versioned management API wrappers#126

Open
kesmit13 wants to merge 15 commits into
mainfrom
versioned-management-api
Open

Add versioned management API wrappers#126
kesmit13 wants to merge 15 commits into
mainfrom
versioned-management-api

Conversation

@kesmit13

@kesmit13 kesmit13 commented Jun 5, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Implement versioned management API layer (ADR 0001) enabling version-switchable access to management API endpoints via mgr.v2 / entity.v2 attribute syntax
  • Move implementation classes into management/v1/ and management/v2/ folders; top-level modules become thin re-export shims routing via config.get_option('management.version')
  • Add VersionedMixin providing cached __getattr__-based version switching for both managers and entities, with credential cloning and from_dict reconstruction

Test plan

  • 36 unit tests in test_versioned_management.py covering:
    • VersionedMixin __getattr__ pattern matching and caching
    • Dynamic module import (success and error paths)
    • Manager credential storage and version cloning
    • Entity version switching via from_dict + versioned manager
    • Top-level shim re-exports and manage_*() version routing
    • v2-inherits-v1 inheritance model
    • No silent fallback (missing class raises ManagementError)
    • management.version config option routing
    • Convention-based module name derivation

🤖 Generated with Claude Code


Note

Medium Risk
Large refactor of management client layout plus removal of manage_cluster; version switching and factory routing affect how all management HTTP calls are targeted.

Overview
Introduces a versioned management API layer (ADR 0001): implementations live under management/v1/ and management/v2/, while top-level modules stay as v1 re-export shims so existing imports keep working.

VersionedMixin on Manager and entities enables cached .v1 / .v2 access—managers clone credentials to the right API base URL; entities rebuild from stored _response via the target version’s from_dict. manage_*() factories (e.g. manage_files, manage_regions) now pick the module from management.version (or the version argument) through dynamic import.

Breaking cleanup: deprecated manage_cluster and cluster.py are removed from the package surface.

Alongside the move, v1 picks up small fixes (billing usage JSON keys, export status listing, ensure_within on folder downloads, files upload path handling) and entities gain _response / mixin wiring for version switching.

Reviewed by Cursor Bugbot for commit b01a039. Bugbot is set up for automated code reviews on this repo. Configure here.

Implement version-switchable management API layer so clients can access
specific API versions (v1, v2) from an existing manager or entity without
creating separate managers from scratch.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Comment thread singlestoredb/management/manager.py Outdated
Comment thread singlestoredb/management/versioned.py Outdated
Comment thread singlestoredb/management/v1/inference_api.py
Comment thread singlestoredb/management/v1/files.py
- Store resolved token (not input None) in Manager._access_token so
  versioned clones don't re-resolve or fail
- Handle wrapper managers (JobsManager, InferenceAPIManager) in
  VersionedMixin._get_versioned via a third code path that clones
  with the versioned parent manager
- Remove manage_* factory re-exports from v2 modules (they'd return
  v1 objects since they hardcode v1 class construction)
- Add missing re-exports: Organization in workspace shim, FileSpace in
  v2/files, space constants in files shim, _get_exports in v2/export
- Add tests for wrapper manager version-switching and token storage

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Comment thread singlestoredb/management/cluster.py Outdated
Remove the never-production ClusterManager (v0beta) entirely and fix
three VersionedMixin bugs: entity from_dict arity mismatch, wrapper
manager misclassification, and FilesObject missing _response/_manager.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Comment thread singlestoredb/management/versioned.py
Comment thread singlestoredb/management/versioned.py
Comment thread singlestoredb/__init__.py

Copilot AI 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.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copilot AI 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.

Pull request overview

Copilot reviewed 35 out of 35 changed files in this pull request and generated 5 comments.

Comment thread singlestoredb/management/versioned.py
Comment thread singlestoredb/management/versioned.py
Comment thread singlestoredb/management/files.py Outdated
Comment thread docs/adr/0001-versioned-management-api-wrappers.md Outdated
Comment thread .flake8
Fix import error masking in _import_versioned_module by validating version
format and only catching ModuleNotFoundError for the expected path. Add
None guards on _manager in entity/wrapper paths. Fix docstring copy/paste
error, clarify ADR re-export behavior, remove dead .flake8 entry.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Comment thread singlestoredb/management/versioned.py Outdated
Route entity and wrapper-manager version switches through
getattr(self._manager, version) instead of calling _get_versioned
directly, so they share the same cached versioned manager instance
that mgr.v2 returns.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Comment thread singlestoredb/management/versioned.py

Copilot AI 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.

Pull request overview

Copilot reviewed 35 out of 35 changed files in this pull request and generated 7 comments.

Comment thread singlestoredb/management/versioned.py
Comment thread singlestoredb/management/versioned.py
Comment thread singlestoredb/management/versioned.py Outdated
Comment thread singlestoredb/management/v1/billing_usage.py
Comment thread singlestoredb/management/v1/billing_usage.py
Comment thread singlestoredb/management/v1/export.py Outdated
Comment thread singlestoredb/management/v1/region.py Outdated
…ports

- Replace fromisoformat() with to_datetime_strict() in UsageItem.from_dict()
- Fix snake_case key access (resource_type -> resourceType, Usage -> usage)
- Propagate _location and region after entity version-switch reconstruction
- Return List[ExportStatus] from _get_exports() instead of raw JSON
- Fix region.py module docstring and manage_files docstring

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Comment thread singlestoredb/management/versioned.py
Comment thread singlestoredb/management/v1/workspace.py
@kesmit13 kesmit13 requested a review from Copilot June 5, 2026 19:45
v2 region listings have no regionID, so v2 Region instances carry id=None.
The previous lookup matched only on id, falling back to a '<unknown>'
placeholder for every workspace group on a v2 manager. Now match by id
first, then by (regionName, provider), and use payload fields for the
final fallback so users see real region info even when no listing match
exists.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Addresses Copilot PR review comments 3365002592 and 3365002611 on
PR #126.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

Copilot AI 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.

Pull request overview

Copilot reviewed 35 out of 35 changed files in this pull request and generated 2 comments.

Comment thread singlestoredb/management/v2/workspace.py
Comment thread singlestoredb/management/versioned.py Outdated
- v2/workspace.py: fall back to self._manager.v1.organization.id in
  WorkspaceGroup.get_metrics. v2 has no organizations/current endpoint
  and the OpenAPI spec for the v2 metrics endpoint explicitly directs
  callers to /v1/organizations/current. Docstring updated to make this
  cross-version exception explicit.
- versioned.py: _import_versioned_module now distinguishes between an
  unsupported API version (the version package itself is missing) and
  a missing submodule under a valid version. Unrelated ModuleNotFound
  errors (e.g., transitive deps inside a valid module) propagate
  untouched instead of being masked.
- test_versioned_management.py: updated tests to assert the new
  submodule-missing message and rewired metrics fallback tests to
  stub the v1 clone's organization via _version_cache.

Addresses Copilot PR review comments 3375344342 and 3375344393 on
PR #126.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

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

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 5196df8. Configure here.

Comment thread singlestoredb/management/v1/region.py

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

Stale comment

Security review found two high-severity path traversal issues in recursive download helpers that can write outside the caller’s chosen local directory when remote entry paths contain traversal segments.

Open in Web View Automation 

Sent by Cursor Security Agent: Security Reviewer (all 3 orgs)

Comment thread singlestoredb/management/v1/files.py Outdated
Comment thread singlestoredb/management/v1/workspace.py Outdated

Copilot AI 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.

Pull request overview

Copilot reviewed 35 out of 35 changed files in this pull request and generated 4 comments.

Comment thread singlestoredb/management/v1/inference_api.py Outdated
Comment thread singlestoredb/management/v1/job.py
Comment thread singlestoredb/management/v1/job.py
Comment thread singlestoredb/management/v1/export.py
- Add path-traversal containment check in recursive folder downloads.
  New `singlestoredb.management.utils.ensure_within` resolves both the
  destination root and the candidate target via realpath and raises
  ManagementError if the target escapes the root. Applied in
  `FileLocation.download_folder` (file and directory branches) and
  `Stage.download_folder`. Defends against `../` segments and symlink
  escapes from a malicious or compromised remote listing.

- Route the v1-namespace `manage_regions`, `manage_workspaces`, and
  `manage_files` factories through `_import_versioned_module` so that
  `version='v2'` returns the correct v2 manager class instead of a v1
  manager pointed at a `/v2/` base URL.

- Convert `singlestoredb/management/v1/inference_api.py` imports from
  absolute (`from singlestoredb.*`) to the relative form used by the
  rest of the v1 modules.

- Fix over-indented continuation lines on two `get_executions`
  signatures in `v1/job.py`.

- Rename `self` to `cls` (and use `cls(...)` for construction) in
  `ExportService.from_export_id`, which is a `@classmethod`.

- Add tests for path-traversal rejection in both download_folder
  methods and for v1-namespace factory routing to v2.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

Copilot AI 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.

Pull request overview

Copilot reviewed 36 out of 36 changed files in this pull request and generated 3 comments.

Comment thread singlestoredb/management/v1/workspace.py
Comment thread singlestoredb/management/v1/region.py
Comment thread singlestoredb/management/v1/files.py

Copilot AI 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.

Pull request overview

Copilot reviewed 36 out of 36 changed files in this pull request and generated 2 comments.

Comment thread singlestoredb/management/v1/workspace.py Outdated
Comment thread singlestoredb/management/v1/files.py Outdated
Stage.upload_folder ignored stage_path and built remote targets from the
local filesystem path (with os.getcwd() basename when include_root=True),
and crashed on subdirectories because glob('**') yields directories.

FileSpace.upload_folder used str.lstrip(local_path), which strips a
character set rather than a prefix, producing incorrect remote paths.

Both now walk files via os.walk, compute the per-file suffix with
os.path.relpath, and honor include_root and recursive=False consistently.
…nager

The v2 RegionManager raised a custom ManagementError when callers used
list_shared_tier_regions, on the grounds that /v2/regions/sharedtier has
no OpenAPI counterpart. Every other v1 endpoint without a v2 counterpart
just 404s through the inherited request path, so singling out this one
method gave a misleading impression of v2 endpoint coverage. Drop the
override, the related docstring paragraph, the now-unused ManagementError
import, and the test that asserted the raise — falling back to the same
404 path used by the rest of the v2 surface.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

Copilot AI 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.

Pull request overview

Copilot reviewed 36 out of 36 changed files in this pull request and generated no new comments.

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.

2 participants