morca · API

orca.remote

The orca command against a deployed orca ui, over HTTPS, as a user of it: log in once, then act from anywhere the UI can be reached.

orca login https://orca.mlake.dev     # asks for a name and a password
orca --remote orca.mlake.dev backfill gharchive 2025-01-02..2025-01-31
orca --remote orca.mlake.dev pause gharchive
orca --remote orca.mlake.dev status gharchive
orca logout https://orca.mlake.dev    # revokes the token

--remote <url> (or --url), else ORCA_REMOTE (or ORCA_URL), picks the UI; without one every command goes to ORCA_DATABASE_URL, as it always has. A bare host is https://<host>. Plain http is refused but to 127.0.0.1, localhost and [::1], where nothing is on the wire: a token, like a password, never crosses a network in the clear.

orca login posts the name and password to /api/login, which checks them as /login does, under the same limit on failures, and answers an API token (orca.tokens). The password is read without echo from the terminal, or as a line of standard input when that isn't one (--user names the user then). The token is kept in ORCA_CREDENTIALS, by default ~/.config/orca/credentials ($XDG_CONFIG_HOME/orca if set), a line per UI: its URL, the user, when the token expires, and the token. The file is written with mode 600 in a directory made with mode 700, and one that others can read is refused, as ssh refuses a key.

The commands that can go to a UI are backfill (--rerun, and --preview, which queues nothing), start, cancel (a pipeline's keys, or one run), pause and unpause, resume and rerun of a run, rebuild, and the reads status, lineage, watchdog status and alerts. An action is a POST of JSON to the path the UI's own button posts to, with Authorization: Bearer <token>, so it's the same code, the same checks and the same row of orca.audit as the button's, from cli. Reads are the pages' JSON, which needs no login, and they send no token. Each prints what the command prints over the database. The token is never in a URL, an argument or a message.

Structs

Credential

struct Credential

Implements Copyable, Movable

Fields
url: String
user: String
expires: String
token: String

Remote

struct Remote

A UI at url, as user with token (empty for reads).

Implements Movable

Fields
url: String
token: String
http: HttpClient

__init__

def __init__(out self, url: String, token: String = "")

get

def get(self, path: String) -> String

post

def post(self, path: String, body: String) -> String

Api

struct Api

What the commands here read and do: a UI's JSON (remote), or the same pages and actions over the database, in this process.

Implements Movable

Fields
remote: Optional[Remote]
db_url: String

__init__

def __init__(out self, var remote: Remote)
def __init__(out self, db_url: String)

get

def get(mut self, path: String) -> String

The JSON GET path answers (path has its query).

post

def post(mut self, path: String, fields: List[Tuple[String, String]]) -> String

The JSON of the action path with fields, or raises why it was refused.

Functions

is_remote_command

def is_remote_command(cmd: String) -> Bool

Whether --remote can run cmd; the others need the database.

remote_url

def remote_url(given: String) -> String

given as a UI's URL, scheme://host[:port] in lower case without a default port, or raises why it's refused: anything but https, but http to this machine; a path, query, fragment or user in it.

remote_target

def remote_target(mut args: List[String]) -> String

The UI the command line picks, --remote <url> (or --url) right after orca, which this removes from args, else ORCA_REMOTE (or ORCA_URL); empty for none.

credentials_path

def credentials_path() -> String

ORCA_CREDENTIALS, else orca/credentials in XDG_CONFIG_HOME, else in ~/.config.

read_credentials

def read_credentials(path: String) -> List[Credential]

The logins kept in path, none if there's no file. Raises if others may read it.

write_credentials

def write_credentials(path: String, creds: List[Credential])

Writes creds to path with mode 600, in a directory made with mode 700 if there's none: a new file, created under umask 077 and moved into place, so the token is never in a file others could read.

find_credential

def find_credential(creds: List[Credential], url: String) -> Int

The index of url's login in creds, or -1.

login_command

def login_command(args: List[String], target: String) -> Int

orca login [<url>] [--user NAME] [--label L] [--days N].

logout_command

def logout_command(args: List[String], target: String) -> Int

orca logout [<url>]: revokes the token there, and forgets it.

remote_api

def remote_api(url: String) -> Api

url's UI as the login kept for it, or with no token if there's none (reads need none).

pressure_status

def pressure_status(v: Value) -> String

orca status's line for the scheduler's host's memory pressure (memory_pressure in /'s JSON, orca.admission), or empty for none.

print_status

def print_status(json: String, one: Bool)

orca status's lines from /'s JSON, or with one a pipeline's page's: its line, any sensing error, and its latest runs.

alert_lines

def alert_lines(json: String) -> List[String]

orca alerts' lines from /api/alerts' JSON: a line per alert, newest first, its time, kind, state and delivery, then its title.

api_command

def api_command(mut api: Api, args: List[String]) -> Int

Runs args (orca <command> ...) through api, printing what the command prints over the database.