salt-api-cli 1.0.0__tar.gz → 1.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- salt_api_cli-1.2.0/PKG-INFO +122 -0
- salt_api_cli-1.2.0/README.md +106 -0
- {salt_api_cli-1.0.0 → salt_api_cli-1.2.0}/pyproject.toml +5 -2
- salt_api_cli-1.2.0/salt_api_cli/cli.py +204 -0
- salt_api_cli-1.2.0/salt_api_cli/highlevel.py +255 -0
- salt_api_cli-1.2.0/salt_api_cli/lowlevel.py +300 -0
- salt_api_cli-1.2.0/salt_api_cli/version.py +1 -0
- salt_api_cli-1.2.0/salt_api_cli.egg-info/PKG-INFO +122 -0
- {salt_api_cli-1.0.0 → salt_api_cli-1.2.0}/salt_api_cli.egg-info/SOURCES.txt +2 -0
- salt_api_cli-1.2.0/salt_api_cli.egg-info/entry_points.txt +2 -0
- salt_api_cli-1.2.0/salt_api_cli.egg-info/requires.txt +5 -0
- salt_api_cli-1.0.0/PKG-INFO +0 -81
- salt_api_cli-1.0.0/README.md +0 -67
- salt_api_cli-1.0.0/salt_api_cli/cli.py +0 -328
- salt_api_cli-1.0.0/salt_api_cli/version.py +0 -1
- salt_api_cli-1.0.0/salt_api_cli.egg-info/PKG-INFO +0 -81
- salt_api_cli-1.0.0/salt_api_cli.egg-info/entry_points.txt +0 -2
- salt_api_cli-1.0.0/salt_api_cli.egg-info/requires.txt +0 -3
- {salt_api_cli-1.0.0 → salt_api_cli-1.2.0}/MANIFEST.in +0 -0
- {salt_api_cli-1.0.0 → salt_api_cli-1.2.0}/salt_api_cli/__init__.py +0 -0
- {salt_api_cli-1.0.0 → salt_api_cli-1.2.0}/salt_api_cli/__main__.py +0 -0
- {salt_api_cli-1.0.0 → salt_api_cli-1.2.0}/salt_api_cli/py.typed +0 -0
- {salt_api_cli-1.0.0 → salt_api_cli-1.2.0}/salt_api_cli.egg-info/dependency_links.txt +0 -0
- {salt_api_cli-1.0.0 → salt_api_cli-1.2.0}/salt_api_cli.egg-info/top_level.txt +0 -0
- {salt_api_cli-1.0.0 → salt_api_cli-1.2.0}/setup.cfg +0 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: salt-api-cli
|
|
3
|
+
Version: 1.2.0
|
|
4
|
+
Summary: CLI to access salt-api
|
|
5
|
+
Author-email: Pradish Bijukchhe <pradish@sandbox.com.np>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/sandbox-pokhara/saltapi-cli
|
|
8
|
+
Project-URL: Issues, https://github.com/sandbox-pokhara/saltapi-cli/issues
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Requires-Python: >=3.11
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
Requires-Dist: rich>=15.0.0
|
|
13
|
+
Requires-Dist: typeguard>=4.5.2
|
|
14
|
+
Provides-Extra: pre-commit
|
|
15
|
+
Requires-Dist: pre-commit; extra == "pre-commit"
|
|
16
|
+
|
|
17
|
+
# salt-api-cli
|
|
18
|
+
|
|
19
|
+
Thin Python CLI for [salt-api](https://docs.saltproject.io/en/latest/ref/netapi/all/salt.netapi.rest_cherrypy.html).
|
|
20
|
+
Depends only on the standard library plus [`rich`](https://github.com/Textualize/rich)
|
|
21
|
+
(readable output) and [`typeguard`](https://github.com/agronholm/typeguard)
|
|
22
|
+
(JSON validation).
|
|
23
|
+
|
|
24
|
+
Logs in once with PAM credentials, caches the token in
|
|
25
|
+
`~/.cache/salt-api-cli/token.json`, then invokes salt-api's `local`,
|
|
26
|
+
`runner`, and `wheel` clients over HTTPS. The cached token self-heals:
|
|
27
|
+
it is refreshed proactively when its stored expiry has passed, and
|
|
28
|
+
reactively when the server rejects it (e.g. after the salt-master
|
|
29
|
+
container restarts and wipes its session store) — on rejection the CLI
|
|
30
|
+
discards the token, logs in again, and retries the request once.
|
|
31
|
+
|
|
32
|
+
Commands come in two layers:
|
|
33
|
+
|
|
34
|
+
- **Low-level** (`local`, `runner`, `wheel`) map directly to the salt-api
|
|
35
|
+
clients and print **raw JSON**.
|
|
36
|
+
- **High-level** (`state`, `keys`) wrap those clients and render
|
|
37
|
+
**readable, colorized output** with `rich`.
|
|
38
|
+
|
|
39
|
+
## Installation
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
pip install salt-api-cli
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Configuration
|
|
46
|
+
|
|
47
|
+
Configuration is resolved in this order (later sources override earlier):
|
|
48
|
+
|
|
49
|
+
1. `~/.saltapiclirc` — INI file, `[salt-api-cli]` section
|
|
50
|
+
2. Environment variables — `SALT_API_URL`, `SALT_API_USER`, `SALT_API_PASS`, `SALT_API_INSECURE`
|
|
51
|
+
3. Command-line flags — `--url`, `--user`, `--password`, `--insecure`, `--relogin`, `--no-token-cache`
|
|
52
|
+
|
|
53
|
+
Example `~/.saltapiclirc`:
|
|
54
|
+
|
|
55
|
+
```ini
|
|
56
|
+
[salt-api-cli]
|
|
57
|
+
url = https://salt.example.com
|
|
58
|
+
user = salt_api
|
|
59
|
+
password = secret
|
|
60
|
+
insecure = false
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`SALT_API_INSECURE=1` (or `insecure = true` in the config) skips TLS
|
|
64
|
+
certificate verification.
|
|
65
|
+
|
|
66
|
+
Token cache control: `--relogin` ignores any cached token and logs in
|
|
67
|
+
fresh (re-caching the new token); `--no-token-cache` neither reads nor
|
|
68
|
+
writes the cache for that run; `salt logout` discards the cached token.
|
|
69
|
+
|
|
70
|
+
## Usage
|
|
71
|
+
|
|
72
|
+
### Low-level commands (raw JSON)
|
|
73
|
+
|
|
74
|
+
These map one-to-one to the salt-api clients and print the response
|
|
75
|
+
verbatim as indented JSON.
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
# Local client — fan out to minions
|
|
79
|
+
salt local '*' test.ping
|
|
80
|
+
salt local 'bml*' cmd.run 'whoami'
|
|
81
|
+
salt local 'bml1' cmd.run 'Get-Date' shell=powershell
|
|
82
|
+
|
|
83
|
+
# Runner client (master-side: manage.status, jobs.list_jobs, ...)
|
|
84
|
+
salt runner manage.status
|
|
85
|
+
salt runner jobs.list_jobs
|
|
86
|
+
|
|
87
|
+
# Wheel client (master-side, low-level)
|
|
88
|
+
salt wheel key.list_all
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### High-level commands (readable, colorized)
|
|
92
|
+
|
|
93
|
+
These wrap the low-level clients and render their output with `rich`.
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
# State runs — a colored table of states, one row each, with a summary.
|
|
97
|
+
# Driven by the local client + state.* functions.
|
|
98
|
+
salt state highstate 'bml1' # apply the highstate
|
|
99
|
+
salt state test 'bml1' # dry-run the highstate (forces test=True)
|
|
100
|
+
salt state apply 'bml1' veyon # apply specific sls module(s)
|
|
101
|
+
salt state apply 'bml1' veyon.ldap test=True
|
|
102
|
+
|
|
103
|
+
# Key management — wraps the wheel client's key.* functions.
|
|
104
|
+
# `keys list` shows one colored panel per status (Accepted/Pending/Denied/Rejected).
|
|
105
|
+
salt keys list
|
|
106
|
+
salt keys accept <id-or-glob>
|
|
107
|
+
salt keys accept-all
|
|
108
|
+
salt keys reject <id-or-glob>
|
|
109
|
+
salt keys delete <id-or-glob>
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Color and panels appear when writing to a terminal; output is plain when
|
|
113
|
+
piped to a file or pager.
|
|
114
|
+
|
|
115
|
+
Any `key=value` argument is parsed as a kwarg to the salt function;
|
|
116
|
+
anything else is positional.
|
|
117
|
+
|
|
118
|
+
You can also invoke the CLI as a module: `python -m salt_api_cli ...`.
|
|
119
|
+
|
|
120
|
+
## License
|
|
121
|
+
|
|
122
|
+
This project is licensed under the terms of the MIT license.
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# salt-api-cli
|
|
2
|
+
|
|
3
|
+
Thin Python CLI for [salt-api](https://docs.saltproject.io/en/latest/ref/netapi/all/salt.netapi.rest_cherrypy.html).
|
|
4
|
+
Depends only on the standard library plus [`rich`](https://github.com/Textualize/rich)
|
|
5
|
+
(readable output) and [`typeguard`](https://github.com/agronholm/typeguard)
|
|
6
|
+
(JSON validation).
|
|
7
|
+
|
|
8
|
+
Logs in once with PAM credentials, caches the token in
|
|
9
|
+
`~/.cache/salt-api-cli/token.json`, then invokes salt-api's `local`,
|
|
10
|
+
`runner`, and `wheel` clients over HTTPS. The cached token self-heals:
|
|
11
|
+
it is refreshed proactively when its stored expiry has passed, and
|
|
12
|
+
reactively when the server rejects it (e.g. after the salt-master
|
|
13
|
+
container restarts and wipes its session store) — on rejection the CLI
|
|
14
|
+
discards the token, logs in again, and retries the request once.
|
|
15
|
+
|
|
16
|
+
Commands come in two layers:
|
|
17
|
+
|
|
18
|
+
- **Low-level** (`local`, `runner`, `wheel`) map directly to the salt-api
|
|
19
|
+
clients and print **raw JSON**.
|
|
20
|
+
- **High-level** (`state`, `keys`) wrap those clients and render
|
|
21
|
+
**readable, colorized output** with `rich`.
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
pip install salt-api-cli
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Configuration
|
|
30
|
+
|
|
31
|
+
Configuration is resolved in this order (later sources override earlier):
|
|
32
|
+
|
|
33
|
+
1. `~/.saltapiclirc` — INI file, `[salt-api-cli]` section
|
|
34
|
+
2. Environment variables — `SALT_API_URL`, `SALT_API_USER`, `SALT_API_PASS`, `SALT_API_INSECURE`
|
|
35
|
+
3. Command-line flags — `--url`, `--user`, `--password`, `--insecure`, `--relogin`, `--no-token-cache`
|
|
36
|
+
|
|
37
|
+
Example `~/.saltapiclirc`:
|
|
38
|
+
|
|
39
|
+
```ini
|
|
40
|
+
[salt-api-cli]
|
|
41
|
+
url = https://salt.example.com
|
|
42
|
+
user = salt_api
|
|
43
|
+
password = secret
|
|
44
|
+
insecure = false
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`SALT_API_INSECURE=1` (or `insecure = true` in the config) skips TLS
|
|
48
|
+
certificate verification.
|
|
49
|
+
|
|
50
|
+
Token cache control: `--relogin` ignores any cached token and logs in
|
|
51
|
+
fresh (re-caching the new token); `--no-token-cache` neither reads nor
|
|
52
|
+
writes the cache for that run; `salt logout` discards the cached token.
|
|
53
|
+
|
|
54
|
+
## Usage
|
|
55
|
+
|
|
56
|
+
### Low-level commands (raw JSON)
|
|
57
|
+
|
|
58
|
+
These map one-to-one to the salt-api clients and print the response
|
|
59
|
+
verbatim as indented JSON.
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
# Local client — fan out to minions
|
|
63
|
+
salt local '*' test.ping
|
|
64
|
+
salt local 'bml*' cmd.run 'whoami'
|
|
65
|
+
salt local 'bml1' cmd.run 'Get-Date' shell=powershell
|
|
66
|
+
|
|
67
|
+
# Runner client (master-side: manage.status, jobs.list_jobs, ...)
|
|
68
|
+
salt runner manage.status
|
|
69
|
+
salt runner jobs.list_jobs
|
|
70
|
+
|
|
71
|
+
# Wheel client (master-side, low-level)
|
|
72
|
+
salt wheel key.list_all
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### High-level commands (readable, colorized)
|
|
76
|
+
|
|
77
|
+
These wrap the low-level clients and render their output with `rich`.
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
# State runs — a colored table of states, one row each, with a summary.
|
|
81
|
+
# Driven by the local client + state.* functions.
|
|
82
|
+
salt state highstate 'bml1' # apply the highstate
|
|
83
|
+
salt state test 'bml1' # dry-run the highstate (forces test=True)
|
|
84
|
+
salt state apply 'bml1' veyon # apply specific sls module(s)
|
|
85
|
+
salt state apply 'bml1' veyon.ldap test=True
|
|
86
|
+
|
|
87
|
+
# Key management — wraps the wheel client's key.* functions.
|
|
88
|
+
# `keys list` shows one colored panel per status (Accepted/Pending/Denied/Rejected).
|
|
89
|
+
salt keys list
|
|
90
|
+
salt keys accept <id-or-glob>
|
|
91
|
+
salt keys accept-all
|
|
92
|
+
salt keys reject <id-or-glob>
|
|
93
|
+
salt keys delete <id-or-glob>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Color and panels appear when writing to a terminal; output is plain when
|
|
97
|
+
piped to a file or pager.
|
|
98
|
+
|
|
99
|
+
Any `key=value` argument is parsed as a kwarg to the salt function;
|
|
100
|
+
anything else is positional.
|
|
101
|
+
|
|
102
|
+
You can also invoke the CLI as a module: `python -m salt_api_cli ...`.
|
|
103
|
+
|
|
104
|
+
## License
|
|
105
|
+
|
|
106
|
+
This project is licensed under the terms of the MIT license.
|
|
@@ -11,14 +11,17 @@ readme = "README.md"
|
|
|
11
11
|
license = "MIT"
|
|
12
12
|
keywords = []
|
|
13
13
|
classifiers = ["Programming Language :: Python :: 3"]
|
|
14
|
-
dependencies = [
|
|
14
|
+
dependencies = [
|
|
15
|
+
"rich>=15.0.0",
|
|
16
|
+
"typeguard>=4.5.2",
|
|
17
|
+
]
|
|
15
18
|
dynamic = ["version"]
|
|
16
19
|
|
|
17
20
|
[project.optional-dependencies]
|
|
18
21
|
pre-commit = ["pre-commit"]
|
|
19
22
|
|
|
20
23
|
[project.scripts]
|
|
21
|
-
salt
|
|
24
|
+
salt = "salt_api_cli.cli:main"
|
|
22
25
|
|
|
23
26
|
[project.urls]
|
|
24
27
|
Homepage = "https://github.com/sandbox-pokhara/saltapi-cli"
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"""salt-api-cli — thin Python CLI for salt-api.
|
|
2
|
+
|
|
3
|
+
Logs in once with PAM creds, caches the token in
|
|
4
|
+
~/.cache/salt-api-cli/token.json, then invokes the salt-api local/
|
|
5
|
+
runner/wheel clients over HTTPS. Depends only on the stdlib plus
|
|
6
|
+
``typeguard`` for validating cached/responded JSON.
|
|
7
|
+
|
|
8
|
+
This module is the CLI glue: it parses arguments and dispatches each
|
|
9
|
+
command, wiring the low-level transport (:mod:`salt_api_cli.lowlevel`) to
|
|
10
|
+
the high-level human-readable rendering (:mod:`salt_api_cli.highlevel`).
|
|
11
|
+
|
|
12
|
+
The cached token self-heals: it is refreshed proactively when its stored
|
|
13
|
+
expiry has passed, and reactively when the server rejects it (HTTP 401 or
|
|
14
|
+
an EAUTH body) — e.g. after the salt-master container restarts and wipes
|
|
15
|
+
its session store. `--relogin` forces a fresh login, `--no-token-cache`
|
|
16
|
+
skips the cache entirely, and the `logout` subcommand discards the token.
|
|
17
|
+
|
|
18
|
+
Configuration (later sources override earlier):
|
|
19
|
+
1. ~/.saltapiclirc INI file, [salt-api-cli] section
|
|
20
|
+
2. environment variables SALT_API_URL, SALT_API_USER,
|
|
21
|
+
SALT_API_PASS, SALT_API_INSECURE
|
|
22
|
+
3. command-line flags --url, --user, --password,
|
|
23
|
+
--insecure, --relogin,
|
|
24
|
+
--no-token-cache
|
|
25
|
+
|
|
26
|
+
Any `key=value` argument to local/runner/wheel is parsed as a kwarg to
|
|
27
|
+
the salt function. Anything else is positional.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
from __future__ import annotations
|
|
31
|
+
|
|
32
|
+
import argparse
|
|
33
|
+
import json
|
|
34
|
+
from typing import Any
|
|
35
|
+
|
|
36
|
+
from salt_api_cli import highlevel
|
|
37
|
+
from salt_api_cli.lowlevel import (
|
|
38
|
+
TOKEN_FILE,
|
|
39
|
+
Config,
|
|
40
|
+
SaltApiError,
|
|
41
|
+
call,
|
|
42
|
+
clear_token,
|
|
43
|
+
load_config,
|
|
44
|
+
split_args,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _run_local(cfg: Config, args: argparse.Namespace) -> None:
|
|
49
|
+
pos, kw = split_args(list(args.args))
|
|
50
|
+
payload: dict[str, Any] = {"tgt": args.target, "fun": args.function, "arg": pos}
|
|
51
|
+
if kw:
|
|
52
|
+
payload["kwarg"] = kw
|
|
53
|
+
print(json.dumps(call(cfg, "local", **payload), indent=2))
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _run_client(cfg: Config, client: str, args: argparse.Namespace) -> None:
|
|
57
|
+
pos, kw = split_args(list(args.args))
|
|
58
|
+
payload: dict[str, Any] = {"fun": args.function, "arg": pos}
|
|
59
|
+
if kw:
|
|
60
|
+
payload["kwarg"] = kw
|
|
61
|
+
print(json.dumps(call(cfg, client, **payload), indent=2))
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _run_state(cfg: Config, args: argparse.Namespace) -> None:
|
|
65
|
+
def local(**kw: Any) -> dict[str, Any]:
|
|
66
|
+
return call(cfg, "local", **kw)
|
|
67
|
+
|
|
68
|
+
highlevel.run_state(args, local)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _run_keys(cfg: Config, args: argparse.Namespace) -> None:
|
|
72
|
+
def wheel(**kw: Any) -> dict[str, Any]:
|
|
73
|
+
return call(cfg, "wheel", **kw)
|
|
74
|
+
|
|
75
|
+
highlevel.run_keys(args, wheel)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _build_parser() -> argparse.ArgumentParser:
|
|
79
|
+
parser = argparse.ArgumentParser(
|
|
80
|
+
prog="salt",
|
|
81
|
+
description="Thin Python CLI for salt-api.",
|
|
82
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
83
|
+
epilog=(
|
|
84
|
+
"low-level (raw JSON):\n"
|
|
85
|
+
" salt local '*' test.ping\n"
|
|
86
|
+
" salt local 'bml*' cmd.run 'whoami'\n"
|
|
87
|
+
" salt local 'bml1' cmd.run 'Get-Date' shell=powershell\n"
|
|
88
|
+
" salt runner manage.status\n"
|
|
89
|
+
" salt wheel key.list_all\n"
|
|
90
|
+
"high-level (readable):\n"
|
|
91
|
+
" salt state highstate 'bml1'\n"
|
|
92
|
+
" salt state test 'bml1' # dry-run highstate (test=True)\n"
|
|
93
|
+
" salt state apply 'bml1' veyon\n"
|
|
94
|
+
" salt keys list\n"
|
|
95
|
+
" salt keys accept '<id-or-glob>'\n"
|
|
96
|
+
" salt keys accept-all\n"
|
|
97
|
+
),
|
|
98
|
+
)
|
|
99
|
+
parser.add_argument("--url", help="salt-api base URL")
|
|
100
|
+
parser.add_argument("--user", help="PAM username")
|
|
101
|
+
parser.add_argument("--password", help="PAM password")
|
|
102
|
+
parser.add_argument(
|
|
103
|
+
"--insecure",
|
|
104
|
+
action="store_true",
|
|
105
|
+
help="skip TLS certificate verification",
|
|
106
|
+
)
|
|
107
|
+
parser.add_argument(
|
|
108
|
+
"--relogin",
|
|
109
|
+
action="store_true",
|
|
110
|
+
help="ignore any cached token and log in fresh (re-caches the new token)",
|
|
111
|
+
)
|
|
112
|
+
parser.add_argument(
|
|
113
|
+
"--no-token-cache",
|
|
114
|
+
dest="no_token_cache",
|
|
115
|
+
action="store_true",
|
|
116
|
+
help="do not read or write the token cache for this run",
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
sub = parser.add_subparsers(dest="command", required=True)
|
|
120
|
+
|
|
121
|
+
p_local = sub.add_parser("local", help="run a function on minions")
|
|
122
|
+
p_local.add_argument("target", help="minion target (id or glob)")
|
|
123
|
+
p_local.add_argument("function", help="salt function (e.g. test.ping)")
|
|
124
|
+
p_local.add_argument(
|
|
125
|
+
"args", nargs=argparse.REMAINDER, help="positional and key=value args"
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
p_runner = sub.add_parser("runner", help="invoke a master-side runner")
|
|
129
|
+
p_runner.add_argument("function")
|
|
130
|
+
p_runner.add_argument("args", nargs=argparse.REMAINDER)
|
|
131
|
+
|
|
132
|
+
p_wheel = sub.add_parser("wheel", help="invoke a master-side wheel function")
|
|
133
|
+
p_wheel.add_argument("function")
|
|
134
|
+
p_wheel.add_argument("args", nargs=argparse.REMAINDER)
|
|
135
|
+
|
|
136
|
+
p_state = sub.add_parser("state", help="apply states with readable output")
|
|
137
|
+
state_sub = p_state.add_subparsers(dest="action", required=True)
|
|
138
|
+
p_highstate = state_sub.add_parser("highstate", help="apply the highstate")
|
|
139
|
+
p_highstate.add_argument("target", help="minion target (id or glob)")
|
|
140
|
+
p_highstate.add_argument(
|
|
141
|
+
"args", nargs=argparse.REMAINDER, help="key=value args, e.g. test=True"
|
|
142
|
+
)
|
|
143
|
+
p_test = state_sub.add_parser(
|
|
144
|
+
"test", help="dry-run the highstate (forces test=True)"
|
|
145
|
+
)
|
|
146
|
+
p_test.add_argument("target", help="minion target (id or glob)")
|
|
147
|
+
p_test.add_argument("args", nargs=argparse.REMAINDER, help="extra key=value args")
|
|
148
|
+
p_apply = state_sub.add_parser("apply", help="apply specific sls module(s)")
|
|
149
|
+
p_apply.add_argument("target", help="minion target (id or glob)")
|
|
150
|
+
p_apply.add_argument("sls", help="sls module to apply (e.g. veyon or veyon.ldap)")
|
|
151
|
+
p_apply.add_argument(
|
|
152
|
+
"args", nargs=argparse.REMAINDER, help="key=value args, e.g. test=True"
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
p_keys = sub.add_parser("keys", help="manage minion keys")
|
|
156
|
+
keys_sub = p_keys.add_subparsers(dest="action", required=True)
|
|
157
|
+
keys_sub.add_parser("list", help="show keys grouped by status")
|
|
158
|
+
p_accept = keys_sub.add_parser("accept", help="accept a key by id or glob")
|
|
159
|
+
p_accept.add_argument("match")
|
|
160
|
+
keys_sub.add_parser("accept-all", help="accept every pending key")
|
|
161
|
+
p_reject = keys_sub.add_parser("reject", help="reject a key by id or glob")
|
|
162
|
+
p_reject.add_argument("match")
|
|
163
|
+
p_delete = keys_sub.add_parser("delete", help="delete a key by id or glob")
|
|
164
|
+
p_delete.add_argument("match")
|
|
165
|
+
|
|
166
|
+
sub.add_parser("logout", help="discard the cached auth token")
|
|
167
|
+
|
|
168
|
+
return parser
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def main() -> None:
|
|
172
|
+
parser = _build_parser()
|
|
173
|
+
args = parser.parse_args()
|
|
174
|
+
|
|
175
|
+
# logout needs no server config — it just drops the local token file.
|
|
176
|
+
if args.command == "logout":
|
|
177
|
+
existed = TOKEN_FILE.exists()
|
|
178
|
+
clear_token()
|
|
179
|
+
print(
|
|
180
|
+
f"discarded cached token ({TOKEN_FILE})"
|
|
181
|
+
if existed
|
|
182
|
+
else f"no cached token to discard ({TOKEN_FILE})"
|
|
183
|
+
)
|
|
184
|
+
return
|
|
185
|
+
|
|
186
|
+
cfg = load_config(args)
|
|
187
|
+
|
|
188
|
+
try:
|
|
189
|
+
if args.command == "local":
|
|
190
|
+
_run_local(cfg, args)
|
|
191
|
+
elif args.command == "runner":
|
|
192
|
+
_run_client(cfg, "runner", args)
|
|
193
|
+
elif args.command == "wheel":
|
|
194
|
+
_run_client(cfg, "wheel", args)
|
|
195
|
+
elif args.command == "state":
|
|
196
|
+
_run_state(cfg, args)
|
|
197
|
+
elif args.command == "keys":
|
|
198
|
+
_run_keys(cfg, args)
|
|
199
|
+
except SaltApiError as e:
|
|
200
|
+
raise SystemExit(str(e))
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
if __name__ == "__main__":
|
|
204
|
+
main()
|