Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
5891409fdb | |||
0e9eba4900 | |||
e02737abd1 | |||
4671cf5fac | |||
88a751c590 | |||
e434173dfb |
10
Pipfile.lock
generated
10
Pipfile.lock
generated
@ -1,7 +1,7 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "13a000de8cd5f6c3d270d059f8df15653008a32b9daa31494cc26bd4c80dd8d0"
|
||||
"sha256": "4c61c72e95ca800fd43f3c1ba0fdbb9d0b96e8684edff51ae5c2f74a693ac20e"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
@ -37,16 +37,18 @@
|
||||
"sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28",
|
||||
"sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==8.1.7"
|
||||
},
|
||||
"goat-monitor": {
|
||||
"editable": true,
|
||||
"file": "."
|
||||
},
|
||||
"gotify": {
|
||||
"hashes": [
|
||||
"sha256:184faec76de78279c5acd6e21dfefd11223d74a816b607f1063ac22df40641b2",
|
||||
"sha256:47bdc0332143cd5c251e284ffa487467429c624a1d40aefb013774f6f4dd4b7d"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.9'",
|
||||
"version": "==0.6.0"
|
||||
},
|
||||
@ -138,7 +140,6 @@
|
||||
"sha256:fac6e277a41163d27dfab5f4ec1f7a83fac94e170665a4a50191b545721c6521",
|
||||
"sha256:fcd8f556cdc8cfe35e70efb92463082b7f43dd7e547eb071ffc36abc0ca4699b"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.10'",
|
||||
"version": "==2.1.1"
|
||||
},
|
||||
@ -155,7 +156,6 @@
|
||||
"sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b",
|
||||
"sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==0.10.2"
|
||||
}
|
||||
|
@ -6,6 +6,8 @@ Yes, I know Gotify doesn't have "goat" in its name but it sounds like it.
|
||||
|
||||
## Configuration
|
||||
|
||||
Configuration lives in a TOML file which should have (at a minimum) the following:
|
||||
|
||||
```toml
|
||||
server = "https://gotify.example.com"
|
||||
app_token = "app_token_from_gotify"
|
||||
@ -15,7 +17,7 @@ app_token = "app_token_from_gotify"
|
||||
## Usage
|
||||
|
||||
```
|
||||
goat_monitor --config ./config.toml --retries -1 -- <COMMAND TO MONITOR>
|
||||
goat_monitor --config ./config.toml --retries 3 -- <COMMAND TO MONITOR>
|
||||
```
|
||||
|
||||
The command can be any shell command including arbitrarily many options / arguments.
|
||||
|
@ -9,7 +9,7 @@ import gotify
|
||||
import numpy as np
|
||||
import toml
|
||||
|
||||
from goat_monitor._version import __version__
|
||||
from goat_monitor._version import __version__ # type: ignore
|
||||
|
||||
|
||||
# %% commands
|
||||
@ -17,7 +17,8 @@ from goat_monitor._version import __version__
|
||||
@click.argument("command", nargs=-1, required=False, type=str)
|
||||
@click.option(
|
||||
"--config",
|
||||
default="~/.config/goat_monitor.toml",
|
||||
# default="~/.config/goat_monitor.toml",
|
||||
required=True,
|
||||
type=click.Path(path_type=Path),
|
||||
help="Use a .toml configuration file",
|
||||
)
|
||||
@ -33,7 +34,13 @@ from goat_monitor._version import __version__
|
||||
default=False,
|
||||
help="Print version and exit",
|
||||
)
|
||||
def wrap(command: List[str], config: Path, retries: int, version):
|
||||
@click.option(
|
||||
"--dry-run",
|
||||
is_flag=True,
|
||||
default=False,
|
||||
help="Run command without sending any notifications",
|
||||
)
|
||||
def wrap(command: List[str], config: Path, retries: int, version: bool, dry_run: bool):
|
||||
"""Wrap an arbitrary command with gotify notifications"""
|
||||
|
||||
if version:
|
||||
@ -45,6 +52,7 @@ def wrap(command: List[str], config: Path, retries: int, version):
|
||||
settings = toml.load(f)
|
||||
|
||||
# gotify configuration
|
||||
if not dry_run:
|
||||
url = settings["server"]
|
||||
app_token = settings["app_token"]
|
||||
with gotify.Gotify(base_url=url, app_token=app_token) as gotify_connection:
|
||||
@ -58,22 +66,28 @@ def wrap(command: List[str], config: Path, retries: int, version):
|
||||
if retries < 0:
|
||||
raise ValueError("Invalid number of retries specified")
|
||||
|
||||
for attempt in range(retries + 1):
|
||||
attempt = 0
|
||||
while attempt <= retries:
|
||||
# run the command
|
||||
result = subprocess.run(
|
||||
with subprocess.Popen(
|
||||
" ".join(command),
|
||||
shell=True,
|
||||
stderr=subprocess.STDOUT,
|
||||
stdout=subprocess.PIPE,
|
||||
encoding="utf-8",
|
||||
)
|
||||
) as proc:
|
||||
stdout = ""
|
||||
while True:
|
||||
c = proc.stdout.read(1)
|
||||
if c == b"":
|
||||
break
|
||||
s = c.decode("utf-8")
|
||||
stdout += s
|
||||
print(s, end="", flush=True)
|
||||
return_code = proc.wait()
|
||||
|
||||
# TODO: print lines real time as the subprocess runs
|
||||
print(result.stdout, end="")
|
||||
|
||||
if result.returncode:
|
||||
if return_code:
|
||||
# failed
|
||||
title = f"Command failed with exit code {result.returncode}"
|
||||
title = f"Command failed with exit code {return_code}"
|
||||
if attempt < retries:
|
||||
title += f" - Retrying (attempt {attempt+1}/{retries})"
|
||||
else:
|
||||
@ -83,7 +97,7 @@ def wrap(command: List[str], config: Path, retries: int, version):
|
||||
title = "Command succeeded"
|
||||
|
||||
MAX_LINES = 20
|
||||
lines = result.stdout.splitlines()
|
||||
lines = stdout.splitlines()
|
||||
if len(lines) > MAX_LINES:
|
||||
lines = lines[-MAX_LINES:]
|
||||
message = (
|
||||
@ -93,14 +107,17 @@ def wrap(command: List[str], config: Path, retries: int, version):
|
||||
+ "\n".join(lines)
|
||||
)
|
||||
|
||||
if not dry_run:
|
||||
with gotify.Gotify(base_url=url, app_token=app_token) as gotify_connection:
|
||||
gotify_connection.create_message(message=message, title=title)
|
||||
|
||||
if not result.returncode:
|
||||
if not return_code:
|
||||
# only retry on failure
|
||||
break
|
||||
|
||||
sys.exit(result.returncode)
|
||||
attempt += 1
|
||||
|
||||
sys.exit(return_code)
|
||||
|
||||
|
||||
# %% main
|
||||
|
Reference in New Issue
Block a user