Files
fastapi_test/server-test
2023-02-22 18:57:12 +01:00

214 lines
10 KiB
Plaintext

from email.quoprimime import body_check
from http.client import HTTPException
# from turtle import title
from typing import Union, Optional
from fastapi import FastAPI, Response, status, HTTPException, Request
from fastapi.params import Body
from fastapi.responses import HTMLResponse, PlainTextResponse
from pydantic import BaseModel
from random import randrange
import os
import subprocess
# from podman import PodmanClient
import json
import yaml
import docker
from fastapi.templating import Jinja2Templates
import socket
import random
import string
dragontool = FastAPI()
#uri = "unix:///run/podman/podman.sock"
#uri = "http+unix://%2frun%2fpodman.sock/v4.0.0/libpod/version"
#podmanapi = PodmanClient(base_url=uri)
podmanapi = docker.DockerClient(base_url='unix://run/user/1000/podman/podman.sock')
yaml_file = open("containers.yaml", 'r')
yaml_content = yaml.load(yaml_file,Loader=yaml.FullLoader)
templates = Jinja2Templates(directory="templates")
class Environment(BaseModel):
username: str
uid: Optional[str] = None
def Random_alphanumeric_string(length):
return ''.join(random.choices(string.ascii_letters + string.digits,k=length))
def Filter(string, substr):
return [str for str in string if
any(sub in str for sub in substr)]
def Unique_list(input_list):
output_list = []
for word in input_list:
if word not in output_list:
output_list.append(word)
return output_list
@dragontool.get("/")
async def root():
return {"message": "Welcome to Dragontool API!"}
@dragontool.post("/api/v1/environments", status_code=status.HTTP_201_CREATED)
async def create_environments(env: Environment):
env_dict = env.dict()
env_dict['username'] = env_dict['username'].replace("-", "_")
if env_dict['uid'] is None:
container_uid = Random_alphanumeric_string(8)
else:
container_uid = env_dict['uid']
try:
network = podmanapi.networks.create(name=env_dict['username']+'-'+container_uid)
except docker.errors.APIError:
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Server returns an error")
if env_dict['username'] == "gitlab":
container_timeout = "86400"
else:
container_timeout = "432000"
for container in yaml_content['containers']:
cmd = subprocess.run(["podman","run","-dt","--rm","-P","--privileged","--memory",container['memory'],"--cpus",container['cpus'],"--timeout",container_timeout,"--name",container['name']+'-'+env_dict['username']+'-'+container_uid,"--network",env_dict['username']+'-'+container_uid,"--network-alias",container['name'],container['image']+':1.0'],stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True, text=True)
# try:
# container = podmanapi.containers.run(image=container['image']+":1.0",name=container['name']+'-'+env_dict['username']+'-'+container_uid,privileged=True,detach=True,publish_all_ports=True, remove=True,network=env_dict['username']+'-'+container_uid)
# except docker.errors.ContainerError:
# raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Environment {env_dict['username']+'-'+env_dict['uid']} already in use!")
# except docker.errors.ImageNotFound:
# raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Image on server does not exist!")
# except docker.errors.APIError:
# raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Server returns an error")
json_response = json.dumps({'Username': env_dict['username'],'uid': container_uid,'Creation': 'successfull'}, indent=4, default=str)
return Response(content=json_response,media_type='application/json')
@dragontool.post("/api/v1/environments/inventory", status_code=status.HTTP_201_CREATED, response_class=HTMLResponse)
async def get_inventory(request: Request, env: Environment):
env_dict = env.dict()
env_dict['username'] = env_dict['username'].replace("-", "_")
env_dict['uid'] = env_dict['uid'].replace("-", "_")
container_list = []
for yaml_container in yaml_content['containers']:
try:
container = podmanapi.containers.get(yaml_container['name']+'-'+env_dict['username']+'-'+env_dict['uid'])
except docker.errors.NotFound:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Environment {env_dict['username']+'-'+env_dict['uid']} not found!")
except docker.errors.APIError:
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Server returns an error")
for priv_port,pub_port in container.ports.items():
if priv_port == '2222/tcp':
for host_port in pub_port:
containers_0 = {}
containers_0['container_alias'] = yaml_container['name']
containers_0['container_name'] = container.name.strip('/')
containers_0['container_pub_ssh_port'] = host_port['HostPort']
containers_0['container_batch'] = yaml_container['batch']
container_list.append(containers_0)
response = templates.TemplateResponse("hosts-template-v2.ini", {"request": request, "container_list": container_list, "host_ip": socket.gethostbyname(socket.gethostname()) })
return response
@dragontool.post("/api/v1/environments/ports", status_code=status.HTTP_201_CREATED, response_class=HTMLResponse)
async def get_ports(request: Request, env: Environment):
env_dict = env.dict()
env_dict['username'] = env_dict['username'].replace("-", "_")
env_dict['uid'] = env_dict['uid'].replace("-", "_")
container_list = []
for yaml_container in yaml_content['containers']:
try:
container = podmanapi.containers.get(yaml_container['name']+'-'+env_dict['username']+'-'+env_dict['uid'])
except docker.errors.NotFound:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Environment {env_dict['username']+'-'+env_dict['uid']} not found!")
except docker.errors.APIError:
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Server returns an error")
for priv_port,pub_port in container.ports.items():
#print(priv_port,pub_port)
if priv_port == '2222/tcp':
for host_port in pub_port:
containers_0 = {}
containers_0['container_alias'] = yaml_container['name']
containers_0['container_name'] = container.name.strip('/')
containers_0['container_pub_ssh_port'] = host_port['HostPort']
containers_0['host_ip'] = socket.gethostbyname(socket.gethostname())
container_list.append(containers_0)
if priv_port == '3890/tcp':
for host_port in pub_port:
containers_0 = {}
containers_0['container_alias'] = yaml_container['name']
containers_0['container_name'] = container.name.strip('/')
containers_0['container_pub_ldap_port'] = host_port['HostPort']
containers_0['host_ip'] = socket.gethostbyname(socket.gethostname())
container_list.append(containers_0)
json_response = json.dumps(container_list, indent=4, default=str)
return Response(content=json_response,media_type='application/json')
@dragontool.delete("/api/v1/environments", status_code=status.HTTP_204_NO_CONTENT)
async def delete_environments(env: Environment):
""" Delete environments of username + uid given """
env_dict = env.dict()
env_dict['username'] = env_dict['username'].replace("-", "_")
env_dict['uid'] = env_dict['uid'].replace("-", "_")
for container in yaml_content['containers']:
try:
container = podmanapi.containers.get(container['name']+'-'+env_dict['username']+'-'+env_dict['uid'])
try:
container.remove(v=True,force=True)
except docker.errors.APIError:
pass
except docker.errors.NotFound:
pass
except docker.errors.APIError:
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Server returns an error")
try:
network = podmanapi.networks.prune()
except docker.errors.APIError:
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Server returns an error")
try:
container = podmanapi.containers.prune()
except docker.errors.APIError:
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Server returns an error")
try:
image = podmanapi.images.prune()
except docker.errors.APIError:
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Server returns an error")
return Response(status_code=status.HTTP_204_NO_CONTENT)
@dragontool.post("/api/v1/environments/list")
async def list_environments(env: Environment):
""" Restrieve environments belonging to username that is given """
env_dict = env.dict()
env_dict['username'] = env_dict['username'].replace("-", "_")
#env_dict['uid'] = env_dict['uid'].replace("-", "_")
containers = podmanapi.containers.list(all=True)
container_list = []
for container in containers:
container_list.append(container.name)
#print(container.status)
substr = [env_dict['username']]
filtered_containers = (Filter(container_list, substr))
container_list = []
for container in yaml_content['containers']:
container_list.append(container['name'])
filtered_containers_list = []
for filtered_container in filtered_containers:
filtered_container = filtered_container.split("-", 2)
filtered_containers_list.extend(filtered_container)
for cont in container_list:
while cont in filtered_containers_list:
filtered_containers_list.remove(cont)
filtered_containers_list.remove(env_dict['username'])
conts_0 = Unique_list(filtered_containers_list)
container_list = []
for cont_0 in conts_0:
containers_0 = {}
containers_0['uid'] = cont_0
container_list.append(containers_0)
json_response = json.dumps(container_list, indent=4, default=str)
return Response(content=json_response,media_type='application/json')