Skip to content

feat(enclave): add enclave (outpost) management commands - #732

Draft
artem-panchenko wants to merge 6 commits into
datarobot-oss:mainfrom
artem-panchenko:apanchenko/enclave-commands
Draft

feat(enclave): add enclave (outpost) management commands#732
artem-panchenko wants to merge 6 commits into
datarobot-oss:mainfrom
artem-panchenko:apanchenko/enclave-commands

Conversation

@artem-panchenko

@artem-panchenko artem-panchenko commented Aug 4, 2026

Copy link
Copy Markdown

RATIONALE

Covalent recently shipped a public Outposts API (/covalent/api/v2/outposts). This adds first-class CLI support so operators can register and manage enclaves (outposts) and control who may use them, instead of hand-rolling curl calls. It mirrors the existing dr workload command tree in layout, output handling, and telemetry wiring.

There is no public activate verb — an enclave activates itself when its installer reports in — so no activate command is provided (documented in --help). Manually deactivated enclaves can be returned to service with reactivate.

CHANGES

New feature-gated dr enclave command tree (gated behind DATAROBOT_CLI_FEATURE_ENCLAVE, mirroring dr workload):

  • dr enclave register --name <n> [--label k=v] — surfaces the one-shot installation secrets (shown once, never persisted server-side; --output-format json to capture them)
  • dr enclave get <id>
  • dr enclave list
  • dr enclave deactivate <id> — takes an enclave out of service
  • dr enclave reactivate <id> — returns a manually deactivated enclave to service (inverse of deactivate)
  • dr enclave delete <id> [--yes] — confirmation prompt + friendly 404
  • dr enclave access grant <id> --role <owner|user|consumer> <recipient>
  • dr enclave access revoke <id> <recipient> — sends the NO_ROLE removal sentinel

access commands wrap the sharedRoles PATCH endpoint, mapping owner|user|consumerOWNER|USER|CONSUMER, with exactly-one recipient selection (--user / --user-id / --group / --org) enforced via MarkFlagsMutuallyExclusive plus a required-one check. --help calls out the server dependencies (ENCLAVE_RBAC_ENABLED, CAN_SHARE, ENCLAVE_ADMIN_ONLY).

