Git status checks and more hacking
This commit is contained in:
parent
0806b4e134
commit
c69bdec4c9
@ -3,17 +3,19 @@
|
|||||||
from os import environ
|
from os import environ
|
||||||
|
|
||||||
import click
|
import click
|
||||||
from PyInquirer import prompt
|
|
||||||
|
|
||||||
from autonomic.config import ACTIONS_DIR
|
from autonomic.config import ACTIONS_DIR, INFRA_DIR
|
||||||
from autonomic.infra import get_passwd, run_play
|
from autonomic.infra import get_passwd, run_play
|
||||||
from autonomic.utils import qlist
|
from autonomic.utils import check_git, qlist
|
||||||
|
from PyInquirer import prompt
|
||||||
|
|
||||||
|
|
||||||
@click.command()
|
@click.command()
|
||||||
@click.pass_context
|
@click.pass_context
|
||||||
def actions(ctx):
|
def actions(ctx):
|
||||||
"""Run an Ansible action."""
|
"""Run an Ansible action."""
|
||||||
|
env = environ.copy()
|
||||||
|
|
||||||
choices = ["addusers", "newhetzner", "rmhetzner", "newdokku"]
|
choices = ["addusers", "newhetzner", "rmhetzner", "newdokku"]
|
||||||
question = qlist("action", "Which Ansible action?", choices,)
|
question = qlist("action", "Which Ansible action?", choices,)
|
||||||
action = prompt(question)["action"]
|
action = prompt(question)["action"]
|
||||||
@ -25,13 +27,9 @@ def actions(ctx):
|
|||||||
|
|
||||||
path = "logins/hetzner/{}/api_key".format(key)
|
path = "logins/hetzner/{}/api_key".format(key)
|
||||||
secret = get_passwd(path)
|
secret = get_passwd(path)
|
||||||
env = environ.copy()
|
|
||||||
env["HCLOUD_TOKEN"] = secret
|
env["HCLOUD_TOKEN"] = secret
|
||||||
|
|
||||||
play = "{}/{}.yml".format(ACTIONS_DIR, action)
|
play = "{}/{}.yml".format(ACTIONS_DIR, action)
|
||||||
run_play(play, env=env)
|
run_play(play, env=env)
|
||||||
|
|
||||||
# TODO(decentral1se):
|
check_git(INFRA_DIR)
|
||||||
# git commit and push on infrastructure if we:
|
|
||||||
# 1. ran an action that adds something new to the pass store
|
|
||||||
# 2. added another machine to the inventory
|
|
||||||
|
@ -20,8 +20,7 @@ from autonomic.utils import is_proc, qlist, run
|
|||||||
@click.pass_context
|
@click.pass_context
|
||||||
def init(ctx):
|
def init(ctx):
|
||||||
"""Initialise the toolbelt."""
|
"""Initialise the toolbelt."""
|
||||||
create_configuration_directory()
|
create_configuration()
|
||||||
create_settings_file()
|
|
||||||
clone_infrastructure_repo()
|
clone_infrastructure_repo()
|
||||||
store_username()
|
store_username()
|
||||||
install_dependencies()
|
install_dependencies()
|
||||||
@ -31,11 +30,15 @@ def init(ctx):
|
|||||||
log.success(emojize(msg, use_aliases=True))
|
log.success(emojize(msg, use_aliases=True))
|
||||||
|
|
||||||
|
|
||||||
def create_configuration_directory():
|
def create_configuration():
|
||||||
"""Create toolbelt config directory."""
|
"""Create toolbelt config directory."""
|
||||||
if not exists(CONFIG_DIR):
|
if not exists(CONFIG_DIR):
|
||||||
mkdir(CONFIG_DIR)
|
mkdir(CONFIG_DIR)
|
||||||
|
|
||||||
|
if not exists(CONFIG_YAML):
|
||||||
|
with open(CONFIG_YAML, "w") as handle:
|
||||||
|
handle.write("---")
|
||||||
|
|
||||||
|
|
||||||
def clone_infrastructure_repo():
|
def clone_infrastructure_repo():
|
||||||
"""Clone or update the infrastructure repository."""
|
"""Clone or update the infrastructure repository."""
|
||||||
@ -58,13 +61,6 @@ def store_username():
|
|||||||
log.success(emojize(msg, use_aliases=True))
|
log.success(emojize(msg, use_aliases=True))
|
||||||
|
|
||||||
|
|
||||||
def create_settings_file():
|
|
||||||
"""Create settings file."""
|
|
||||||
if not exists(CONFIG_YAML):
|
|
||||||
with open(CONFIG_YAML, "w") as handle:
|
|
||||||
handle.write("---")
|
|
||||||
|
|
||||||
|
|
||||||
def install_dependencies():
|
def install_dependencies():
|
||||||
"""Install infrastructure dependencies."""
|
"""Install infrastructure dependencies."""
|
||||||
cmd = ["/usr/bin/python3", "-m", "venv", ".venv"]
|
cmd = ["/usr/bin/python3", "-m", "venv", ".venv"]
|
||||||
@ -86,7 +82,7 @@ def install_dependencies():
|
|||||||
def ssh_sanity_check():
|
def ssh_sanity_check():
|
||||||
"""Try to recommend some SSH tips."""
|
"""Try to recommend some SSH tips."""
|
||||||
if not is_proc("ssh-agent"):
|
if not is_proc("ssh-agent"):
|
||||||
msg = "ssh-agent is not running :sob:"
|
msg = "warning: ssh-agent is not running :sob:"
|
||||||
log.warning(emojize(msg, use_aliases=True))
|
log.warning(emojize(msg, use_aliases=True))
|
||||||
else:
|
else:
|
||||||
msg = "ssh-agent is running :rocket:"
|
msg = "ssh-agent is running :rocket:"
|
||||||
|
@ -9,21 +9,36 @@ from autonomic.config import CONFIG_YAML
|
|||||||
from autonomic.utils import yaml_dump, yaml_load
|
from autonomic.utils import yaml_dump, yaml_load
|
||||||
|
|
||||||
|
|
||||||
def add(data):
|
def add(yaml):
|
||||||
"""Add values to the settings file."""
|
"""Add YAML to the settings file."""
|
||||||
|
from autonomic.command.init import create_configuration
|
||||||
|
|
||||||
|
create_configuration()
|
||||||
settings = yaml_load(CONFIG_YAML)
|
settings = yaml_load(CONFIG_YAML)
|
||||||
|
|
||||||
if settings is None:
|
if settings is None:
|
||||||
settings = {}
|
settings = {}
|
||||||
|
|
||||||
for key in data:
|
for key in yaml:
|
||||||
settings[key] = data[key]
|
settings[key] = yaml[key]
|
||||||
|
|
||||||
|
yaml_dump(CONFIG_YAML, settings)
|
||||||
|
|
||||||
|
|
||||||
|
def remove(key):
|
||||||
|
"""Remove key from the settings file."""
|
||||||
|
settings = yaml_load(CONFIG_YAML)
|
||||||
|
|
||||||
|
if settings is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
settings.pop(key, None)
|
||||||
|
|
||||||
yaml_dump(CONFIG_YAML, settings)
|
yaml_dump(CONFIG_YAML, settings)
|
||||||
|
|
||||||
|
|
||||||
def get(key):
|
def get(key):
|
||||||
"""Retrieve setting values."""
|
"""Retrieve settings key."""
|
||||||
settings = yaml_load(CONFIG_YAML)
|
settings = yaml_load(CONFIG_YAML)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -8,10 +8,11 @@ things here.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from os import chdir
|
from os import chdir
|
||||||
from subprocess import CalledProcessError, check_output
|
from subprocess import check_output
|
||||||
|
|
||||||
from psutil import process_iter
|
from psutil import process_iter
|
||||||
|
|
||||||
|
from autonomic.config import INFRA_DIR
|
||||||
from autonomic.logger import log
|
from autonomic.logger import log
|
||||||
from autonomic.yaml import yaml
|
from autonomic.yaml import yaml
|
||||||
|
|
||||||
@ -29,7 +30,7 @@ def run(cmd, cwd=None, **kwargs):
|
|||||||
log.info("Changed directory to {}".format(cwd))
|
log.info("Changed directory to {}".format(cwd))
|
||||||
log.info("Running {}".format(" ".join(cmd)))
|
log.info("Running {}".format(" ".join(cmd)))
|
||||||
return check_output(cmd, **kwargs)
|
return check_output(cmd, **kwargs)
|
||||||
except CalledProcessError as exception:
|
except Exception as exception:
|
||||||
msg = "{} failed! Saw {}".format(" ".join(cmd), str(exception))
|
msg = "{} failed! Saw {}".format(" ".join(cmd), str(exception))
|
||||||
exit(msg)
|
exit(msg)
|
||||||
|
|
||||||
@ -84,3 +85,13 @@ def is_proc(name):
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def git_status(fpath):
|
||||||
|
"""Check if Git reports changes to be committed."""
|
||||||
|
cmd = ["git", "status", "--porcelain"]
|
||||||
|
output = run(cmd, cwd=fpath)
|
||||||
|
if output is not None:
|
||||||
|
msg = "warning: git reports uncommitted changes in {}".format(fpath)
|
||||||
|
log.warning(msg)
|
||||||
|
log.warning(output)
|
||||||
|
@ -6,7 +6,7 @@ max-line-length = 80
|
|||||||
|
|
||||||
[isort]
|
[isort]
|
||||||
known_first_party = autonomic
|
known_first_party = autonomic
|
||||||
known_third_party = pytest
|
known_third_party = pytest, psutil
|
||||||
line_length = 80
|
line_length = 80
|
||||||
multi_line_output = 3
|
multi_line_output = 3
|
||||||
skip = .venv, .tox
|
skip = .venv, .tox
|
||||||
|
11
test/test_settings.py
Normal file
11
test/test_settings.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
from autonomic.settings import add, get, remove
|
||||||
|
|
||||||
|
|
||||||
|
def test_add_get_remove():
|
||||||
|
add({"foo": "bar"})
|
||||||
|
|
||||||
|
assert get("doesnt-exist") is None
|
||||||
|
assert get("foo") == "bar"
|
||||||
|
|
||||||
|
remove("foo")
|
||||||
|
assert get("foo") is None
|
58
test/test_utils.py
Normal file
58
test/test_utils.py
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
from subprocess import STDOUT
|
||||||
|
|
||||||
|
from autonomic.utils import is_proc, qlist, run, yaml_dump, yaml_load
|
||||||
|
|
||||||
|
|
||||||
|
def test_run_kwargs():
|
||||||
|
assert run(["whoami"], stderr=STDOUT) is not None
|
||||||
|
|
||||||
|
|
||||||
|
def test_run_cwd(tmp_path):
|
||||||
|
directory = tmp_path / "test"
|
||||||
|
directory.mkdir()
|
||||||
|
|
||||||
|
testfile = directory / "testfile.txt"
|
||||||
|
testfile.write_text("hello, world")
|
||||||
|
|
||||||
|
output = run(["ls"], cwd=directory.absolute())
|
||||||
|
assert "testfile.txt" in output.decode()
|
||||||
|
|
||||||
|
|
||||||
|
def test_make_qlist():
|
||||||
|
output = qlist("foo", "bar", ["bang"])
|
||||||
|
|
||||||
|
expected = {
|
||||||
|
"type": "list",
|
||||||
|
"name": "foo",
|
||||||
|
"message": "bar",
|
||||||
|
"choices": ["bang"],
|
||||||
|
}
|
||||||
|
|
||||||
|
for key, val in expected.items():
|
||||||
|
assert expected[key] == output[0][key]
|
||||||
|
|
||||||
|
|
||||||
|
def test_yaml_load(tmp_path):
|
||||||
|
directory = tmp_path / "test"
|
||||||
|
directory.mkdir()
|
||||||
|
|
||||||
|
testfile = directory / "testfile.yml"
|
||||||
|
testfile.write_text("---\nusername: foobar")
|
||||||
|
|
||||||
|
loaded = yaml_load(testfile.absolute())
|
||||||
|
assert loaded["username"] == "foobar"
|
||||||
|
|
||||||
|
|
||||||
|
def test_yaml_dump(tmp_path):
|
||||||
|
directory = tmp_path / "test"
|
||||||
|
directory.mkdir()
|
||||||
|
|
||||||
|
testfile = directory / "testfile.yml"
|
||||||
|
yaml_dump(testfile.absolute(), {"username": "foobar"})
|
||||||
|
|
||||||
|
loaded = yaml_load(testfile.absolute())
|
||||||
|
assert loaded["username"] == "foobar"
|
||||||
|
|
||||||
|
|
||||||
|
def test_is_proc():
|
||||||
|
assert is_proc("pytest") is True
|
@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
|
|
||||||
def test_version_fails_gracefully(mocker):
|
def test_version_fails_gracefully(mocker):
|
||||||
target = 'pkg_resources.get_distribution'
|
target = "pkg_resources.get_distribution"
|
||||||
mocker.patch(target, side_effect=Exception())
|
mocker.patch(target, side_effect=Exception())
|
||||||
|
|
||||||
from autonomic.__init__ import __version__
|
from autonomic.__init__ import __version__
|
||||||
|
|
||||||
assert __version__ == 'unknown'
|
assert __version__ == "unknown"
|
||||||
|
5
test/test_yaml.py
Normal file
5
test/test_yaml.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
from autonomic.yaml import yaml
|
||||||
|
|
||||||
|
|
||||||
|
def test_yaml_config():
|
||||||
|
assert yaml.explicit_start is True
|
Reference in New Issue
Block a user