/
apply
executable file
·99 lines (83 loc) · 3.51 KB
/
apply
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#!/usr/bin/env python3
import argparse
import pathlib
import shutil
import subprocess
import sys
import tempfile
BASE_PATH = pathlib.Path(__file__).resolve().parent
VENV_PATH = BASE_PATH / ".venv"
# Ansible changes a lot between releases and deprecates a lot of stuff each of
# them. Using a pinned ansible identical between all team members should
# reduce the churn.
def install_ansible():
requirements = BASE_PATH / "requirements.txt"
venv_requirements = VENV_PATH / "installed-requirements.txt"
# Avoid installing ansible in the virtualenv multiple times
if venv_requirements.exists() and \
venv_requirements.read_bytes() == requirements.read_bytes():
return
print("creating a new virtual environment and install ansible in it...")
shutil.rmtree(VENV_PATH, ignore_errors=True)
subprocess.run([sys.executable, "-m", "venv", str(VENV_PATH)], check=True)
subprocess.run([
str(VENV_PATH / "bin" / "pip"), "install", "-r", str(requirements),
], check=True)
shutil.copy(str(requirements), str(venv_requirements))
def install_ansible_galaxy_dependencies():
requirements = BASE_PATH / "requirements.yml"
venv_requirements = VENV_PATH / "installed-requirements.yml"
# Avoid unnecessary work by checking if the requirements are already installed
if venv_requirements.exists() and \
venv_requirements.read_bytes() == requirements.read_bytes():
return
subprocess.run([sys.executable, "-m", "venv", str(VENV_PATH)], check=True)
subprocess.run([
str(VENV_PATH / "bin" / "ansible-galaxy"), "install", "-r", str(requirements),
], check=True)
shutil.copy(str(requirements), str(venv_requirements))
def run_playbook(args):
env_dir = BASE_PATH / "envs" / args.env
tempdir = pathlib.Path(tempfile.mkdtemp())
try:
# Create a temporary directory merging together the chosen
# environment, the chosen playbook and the shared files.
(tempdir / "play").mkdir()
(tempdir / "play" / "roles").symlink_to(BASE_PATH / "roles")
(tempdir / "play" / "group_vars").symlink_to(BASE_PATH / "group_vars")
(tempdir / "play" / "playbook.yml").symlink_to(
BASE_PATH / "playbooks" / (args.playbook + ".yml")
)
(tempdir / "env").symlink_to(env_dir)
(tempdir / "ansible.cfg").symlink_to(BASE_PATH / "ansible.cfg")
# Finally invoke the ansible binary installed in the virtualenv
ansible_args = [
str(VENV_PATH / "bin" / "ansible-playbook"),
"-i", str(tempdir / "env" / "hosts"),
"--extra-vars", f"vars_environment={args.env}",
str(tempdir / "play" / "playbook.yml"),
]
if args.user is not None:
ansible_args += ["-u", args.user]
if args.start_at_task is not None:
ansible_args += ["--start-at-task", args.start_at_task]
res = subprocess.run(ansible_args, cwd=str(tempdir))
if res.returncode != 0:
exit(1)
finally:
shutil.rmtree(str(tempdir), ignore_errors=True)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("env")
parser.add_argument("playbook")
parser.add_argument(
"-u", "--user", help="user to log into instances as", default=None,
)
parser.add_argument(
"--start-at-task", help="start at a task with the provided name",
default=None,
)
args = parser.parse_args()
install_ansible()
install_ansible_galaxy_dependencies()
run_playbook(args)