Charmed-Kubernetes/etcd/actions/health

133 lines
3.4 KiB
Plaintext
Executable File

#!/usr/local/sbin/charm-env python3
import os
import re
import shlex
import subprocess
import sys
from charms import layer
from etcdctl import EtcdCtl
from charmhelpers.core.hookenv import action_get, action_set, action_fail, action_name
CTL = EtcdCtl()
def action_fail_now(*args, **kw):
"""Call action_fail() and exit immediately."""
action_fail(*args, **kw)
sys.exit(0)
def requires_etcd_version(version_regex, human_version=None):
"""Decorator that enforces a specific version of etcdctl be present.
The decorated function will only be executed if the required version
of etcdctl is present. Otherwise, action_fail() will be called and
the process will exit immediately.
"""
def wrap(f):
def wrapped_f(*args):
version = CTL.version()
if not re.match(version_regex, version):
required_version = human_version or version_regex
action_fail_now(
"This action requires etcd version {}".format(required_version)
)
f(*args)
return wrapped_f
return wrap
requires_etcd_v2 = requires_etcd_version(r"2\..*", human_version="2.x")
requires_etcd_v3 = requires_etcd_version(r"3\..*", human_version="3.x")
@requires_etcd_v3
def alarm_disarm():
"""Call `etcdctl alarm disarm`."""
try:
output = CTL.run("alarm disarm")
action_set(dict(output=output))
except subprocess.CalledProcessError as e:
action_fail_now(e.output)
@requires_etcd_v3
def alarm_list():
"""Call `etcdctl alarm list`."""
try:
output = CTL.run("alarm list")
action_set(dict(output=output))
except subprocess.CalledProcessError as e:
action_fail_now(e.output)
@requires_etcd_v3
def compact():
"""Call `etcdctl compact`."""
def get_latest_revision():
try:
output = CTL.run("endpoint status --write-out json")
except subprocess.CalledProcessError as e:
action_fail_now(
"Failed to determine latest revision for " "compaction: {}".format(e)
)
m = re.search(r'"revision":(\d*)', output)
if not m:
action_fail_now(
"Failed to get revision from 'endpoint status' "
"output: {}".format(output)
)
return m.group(1)
revision = action_get("revision") or get_latest_revision()
physical = "true" if action_get("physical") else "false"
command = "compact {} --physical={}".format(revision, physical)
try:
output = CTL.run(command)
action_set(dict(output=output))
except subprocess.CalledProcessError as e:
action_fail_now(e.output)
@requires_etcd_v3
def defrag():
"""Call `etcdctl defrag`."""
try:
output = CTL.run("defrag")
action_set(dict(output=output))
except subprocess.CalledProcessError as e:
action_fail_now(e.output)
def health():
"""Call etcdctl cluster-health"""
try:
output = CTL.cluster_health(True)
action_set(dict(output=output))
except subprocess.CalledProcessError as e:
action_fail_now(e.output)
if __name__ == "__main__":
ACTIONS = {
"alarm-disarm": alarm_disarm,
"alarm-list": alarm_list,
"compact": compact,
"defrag": defrag,
"health": health,
}
action = action_name()
ACTIONS[action]()