Compare commits

...

4 Commits

Author SHA1 Message Date
e7f26fbf6f Replaced self_service.sh with service.py 2022-03-14 21:58:25 +01:00
cdca807aa0 Added php7.4-pgsql dep to nginx-webserver 2022-03-14 15:20:10 +01:00
ba93280fd6 Updated index.php 2022-03-14 15:19:44 +01:00
790e83b8fb Added copying of sample-data to db vm 2022-03-14 14:39:23 +01:00
7 changed files with 236 additions and 71 deletions

View File

@ -1,4 +0,0 @@
#!/usr/bin/env bash
USER_DIR=./customers/$1
(cd $USER_DIR && vagrant destroy -f)
rm -rf $USER_DIR

View File

@ -7,6 +7,7 @@
- php7.4
- php7.4-fpm
- php7.4-cli
- php7.4-pgsql
state: present
update_cache: yes
become: true

View File

@ -14,5 +14,20 @@
<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>
{% endif %}
</body>
</html>

View File

@ -44,12 +44,15 @@
columns:
- id bigserial primary key
- content text
# TODO: Figure out what would be the correct `copy_from`
- 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: sample.csv
copy_from: /tmp/sample.csv
db: test
dst: message
columns: content
@ -60,9 +63,10 @@
become: yes
community.postgresql.postgresql_user:
name: postgres
password: coolshit
password: "{{ psql_pass }}"
- name: Restart postgresql service
service:
name: postgresql
state: restarted
enabled: yes
become: true

View File

@ -1,56 +0,0 @@
#!/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
# read -p "Number of postgresql instances: " numPostgresql
ipAddr=15
numWebserver=0
numLoadbalancers=0
numPostgresql=1
# 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
sed -i "s/#{numPostgresql}/$numPostgresql/" ./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))
write_inventory_group "postgresql" $ipOffset $numPostgresql
((ipOffset+=numPostgresql))
# 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

205
service.py Executable file
View File

@ -0,0 +1,205 @@
#!/usr/bin/env python3
import argparse
import sys
from os import path
from pathlib import Path
import os
import time
from typing import Any, Callable, DefaultDict, Iterable, Mapping
from jinja2 import Template
import itertools
import subprocess as sub
import shutil
import string
import secrets
TEMPLATE_DIR = "./templates"
def gen_pass() -> str:
alphabet = string.ascii_letters + string.digits
password = "".join(secrets.choice(alphabet) for _ in range(20))
return password
def check_positive(value: str):
ivalue = int(value)
if ivalue <= 0:
raise Exception("Supplied number must be >= 0")
return ivalue
def encode_member(member: str, mapping: Mapping[str, Any]) -> str:
return member + " " + " ".join([f"{k}={v}" for k, v in mapping.items()])
def iter_ips(ip_format: str, start_octet: int):
ip_int = start_octet
ip_fmt = ip_format
while ip_int < 255:
yield ip_fmt.format(ip_int)
ip_int += 1
class InventoryWriter:
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")
def copy_template(src: str, dest: str, mapping: Mapping[str, Any] = {}):
c = Path(src).read_text()
t: Template = Template(c)
r = t.render(mapping)
Path(dest).write_text(r)
def list_envs(args: argparse.Namespace):
try:
customer_path = path.join("customers", args.customer_name, "envs")
print(" ".join(os.listdir(customer_path)))
except FileNotFoundError:
raise Exception(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 create_env(args: argparse.Namespace):
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)
# 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)
psql_gen_pass: Callable[[str], str] = lambda x: 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")
mapping = {
"env": args.env_name,
"customer_name": args.customer_name,
"ip_int": args.ip_int,
"ip_format": args.ip_format.replace("{}", "%d"),
"num_webserver": args.num_nginx_web,
"num_loadbalancers": args.num_nginx_lb,
"num_postgres": args.num_postgres,
}
copy_template(src=src, dest=dest, mapping=mapping)
# Generate .ssh
ssh_dir = path.join(env_path, ".ssh")
Path(ssh_dir).mkdir(exist_ok=True)
ssh_key_cmd = [
"ssh-keygen",
"-t",
"rsa",
"-b",
"2048",
"-f",
path.join(ssh_dir, "id_rsa"),
]
sub.call(ssh_key_cmd)
# Provision and configure machines
sub.call(["vagrant", "up"], cwd=env_path)
time.sleep(1)
sub.call(["ansible-playbook", "../../../../site.yml"], cwd=env_path)
def main() -> int:
parser = argparse.ArgumentParser()
sub_parser = parser.add_subparsers()
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)
cenv_parser = sub_parser.add_parser("create", help="create a new 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)
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)
args = parser.parse_args(sys.argv[1:])
args.func(args)
return 0
if __name__ == "__main__":
raise SystemExit(main())

View File

@ -1,7 +1,7 @@
$ip_int = #{ipAddr}
$ip_int = {{ ip_int }}
def increment_ip()
ip = "192.168.56.%d" % [$ip_int]
ip = "{{ ip_format }}" % [$ip_int]
$ip_int += 1
return ip
end
@ -10,12 +10,12 @@ Vagrant.configure("2") do |config|
config.ssh.insert_key = false
config.ssh.private_key_path = ["./.ssh/id_rsa","~/.vagrant.d/insecure_private_key"]
num_webserver = #{numWebserver}
num_loadbalancer = #{numLoadbalancers}
num_postgresql = #{numPostgresql}
num_webserver = {{ num_webserver }}
num_loadbalancer = {{ num_loadbalancers }}
num_postgresql = {{ num_postgres }}
(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()
config.vm.define machine_id do |web|
@ -34,7 +34,7 @@ Vagrant.configure("2") do |config|
end
(1..num_loadbalancer).each do |nth|
machine_id = "#{customerName}-bloated-debian-lb%d" % [nth]
machine_id = "{{ customer_name }}-{{ env }}-lb%d" % [nth]
machine_ip = increment_ip()
config.vm.define machine_id do |web|
@ -53,7 +53,7 @@ Vagrant.configure("2") do |config|
end
(1..num_postgresql).each do |nth|
machine_id = "#{customerName}-bloated-debian-db%d" % [nth]
machine_id = "{{ customer_name }}-{{ env }}-db%d" % [nth]
machine_ip = increment_ip()
config.vm.define machine_id do |web|