feat: better tooling (#2)

feat: better tooling
This commit is contained in:
Marc 2022-08-26 14:15:21 -04:00 committed by GitHub
parent 0f990efd86
commit e3e7a60365
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 167 additions and 3 deletions

4
.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
spadinaistan.venv
**/healthcheck.json
**/config.json

1
.python-version Normal file
View file

@ -0,0 +1 @@
3.9.6

View file

@ -1,3 +0,0 @@
#!/bin/bash
sudo docker-compose up -d

132
plex/tasks.py Normal file
View file

@ -0,0 +1,132 @@
import invoke
import pathlib
import typing
import json
PATH = pathlib.Path(__file__).parent
class BlockDevice(typing.TypedDict):
mountpoints: typing.List[str]
uuid: str
class ListBlockDevicesOutput(typing.TypedDict):
blockdevices: typing.List[BlockDevice]
class Configuration(typing.TypedDict):
mounts: typing.Dict[str, str]
def collect_mounted_resources(
lsblk_output: ListBlockDevicesOutput,
) -> typing.Dict[str, str]:
"""
Gathers a map of block device mountpoints to UUID to mountpoints from the
output of lsblk.
"""
block_devices = lsblk_output["blockdevices"]
mounted_resources: typing.Dict[str, str] = {}
for device in block_devices:
if not all(device["mountpoints"]):
continue
for mountpoint in device["mountpoints"]:
mounted_resources[mountpoint] = device["uuid"]
return mounted_resources
def load_configuration() -> Configuration:
configuration_path = pathlib.Path(PATH, "config.json")
with open(configuration_path, "r") as config_file:
config = config_file.read()
config = json.loads(config)
return config
@invoke.task()
def start(ctx):
with ctx.cd(PATH):
ctx.run("docker-compose up -d")
@invoke.task()
def stop(ctx):
with ctx.cd(PATH):
ctx.run("docker-compose down")
@invoke.task()
def restart(ctx):
with ctx.cd(PATH):
ctx.run("docker-compose restart")
@invoke.task()
def healthcheck(ctx, as_json=False):
config = load_configuration()
report = {
"containers_running": False,
"mounted_devices": False,
}
with ctx.cd(PATH):
healthy = True
# Check that the container is running
running_containers = (
ctx.run("docker-compose ps --services --status running", hide=True)
.stdout.strip()
.split()
)
if "plex" in running_containers:
print("✅ Plex container is running!")
report["containers_running"] = True
else:
print("❌ Plex is not running, use inv plex.start.")
healthy = False
lsblk_output = json.loads(
ctx.run("lsblk --json --output UUID,MOUNTPOINTS", hide=True).stdout.strip()
)
mounted_devices = collect_mounted_resources(lsblk_output)
has_expected_mounts = True
for expected_mount, expected_uuid in config["mounts"].items():
if mounted_devices.get(expected_mount) != expected_uuid:
print(
f"❌ Expected {expected_mount} to be a mountpoint for device {expected_uuid}. Mount the device to rectify."
)
has_expected_mounts = False
if has_expected_mounts:
print("✅ All expected mounted devices found")
report["mounted_devices"] = True
else:
print("❌ Some expected mounted devices are missing")
healthy = False
if healthy:
print("✅ Plex is healthy!")
else:
print("❌ Plex has problems")
if as_json:
with open(pathlib.Path(PATH, 'healthcheck.json'), 'w') as outfile:
outfile.write(json.dumps(report))
ns = invoke.Collection("plex")
ns.add_task(start)
ns.add_task(restart)
ns.add_task(stop)
ns.add_task(healthcheck)

15
requirements.txt Normal file
View file

@ -0,0 +1,15 @@
astroid==2.11.7
black==22.6.0
click==8.1.3
dill==0.3.5.1
invoke==1.7.1
isort==5.10.1
lazy-object-proxy==1.7.1
mccabe==0.7.0
mypy-extensions==0.4.3
pathspec==0.9.0
platformdirs==2.5.2
tomli==2.0.1
tomlkit==0.11.4
typing_extensions==4.3.0
wrapt==1.14.1

8
script/bootstrap Normal file
View file

@ -0,0 +1,8 @@
#!/bin/bash
VENV="spadinaistan.venv"
test -d $VENV || python3 -m venv $VENV || return
. $VENV/bin/activate
python -m pip install -U pip --no-cache-dir
python -m pip install -r requirements.txt

7
tasks.py Normal file
View file

@ -0,0 +1,7 @@
import invoke
import plex.tasks
ns = invoke.Collection()
ns.add_collection(plex.tasks.ns)