parent
b250604df5
commit
e5df45650d
|
@ -1,4 +1,4 @@
|
||||||
"""autonomic module."""
|
"""Autonomic module."""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import pkg_resources
|
import pkg_resources
|
||||||
|
@ -7,6 +7,6 @@ except ImportError:
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
__version__ = pkg_resources.get_distribution('autonomic').version
|
__version__ = pkg_resources.get_distribution("autonomic").version
|
||||||
except Exception:
|
except Exception:
|
||||||
__version__ = 'unknown'
|
__version__ = "unknown"
|
||||||
|
|
|
@ -1,10 +1,21 @@
|
||||||
"""Command-line entrypoint."""
|
"""Command-line entrypoint."""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
import click
|
import click
|
||||||
|
|
||||||
|
from autonomic.command import init
|
||||||
|
|
||||||
@click.command()
|
|
||||||
def main():
|
@click.group()
|
||||||
|
@click.option(
|
||||||
|
"--debug/--no-debug",
|
||||||
|
default=False,
|
||||||
|
help="Enable or disable debug mode",
|
||||||
|
show_default=True,
|
||||||
|
)
|
||||||
|
@click.pass_context
|
||||||
|
def autonomic(ctx, debug):
|
||||||
"""
|
"""
|
||||||
\b
|
\b
|
||||||
___ _ _
|
___ _ _
|
||||||
|
@ -14,8 +25,9 @@ def main():
|
||||||
| | | | |_| | || (_) | | | | (_) | | | | | | | (__
|
| | | | |_| | || (_) | | | | (_) | | | | | | | (__
|
||||||
\_| |_/\__,_|\__\___/|_| |_|\___/|_| |_| |_|_|\___|
|
\_| |_/\__,_|\__\___/|_| |_|\___/|_| |_| |_|_|\___|
|
||||||
""" # noqa
|
""" # noqa
|
||||||
pass
|
ctx.obj = {}
|
||||||
|
ctx.obj["DEBUG"] = debug
|
||||||
|
ctx.obj["HOME"] = "/home/{user}".format(user=os.getlogin())
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
autonomic.add_command(init.init)
|
||||||
main()
|
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
"""Initialise the toolbelt."""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
import click
|
||||||
|
from PyInquirer import prompt
|
||||||
|
|
||||||
|
from autonomic import logger
|
||||||
|
from autonomic.config import add_to_config
|
||||||
|
from autonomic.infrastructure import get_members
|
||||||
|
from autonomic.settings import (
|
||||||
|
AUTONOMIC_YAML,
|
||||||
|
CONFIG_PATH,
|
||||||
|
INFRASTRUCTURE_PATH,
|
||||||
|
INFRASTRUCTURE_REPOSITORY,
|
||||||
|
)
|
||||||
|
from autonomic.system import ensure_installed, run_command
|
||||||
|
|
||||||
|
log = logger.get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@click.command()
|
||||||
|
@click.pass_context
|
||||||
|
def init(ctx):
|
||||||
|
"""Initialise the toolbelt."""
|
||||||
|
create_configuration_directory()
|
||||||
|
clone_infrastructure_repo()
|
||||||
|
create_configuration_file()
|
||||||
|
ask_to_login()
|
||||||
|
|
||||||
|
|
||||||
|
def create_configuration_directory():
|
||||||
|
"""Create toolbelt config directory."""
|
||||||
|
if not os.path.exists(CONFIG_PATH):
|
||||||
|
os.mkdir(CONFIG_PATH)
|
||||||
|
|
||||||
|
|
||||||
|
def clone_infrastructure_repo():
|
||||||
|
"""Clone the infrastructure repository."""
|
||||||
|
if not os.path.exists(INFRASTRUCTURE_PATH):
|
||||||
|
ensure_installed("git")
|
||||||
|
run_command(
|
||||||
|
["git", "clone", INFRASTRUCTURE_REPOSITORY, INFRASTRUCTURE_PATH]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
os.chdir(INFRASTRUCTURE_PATH)
|
||||||
|
run_command(["git", "pull", "origin", "master"])
|
||||||
|
|
||||||
|
|
||||||
|
def ask_to_login():
|
||||||
|
"""Log in as your autonomic member username."""
|
||||||
|
members = get_members()
|
||||||
|
choices = [info["username"] for info in members["autonomic_members"]]
|
||||||
|
question = [
|
||||||
|
{
|
||||||
|
"type": "list",
|
||||||
|
"name": "username",
|
||||||
|
"message": "What is your Autonomic username?",
|
||||||
|
"choices": choices,
|
||||||
|
"filter": lambda val: val.lower(),
|
||||||
|
}
|
||||||
|
]
|
||||||
|
answer = prompt(question)
|
||||||
|
add_to_config(answer)
|
||||||
|
|
||||||
|
|
||||||
|
def create_configuration_file():
|
||||||
|
"""Create toolbelt config file."""
|
||||||
|
if not os.path.exists(AUTONOMIC_YAML):
|
||||||
|
with open(AUTONOMIC_YAML, "w") as handle:
|
||||||
|
handle.write("---")
|
|
@ -0,0 +1,34 @@
|
||||||
|
"""Configuration handling module."""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from autonomic import logger
|
||||||
|
from autonomic.settings import AUTONOMIC_YAML
|
||||||
|
from autonomic.system import exit_with_msg
|
||||||
|
from autonomic.yaml import yaml
|
||||||
|
|
||||||
|
log = logger.get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_config():
|
||||||
|
"""Ensure the configuration exists."""
|
||||||
|
if not os.path.exists(AUTONOMIC_YAML):
|
||||||
|
msg = "{} is missing, run: autonomic init".format(AUTONOMIC_YAML)
|
||||||
|
exit_with_msg(msg)
|
||||||
|
|
||||||
|
|
||||||
|
def add_to_config(data):
|
||||||
|
"""Add values to the autonomic.yml file."""
|
||||||
|
ensure_config()
|
||||||
|
|
||||||
|
with open(AUTONOMIC_YAML, "r") as handle:
|
||||||
|
config = yaml.load(handle.read())
|
||||||
|
|
||||||
|
if config is None:
|
||||||
|
config = {}
|
||||||
|
|
||||||
|
for key in data:
|
||||||
|
config[key] = data[key]
|
||||||
|
|
||||||
|
with open(AUTONOMIC_YAML, "w") as handle:
|
||||||
|
yaml.dump(config, handle)
|
|
@ -0,0 +1,20 @@
|
||||||
|
"""Infrastructure handling module."""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from autonomic.settings import MEMBERS_YAML
|
||||||
|
from autonomic.system import exit_with_msg
|
||||||
|
from autonomic.yaml import yaml
|
||||||
|
|
||||||
|
|
||||||
|
def get_members():
|
||||||
|
"""Get list of Autonomic members."""
|
||||||
|
if not os.path.exists(MEMBERS_YAML):
|
||||||
|
msg = "{} is missing, run: autonomic init".format(MEMBERS_YAML)
|
||||||
|
exit_with_msg(msg)
|
||||||
|
|
||||||
|
with open(MEMBERS_YAML, "r") as handle:
|
||||||
|
try:
|
||||||
|
return yaml.load(handle.read())
|
||||||
|
except Exception as exception:
|
||||||
|
exit_with_msg(str(exception))
|
|
@ -0,0 +1,142 @@
|
||||||
|
"""Logging Module."""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import colorama
|
||||||
|
|
||||||
|
|
||||||
|
def should_do_markup():
|
||||||
|
return sys.stdout.isatty() and os.environ.get("TERM") != "dumb"
|
||||||
|
|
||||||
|
|
||||||
|
SUCCESS = 100
|
||||||
|
OUT = 101
|
||||||
|
|
||||||
|
|
||||||
|
class LogFilter(object):
|
||||||
|
def __init__(self, level):
|
||||||
|
self.__level = level
|
||||||
|
|
||||||
|
def filter(self, logRecord):
|
||||||
|
return logRecord.levelno <= self.__level
|
||||||
|
|
||||||
|
|
||||||
|
class CustomLogger(logging.getLoggerClass()):
|
||||||
|
def __init__(self, name, level=logging.NOTSET):
|
||||||
|
super(logging.getLoggerClass(), self).__init__(name, level)
|
||||||
|
logging.addLevelName(SUCCESS, "SUCCESS")
|
||||||
|
logging.addLevelName(OUT, "OUT")
|
||||||
|
|
||||||
|
def success(self, msg, *args, **kwargs):
|
||||||
|
if self.isEnabledFor(SUCCESS):
|
||||||
|
self._log(SUCCESS, msg, args, **kwargs)
|
||||||
|
|
||||||
|
def out(self, msg, *args, **kwargs):
|
||||||
|
if self.isEnabledFor(OUT):
|
||||||
|
self._log(OUT, msg, args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class TrailingNewlineFormatter(logging.Formatter):
|
||||||
|
def format(self, record):
|
||||||
|
if record.msg:
|
||||||
|
record.msg = record.msg.rstrip()
|
||||||
|
return super(TrailingNewlineFormatter, self).format(record)
|
||||||
|
|
||||||
|
|
||||||
|
def get_logger(name=None):
|
||||||
|
logging.setLoggerClass(CustomLogger)
|
||||||
|
|
||||||
|
logger = logging.getLogger(name)
|
||||||
|
logger.setLevel(logging.DEBUG)
|
||||||
|
|
||||||
|
logger.addHandler(_get_info_handler())
|
||||||
|
logger.addHandler(_get_out_handler())
|
||||||
|
logger.addHandler(_get_warn_handler())
|
||||||
|
logger.addHandler(_get_error_handler())
|
||||||
|
logger.addHandler(_get_critical_handler())
|
||||||
|
logger.addHandler(_get_success_handler())
|
||||||
|
logger.propagate = False
|
||||||
|
|
||||||
|
return logger
|
||||||
|
|
||||||
|
|
||||||
|
def _get_info_handler():
|
||||||
|
handler = logging.StreamHandler(sys.stdout)
|
||||||
|
handler.setLevel(logging.INFO)
|
||||||
|
handler.addFilter(LogFilter(logging.INFO))
|
||||||
|
handler.setFormatter(
|
||||||
|
TrailingNewlineFormatter("--> {}".format(cyan_text("%(message)s")))
|
||||||
|
)
|
||||||
|
|
||||||
|
return handler
|
||||||
|
|
||||||
|
|
||||||
|
def _get_out_handler():
|
||||||
|
handler = logging.StreamHandler(sys.stdout)
|
||||||
|
handler.setLevel(OUT)
|
||||||
|
handler.addFilter(LogFilter(OUT))
|
||||||
|
handler.setFormatter(TrailingNewlineFormatter(" %(message)s"))
|
||||||
|
|
||||||
|
return handler
|
||||||
|
|
||||||
|
|
||||||
|
def _get_warn_handler():
|
||||||
|
handler = logging.StreamHandler(sys.stdout)
|
||||||
|
handler.setLevel(logging.WARN)
|
||||||
|
handler.addFilter(LogFilter(logging.WARN))
|
||||||
|
handler.setFormatter(TrailingNewlineFormatter(yellow_text("%(message)s")))
|
||||||
|
|
||||||
|
return handler
|
||||||
|
|
||||||
|
|
||||||
|
def _get_error_handler():
|
||||||
|
handler = logging.StreamHandler(sys.stderr)
|
||||||
|
handler.setLevel(logging.ERROR)
|
||||||
|
handler.addFilter(LogFilter(logging.ERROR))
|
||||||
|
handler.setFormatter(TrailingNewlineFormatter(red_text("%(message)s")))
|
||||||
|
|
||||||
|
return handler
|
||||||
|
|
||||||
|
|
||||||
|
def _get_critical_handler():
|
||||||
|
handler = logging.StreamHandler(sys.stderr)
|
||||||
|
handler.setLevel(logging.CRITICAL)
|
||||||
|
handler.addFilter(LogFilter(logging.CRITICAL))
|
||||||
|
handler.setFormatter(
|
||||||
|
TrailingNewlineFormatter(red_text("ERROR: %(message)s"))
|
||||||
|
)
|
||||||
|
|
||||||
|
return handler
|
||||||
|
|
||||||
|
|
||||||
|
def _get_success_handler():
|
||||||
|
handler = logging.StreamHandler(sys.stdout)
|
||||||
|
handler.setLevel(SUCCESS)
|
||||||
|
handler.addFilter(LogFilter(SUCCESS))
|
||||||
|
handler.setFormatter(TrailingNewlineFormatter(green_text("%(message)s")))
|
||||||
|
|
||||||
|
return handler
|
||||||
|
|
||||||
|
|
||||||
|
def red_text(msg):
|
||||||
|
return color_text(colorama.Fore.RED, msg)
|
||||||
|
|
||||||
|
|
||||||
|
def yellow_text(msg):
|
||||||
|
return color_text(colorama.Fore.YELLOW, msg)
|
||||||
|
|
||||||
|
|
||||||
|
def green_text(msg):
|
||||||
|
return color_text(colorama.Fore.GREEN, msg)
|
||||||
|
|
||||||
|
|
||||||
|
def cyan_text(msg):
|
||||||
|
return color_text(colorama.Fore.CYAN, msg)
|
||||||
|
|
||||||
|
|
||||||
|
def color_text(color, msg):
|
||||||
|
if should_do_markup():
|
||||||
|
return "{}{}{}".format(color, msg, colorama.Style.RESET_ALL)
|
||||||
|
return msg
|
|
@ -0,0 +1,13 @@
|
||||||
|
"""Static settings."""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
USER = os.getlogin()
|
||||||
|
HOME = "/home/{}".format(USER)
|
||||||
|
CONFIG_PATH = "{}/.autonomic".format(HOME)
|
||||||
|
INFRASTRUCTURE_REPOSITORY = (
|
||||||
|
"ssh://git@git.autonomic.zone:222/autonomic-cooperative/infrastructure.git"
|
||||||
|
)
|
||||||
|
INFRASTRUCTURE_PATH = "{}/infrastructure".format(CONFIG_PATH)
|
||||||
|
MEMBERS_YAML = "{}/resources/members.yml".format(INFRASTRUCTURE_PATH)
|
||||||
|
AUTONOMIC_YAML = "{}/autonomic.yml".format(CONFIG_PATH)
|
|
@ -0,0 +1,35 @@
|
||||||
|
"""System related functions."""
|
||||||
|
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from autonomic import logger
|
||||||
|
|
||||||
|
log = logger.get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_installed(package):
|
||||||
|
"""Ensure a system dependency is installed"""
|
||||||
|
if shutil.which(package) is None:
|
||||||
|
msg = "{} is not installed?".format(package)
|
||||||
|
exit_with_msg(msg)
|
||||||
|
|
||||||
|
|
||||||
|
def run_command(command):
|
||||||
|
"""Run a command."""
|
||||||
|
try:
|
||||||
|
log.info("Running '{}'".format(" ".join(command)))
|
||||||
|
subprocess.check_output(command)
|
||||||
|
except subprocess.CalledProcessError as exception:
|
||||||
|
msg = "{} failed! Saw {}".format(" ".join(command), str(exception))
|
||||||
|
exit_with_msg(msg)
|
||||||
|
|
||||||
|
|
||||||
|
def exit(code=1):
|
||||||
|
sys.exit(code)
|
||||||
|
|
||||||
|
|
||||||
|
def exit_with_msg(msg, code=1):
|
||||||
|
log.critical(msg)
|
||||||
|
exit(code)
|
|
@ -0,0 +1,6 @@
|
||||||
|
"""YAML initialisation module."""
|
||||||
|
|
||||||
|
from ruamel.yaml import YAML
|
||||||
|
|
||||||
|
yaml = YAML()
|
||||||
|
yaml.explicit_start = True
|
|
@ -0,0 +1,7 @@
|
||||||
|
"""YAML initialisation module."""
|
||||||
|
|
||||||
|
from ruamel.yaml import YAML
|
||||||
|
|
||||||
|
|
||||||
|
yaml = YAML()
|
||||||
|
yaml.explicit_start = True
|
|
@ -20,11 +20,9 @@ black = "^19.10b0"
|
||||||
isort = "^4.3.21"
|
isort = "^4.3.21"
|
||||||
flake8 = "^3.7.9"
|
flake8 = "^3.7.9"
|
||||||
|
|
||||||
|
|
||||||
[tool.black]
|
[tool.black]
|
||||||
line-length = 80
|
line-length = 80
|
||||||
target-version = ["py38"]
|
target-version = ["py38"]
|
||||||
skip-string-normalization = true
|
|
||||||
include = '\.pyi?$'
|
include = '\.pyi?$'
|
||||||
|
|
||||||
[tool.towncrier]
|
[tool.towncrier]
|
||||||
|
|
|
@ -43,13 +43,16 @@ packages = find:
|
||||||
zip_safe = False
|
zip_safe = False
|
||||||
install_requires =
|
install_requires =
|
||||||
click >= 7.1.1, <= 8.0
|
click >= 7.1.1, <= 8.0
|
||||||
|
colorama >= 0.4.3, <= 0.5
|
||||||
|
pyinquirer >= 1.0.3, <= 1.1
|
||||||
|
ruamel.yaml >= 0.16.10, <= 0.17
|
||||||
|
|
||||||
[options.packages.find]
|
[options.packages.find]
|
||||||
where = .
|
where = .
|
||||||
|
|
||||||
[options.entry_points]
|
[options.entry_points]
|
||||||
console_scripts =
|
console_scripts =
|
||||||
autonomic = autonomic.__main__:main
|
autonomic = autonomic.__main__:autonomic
|
||||||
|
|
||||||
[build_sphinx]
|
[build_sphinx]
|
||||||
all_files = 1
|
all_files = 1
|
||||||
|
|
Reference in New Issue