Skip to content

Commit

Permalink
Merge pull request #147 from SelfhostedPro/develop
Browse files Browse the repository at this point in the history
Alpha 4 (v0.0.4-alpha)
  • Loading branch information
SelfhostedPro authored Oct 17, 2020
2 parents 0aed12e + 0849d98 commit c564b71
Show file tree
Hide file tree
Showing 44 changed files with 3,326 additions and 224 deletions.
11 changes: 7 additions & 4 deletions backend/alembic/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from sqlalchemy import engine_from_config, MetaData
from sqlalchemy import pool
from alembic import context

# this is the Alembic Config object, which provides
# access to the values within the .ini file in use.
config = context.config
Expand All @@ -18,20 +19,24 @@
import os
import sys
from os.path import abspath, dirname

sys.path.insert(0, dirname(dirname(abspath(__file__))))


from api.db import models
from api.settings import Settings
from api.auth import Base

# Combine metadata from auth and containers/templates
combined_meta_data = MetaData()
for declarative_base in [models.Base, Base]:
for (table_name, table) in declarative_base.metadata.tables.items():
combined_meta_data._add_table(table_name, table.schema, table)

target_metadata = combined_meta_data
config.set_main_option("sqlalchemy.url", os.environ.get('DATABASE_URL', 'sqlite:///config/data.sqlite'))
config.set_main_option(
"sqlalchemy.url", os.environ.get("DATABASE_URL", "sqlite:///config/data.sqlite")
)

# other values from the config, defined by the needs of env.py,
# can be acquired:
Expand Down Expand Up @@ -77,9 +82,7 @@ def run_migrations_online():
)

with connectable.connect() as connection:
context.configure(
connection=connection, target_metadata=target_metadata
)
context.configure(connection=connection, target_metadata=target_metadata)

with context.begin_transaction():
context.run_migrations()
Expand Down
160 changes: 97 additions & 63 deletions backend/api/actions/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from fastapi import HTTPException
from ..db import models, schemas
from ..utils import *
from ..utils import check_updates as _update_check

from datetime import datetime
import time
Expand All @@ -16,33 +17,35 @@ def get_running_apps():
apps = dclient.containers.list()
for app in apps:
attrs = app.attrs
attrs.update(conv2dict('name', app.name))
attrs.update(conv2dict('ports', app.ports))
attrs.update(conv2dict('short_id', app.short_id))
attrs.update(conv2dict("name", app.name))
attrs.update(conv2dict("ports", app.ports))
attrs.update(conv2dict("short_id", app.short_id))
apps_list.append(attrs)

return apps_list


def check_app_updates():
apps_list = []
dclient = docker.from_env()
apps = dclient.containers.list(all=True)
for app in apps:
if app.attrs['Config']['Image']:
if check_updates(app.attrs['Config']['Image']):
if app.attrs["Config"]["Image"]:
if _update_check(app.attrs["Config"]["Image"]):
apps_list.append(app.name)
return apps_list


def get_apps():
apps_list = []
dclient = docker.from_env()
apps = dclient.containers.list(all=True)
for app in apps:
attrs = app.attrs

attrs.update(conv2dict('name', app.name))
attrs.update(conv2dict('ports', app.ports))
attrs.update(conv2dict('short_id', app.short_id))
attrs.update(conv2dict("name", app.name))
attrs.update(conv2dict("ports", app.ports))
attrs.update(conv2dict("short_id", app.short_id))
apps_list.append(attrs)

return apps_list
Expand All @@ -52,28 +55,30 @@ def get_app(app_name):
dclient = docker.from_env()
app = dclient.containers.get(app_name)
attrs = app.attrs
attrs.update(conv2dict('ports', app.ports))
attrs.update(conv2dict('short_id', app.short_id))
attrs.update(conv2dict('name', app.name))

