parent
0f990efd86
commit
e3e7a60365
7 changed files with 167 additions and 3 deletions
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
spadinaistan.venv
|
||||
|
||||
**/healthcheck.json
|
||||
**/config.json
|
1
.python-version
Normal file
1
.python-version
Normal file
|
@ -0,0 +1 @@
|
|||
3.9.6
|
|
@ -1,3 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
sudo docker-compose up -d
|
132
plex/tasks.py
Normal file
132
plex/tasks.py
Normal 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
15
requirements.txt
Normal 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
8
script/bootstrap
Normal 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
7
tasks.py
Normal file
|
@ -0,0 +1,7 @@
|
|||
import invoke
|
||||
|
||||
import plex.tasks
|
||||
|
||||
ns = invoke.Collection()
|
||||
|
||||
ns.add_collection(plex.tasks.ns)
|
Reference in a new issue