Skip to content

cli on top of datumctl#158

Draft
gianarb wants to merge 16 commits into
mainfrom
feat/cli-tunnel-datumctl
Draft

cli on top of datumctl#158
gianarb wants to merge 16 commits into
mainfrom
feat/cli-tunnel-datumctl

Conversation

@gianarb
Copy link
Copy Markdown
Collaborator

@gianarb gianarb commented May 18, 2026

This is based on #130

I removed the commands that are convered in datumctl and I changed datum-connect authentication to work on top of datumctl.

Do you want to login? use the datumctl. Do you want to swtich in between projects? use the datumctl.

Do you want to create and manage tunnels? use datum-connect.

What else we can do?!

We can implement a plugin system in datumctl simlar to how kubectl plugin works. https://kubernetes.io/docs/tasks/extend-kubectl/kubectl-plugins/

And we can distribute this CLI with a name similar to datumctl-connect and people installing this plugin will be able to run something like:

datumctl connect (tunnel|listen|...)

This is just an idea and I had to do this work primarily to simplify the work I am doing for demo.datum.net

drewr and others added 14 commits May 14, 2026 00:39
- Add 'tunnel' subcommand to datum-connect CLI with:
  - 'tunnel list': read-only listing of tunnels (no side effects)
  - 'tunnel listen': create/update and run tunnel in foreground
  - 'tunnel update': update tunnel label/endpoint
  - 'tunnel delete': delete a tunnel
- Add 'nix run .#connect' app to flake.nix
- Split find_connector_readonly for list operations
- Remove side effects from tunnel list (no patching Connector)
- Listen command:
  - Generates random label if not provided
  - Confirms before updating existing tunnel
  - Handles Ctrl+C to disable tunnel on exit
- Add 'auth' subcommand to CLI with:
  - 'auth status': Show current authentication and selected context
  - 'auth login': Log in via browser OAuth with account picker
  - 'auth logout': Log out and clear credentials
  - 'auth list': Show current authenticated user
  - 'auth switch': Log out current user and prompt for new login

Also add is_authenticated(), login(), logout() methods to DatumCloudClient.
delete_project returned early when find_connector returned None,
skipping deletion of HTTPProxy/ConnectorAdvertisement/TrafficProtectionPolicy.

Connector lookup is only needed for post-deletion cleanup (deciding
whether to delete the shared connector). Move it into an Option and
gate the cleanup block on Some, so resource deletion always proceeds.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Three interrelated bugs fixed in the tunnel listen command:

- Random label was generated before checking for an existing tunnel,
  so re-running listen on the same endpoint always triggered the update
  prompt. Moved label generation into the create-new path only; existing
  tunnels reuse their stored label unless --label is explicitly provided
  and differs.

- Default label format changed from tunnel-<u16> (collides with resource
  ID format) to 12 hex chars of random entropy (e.g. a3f9c2e1b047).
  Adds hex as a dependency.

- tunnel listen was missing the HeartbeatAgent that continuously patches
  status.connectionDetails on the connector (relay URL, addresses, public
  key). Without it the gateway has no routing info and tunnels never
  carry traffic. Now starts the heartbeat and registers the project before
  enabling the tunnel, then polls until accepted+programmed before
  printing the hostname.

Also simplifies tunnel delete output: connector cleanup is an internal
detail, so "Deleted tunnel <id>" replaces "(connector deleted: false)".

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
  - After auth login/switch, prompt user to select an org and project
    and persist the selection as the active context
  - Store the selected context in config.yml instead of a separate file
  - Add --project flag to the tunnel command to override the active
    project for a single invocation
  - Add projects list and projects switch commands for managing the
    active project outside of the auth flow
  - Fix tunnel listen to print id and label after creation
The gateway sends `CONNECT localhost:<port>` regardless of whether the
tunnel was registered with `localhost` or `127.0.0.1`, causing auth to
fail with Forbidden and the caller to see "upstream connect error or
disconnect/reset before headers."

Normalize `localhost`, `127.0.0.1`, and `::1` to a canonical form on
both sides of the host comparison in `tcp_proxy_exists`.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit removes all the features that are covered by the datumctl
and it makes the authentication of datum-connect to work on top of the
datumctl
@gianarb gianarb requested review from drewr and scotwells May 18, 2026 13:31
drewr added 2 commits May 18, 2026 14:31
pkgs.xdo is a standalone CLI tool with no library output; libxdo-sys
requires libxdo.so which is provided by pkgs.xdotool. Also replace the
explicit PKG_CONFIG_PATH override (which prevented nix from auto-populating
it) with RUSTFLAGS=-L so the linker can find libxdo regardless of whether
pkg-config resolves it.
- Remove unused FAVICON_LIGHT_32 static in auth.rs
- Remove unused NativeIcon import in main.rs
- Gate FAVICON_*_196 constants behind #[cfg(target_os = "macos")]
- Move title_bar_bg binding inside its #[cfg(target_os = "macos")] block
- Drop unnecessary mut from five Signal bindings in App()
- Prefix unused tx/checker locals with _ in fake-update path
- Add #[allow(dead_code)] to SelectSize::Small (implemented but unconstructed)
- Remove unused listen_node() method from AppState
Copy link
Copy Markdown
Contributor

@drewr drewr left a comment

Choose a reason for hiding this comment

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

I think I'd still prefer if we had just one binary to cover it all, but this is probably a good compromise for the time being.

Also just logging that this (probably my work with sonnet/opus) still took like 20 minutes for the tunnel to actually work:

% cargo run -p datum-connect -- tunnel listen --endpoint 127.0.0.1:8000
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.82s
     Running `target/debug/datum-connect tunnel listen --endpoint '127.0.0.1:8000'`
2026-05-18T15:08:49.477806Z  WARN lib::repo: secret key does not exist. creating new key
2026-05-18T15:08:49.478488Z  WARN lib::repo: secret key does not exist. creating new key
Created tunnel:
  id: tunnel-59lnm
  label: 186e5173de95

Your endpoint ID: a895662648238bec3d8425b7b301c4183934e941a57a1c535f1f6c04e603a046
Setting up tunnel...
Tunnel ready after 261 sec: https://helium-divide-z8zth.datumproxy.net
Press Ctrl+C to stop...

@gianarb
Copy link
Copy Markdown
Collaborator Author

gianarb commented May 18, 2026

For it takes ~ half of it but yeah not ideal

@gianarb
Copy link
Copy Markdown
Collaborator Author

gianarb commented May 18, 2026

I think I'd still prefer if we had just one binary to cover it all, but this is probably a good compromise for the time being.

yeah that will be ideal I am not sure how much it will take to get the tunnel working in pure Go. It will be nice to try!! Not sure if Iroh has some ongoing work there

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