attrs.update(conv2dict("ports", app.ports))
attrs.update(conv2dict("short_id", app.short_id))
attrs.update(conv2dict("name", app.name))

return attrs


def get_app_processes(app_name):
dclient = docker.from_env()
app = dclient.containers.get(app_name)
if app.status == 'running':
if app.status == "running":
processes = app.top()
return schemas.Processes(Processes=processes['Processes'], Titles=processes['Titles'])
return schemas.Processes(
Processes=processes["Processes"], Titles=processes["Titles"]
)
else:
return None


def get_app_logs(app_name):
dclient = docker.from_env()
app = dclient.containers.get(app_name)
if app.status == 'running':
if app.status == "running":
return schemas.AppLogs(logs=app.logs())
else:
return None
Expand All @@ -85,33 +90,53 @@ def deploy_app(template: schemas.DeployForm):
template.name,
conv_image2data(template.image),
conv_restart2data(template.restart_policy),
conv_ports2data(template.ports),
conv_ports2data(template.ports, template.network, template.network_mode),
conv_portlabels2data(template.ports),
template.network_mode,
template.network,
conv_volumes2data(template.volumes),
conv_env2data(template.env),
conv_devices2data(template.devices),
conv_labels2data(template.labels),
conv_sysctls2data(template.sysctls),
conv_caps2data(template.cap_add)
conv_caps2data(template.cap_add),
)

except Exception as exc:
raise HTTPException(status_code=exc.response.status_code, detail=exc.explanation)
print('done deploying')
raise HTTPException(
status_code=exc.response.status_code, detail=exc.explanation
)
print("done deploying")

return schemas.DeployLogs(logs=launch.logs())

def Merge(dict1, dict2):

def Merge(dict1, dict2):
if dict1 and dict2:
return(dict2.update(dict1))
return dict2.update(dict1)
elif dict1:
return dict1
elif dict2:
return dict2
else:
return None

def launch_app(name, image, restart_policy, ports, portlabels, volumes, env, devices, labels, sysctls, caps):

def launch_app(
name,
image,
restart_policy,
ports,
portlabels,
network_mode,
network,
volumes,
env,
devices,
labels,
sysctls,
caps,
):
dclient = docker.from_env()
combined_labels = Merge(portlabels, labels)
try:
Expand All @@ -120,26 +145,30 @@ def launch_app(name, image, restart_policy, ports, portlabels, volumes, env, dev
image=image,
restart_policy=restart_policy,
ports=ports,
network=network,
network_mode=network_mode,
volumes=volumes,
environment=env,
sysctls=sysctls,
labels=combined_labels,
devices=devices,
cap_add=caps,
detach=True
detach=True,
)
except Exception as e:
if e.status_code == 500:
failed_app = dclient.containers.get(name)
failed_app.remove()
raise e

