Commit Graph
193 Commits
Author SHA1 Message Date
a9a720f3c3 feat: Add uc service start/stop commands (#195)
* feat: Add `uc service start/stop` commands

* Add nolint:dupl for service start/stop commands

Co-authored-by: Pasha Sviderski <me@psviderski.name>

* Add --signal and --timeout options to uc service stop

* Check whether service stop --timeout flag was used to set options properly

---------

Co-authored-by: Pasha Sviderski <me@psviderski.name>
2025-12-09 15:58:09 +10:00
Pasha Sviderski 27cfe1c4f3 feat: 'uc logs' without argements streams logs for services in the local Compose file 2025-12-04 15:40:24 +10:00
Pasha Sviderski 1e6aaf451e feat: support filtering service logs by machine (-m/--machine) 2025-12-03 15:01:23 +10:00
Pasha Sviderski bf65fbaca5 feat --utc flag for 'uc logs' command to print timestamps in UTC 2025-12-03 12:52:20 +10:00
79dc05cb66 feat: service logs command to stream service logs (#196)
* chore: fix landing logo shadow

* feat: implement service logs command with colored output and strict ordering

* revert Makefile

* fix after rebase

* move logs command under services with root shortcut

* simplify server options for streaming logs and CLI flags

* refactor ContainerLogs grpc server

* update --tail flag

* minor docker.proto

* refactor client ServiceLogs and ContainerLogs

* move ProxyMachinesContext from api to client pkg

* minor refactor proto Stream

* add api/logs

* implement LogMerger

* fix LogMerger to correctly use semaphore

* increate inflish entries to 100 per stream

* send heartbeats

* refactor ContainerLogs to synchronise Send of entries and heartbeats to the steram

* minor logmerege

* remove ContainerName form ServiceLogEntryMetadata

* refactor ContainerLogs into docker.Service

* detect stalled container logs streams

* update logmerger tests

* fix comment in test

* refactor LogMerger with options

* uc logs: format one or multiple services

* make LogMerger emit heartbeats, emit entries <= watermark, rewrite tests

* update uc logs with new LogMerger

* go mod tidy

* fix after merge

---------

Co-authored-by: Evgenii Orlov <evgenii.orlov@semrush.com>
2025-12-02 19:50:48 +10:00
Justin BradfordandGitHub d89bfb8e03 feat: add uc ps command to list all containers in the cluster (#165)
* feat: Add `uc ps` command to list all containers in the cluster

* Fix indentation

* Improvements to the container state highlights code (use enum, better var naming)

* Add group/sort option by "health"

* Rename `uc ps --group-by` flag to `--sort`. Also, remove `--context` flag.

* Use huh.spinner with standard style/type

* Remove pointless TrimPrefix on container name

* Move machine lookup out of services loop

* Use more efficient `ListServiceContainers`

* Use consistent header other

* Use api.ProxyMachinesContext helper for context to query all machines for service containers

* Make errored MachineServiceContainer entries a warning, not return an error immediately, in `uc ps`

* Use lipgloss table instead of tabwriter for "uc ps" command

* Handle nil metadata in `uc ps` on container when cluster only has one machine
2025-11-27 20:05:58 +10:00
91a09d5d37 feat: add CLI connector for unix domain socket (#186)
* feat: Add cli connector for unix domain socket

* Update cmd/uncloud/main.go

---------

Co-authored-by: Pasha Sviderski <me@psviderski.name>
2025-11-25 21:45:07 +10:00
Pasha Sviderski 4433095045 chore: show links to docs and Discord for the root 'uc --help' command 2025-11-21 22:08:32 +10:00
Pasha Sviderski 3fbba6d540 chore: sort services in 'uc ls' output by name 2025-11-21 18:11:20 +10:00
Justin BradfordandGitHub 76b4369aa6 feat: store machine id on connection entries in Uncloud config so it can be removed with machine (#182)
* fix: Store machine id on connection entries so it can be removed when machine is

* Add "GetContextOverrideOrCurrent" helper method to cli and use in `uc machine rm` to clean up connections
2025-11-20 16:49:37 +10:00
Pasha Sviderski 74c7738bc3 docs: update 'uc service rm' description that volumes are preserved 2025-11-20 16:36:36 +10:00
Justin BradfordandGitHub 939645e144 refactor: Make --context cli flag a global option (#174)
* Make `--context` flag a global option and remove duplication

* Remove unused dns showOptions struct

* First pass of refactoring "active context" determination and validation

* Undo some refactoring in cli.go to keep diff more focused
2025-11-19 20:30:32 +10:00
Justin BradfordandGitHub 1d413734d8 feat: Interactive 'uc ctx connection` command to select preferred cluster connection (#170)
* feat: Interactive uc command to select preferred cluster connection

https://github.com/psviderski/uncloud/issues/125

* Simplify connection selection and reordering by using the index instead of a pointer

* Move connection reordering logic to a new SetDefaultConnection on context
2025-11-19 13:53:29 +10:00
Luis LavenaandGitHub eea81723b8 feat(ssh+cli): Support SSH CLI on machine init and add commands (#173)
* Add SSHCLIRemote type with buildSSHArgs

Implement's Executor interface (Run, Stream, Close)

* Add UseSSHCLI field to RemoteMachine struct

Allow us to differentiate regular ssh from ssh+cli.

* Parse ssh+cli:// scheme on machine init/add

* Support SSH CLI when provisioning

* Update docs to reflect ssh+cli:// support

* Revert removal of `init` examples

Fixes copy & pasta mistake when documenting the new ssh+cli connection
methods.
2025-11-17 20:11:31 +10:00
Pasha Sviderski 90d244fea8 chore: 'uc image push' fix long description 2025-11-12 09:28:54 +10:00
Pasha Sviderski 497b9483f6 chore: fix the examples for 'uc image push' command after changing default 2025-11-12 09:25:19 +10:00
Pasha Sviderski 2b93a1c089 chore: update --container flag help that accepts ID prefix 2025-11-10 08:41:25 +10:00
Anton OvchinnikovandGitHub 15d4ef5518 feat: Allow container matching by ID prefix (#175) 2025-11-10 08:38:20 +10:00
Pasha Sviderski 9770151583 fix: 'uc deploy' push image to all machines if x-machines is not specified 2025-11-07 15:38:52 +10:00
Luis LavenaandGitHub 48d2239f5d Connect to remote SSH nodes using SSH CLI (#152)
* Connect to remote SSH nodes using SSH CLI

Replace Go-native SSH implementation with SSH CLI execution
to support diverse SSH configurations and agents. Implements
'uncloudd dial-stdio' subcommand that proxies gRPC connections
over stdin/stdout, similar to Docker's approach.

This change addresses compatibility issues with:
- SSH agents exposing many keys (1Password, causing "too many
  authentication failures")
- Tailscale SSH (which doesn't support advanced SSH channel
  types like direct-streamlocal)
- Custom SSH configurations in ~/.ssh/config

The dial-stdio approach reduces SSH feature requirements by
streaming the unix socket connection over stdin/stdout instead
of using SSH channel forwarding.

Changes:
- Add 'uncloudd dial-stdio' hidden subcommand for socket proxy
- Add SSHCLIConnector using ssh command + dial-stdio
- Update connection logic to use SSH CLI connector
- Maintain backward compatibility with SSHKeyFile config

Resolves #131

* Fix sshcli tests missing ConnectionTimeout

Introduced short connection timeout on the first change but forgot to
update tests to match.

* Add SSHCLI field and update MachineConnection String() format

- Add SSHCLI field to support ssh_cli YAML configuration
- Update String() to use URI-like format (ssh://, ssh+cli://, tcp://)

* Add Validate() method and tests for MachineConnection

- Add Validate() to ensure connection methods are mutually exclusive
- Add tests for validation and String() method

* Unify SSH connector configs to use SSHConnectorConfig

* Update connectCluster to support both SSH connector types

* Restore Go SSH connector as default for machine init/add

Revert provisionOrConnectRemoteMachine to use Go SSH connector:
- Root users: reuse SSH connection from provisioning
- Non-root users: establish new connection for group membership
- Remove SSH CLI as default connector

SSH CLI connector remains available via ssh_cli config field.

* Add sshCLIDialer with DialContext method

Implement proxy.ContextDialer for SSHCLIConnector using SSH -W flag.
Each dial spawns a new SSH process for TCP forwarding, enabling
independent connections separate from the gRPC dial-stdio connection.

* Implement SSHCLIConnector.Dialer() method

Return sshCLIDialer instead of error, enabling uc image push
functionality with SSHCLIConnector. Validates connector is
configured before returning dialer.

* Fix half-closing implementation matchin Docker's approach

* Use testify assertions for connection tests

* Allow ssh+cli:// to be used with --connect

This way I can skip the configuration file while testing things out,
and confirm it works correctly:

  $ unset SSH_AUTH_SOCK

  $ ./uncloud --connect ssh://provision@blatta11 machine ls
  Error: connect to cluster: connect to machine: SSH login to
    provision@blatta11:22: connect using SSH agent: connect to SSH
    agent: dial unix: missing address

  $ ./uncloud --connect ssh+cli://provision@blatta11 machine ls
  NAME       STATE   ADDRESS         PUBLIC IP   WIREGUARD ENDPOINTS                                                                                                                  MACHINE ID
  blatta11   Up      10.210.0.1/24   -           100.64.0.22:51820, ...

* Validates configuration before connecting to cluster

* Do not tie client constructor with real validation

No longer attempt to validate the connection when instantiating a new
client.

Later on we could validate it in different places.

* Cleanup test and remove AI-slop

There were some serious slop in those tests, so took the time to clean
them up and kept only the relevant ones.

There is some repetition between buildSSHArgs and buildDialArgs but can
be tackled at a later stage.

* Fix connection representation tests

Prefix connection with ssh ssh+cli respectively.

* Wait for stdout before returning

Missed copy & pasta from Docker dial-stdio implementation (this happens
when you stare at the code for too long that it burns your eyes).
2025-11-06 09:44:29 +10:00
Anton OvchinnikovandGitHub abea3e229e feat: "exec" command to start processes inside remote containers (#139) 2025-11-05 23:47:24 +01:00
Pasha Sviderski 809d1eca77 lint 2025-11-04 18:20:10 +10:00
Pasha Sviderski 882f2f5d03 feat(build,deploy): build service images using compose (bake/buildkit), push to cluster, and deploy 2025-11-04 18:14:42 +10:00
Pasha Sviderski c3ecd378f8 feat(build): --push and --push-registry flags to push build images to cluster or registries 2025-11-03 15:38:59 +10:00
Pasha Sviderski 65c3e0a68d feat(build): print if no services to build, build dependencies --dep, check build configuration --check 2025-10-30 20:54:15 +10:00
Pasha Sviderski 5c4f49b685 feat: new cbuild (compose build) command using Compose implementation 2025-10-30 20:54:15 +10:00
Anton OvchinnikovandGitHub 6af7a9861d feat: Allow to match containers against truncated ID (#160) 2025-10-28 18:44:04 +01:00
Pasha Sviderski 9a0b1a4ce3 chore: print (custom Caddy config) for service ENDPOINTS if x-caddy is used 2025-10-21 11:42:18 +10:00
Pasha Sviderski 265042e2c8 lint 2025-10-08 16:38:40 +10:00
Pasha Sviderski 0fc5032b27 feat(images): add IN USE column to highlight which images are used by any container 2025-10-08 15:43:54 +10:00
Pasha Sviderski a2c6cbe633 chore(images): filter images by name with wildcard pattern using Docker filter 2025-10-08 12:33:13 +10:00
Pasha Sviderski 1f9c2c873d feat(images): list images filtered by name 2025-10-07 20:39:31 +10:00
Pasha Sviderski 509c9eb7d3 chore(images): format platforms as pills, sort images by name 2025-10-07 19:14:40 +10:00
Pasha Sviderski fba03b3df7 feat(images): list image platforms and do not group images by machine 2025-10-07 17:06:52 +10:00
Pasha Sviderski c6d18f5d49 chore: NAME -> IMAGE column name 2025-10-07 15:12:05 +10:00
Pasha Sviderski 6d2e100d63 feat(images): 'uc image ls' and 'uc images' (alias) commands to list images on machines 2025-10-03 20:53:30 +10:00
Pasha Sviderski 684f0d38ee feat(push): '--platform all' to push image to all machines in cluster 2025-09-30 19:23:01 +10:00
Pasha Sviderski 332e7bca90 feat(push): --platform flag to push a specific platform of a multi-platform image 2025-09-30 18:59:03 +10:00
Pasha Sviderski 6b758c810e docs: image push example 2025-09-30 15:24:40 +10:00
Pasha Sviderski ffed906cef feat(push): 'image push' to single or multiple machines via unregistry proxy 2025-09-30 15:18:26 +10:00
Pasha Sviderski 20cf98d42e fix: return an error if 'uc rm' tries to remove a service that doesn't exist 2025-09-26 21:24:56 +10:00
Justin BradfordandGitHub 2d361d3ee6 Adding machine.service.internal dns entries (#123) 2025-09-24 20:06:54 +10:00
Pasha Sviderski 9f6880b701 feat(push): stub for 'image push' command and Dialer interface for cluster connectors 2025-09-23 16:54:47 +10:00
Pasha Sviderski 60926f64cc feat: show IMAGE column when listing services (uc ls) #13 2025-09-22 14:03:45 +10:00
Pasha Sviderski 8f906cfd95 fix: do not auto-confirm deploy plan on CI (no TTY), require explicit --yes or UNCLOUD_AUTO_CONFIRM=true 2025-09-18 12:12:06 +10:00
Pasha Sviderski 7239cd3a6b docs: clarify 'machine init' help, --context flag description, add examples 2025-09-17 15:10:59 +10:00
Pasha Sviderski 3db07ca2d4 feat: allow setting config and connection with UNCLOUD_CONFIG and UNCLOUD_CONNECT env vars 2025-09-16 10:17:44 +10:00
Pasha Sviderski f8fe3c7af3 feat: --no-install flag for 'machine init/add' to skip installing Uncloud daemon and dependencies #122 2025-09-15 20:44:35 +10:00
Pasha Sviderski bc078472d4 feat: add -y|--yes flag for 'us deploy' to auto-confirm deployment plan 2025-09-12 22:52:06 +10:00
Pasha Sviderski 8a273dbf63 chore: rename cluster -> context option in commands for consistency 2025-09-11 20:21:07 +10:00