Compare commits
No commits in common. "main" and "inv-alias" have entirely different histories.
1
activate.sh
Normal file
1
activate.sh
Normal file
@ -0,0 +1 @@
|
|||||||
|
export PATH="$PATH:$PWD/scripts/bin"
|
2
build_binaries.sh
Executable file
2
build_binaries.sh
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
cd ./scripts
|
||||||
|
go build -o ./bin/inv-alias ./inv-alias.go
|
378
cli.py
378
cli.py
@ -1,378 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
from __future__ import annotations
|
|
||||||
import argparse
|
|
||||||
import dataclasses
|
|
||||||
import sys
|
|
||||||
from os import path
|
|
||||||
from pathlib import Path
|
|
||||||
import os
|
|
||||||
import time
|
|
||||||
from typing import Any, DefaultDict, Iterable, Mapping
|
|
||||||
from jinja2 import Template
|
|
||||||
import itertools
|
|
||||||
import subprocess as sub
|
|
||||||
import shutil
|
|
||||||
import string
|
|
||||||
import secrets
|
|
||||||
from dataclasses import dataclass
|
|
||||||
|
|
||||||
TEMPLATE_DIR = "./templates"
|
|
||||||
|
|
||||||
|
|
||||||
#region util
|
|
||||||
def gen_pass(pass_length: int = 20) -> str:
|
|
||||||
"""Generates a simple password with the provided length
|
|
||||||
|
|
||||||
Args:
|
|
||||||
pass_length (int, optional): Length of password. Defaults to 20.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
str: The generated password.
|
|
||||||
"""
|
|
||||||
alphabet = string.ascii_letters + string.digits
|
|
||||||
password = "".join(secrets.choice(alphabet) for _ in range(pass_length))
|
|
||||||
return password
|
|
||||||
|
|
||||||
|
|
||||||
def check_positive(value: str) -> int:
|
|
||||||
"""`argparse` type helper to check whether a given input is a positive integer.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
value (str): Input to validate
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
Exception: Input is neither a decimal or positive
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
int: The parsed input if valid
|
|
||||||
"""
|
|
||||||
ivalue = int(value)
|
|
||||||
if ivalue < 0:
|
|
||||||
raise Exception(f"Supplied number must be >= 0")
|
|
||||||
return ivalue
|
|
||||||
|
|
||||||
|
|
||||||
def encode_member(member: str, mapping: Mapping[str, Any]) -> str:
|
|
||||||
"""Encodes the member-entry of an inventory file with additional mappings.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
member (str)
|
|
||||||
mapping (Mapping[str, Any])
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
str: member with mapping encoded
|
|
||||||
"""
|
|
||||||
return member + " " + " ".join([f"{k}={v}" for k, v in mapping.items()])
|
|
||||||
|
|
||||||
|
|
||||||
def iter_ips(ip_format: str, start_octet: int):
|
|
||||||
"""Simple iterator for generating ip's
|
|
||||||
|
|
||||||
Args:
|
|
||||||
ip_format (str)
|
|
||||||
start_octet (int)
|
|
||||||
|
|
||||||
Yields:
|
|
||||||
Yeah idk too lazy too look up what the type annotation for a generator is
|
|
||||||
"""
|
|
||||||
ip_int = start_octet
|
|
||||||
ip_fmt = ip_format
|
|
||||||
while ip_int < 255:
|
|
||||||
yield ip_fmt.format(ip_int)
|
|
||||||
ip_int += 1
|
|
||||||
|
|
||||||
|
|
||||||
def copy_template(src: str, dest: str, mapping: Mapping[str, Any] = {}):
|
|
||||||
"""Templates and writes a template file using Jinja as templating engine.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
src (str): content of the file
|
|
||||||
dest (str): place to write templated file to
|
|
||||||
mapping (Mapping[str, Any], optional): datamapping. Defaults to {}.
|
|
||||||
"""
|
|
||||||
c = Path(src).read_text()
|
|
||||||
t: Template = Template(c)
|
|
||||||
r = t.render(mapping)
|
|
||||||
Path(dest).write_text(r)
|
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region models
|
|
||||||
@dataclass
|
|
||||||
class MachineResources:
|
|
||||||
cpus: int
|
|
||||||
mem: int
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def from_prompt() -> "MachineResources":
|
|
||||||
"""Generate `MachineResources` from prompt.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
Exception
|
|
||||||
Exception
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
MachineResources
|
|
||||||
"""
|
|
||||||
cpus = input(
|
|
||||||
"How many processors would you like to assign (default=1): ")
|
|
||||||
if not cpus:
|
|
||||||
cpus = "1"
|
|
||||||
|
|
||||||
if not cpus.isdigit() or int(cpus) < 0:
|
|
||||||
raise Exception("Expected a postive amount of processors")
|
|
||||||
|
|
||||||
mem = input(
|
|
||||||
"How many megabytes of RAM would you like to assign (default=1024): "
|
|
||||||
)
|
|
||||||
if not mem:
|
|
||||||
mem = "1024"
|
|
||||||
|
|
||||||
if not mem.isdigit() or int(mem) < 0:
|
|
||||||
raise Exception("Expected a postive amount of memory")
|
|
||||||
|
|
||||||
return MachineResources(cpus=int(cpus), mem=int(mem))
|
|
||||||
|
|
||||||
|
|
||||||
class InventoryWriter:
|
|
||||||
"""
|
|
||||||
Helper class for generating Ansible inventory files.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, location: str) -> None:
|
|
||||||
self._file_handle = Path(location)
|
|
||||||
self._groups: dict[str, set[str]] = DefaultDict(set)
|
|
||||||
|
|
||||||
def add(self, name: str, members: Iterable[str]):
|
|
||||||
self._groups[name] |= set(members)
|
|
||||||
|
|
||||||
def _build_group(self, name: str, members: set[str]):
|
|
||||||
fmt = f"[{name}]\n" + "\n".join(members)
|
|
||||||
return fmt
|
|
||||||
|
|
||||||
def flush(self):
|
|
||||||
txt = ""
|
|
||||||
for name, members in self._groups.items():
|
|
||||||
txt += self._build_group(name, members) + "\n\n"
|
|
||||||
self._file_handle.write_text(txt, encoding="utf8")
|
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region CLI positional flows
|
|
||||||
def list_envs(args: argparse.Namespace):
|
|
||||||
try:
|
|
||||||
customer_path = path.join("customers", args.customer_name, "envs")
|
|
||||||
print(" ".join(os.listdir(customer_path)))
|
|
||||||
except FileNotFoundError:
|
|
||||||
print(f"Customer `{args.customer_name}` does not exist.")
|
|
||||||
|
|
||||||
|
|
||||||
def delete_env(args: argparse.Namespace):
|
|
||||||
for env in args.env_names:
|
|
||||||
env_path = path.join("customers", args.customer_name, "envs", env)
|
|
||||||
sub.call(["vagrant", "destroy", "-f"], cwd=env_path)
|
|
||||||
shutil.rmtree(env_path)
|
|
||||||
print(f"Deleted `{env}` from customer `{ args.customer_name}`")
|
|
||||||
|
|
||||||
|
|
||||||
def recover_env(args: argparse.Namespace):
|
|
||||||
for env in args.env_names:
|
|
||||||
env_path = path.join("customers", args.customer_name, "envs", env)
|
|
||||||
sub.call(["vagrant", "up"], cwd=env_path)
|
|
||||||
|
|
||||||
# Artificial sleep waiting for sshd on VM to correctly start
|
|
||||||
print("Waiting on virtual machines...")
|
|
||||||
time.sleep(5)
|
|
||||||
|
|
||||||
sub.call(["ansible-playbook", "../../../../site.yml"], cwd=env_path)
|
|
||||||
print(f"Recovered `{env}` from customer `{ args.customer_name}`")
|
|
||||||
|
|
||||||
|
|
||||||
def create_env(args: argparse.Namespace):
|
|
||||||
"""
|
|
||||||
Managing environments works in a declarative way and thus it can
|
|
||||||
also be used for updating.
|
|
||||||
"""
|
|
||||||
if (args.num_nginx_web + args.num_nginx_lb + args.num_postgres) == 0:
|
|
||||||
raise Exception("At least one item should be deployed")
|
|
||||||
|
|
||||||
env_path = path.join("customers", args.customer_name, "envs",
|
|
||||||
args.env_name)
|
|
||||||
Path(env_path).mkdir(exist_ok=True, parents=True)
|
|
||||||
vagrant_mapping: dict[str, Any] = {
|
|
||||||
"webserver_specs": None,
|
|
||||||
"loadbalancers_specs": None,
|
|
||||||
"postgres_specs": None,
|
|
||||||
"num_webserver": args.num_nginx_web,
|
|
||||||
"num_loadbalancers": args.num_nginx_lb,
|
|
||||||
"num_postgres": args.num_postgres,
|
|
||||||
"env": args.env_name,
|
|
||||||
"customer_name": args.customer_name,
|
|
||||||
"ip_int": args.ip_int,
|
|
||||||
"ip_format": args.ip_format.replace("{}", "%d"),
|
|
||||||
}
|
|
||||||
|
|
||||||
if args.num_nginx_web > 0:
|
|
||||||
print("\nNginx webserver resources:")
|
|
||||||
web_specs = MachineResources.from_prompt()
|
|
||||||
vagrant_mapping["webserver_specs"] = dataclasses.asdict(web_specs)
|
|
||||||
|
|
||||||
if args.num_nginx_lb > 0:
|
|
||||||
print("\nNginx loadbalancer resources: ")
|
|
||||||
lb_specs = MachineResources.from_prompt()
|
|
||||||
vagrant_mapping["loadbalancers_specs"] = dataclasses.asdict(lb_specs)
|
|
||||||
|
|
||||||
if args.num_postgres > 0:
|
|
||||||
print("\nPostgresql machine resources: ")
|
|
||||||
psql_specs = MachineResources.from_prompt()
|
|
||||||
vagrant_mapping["postgres_specs"] = dataclasses.asdict(psql_specs)
|
|
||||||
|
|
||||||
# Template `ansible.cfg`
|
|
||||||
src = path.join(TEMPLATE_DIR, "ansible.cfg.template")
|
|
||||||
dest = path.join(env_path, "ansible.cfg")
|
|
||||||
copy_template(src=src, dest=dest)
|
|
||||||
|
|
||||||
# Create inventory file
|
|
||||||
inv_path = path.join(env_path, "inventory")
|
|
||||||
iw = InventoryWriter(inv_path)
|
|
||||||
ip_generator = iter_ips(args.ip_format, args.ip_int)
|
|
||||||
|
|
||||||
web_ips = itertools.islice(ip_generator, args.num_nginx_web)
|
|
||||||
iw.add("webserver", web_ips)
|
|
||||||
|
|
||||||
lb_ips = itertools.islice(ip_generator, args.num_nginx_lb)
|
|
||||||
iw.add("loadbalancer", lb_ips)
|
|
||||||
|
|
||||||
def psql_gen_pass(x: str) -> str:
|
|
||||||
return encode_member(x, {"psql_pass": gen_pass()})
|
|
||||||
|
|
||||||
psql_ips = list(itertools.islice(ip_generator, args.num_postgres))
|
|
||||||
psql_ips = map(psql_gen_pass, psql_ips)
|
|
||||||
iw.add("postgresql", psql_ips)
|
|
||||||
|
|
||||||
iw.flush()
|
|
||||||
|
|
||||||
# Template `Vagrantfile`
|
|
||||||
src = path.join(TEMPLATE_DIR, "Vagrantfile.template")
|
|
||||||
dest = path.join(env_path, "Vagrantfile")
|
|
||||||
should_reload = Path(dest).exists()
|
|
||||||
copy_template(src=src, dest=dest, mapping=vagrant_mapping)
|
|
||||||
|
|
||||||
# Generate .ssh if it doesn't exist already
|
|
||||||
ssh_dir = path.join(env_path, ".ssh")
|
|
||||||
Path(ssh_dir).mkdir(exist_ok=True)
|
|
||||||
rsa_path = path.join(ssh_dir, "id_rsa")
|
|
||||||
if not Path(rsa_path).exists():
|
|
||||||
print(end="\n")
|
|
||||||
sub.call([
|
|
||||||
"ssh-keygen",
|
|
||||||
"-t",
|
|
||||||
"rsa",
|
|
||||||
"-b",
|
|
||||||
"2048",
|
|
||||||
"-f",
|
|
||||||
rsa_path,
|
|
||||||
])
|
|
||||||
|
|
||||||
# Provision and configure machines
|
|
||||||
# Create VM's that do not exist yet
|
|
||||||
sub.call(["vagrant", "up"], cwd=env_path)
|
|
||||||
|
|
||||||
# Update VM's that already existed
|
|
||||||
if should_reload:
|
|
||||||
sub.call(["vagrant", "reload", "--provision"], cwd=env_path)
|
|
||||||
|
|
||||||
# Artificial sleep waiting for sshd on VM to correctly start
|
|
||||||
print("Waiting on virtual machines...")
|
|
||||||
time.sleep(5)
|
|
||||||
|
|
||||||
sub.call(["ansible-playbook", "../../../../site.yml"], cwd=env_path)
|
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
def main() -> int:
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
sub_parser = parser.add_subparsers()
|
|
||||||
|
|
||||||
# CLI definition for positional arg "list"
|
|
||||||
list_parser = sub_parser.add_parser(
|
|
||||||
"list", help="list customer-owned environments")
|
|
||||||
list_parser.add_argument("customer_name",
|
|
||||||
type=str,
|
|
||||||
help="name of the customer")
|
|
||||||
list_parser.set_defaults(func=list_envs)
|
|
||||||
|
|
||||||
# CLI definition for positional arg "create"
|
|
||||||
cenv_parser = sub_parser.add_parser("create",
|
|
||||||
help="create/update an environment")
|
|
||||||
cenv_parser.add_argument("customer_name",
|
|
||||||
type=str,
|
|
||||||
help="name of the customer")
|
|
||||||
cenv_parser.add_argument("env_name",
|
|
||||||
type=str,
|
|
||||||
help="name of the environment")
|
|
||||||
cenv_parser.add_argument(
|
|
||||||
"--num-postgres",
|
|
||||||
type=check_positive,
|
|
||||||
help="number of postgres databases",
|
|
||||||
default=0,
|
|
||||||
)
|
|
||||||
cenv_parser.add_argument(
|
|
||||||
"--num-nginx-web",
|
|
||||||
type=check_positive,
|
|
||||||
help="number of nginx webservers",
|
|
||||||
default=0,
|
|
||||||
)
|
|
||||||
cenv_parser.add_argument(
|
|
||||||
"--num-nginx-lb",
|
|
||||||
type=check_positive,
|
|
||||||
help="number of nginx loadbalancers",
|
|
||||||
default=0,
|
|
||||||
)
|
|
||||||
cenv_parser.add_argument("--ip-format",
|
|
||||||
type=str,
|
|
||||||
help="format of ip",
|
|
||||||
default="192.168.56.{}")
|
|
||||||
cenv_parser.add_argument("--ip-int",
|
|
||||||
type=check_positive,
|
|
||||||
help="4th octet to start at",
|
|
||||||
default="10")
|
|
||||||
cenv_parser.set_defaults(func=create_env)
|
|
||||||
|
|
||||||
# CLI definition for positional arg "delete"
|
|
||||||
denv_parser = sub_parser.add_parser("delete", help="delete an environment")
|
|
||||||
denv_parser.add_argument("customer_name",
|
|
||||||
type=str,
|
|
||||||
help="name of the customer")
|
|
||||||
denv_parser.add_argument("env_names",
|
|
||||||
type=str,
|
|
||||||
nargs="+",
|
|
||||||
help="name of one or more environments")
|
|
||||||
denv_parser.set_defaults(func=delete_env)
|
|
||||||
|
|
||||||
# CLI definition for positional arg "recover"
|
|
||||||
denv_parser = sub_parser.add_parser("recover",
|
|
||||||
help="attempts to recover an env")
|
|
||||||
denv_parser.add_argument("customer_name",
|
|
||||||
type=str,
|
|
||||||
help="name of the customer")
|
|
||||||
denv_parser.add_argument("env_names",
|
|
||||||
type=str,
|
|
||||||
nargs="+",
|
|
||||||
help="name of one or more environments")
|
|
||||||
denv_parser.set_defaults(func=recover_env)
|
|
||||||
|
|
||||||
# Parse args
|
|
||||||
args = parser.parse_args(sys.argv[1:])
|
|
||||||
args.func(args)
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
raise SystemExit(main())
|
|
@ -1,4 +1 @@
|
|||||||
#!/usr/bin/env bash
|
sudo apt-get -y install virtualbox vagrant ansible
|
||||||
sudo apt update --yes && sudo apt upgrade --yes
|
|
||||||
sudo apt install --yes virtualbox vagrant ansible
|
|
||||||
ansible-galaxy collection install -r requirements.yml
|
|
@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
# ansible-galaxy requirements for this repository
|
|
||||||
collections:
|
|
||||||
- community.postgresql
|
|
4
rm_customer.sh
Executable file
4
rm_customer.sh
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
USER_DIR=./customers/$1
|
||||||
|
(cd $USER_DIR && vagrant destroy -f)
|
||||||
|
rm -rf $USER_DIR
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
# handlers file for nginx-webserver
|
# handlers file for nginx-webserver
|
||||||
- name: reload nginx
|
- name: restart nginx
|
||||||
ansible.builtin.service:
|
ansible.builtin.service:
|
||||||
name: nginx
|
name: nginx
|
||||||
state: restarted
|
state: restarted
|
||||||
|
@ -1,36 +1,14 @@
|
|||||||
---
|
---
|
||||||
# tasks file for nginx-webserver
|
# tasks file for nginx-webserver
|
||||||
- name: Install nginx and php
|
- name: Install nginx
|
||||||
package:
|
package:
|
||||||
name:
|
name: nginx
|
||||||
- nginx
|
|
||||||
- php7.4
|
|
||||||
- php7.4-fpm
|
|
||||||
- php7.4-cli
|
|
||||||
- php7.4-pgsql
|
|
||||||
state: present
|
state: present
|
||||||
update_cache: yes
|
update_cache: yes
|
||||||
become: true
|
become: true
|
||||||
- name: Copy over nginx.conf
|
notify: restart nginx
|
||||||
|
- name: Copy over index.html
|
||||||
ansible.builtin.template:
|
ansible.builtin.template:
|
||||||
src: ./templates/nginx.cfg.j2
|
src: ./templates/index.html.j2
|
||||||
dest: /etc/nginx/sites-available/nginx.cfg
|
dest: /var/www/html/index.html
|
||||||
become: true
|
|
||||||
notify: reload nginx
|
|
||||||
- name: Enable nginx.conf
|
|
||||||
file:
|
|
||||||
src: /etc/nginx/sites-available/nginx.cfg
|
|
||||||
dest: /etc/nginx/sites-enabled/default
|
|
||||||
state: link
|
|
||||||
become: true
|
|
||||||
notify: reload nginx
|
|
||||||
- name: Remove nginx default crap
|
|
||||||
file:
|
|
||||||
state: absent
|
|
||||||
path: /var/www/html/*
|
|
||||||
become: true
|
|
||||||
- name: Copy over index.php
|
|
||||||
ansible.builtin.template:
|
|
||||||
src: ./templates/index.php.j2
|
|
||||||
dest: /var/www/html/index.php
|
|
||||||
become: true
|
become: true
|
||||||
|
17
roles/nginx-webserver/templates/index.html.j2
Normal file
17
roles/nginx-webserver/templates/index.html.j2
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Hello</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<p>Hostname: {{ ansible_facts.nodename }}</p>
|
||||||
|
<p>OS: {{ ansible_facts.distribution }} {{ ansible_facts.distribution_version }}</p>
|
||||||
|
<p>Kernel: {{ ansible_facts.kernel }}</p>
|
||||||
|
<p>Memory usage: {{ ansible_facts.memfree_mb }}/{{ ansible_facts.memtotal_mb }}MB</p>
|
||||||
|
<p>Python version: {{ ansible_facts.python_version }}</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -1,35 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<title>Hello</title>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<h1><?php echo 'Hello, World!'; ?></h1>
|
|
||||||
<p>Hostname: {{ ansible_facts.nodename }}</p>
|
|
||||||
<p>OS: {{ ansible_facts.distribution }} {{ ansible_facts.distribution_version }}</p>
|
|
||||||
<p>Kernel: {{ ansible_facts.kernel }}</p>
|
|
||||||
<p>Memory usage: {{ ansible_facts.memfree_mb }}/{{ ansible_facts.memtotal_mb }}MB</p>
|
|
||||||
<p>Python version: {{ ansible_facts.python_version }}</p>
|
|
||||||
{% if groups['postgresql'] is defined and groups['postgresql']|length > 0 %}
|
|
||||||
<p>
|
|
||||||
<?php
|
|
||||||
$db_handle = pg_connect("host={{ groups['postgresql'][0] }} dbname=test user=postgres password={{ hostvars[groups['postgresql'][0]]['psql_pass'] }}");
|
|
||||||
if ($db_handle) {
|
|
||||||
echo "Connection attempt succeeded.\n";
|
|
||||||
} else {
|
|
||||||
echo "Connection attempt failed.\n";
|
|
||||||
}
|
|
||||||
$query = "SELECT m.* FROM test.public.message m";
|
|
||||||
$result = pg_exec($db_handle, $query);
|
|
||||||
var_dump(pg_fetch_all($result));
|
|
||||||
?>
|
|
||||||
</p>
|
|
||||||
{% else %}
|
|
||||||
<p>No postgres instance detected.</p>
|
|
||||||
{% endif %}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,15 +0,0 @@
|
|||||||
server {
|
|
||||||
listen 80;
|
|
||||||
|
|
||||||
root /var/www/html;
|
|
||||||
index index.php;
|
|
||||||
|
|
||||||
location / {
|
|
||||||
try_files $uri $uri/ =404;
|
|
||||||
}
|
|
||||||
|
|
||||||
location ~ \.php$ {
|
|
||||||
include snippets/fastcgi-php.conf;
|
|
||||||
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,2 +0,0 @@
|
|||||||
hello
|
|
||||||
world
|
|
|
@ -1,2 +0,0 @@
|
|||||||
---
|
|
||||||
# handlers file for postgresql
|
|
@ -1,10 +0,0 @@
|
|||||||
galaxy_info:
|
|
||||||
author: strNophix
|
|
||||||
description: Postgresql Role
|
|
||||||
|
|
||||||
license: MIT
|
|
||||||
min_ansible_version: 2.1
|
|
||||||
|
|
||||||
galaxy_tags: []
|
|
||||||
|
|
||||||
dependencies: []
|
|
@ -1,72 +0,0 @@
|
|||||||
---
|
|
||||||
# tasks file for postgresql
|
|
||||||
- name: Install package dependencies
|
|
||||||
package:
|
|
||||||
name:
|
|
||||||
- postgresql
|
|
||||||
- postgresql-contrib
|
|
||||||
- python3-pip
|
|
||||||
- acl
|
|
||||||
state: present
|
|
||||||
update_cache: yes
|
|
||||||
become: true
|
|
||||||
- name: Install `psycopg2` driver for postgresql
|
|
||||||
pip:
|
|
||||||
name: psycopg2-binary
|
|
||||||
state: present
|
|
||||||
become: true
|
|
||||||
- name: Update `listen_address` in `/etc/postgresql/12/main/postgresql.conf`
|
|
||||||
lineinfile:
|
|
||||||
path: /etc/postgresql/12/main/postgresql.conf
|
|
||||||
regexp: ^#listen_addresses = 'localhost'
|
|
||||||
line: listen_addresses='*'
|
|
||||||
become: true
|
|
||||||
- name: Update `pg_hba.conf`
|
|
||||||
community.postgresql.postgresql_pg_hba:
|
|
||||||
dest: /etc/postgresql/12/main/pg_hba.conf
|
|
||||||
contype: host
|
|
||||||
users: postgres
|
|
||||||
source: 192.168.56.0/24
|
|
||||||
method: md5
|
|
||||||
create: true
|
|
||||||
become: true
|
|
||||||
- name: Create new test-database
|
|
||||||
become_user: postgres
|
|
||||||
become: yes
|
|
||||||
community.postgresql.postgresql_db:
|
|
||||||
name: test
|
|
||||||
- name: Create table `test`.`message`
|
|
||||||
become_user: postgres
|
|
||||||
become: yes
|
|
||||||
community.postgresql.postgresql_table:
|
|
||||||
db: test
|
|
||||||
name: message
|
|
||||||
columns:
|
|
||||||
- id bigserial primary key
|
|
||||||
- content text
|
|
||||||
- name: Copy over dummy-data for `test`.`message`
|
|
||||||
copy:
|
|
||||||
src: "{{ role_path }}/files/sample.csv"
|
|
||||||
dest: /tmp/sample.csv
|
|
||||||
- name: Insert sample data into `test`.`message`
|
|
||||||
become_user: postgres
|
|
||||||
become: yes
|
|
||||||
community.postgresql.postgresql_copy:
|
|
||||||
copy_from: /tmp/sample.csv
|
|
||||||
db: test
|
|
||||||
dst: message
|
|
||||||
columns: content
|
|
||||||
options:
|
|
||||||
format: csv
|
|
||||||
- name: Update password of postgres user
|
|
||||||
become_user: postgres
|
|
||||||
become: yes
|
|
||||||
community.postgresql.postgresql_user:
|
|
||||||
name: postgres
|
|
||||||
password: "{{ psql_pass }}"
|
|
||||||
- name: Restart postgresql service
|
|
||||||
service:
|
|
||||||
name: postgresql
|
|
||||||
state: restarted
|
|
||||||
enabled: yes
|
|
||||||
become: true
|
|
54
scripts/bin/hosto
Executable file
54
scripts/bin/hosto
Executable file
@ -0,0 +1,54 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
VERSION="0.1.0"
|
||||||
|
|
||||||
|
function help() {
|
||||||
|
echo -e \
|
||||||
|
"Usage: $(basename $0) [OPTIONS] [COMMAND]\n\n" \
|
||||||
|
"Options:\n" \
|
||||||
|
" -i, --inv-file <path> Specify the Ansible inventory to add.\n" \
|
||||||
|
" -h, --help Show help.\n" \
|
||||||
|
" -v, --version Show version."
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ $# -eq 0 ]]; then
|
||||||
|
help
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
INVENTORY_FILE="$(pwd)/inventory"
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
-i|--inv-file)
|
||||||
|
INVENTORY_FILE="$2"
|
||||||
|
shift
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
help
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
-v|--version)
|
||||||
|
echo $VERSION
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
-*|--*)
|
||||||
|
echo "hosto: unrecognized option '$1'"
|
||||||
|
help
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -f $INVENTORY_FILE ]; then
|
||||||
|
sudo inv-alias add $INVENTORY_FILE
|
||||||
|
eval $@
|
||||||
|
sudo inv-alias rm $INVENTORY_FILE
|
||||||
|
else
|
||||||
|
echo "hosto: Could not find inventory file at $INVENTORY_FILE"
|
||||||
|
eval $@
|
||||||
|
fi
|
150
scripts/inv-alias.go
Normal file
150
scripts/inv-alias.go
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/fs"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AliasMap map[string]string
|
||||||
|
|
||||||
|
const (
|
||||||
|
HostsFile string = "/etc/hosts"
|
||||||
|
)
|
||||||
|
|
||||||
|
func FixedSplit(s, sep string, parts int) []string {
|
||||||
|
n := make([]string, parts)
|
||||||
|
p := strings.SplitN(s, sep, parts)
|
||||||
|
copy(n, p)
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsLegalLine(line string) bool {
|
||||||
|
c := line[0]
|
||||||
|
return c != '[' && c != '#'
|
||||||
|
}
|
||||||
|
|
||||||
|
func BuildRegionString(regionName string, aliases AliasMap) string {
|
||||||
|
b := strings.Builder{}
|
||||||
|
b.WriteString("#region ")
|
||||||
|
b.WriteString(regionName)
|
||||||
|
b.WriteString("\n")
|
||||||
|
|
||||||
|
for ip, alias := range aliases {
|
||||||
|
b.WriteString(ip)
|
||||||
|
b.WriteString("\t")
|
||||||
|
b.WriteString(alias)
|
||||||
|
b.WriteString("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
b.WriteString("#endregion")
|
||||||
|
return b.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func BuildRegionRegexp(regionName string) *regexp.Regexp {
|
||||||
|
b := strings.Builder{}
|
||||||
|
b.WriteString("(?s)\n#region ")
|
||||||
|
b.WriteString(regexp.QuoteMeta(regionName))
|
||||||
|
b.WriteString(".*#endregion")
|
||||||
|
r := regexp.MustCompile(b.String())
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func ScanAliases(fileReader io.Reader) (AliasMap, error) {
|
||||||
|
aliasMap := AliasMap{}
|
||||||
|
scanner := bufio.NewScanner(fileReader)
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := scanner.Text()
|
||||||
|
if IsLegalLine(line) {
|
||||||
|
s := FixedSplit(line, "#", 2)
|
||||||
|
ip, alias := strings.TrimSpace(s[0]), strings.TrimSpace(s[1])
|
||||||
|
if _, ok := aliasMap[ip]; !ok && alias != "" {
|
||||||
|
aliasMap[ip] = alias
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return aliasMap, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddAliases(fileName string) {
|
||||||
|
file, err := os.Open(fileName)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
h, err := ScanAliases(file)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
file.Close()
|
||||||
|
|
||||||
|
r := BuildRegionRegexp(fileName)
|
||||||
|
s := BuildRegionString(fileName, h)
|
||||||
|
|
||||||
|
content, err := ioutil.ReadFile(HostsFile)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c := r.ReplaceAllString(string(content), s)
|
||||||
|
if !r.MatchString(c) {
|
||||||
|
c += ("\n" + s)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.WriteFile(HostsFile, []byte(c[:]), fs.FileMode(os.O_WRONLY|os.O_TRUNC))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func RemoveAliases(fileName string) {
|
||||||
|
regionReg := BuildRegionRegexp(fileName)
|
||||||
|
content, err := ioutil.ReadFile(HostsFile)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c := regionReg.ReplaceAll(content, []byte(""))
|
||||||
|
err = os.WriteFile(HostsFile, c, fs.FileMode(os.O_WRONLY|os.O_TRUNC))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
u := fmt.Sprintf("Please use: %s <add|rm> <file:path>\n", os.Args[0])
|
||||||
|
|
||||||
|
if len(os.Args) < 3 {
|
||||||
|
fmt.Println(u)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
p, err := filepath.Abs(os.Args[2])
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch os.Args[1] {
|
||||||
|
case "add":
|
||||||
|
AddAliases(p)
|
||||||
|
case "rm":
|
||||||
|
RemoveAliases(p)
|
||||||
|
default:
|
||||||
|
fmt.Println(u)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
47
self_service.sh
Executable file
47
self_service.sh
Executable file
@ -0,0 +1,47 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
copy_template() {
|
||||||
|
cp -f ../../templates/$1 ./$2
|
||||||
|
}
|
||||||
|
|
||||||
|
write_inventory_group() {
|
||||||
|
local fmt="[$1]\n"
|
||||||
|
for ((i=$2; i<$2+$3; i++)) do
|
||||||
|
fmt+="192.168.56.$i\n"
|
||||||
|
done
|
||||||
|
echo -e $fmt >> ./inventory
|
||||||
|
}
|
||||||
|
|
||||||
|
# Take customer inputs
|
||||||
|
read -p "Klantnaam: " customerName
|
||||||
|
read -p "IpInt: " ipAddr
|
||||||
|
read -p "Number of webservers: " numWebserver
|
||||||
|
read -p "Number of loadbalancers: " numLoadbalancers
|
||||||
|
|
||||||
|
# Create customer directory and cd
|
||||||
|
mkdir -p ./customers/$customerName && cd $_
|
||||||
|
|
||||||
|
# Copy and fill-in necessary templates
|
||||||
|
copy_template ./Vagrantfile.template ./Vagrantfile
|
||||||
|
sed -i "s/#{customerName}/$customerName/" ./Vagrantfile
|
||||||
|
sed -i "s/#{ipAddr}/$ipAddr/" ./Vagrantfile
|
||||||
|
sed -i "s/#{numWebserver}/$numWebserver/" ./Vagrantfile
|
||||||
|
sed -i "s/#{numLoadbalancers}/$numLoadbalancers/" ./Vagrantfile
|
||||||
|
|
||||||
|
copy_template ./ansible.cfg.template ./ansible.cfg
|
||||||
|
|
||||||
|
# Generate ansible inventory file.
|
||||||
|
ipOffset=$ipAddr
|
||||||
|
|
||||||
|
write_inventory_group "webserver" $ipOffset $numWebserver
|
||||||
|
((ipOffset+=numWebserver))
|
||||||
|
|
||||||
|
write_inventory_group "loadbalancer" $ipOffset $numLoadbalancers
|
||||||
|
((ipOffset+=numLoadbalancers))
|
||||||
|
|
||||||
|
# Generate a new seperate ssh key for the customer
|
||||||
|
mkdir -p ./.ssh/
|
||||||
|
ssh-keygen -t rsa -b 2048 -f ./.ssh/id_rsa
|
||||||
|
|
||||||
|
# Provision and configure machines
|
||||||
|
vagrant up
|
||||||
|
ansible-playbook ../../site.yml
|
227
service.py
227
service.py
@ -1,227 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
from __future__ import annotations
|
|
||||||
from pathlib import Path
|
|
||||||
from os import path
|
|
||||||
import subprocess as sub
|
|
||||||
import re
|
|
||||||
from typing import Any, Callable
|
|
||||||
from enum import Enum
|
|
||||||
|
|
||||||
P_BANNER = """
|
|
||||||
██╗ ██╗███████╗██╗ ██╗ ██╗ ██████╗ ███╗ ███╗
|
|
||||||
██║ ██║██╔════╝██║ ██║ ██╔╝██╔═══██╗████╗ ████║
|
|
||||||
██║ █╗ ██║█████╗ ██║ █████╔╝ ██║ ██║██╔████╔██║
|
|
||||||
██║███╗██║██╔══╝ ██║ ██╔═██╗ ██║ ██║██║╚██╔╝██║
|
|
||||||
╚███╔███╔╝███████╗███████╗██║ ██╗╚██████╔╝██║ ╚═╝ ██║
|
|
||||||
╚══╝╚══╝ ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝
|
|
||||||
"""
|
|
||||||
|
|
||||||
P_OPTIONS = """
|
|
||||||
Opties:
|
|
||||||
0) Afsluiten
|
|
||||||
1) Maak/Wijzig omgeving(en)
|
|
||||||
2) Vernietig omgeving(en)
|
|
||||||
3) Recover omgeving(en)
|
|
||||||
4) List omgeving(en)
|
|
||||||
"""
|
|
||||||
class PortalOptions(Enum):
|
|
||||||
EXIT = "0"
|
|
||||||
CREATE = "1"
|
|
||||||
DESTROY = "2"
|
|
||||||
RECOVER = "3"
|
|
||||||
LIST = "4"
|
|
||||||
|
|
||||||
|
|
||||||
RE_TEXT = re.compile(r"^\w+$")
|
|
||||||
RE_NUM = re.compile(r"^\d+$")
|
|
||||||
RE_ANY = re.compile(r".+")
|
|
||||||
|
|
||||||
|
|
||||||
class Prompter:
|
|
||||||
|
|
||||||
def __init__(self, ps1: str = "") -> None:
|
|
||||||
self.ps1 = ps1
|
|
||||||
|
|
||||||
def _build_prompt(self, prompt: str) -> str:
|
|
||||||
return self.ps1 + prompt
|
|
||||||
|
|
||||||
def take_input(self,
|
|
||||||
prompt: str,
|
|
||||||
pattern: re.Pattern[Any],
|
|
||||||
default: str = "") -> str:
|
|
||||||
prompt = self._build_prompt(prompt)
|
|
||||||
return Prompter.input(prompt, lambda x: bool(pattern.match(x)),
|
|
||||||
default)
|
|
||||||
|
|
||||||
def take_choice(self, prompt: str, options: list[str]) -> str:
|
|
||||||
prompt = self._build_prompt(prompt)
|
|
||||||
return Prompter.input(prompt, lambda x: x in options)
|
|
||||||
|
|
||||||
def take_confirmation(self, prompt: str, default: str = "y") -> bool:
|
|
||||||
prompt = self._build_prompt(prompt)
|
|
||||||
i = Prompter.input(prompt, lambda x: x.lower() in ["y", "n"], default=default)
|
|
||||||
return i == "y"
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def input(prompt: str,
|
|
||||||
validate: Callable[[str], bool],
|
|
||||||
default: str = "") -> str:
|
|
||||||
while True:
|
|
||||||
i = input(prompt)
|
|
||||||
if i == "":
|
|
||||||
i = default
|
|
||||||
if validate(i):
|
|
||||||
return i
|
|
||||||
|
|
||||||
def get_env_list(customer: str) -> list[str]:
|
|
||||||
"""Fetches and parses a list of a customer's environments
|
|
||||||
|
|
||||||
Args:
|
|
||||||
customer (str): The customer to fetch environments from
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[str]: The parsed environments
|
|
||||||
"""
|
|
||||||
return sub.check_output(["python3", "cli.py", "list",
|
|
||||||
customer]).decode().strip("\n").split(" ")
|
|
||||||
|
|
||||||
|
|
||||||
def main() -> int:
|
|
||||||
print(P_BANNER)
|
|
||||||
customer_name = Prompter.input("Wat is uw naam: ",
|
|
||||||
lambda x: bool(RE_TEXT.match(x)))
|
|
||||||
"""
|
|
||||||
Ensures the necessary customer setup.
|
|
||||||
|
|
||||||
NOTE: The customer and the `envs` directory inside of it never get removed.
|
|
||||||
"""
|
|
||||||
envs_dir = path.join("customers", customer_name, "envs")
|
|
||||||
Path(envs_dir).mkdir(parents=True, exist_ok=True)
|
|
||||||
|
|
||||||
p = Prompter(ps1=f"{customer_name} > ")
|
|
||||||
while True:
|
|
||||||
print(P_OPTIONS)
|
|
||||||
choice = p.take_input("Keuze: ", RE_ANY)
|
|
||||||
print(end="\n")
|
|
||||||
|
|
||||||
if choice == PortalOptions.EXIT.value:
|
|
||||||
"""
|
|
||||||
Used to break out of the loop and exit the portal.
|
|
||||||
"""
|
|
||||||
break
|
|
||||||
|
|
||||||
if choice == PortalOptions.CREATE.value:
|
|
||||||
"""
|
|
||||||
Used to either update or create an environment.
|
|
||||||
"""
|
|
||||||
envs = get_env_list(customer_name)
|
|
||||||
print(
|
|
||||||
f"NOTE: Kies een albestaande omgevingen {envs} of iets nieuws..."
|
|
||||||
)
|
|
||||||
fmt = "Omgevingsnaam: "
|
|
||||||
env_name = p.take_input(fmt, RE_TEXT)
|
|
||||||
|
|
||||||
# Loop until customer has confirmed their desired combination of machines
|
|
||||||
while True:
|
|
||||||
templates = ["production", "acceptance", "test", "custom"]
|
|
||||||
fmt = f"Het type omgeving {templates}: "
|
|
||||||
template_name = p.take_choice(fmt, templates)
|
|
||||||
if template_name == "custom":
|
|
||||||
"""
|
|
||||||
Asks for all machine's individually
|
|
||||||
"""
|
|
||||||
fmt = "Aantal nginx webservers (default=1): "
|
|
||||||
amnt_nginx_web = p.take_input(fmt, RE_NUM, default="1")
|
|
||||||
|
|
||||||
fmt = "Aantal nginx loadbalancers (default=1): "
|
|
||||||
amnt_nginx_lb = p.take_input(fmt, RE_NUM, default="1")
|
|
||||||
|
|
||||||
fmt = "Aantal postgres instances (default=1): "
|
|
||||||
amnt_psql = p.take_input(fmt, RE_NUM, default="1")
|
|
||||||
elif template_name == "production":
|
|
||||||
amnt_nginx_web = "2"
|
|
||||||
amnt_nginx_lb = "1"
|
|
||||||
amnt_psql = "1"
|
|
||||||
|
|
||||||
elif template_name == "acceptance":
|
|
||||||
amnt_nginx_web = "1"
|
|
||||||
amnt_nginx_lb = "0"
|
|
||||||
amnt_psql = "1"
|
|
||||||
# elif template_name == "test":
|
|
||||||
else:
|
|
||||||
amnt_nginx_web = "1"
|
|
||||||
amnt_nginx_lb = "0"
|
|
||||||
amnt_psql = "0"
|
|
||||||
|
|
||||||
# TODO: migrate different machine types to a dict model
|
|
||||||
print(end="\n")
|
|
||||||
print("Deze omgeving bevat:")
|
|
||||||
if amnt_nginx_web > "0":
|
|
||||||
print(f" - {amnt_nginx_web} Nginx webserver(s)")
|
|
||||||
|
|
||||||
if amnt_nginx_lb > "0":
|
|
||||||
print(f" - {amnt_nginx_lb} Nginx loadbalancer(s)")
|
|
||||||
|
|
||||||
if amnt_psql > "0":
|
|
||||||
print(f" - {amnt_psql} Postgres instance(s)")
|
|
||||||
print(end="\n")
|
|
||||||
|
|
||||||
if p.take_confirmation("Bevestig (Y/n): "):
|
|
||||||
break
|
|
||||||
|
|
||||||
"""
|
|
||||||
Define the format for templating ip-addresses.`{}` is required
|
|
||||||
and will be subbed at runtime with the correct octet.
|
|
||||||
"""
|
|
||||||
print(end="\n")
|
|
||||||
fmt = "NOTE: `{}` will be replaced with the correct octet at runtime"
|
|
||||||
print(fmt)
|
|
||||||
fmt = "Format of ip (default=192.168.56.{}): "
|
|
||||||
ip_format = p.take_input(fmt, RE_ANY, default="192.168.56.{}")
|
|
||||||
|
|
||||||
fmt = "Number to start formatting the IP from (default=10): "
|
|
||||||
ip_int = p.take_input(fmt, RE_NUM, default="10")
|
|
||||||
|
|
||||||
sub.call([
|
|
||||||
"python3", "cli.py", "create", customer_name, env_name,
|
|
||||||
"--num-nginx-web", amnt_nginx_web, "--num-postgres", amnt_psql,
|
|
||||||
"--num-nginx-lb", amnt_nginx_lb, "--ip-format", ip_format,
|
|
||||||
"--ip-int", ip_int
|
|
||||||
])
|
|
||||||
print(f"Omgeving `{env_name}` successvol gemaakt.")
|
|
||||||
|
|
||||||
if choice == PortalOptions.DESTROY.value:
|
|
||||||
"""
|
|
||||||
Deletes all traces of the chosen environment.
|
|
||||||
"""
|
|
||||||
envs = get_env_list(customer_name)
|
|
||||||
fmt = f"Omgevingsnaam {envs}: "
|
|
||||||
env_name = p.take_choice(fmt, envs)
|
|
||||||
sub.call(["python3", "cli.py", "delete", customer_name, env_name])
|
|
||||||
|
|
||||||
if choice == PortalOptions.RECOVER.value:
|
|
||||||
"""
|
|
||||||
Allows the customer to "force" their environment into the desired `up-state`.
|
|
||||||
This `up-state` is a representation of the Vagrantfile, Ansible inventory and
|
|
||||||
.ssh directory of that specific environment. The .ssh directory is only
|
|
||||||
necessary in case of an existing storage-volume. Otherwise a new one
|
|
||||||
keypair can be manually created or created using option 1.
|
|
||||||
"""
|
|
||||||
envs = get_env_list(customer_name)
|
|
||||||
fmt = f"Omgevingsnaam {envs}: "
|
|
||||||
env_name = p.take_choice(fmt, envs)
|
|
||||||
sub.call(["python3", "cli.py", "recover", customer_name, env_name])
|
|
||||||
|
|
||||||
if choice == PortalOptions.LIST.value:
|
|
||||||
"""
|
|
||||||
This branch displays the customer's existing environments
|
|
||||||
"""
|
|
||||||
print("De volgende omgeving(en) zijn aanwezig: ")
|
|
||||||
for env in get_env_list(customer_name):
|
|
||||||
print(f" - {env}")
|
|
||||||
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
raise SystemExit(main())
|
|
4
site.yml
4
site.yml
@ -6,7 +6,3 @@
|
|||||||
- hosts: loadbalancer
|
- hosts: loadbalancer
|
||||||
roles:
|
roles:
|
||||||
- nginx-loadbalancer
|
- nginx-loadbalancer
|
||||||
|
|
||||||
- hosts: postgresql
|
|
||||||
roles:
|
|
||||||
- postgresql
|
|
@ -1,7 +1,7 @@
|
|||||||
$ip_int = {{ ip_int }}
|
$ip_int = #{ipAddr}
|
||||||
|
|
||||||
def increment_ip()
|
def increment_ip()
|
||||||
ip = "{{ ip_format }}" % [$ip_int]
|
ip = "192.168.56.%d" % [$ip_int]
|
||||||
$ip_int += 1
|
$ip_int += 1
|
||||||
return ip
|
return ip
|
||||||
end
|
end
|
||||||
@ -10,11 +10,11 @@ Vagrant.configure("2") do |config|
|
|||||||
config.ssh.insert_key = false
|
config.ssh.insert_key = false
|
||||||
config.ssh.private_key_path = ["./.ssh/id_rsa","~/.vagrant.d/insecure_private_key"]
|
config.ssh.private_key_path = ["./.ssh/id_rsa","~/.vagrant.d/insecure_private_key"]
|
||||||
|
|
||||||
num_postgresql = {{ num_postgres }}
|
num_webserver = #{numWebserver}
|
||||||
|
num_loadbalancer = #{numLoadbalancers}
|
||||||
|
|
||||||
{% if webserver_specs is not none %}
|
(1..num_webserver).each do |nth|
|
||||||
(1..{{ num_webserver }}).each do |nth|
|
machine_id = "#{customerName}-bloated-debian-web%d" % [nth]
|
||||||
machine_id = "{{ customer_name }}-{{ env }}-web%d" % [nth]
|
|
||||||
machine_ip = increment_ip()
|
machine_ip = increment_ip()
|
||||||
|
|
||||||
config.vm.define machine_id do |web|
|
config.vm.define machine_id do |web|
|
||||||
@ -25,18 +25,15 @@ Vagrant.configure("2") do |config|
|
|||||||
web.vm.provision "file", source: "./.ssh/id_rsa.pub", destination: "~/.ssh/authorized_keys"
|
web.vm.provision "file", source: "./.ssh/id_rsa.pub", destination: "~/.ssh/authorized_keys"
|
||||||
|
|
||||||
web.vm.provider "virtualbox" do |vb|
|
web.vm.provider "virtualbox" do |vb|
|
||||||
vb.memory = {{ webserver_specs["mem"] }}
|
vb.memory = "1024"
|
||||||
vb.cpus = {{ webserver_specs["cpus"] }}
|
|
||||||
vb.gui = false
|
vb.gui = false
|
||||||
vb.name = machine_id
|
vb.name = machine_id
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if loadbalancers_specs is not none %}
|
(1..num_loadbalancer).each do |nth|
|
||||||
(1..{{ num_loadbalancers }}).each do |nth|
|
machine_id = "#{customerName}-bloated-debian-lb%d" % [nth]
|
||||||
machine_id = "{{ customer_name }}-{{ env }}-lb%d" % [nth]
|
|
||||||
machine_ip = increment_ip()
|
machine_ip = increment_ip()
|
||||||
|
|
||||||
config.vm.define machine_id do |web|
|
config.vm.define machine_id do |web|
|
||||||
@ -47,34 +44,10 @@ Vagrant.configure("2") do |config|
|
|||||||
web.vm.provision "file", source: "./.ssh/id_rsa.pub", destination: "~/.ssh/authorized_keys"
|
web.vm.provision "file", source: "./.ssh/id_rsa.pub", destination: "~/.ssh/authorized_keys"
|
||||||
|
|
||||||
web.vm.provider "virtualbox" do |vb|
|
web.vm.provider "virtualbox" do |vb|
|
||||||
vb.memory = {{ loadbalancers_specs["mem"] }}
|
vb.memory = "1024"
|
||||||
vb.cpus = {{ loadbalancers_specs["cpus"] }}
|
|
||||||
vb.gui = false
|
vb.gui = false
|
||||||
vb.name = machine_id
|
vb.name = machine_id
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if postgres_specs is not none %}
|
|
||||||
(1..{{ num_postgres }}).each do |nth|
|
|
||||||
machine_id = "{{ customer_name }}-{{ env }}-db%d" % [nth]
|
|
||||||
machine_ip = increment_ip()
|
|
||||||
|
|
||||||
config.vm.define machine_id do |web|
|
|
||||||
web.vm.box = "ubuntu/focal64"
|
|
||||||
web.vm.hostname = machine_id
|
|
||||||
|
|
||||||
web.vm.network "private_network", ip: machine_ip
|
|
||||||
web.vm.provision "file", source: "./.ssh/id_rsa.pub", destination: "~/.ssh/authorized_keys"
|
|
||||||
|
|
||||||
web.vm.provider "virtualbox" do |vb|
|
|
||||||
vb.memory = {{ postgres_specs["mem"] }}
|
|
||||||
vb.cpus = {{ postgres_specs["cpus"] }}
|
|
||||||
vb.gui = false
|
|
||||||
vb.name = machine_id
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
{% endif %}
|
|
||||||
end
|
end
|
||||||
|
@ -3,6 +3,3 @@ private_key_file = "./.ssh/id_rsa"
|
|||||||
remote_user = "vagrant"
|
remote_user = "vagrant"
|
||||||
inventory = ./inventory
|
inventory = ./inventory
|
||||||
host_key_checking = False
|
host_key_checking = False
|
||||||
|
|
||||||
[ssh_connection]
|
|
||||||
retries=2
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user