print(f'''Container started successfully.
print(
f"""Container started successfully.
Name: {name},
Image: {image},
Ports: {ports},
Volumes: {volumes},
Env: {env}''')
Env: {env}"""
)
return lauch


Expand All @@ -148,7 +177,7 @@ def app_action(app_name, action):
dclient = docker.from_env()
app = dclient.containers.get(app_name)
_action = getattr(app, action)
if action == 'remove':
if action == "remove":
try:
_action(force=True)
except Exception as exc:
Expand All @@ -161,93 +190,98 @@ def app_action(app_name, action):
apps_list = get_apps()
return apps_list


def app_update(app_name):
dclient = docker.from_env()
try:
old = dclient.containers.get(app_name)
except Exception as exc:
print(exc)
if exc.response.status_code == 404:
raise HTTPException(status_code=exc.response.status_code, detail="Unable to get container ID")
raise HTTPException(
status_code=exc.response.status_code,
detail="Unable to get container ID",
)
else:
raise HTTPException(status_code=exc.response.status_code, detail=exc.explanation)
raise HTTPException(
status_code=exc.response.status_code, detail=exc.explanation
)

volumes ={'/var/run/docker.sock': {'bind':'/var/run/docker.sock', 'mode': 'rw'}}
volumes = {"/var/run/docker.sock": {"bind": "/var/run/docker.sock", "mode": "rw"}}
try:
updater = dclient.containers.run(
image='containrrr/watchtower:latest',
command='--run-once '+old.name,
image="containrrr/watchtower:latest",
command="--run-once " + old.name,
remove=True,
detach=True,
volumes=volumes
volumes=volumes,
)
except Exception as exc:
print(exc)
raise HTTPException(status_code=exc.response.status_code, detail=exc.explanation)
raise HTTPException(
status_code=exc.response.status_code, detail=exc.explanation
)

print('**** Updating '+old.name+'****')
print("**** Updating " + old.name + "****")
result = updater.wait(timeout=120)
print(result)
time.sleep(1)
return get_apps()


def update_self():
dclient = docker.from_env()
bash_command = "head -1 /proc/self/cgroup|cut -d/ -f3"
yacht_id = subprocess.check_output(['bash','-c', bash_command]).decode('UTF-8').strip()
yacht_id = (
subprocess.check_output(["bash", "-c", bash_command]).decode("UTF-8").strip()
)
try:
yacht = dclient.containers.get(yacht_id)
except Exception as exc:
print(exc)
if exc.response.status_code == 404:
raise HTTPException(status_code=exc.response.status_code, detail="Unable to get Yacht container ID")
raise HTTPException(
status_code=exc.response.status_code,
detail="Unable to get Yacht container ID",
)
else:
raise HTTPException(status_code=exc.response.status_code, detail=exc.explanation)
raise HTTPException(
status_code=exc.response.status_code, detail=exc.explanation
)

volumes ={'/var/run/docker.sock': {'bind':'/var/run/docker.sock', 'mode': 'rw'}}
print('**** Updating '+yacht.name+'****')
volumes = {"/var/run/docker.sock": {"bind": "/var/run/docker.sock", "mode": "rw"}}
print("**** Updating " + yacht.name + "****")
updater = dclient.containers.run(
image='containrrr/watchtower:latest',
command='--run-once '+yacht.name,
image="containrrr/watchtower:latest",
command="--run-once " + yacht.name,
remove=True,
detach=True,
volumes=volumes
volumes=volumes,
)
result = updater.wait(timeout=120)
print(result)
time.sleep(1)
return result

def prune_images():
dclient = docker.from_env()
deleted_everything = {}
deleted_volumes = dclient.volumes.prune()
deleted_images = dclient.images.prune()
deleted_networks = dclient.networks.prune()

deleted_everything.update(deleted_networks)
deleted_everything.update(deleted_volumes)
deleted_everything.update(deleted_images)

return deleted_everything
def prune_resources(resource):
dclient = docker.from_env()
action = getattr(dclient, resource)
deleted_resource = action.prune()
return deleted_resource


def check_self_update():
dclient = docker.from_env()
bash_command = "head -1 /proc/self/cgroup|cut -d/ -f3"
yacht_id = subprocess.check_output(['bash','-c', bash_command]).decode('UTF-8').strip()
yacht_id = (
subprocess.check_output(["bash", "-c", bash_command]).decode("UTF-8").strip()
)
try:
yacht = dclient.containers.get(yacht_id)
except Exception as exc:
print(exc)
if exc.response.status_code == 404:
raise HTTPException(status_code=exc.response.status_code, detail="Unable to get Yacht container ID")
raise HTTPException(
status_code=exc.response.status_code,
detail="Unable to get Yacht container ID",
)
else:
raise HTTPException(status_code=exc.response.status_code, detail=exc.explanation)
raise HTTPException(
status_code=exc.response.status_code, detail=exc.explanation
)

return check_updates(yacht.image.tags[0])
Loading

0 comments on commit c564b71

Please sign in to comment.