Luke Murphy 10 months ago
parent
commit
e5df45650d
Signed by: decentral1se GPG Key ID: 5E2EF5A63E3718CC
13 changed files with 352 additions and 11 deletions
  1. +3
    -3
      autonomic/__init__.py
  2. +17
    -5
      autonomic/__main__.py
  3. +0
    -0
      autonomic/command/__init__.py
  4. +71
    -0
      autonomic/command/init.py
  5. +34
    -0
      autonomic/config.py
  6. +20
    -0
      autonomic/infrastructure.py
  7. +142
    -0
      autonomic/logger.py
  8. +13
    -0
      autonomic/settings.py
  9. +35
    -0
      autonomic/system.py
  10. +6
    -0
      autonomic/yaml.py
  11. +7
    -0
      autonomic/yaml.yml
  12. +0
    -2
      pyproject.toml
  13. +4
    -1
      setup.cfg

+ 3
- 3
autonomic/__init__.py View File

@ -1,4 +1,4 @@
"""autonomic module."""
"""Autonomic module."""
try:
import pkg_resources
@ -7,6 +7,6 @@ except ImportError:
try:
__version__ = pkg_resources.get_distribution('autonomic').version
__version__ = pkg_resources.get_distribution("autonomic").version
except Exception:
__version__ = 'unknown'
__version__ = "unknown"

+ 17
- 5
autonomic/__main__.py View File

@ -1,10 +1,21 @@
"""Command-line entrypoint."""
import os
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
___ _ _
@ -14,8 +25,9 @@ def main():
| | | | |_| | || (_) | | | | (_) | | | | | | | (__
\_| |_/\__,_|\__\___/|_| |_|\___/|_| |_| |_|_|\___|
""" # noqa
pass
ctx.obj = {}
ctx.obj["DEBUG"] = debug
ctx.obj["HOME"] = "/home/{user}".format(user=os.getlogin())
if __name__ == '__main__':
main()
autonomic.add_command(init.init)

autonomic/__version__.py → autonomic/command/__init__.py View File


+ 71
- 0
autonomic/command/init.py View File

@ -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("---")

+ 34
- 0
autonomic/config.py View File

@ -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)

+ 20
- 0
autonomic/infrastructure.py View File

@ -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))

+ 142
- 0
autonomic/logger.py View File

@ -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

+ 13
- 0
autonomic/settings.py View File

@ -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)

+ 35
- 0
autonomic/system.py View File

@ -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)

+ 6
- 0
autonomic/yaml.py View File

@ -0,0 +1,6 @@
"""YAML initialisation module."""
from ruamel.yaml import YAML
yaml = YAML()
yaml.explicit_start = True

+ 7
- 0
autonomic/yaml.yml View File

@ -0,0 +1,7 @@
"""YAML initialisation module."""
from ruamel.yaml import YAML
yaml = YAML()
yaml.explicit_start = True

+ 0
- 2
pyproject.toml View File

@ -20,11 +20,9 @@ black = "^19.10b0"
isort = "^4.3.21"
flake8 = "^3.7.9"
[tool.black]
line-length = 80
target-version = ["py38"]
skip-string-normalization = true
include = '\.pyi?$'
[tool.towncrier]


+ 4
- 1
setup.cfg View File

@ -43,13 +43,16 @@ packages = find:
zip_safe = False
install_requires =
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]
where = .
[options.entry_points]
console_scripts =
autonomic = autonomic.__main__:main
autonomic = autonomic.__main__:autonomic
[build_sphinx]
all_files = 1