Layout:

  • internal/enclave/ — API client (enclave.go), sharing client (sharing.go), output rendering (output.go)
  • cmd/enclave/** — parent group + per-verb packages (register, get, list, deactivate, reactivate, del, access/{grant,revoke})
  • Registered in cmd/root.go; telemetry-wiring assertions added in cmd/telemetry_wiring_test.go

TESTING

  • go build ./..., go vet, gofmt clean
  • Unit tests: httptest-backed client (register incl. 409, get + id-escaping, list, deactivate, reactivate, delete + 404, sharedRoles grant/revoke body + path), role/recipient parsing, flag/arg validation, telemetry wiring — all pass
  • go test ./cmd/enclave/... ./internal/enclave/... ./cmd/ green

Note: golangci-lint was not run in the authoring environment due to a Go toolchain version gap (repo targets 1.26.5); please rely on CI lint. All wsl/formatting conventions were matched against existing lint-passing packages.

Add a feature-gated `dr enclave` command tree over the public Outposts
API at /covalent/api/v2/outposts:

  register, get, list, deactivate, delete
  access grant / access revoke  (sharedRoles)

`register` surfaces the one-shot installation secrets (shown once, never
persisted server-side). `access grant/revoke` wrap the sharedRoles PATCH
endpoint, mapping owner|user|consumer -> OWNER|USER|CONSUMER and NO_ROLE
for removal, with exactly-one recipient selection (--user/--user-id/
--group/--org).

Gated behind DATAROBOT_CLI_FEATURE_ENCLAVE, mirroring `workload`. Includes
unit tests (httptest-backed client, flag/arg validation) and telemetry
wiring assertions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@datarobot-pr-review-router

Copy link
Copy Markdown

👋 Thanks so much for contributing to the DataRobot community!

As a quick heads-up on how our team handles reviews: if you're still iterating on
this code or running tests, please feel free to convert this to a Draft PR.
We rely heavily on GitHub Drafts to give contributors a stress-free sandbox to experiment!

Once everything is finalized and you're ready for feedback, just click "Ready for review"
and the maintainers will be notified to jump in. (And if this PR is already 100% ready
to go, no action needed, we'll take a look soon!)

Wrap the new POST /covalent/api/v2/outposts/{id}/reactivate endpoint so a
manually deactivated enclave can be returned to service from the CLI — the
inverse of `dr enclave deactivate`. Mirrors deactivate: 200 with the updated
enclave, no request body. Includes client + command tests and telemetry
wiring.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ajalon1

ajalon1 commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

hey @artem-panchenko, thanks!. Have you already talked to @carsongee or @shreyaag-dr about this work? We'd like to see overall what your plans are for the CLI command hierarchy and API, and how they dovetail with the rest of the CLI.

@ajalon1

ajalon1 commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Note: golangci-lint was not run in the authoring environment due to a Go toolchain version gap (repo targets 1.26.5).

Were you running into something like this?

compile: version "go1.X.Y" does not match go tool version "go1.X.Z"

If so, https://github.com/datarobot-oss/cli/blob/main/docs/development/building.md#go-version-requirements-for-race-detection

artem-panchenko and others added 4 commits August 6, 2026 19:27
Manage the collection-level enclave "create" permission — the right to register
new enclaves — as a permission a system administrator delegates, rather than a
role the CLI infers.

  dr enclave permission grant  --permission create --org <id>
  dr enclave permission revoke --permission create --user-id <id>

Wraps PATCH /covalent/api/v2/outposts/createAccess (server CAN_CREATE on the
enclave collection). Recipients are id-based only (--user-id / --group / --org):
that endpoint takes an id, so there is no --user <username> form as there is for
`dr enclave access`. A username-only recipient fails before the request is sent,
and ResolveRecipientByID's errors name only the flags these commands offer.

--permission is validated (create is the only value today) so the surface can
grow without changing the command shape.

Also drops ENCLAVE_ADMIN_ONLY from the `dr enclave access` help text: that server
flag no longer exists — system admins may manage any enclave, and creation is
governed by this new permission.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Show what you can actually do with an enclave, and where it comes from:

  dr enclave access show <enclave-id>
  dr enclave access show <enclave-id> --user-id <id>   # admins: inspect a user

Wraps GET /covalent/api/v2/outposts/{id}/permissions. An empty list is the usual
explanation for a workload failing to schedule with "not permitted to deploy",
so the command reports it plainly rather than erroring.

Text output names the source, because a full permission set is ambiguous
otherwise: a system administrator and a server with enclave RBAC disabled both
hold everything without any grant, which looks identical to being the owner.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ypass

Two visibility gaps made it impossible to confirm a share had landed.

`dr enclave access list <id>` (alias ls) lists who an enclave is shared with and
the role each holds, over the new GET .../sharedRoles. "access show" answers only
for one subject, and for a system administrator it answers from the bypass, so
neither revealed the enclave's actual shares. An empty result reads as "not shared
with anyone" rather than an error -- which also covers an enclave registered
before RBAC was enabled, whose owner grant was never written.

"access show" now also prints a Granted: line when the sys-admin bypass supplied
the answer, so an admin can see whether the subject holds anything of its own. It
is omitted otherwise, where it would just repeat Permissions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Makes the collection-level create permission as inspectable as a per-enclave
share, mirroring `dr enclave access list/show`:

  dr enclave permission show [--user-id <id>]   # may I (or they) create enclaves?
  dr enclave permission list                    # who has been granted it (alias ls)

show reports the source, because a full answer is ambiguous otherwise: a system
administrator may create regardless of grants, and a server with RBAC disabled
enforces nothing. Under the bypass it also prints Granted:, so an admin can see
whether the subject holds anything of its own.

list is the "did my grant land?" view for `permission grant` — show answers for
one subject and short-circuits for admins, so neither revealed who was actually
granted. An empty result reads as "nobody has been granted it", and notes that
system administrators do not appear because they bypass the permission.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

2 participants