Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/robinovitch61/wander
A terminal app/TUI for HashiCorp Nomad
https://github.com/robinovitch61/wander
bubbletea charm charmbracelet hacktoberfest hashicorp hashicorp-nomad nomad terminal tui wish
Last synced: 10 days ago
JSON representation
A terminal app/TUI for HashiCorp Nomad
- Host: GitHub
- URL: https://github.com/robinovitch61/wander
- Owner: robinovitch61
- License: mit
- Created: 2022-04-13T06:21:28.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2024-06-18T23:55:45.000Z (5 months ago)
- Last Synced: 2024-08-02T06:14:09.378Z (3 months ago)
- Topics: bubbletea, charm, charmbracelet, hacktoberfest, hashicorp, hashicorp-nomad, nomad, terminal, tui, wish
- Language: Go
- Homepage:
- Size: 62.8 MB
- Stars: 426
- Watchers: 7
- Forks: 16
- Open Issues: 4
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-tuis - wander
- awesome-nomad - robinovitch61/wander - A terminal UI for Nomad. (User interfaces)
- charm-in-the-wild - wander - A HashiCorp Nomad terminal client. (_built with Bubble Tea_) (Applications / Cloud and DevOps)
README
# wander
An efficient terminal application/TUI for interacting with your [HashiCorp Nomad](https://www.nomadproject.io/) cluster.
- Browse jobs, allocations, and tasks
- Live tail logs
- Tail global or targeted events
- Exec to interact with running tasks
- Administrative actions (e.g. restart tasks)
- View resource usage stats (memory, CPU)
- See full job or allocation specs
- Save any content to a local file`wander` is written with tools from [Charm](https://charm.sh/).
[Feature requests and bug reports are welcome](https://github.com/robinovitch61/wander/issues/new/choose).
## Demo
![](./img/wander.gif)
[Screenshots](./img/screenshots#readme)
## Flow Diagram
![](./img/wander_flow.drawio.png)## Installation
The following options are available depending on your platform and tooling:
```shell
# homebrew
brew install robinovitch61/tap/wander# upgrade using homebrew
brew update && brew upgrade wander# nix-shell
# ensure NUR is accessible (https://github.com/nix-community/NUR)
nix-shell -p nur.repos.robinovitch61.wander# nix flakes
# ensure flake support is enabled (https://nixos.wiki/wiki/Flakes#Enable_flakes_temporarily)
nix run github:robinovitch61/nur-packages#wander# arch linux
# PKGBUILD available at https://aur.archlinux.org/packages/wander
yay -S wander-bin# with go (https://go.dev/doc/install)
go install github.com/robinovitch61/wander@latest# windows with winget
winget install robinovitch61.wander# windows with scoop
scoop bucket add robinovitch61 https://github.com/robinovitch61/scoop-bucket
scoop install wander# windows with chocolatey
choco install wander
```You can also download [prebuilt releases](https://github.com/robinovitch61/wander/releases) and move the unpacked
executable to somewhere in your `PATH`, e.g. `/usr/local/bin`.## Usage
Run the app by running `wander` in a terminal. See `wander --help` and config section below for details.
## Configuration
`wander` can be configured in three ways:
1. Command line arguments, visible by running `wander --help`.
2. Environment variables. These map to the configuration file below (e.g. `nomad_addr` in yaml is the `NOMAD_ADDR`
environment variable).
3. A yaml config file at `$HOME/.wander.yaml`, or a custom config file path passed to the `--config` argument. Complete
example below.Priority in order of highest to lowest is command line arguments, then environment variables, then the config file.
Example yaml file showing all options (copy this into `$HOME/.wander.yaml` and uncomment/edit as desired):
```yaml
# Nomad address. Default "http://localhost:4646"
#nomad_addr: "http://localhost:4646"# Nomad token
#nomad_token: ""# Nomad region
#nomad_region: ""# Nomad namespace. Default "*"
#nomad_namespace: "*"# Nomad http auth, in the form of "user" or "user:pass"
#nomad_http_auth: ""# Path to a PEM encoded CA cert file to use to verify the Nomad server SSL certificate
#nomad_cacert: ""# Path to a directory of PEM encoded CA cert files to verify the Nomad server SSL certificate. If both cacert and capath are specified, cacert is used
#nomad_capath: ""# Path to a PEM encoded client cert for TLS authentication to the Nomad server. Must also specify client key
#nomad_client_cert: ""# Path to an unencrypted PEM encoded private key matching the client cert
#nomad_client_key: ""# The server name to use as the SNI host when connecting via TLS
#nomad_tls_server_name: ""# If True, do not verify TLS certificates. Default False
#nomad_skip_verify: False# Seconds between updates for job & allocation pages. Disable with -1. Default 2
#wander_update_seconds: 2# Columns to display for Jobs view - can reference Meta keys. Default "Job,Type,Namespace,Status,Count,Submitted,Since Submit"
#wander_job_columns: "Job,Type,Namespace,Status,Count,Submitted,Since Submit"# Columns to display for Tasks for Job view. Default "Node ID,Alloc ID,Task Group,Alloc Name,Task Name,State,Started,Finished,Uptime"
#wander_tasks_for_job_columns: "Node ID,Alloc ID,Task Group,Alloc Name,Task Name,State,Started,Finished,Uptime"# Columns to display for All Tasks view. Default "Job,Node ID,Alloc ID,Task Group,Alloc Name,Task Name,State,Started,Finished,Uptime"
#wander_all_tasks_columns: "Job,Node ID,Alloc ID,Task Group,Alloc Name,Task Name,State,Started,Finished,Uptime"# If True, start with compact header. Default False
#wander_compact_header: False# If True, start in All Tasks view. Default False
#wander_start_all_tasks: False# If True, remove unnecessary gaps between table columns when possible. Default True
# If you want column positions to remain static as you scroll and filter, set this to False
#wander_compact_tables: True# Log byte offset from which logs start. Default 1000000
#wander_log_offset: 1000000# If True, start with filtering active on first view. Default False
#wander_start_filtering: False# If True, filtering highlights and allows cycling through matches, but does not remove surrounding context. Default True
#wander_filter_with_context: True# If True, follow new logs as they come in rather than having to reload. Default True
#wander_log_tail: True# If True, copy the full path to file after save. Default False
#wander_copy_save_path: False# Topics to follow in event streams, comma-separated. Default "Job,Allocation,Deployment,Evaluation"
# see https://www.nomadproject.io/api-docs/events#event-stream
#wander_event_topics: "Job,Allocation,Deployment,Evaluation"# Namespace used in stream for all events. "*" for all namespaces. Default "default"
#wander_event_namespace: "default"# The jq (https://stedolan.github.io/jq/) query used for parsing general events. "." to show entire event JSON. Default is:
# .Events[] | {
# "1:Index": .Index,
# "2:Topic": .Topic,
# "3:Type": .Type,
# "4:Name": .Payload | (.Job // .Allocation // .Deployment // .Evaluation) | (.JobID // .ID),
# "5:ID": .Payload | (.Job.ID // (.Allocation // .Deployment // .Evaluation).ID[:8])
# }
# The numbering exists to preserve ordering, as https://github.com/itchyny/gojq does not keep the order of object keys
#wander_event_jq_query: >
# .Events[] | {
# "1:Index": .Index,
# "2:Topic": .Topic,
# "3:Type": .Type,
# "4:Name": .Payload | (.Job // .Allocation // .Deployment // .Evaluation) | (.JobID // .ID),
# "5:ID": .Payload | (.Job.ID // (.Allocation // .Deployment // .Evaluation).ID[:8])
# }# The jq (https://stedolan.github.io/jq/) query used for parsing allocation-specific events. "." to show entire event JSON. Default is:
# .Index as $index | .Events[] | .Type as $type | .Payload.Allocation |
# .DeploymentStatus.Healthy as $healthy | .ClientStatus as $clientStatus | .Name as $allocName |
# (.TaskStates // {"":{"Events": [{}]}}) | to_entries[] | .key as $k | .value.Events[] | {
# "0:Index": $index,
# "1:AllocName": $allocName,
# "2:TaskName": $k,
# "3:Type": $type,
# "4:Time": ((.Time // 0) / 1000000000 | todate),
# "5:Msg": .DisplayMessage,
# "6:Healthy": $healthy,
# "7:ClientStatus": $clientStatus
# }
# The numbering exists to preserve ordering, as https://github.com/itchyny/gojq does not keep the order of object keys
#wander_alloc_event_jq_query: >
# .Index as $index | .Events[] | .Type as $type | .Payload.Allocation |
# .DeploymentStatus.Healthy as $healthy | .ClientStatus as $clientStatus | .Name as $allocName |
# (.TaskStates // {"":{"Events": [{}]}}) | to_entries[] | .key as $k | .value.Events[] | {
# "0:Index": $index,
# "1:AllocName": $allocName,
# "2:TaskName": $k,
# "3:Type": $type,
# "4:Time": ((.Time // 0) / 1000000000 | todate),
# "5:Msg": .DisplayMessage,
# "6:Healthy": $healthy,
# "7:ClientStatus": $clientStatus
# }# For `wander serve`. Hostname of the machine hosting the ssh server. Default "localhost"
#wander_host: "localhost"# For `wander serve`. Port for the ssh server. Default 21324
#wander_port: 21324# For `wander serve`. Host key path for wander ssh server
#wander_host_key_path: ""# For `wander serve`. Host key PEM block for wander ssh server
#wander_host_key_pem: ""# Custom colors
#wander_logo_color: "#DBBD70"
```## Exec Command
`wander` ships with an `exec` command similar to the [`nomad alloc exec`](https://developer.hashicorp.com/nomad/docs/commands/alloc/exec)
utility. Example usage:```shell
# specify job and task, assuming single allocation
wander exec alright_stop --task redis echo "hi"# specify allocation, assuming single task
wander exec 3dca0982 echo "hi"# use prefixes of jobs or allocation ids
wander exec al echo "hi" # prefix of job "alright_stop"
wander exec 3d echo "hi" # prefix of alloc ID "3dca0982"# specify flags for the exec command with --
wander exec alright_stop --task redis -- echo -n "hi"
```## SSH App
`wander` can be served via ssh application. For example, you could host an internal ssh application for your company
such that anyone on the internal network can `ssh -p ` and immediately access `wander` without
installing or configuring anything.Optionally, users can pass in their own nomad token with `ssh -p -t `. The `-t` argument does not
stand for token - it forces `ssh` to allocate a pty.Serve the ssh app with `wander serve`.
## Trying It Out
You can try `wander` out by running a local development nomad cluster following [these instructions](https://learn.hashicorp.com/tutorials/nomad/get-started-run?in=nomad/get-started):
```sh
# in first terminal session, start and leave nomad running in dev mode
sudo nomad agent -dev -bind 0.0.0.0 -log-level INFO# in a different terminal session, create example job and run it
nomad job init
nomad job run example.nomad# run wander
wander
```## Manually Specifying the `wander` Version
`wander` uses [carlmjohnson/versioninfo](https://blog.carlmjohnson.net/post/2023/golang-git-hash-how-to/) to expose
version/revision info. If the environment in which you're installing wander does not allow for git repos, prebuilt
binaries, or `go install`, then you can manually specify the output of `wander --version` at build time as follows:```sh
go build -ldflags "-X github.com/robinovitch61/wander/cmd.Version=vX.Y.Z"
```In this case, you're responsible for ensuring the specified version is in sync with what is actually being built.
## Development
To manually build:
```shell
git clone [email protected]:robinovitch61/wander.git
cd wander
go build # outputs ./wander executable
```The [scripts](/scripts) directory contains various development helper scripts.
If the `WANDER_DEBUG` environment variable is set to `true`, the `dev.Debug(s string)` function outputs to `WANDER_DEBUG_PATH` (defaults to `wander.log`).