Skip to content

Commit

Permalink
Merge pull request #141 from SelfhostedPro/develop
Browse files Browse the repository at this point in the history
Alpha 3 (v0.0.3-alpha) Update
  • Loading branch information
SelfhostedPro authored Oct 3, 2020
2 parents d11eea3 + 5e3c11e commit 7a5efb4
Show file tree
Hide file tree
Showing 23 changed files with 1,116 additions and 107 deletions.
94 changes: 92 additions & 2 deletions backend/api/actions/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
from ..utils import *

from datetime import datetime
import time
import subprocess
import docker


Expand All @@ -21,12 +23,22 @@ def get_running_apps():

return apps_list

def check_app_updates():
apps_list = []
dclient = docker.from_env()
apps = dclient.containers.list(all=True)
for app in apps:
if check_updates(app.image.tags[0]):
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))
Expand All @@ -39,7 +51,7 @@ 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))
Expand Down Expand Up @@ -148,6 +160,63 @@ 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")
else:
raise HTTPException(status_code=exc.response.status_code, detail=exc.explanation)

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,
remove=True,
detach=True,
volumes=volumes
)
except Exception as exc:
print(exc)
raise HTTPException(status_code=exc.response.status_code, detail=exc.explanation)

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()
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")
else:
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+'****')
updater = dclient.containers.run(
image='containrrr/watchtower:latest',
command='--run-once '+yacht.name,
remove=True,
detach=True,
volumes=volumes
)
result = updater.wait(timeout=120)
print(result)
time.sleep(1)
return result

def prune_images():
dclient = docker.from_env()
deleted_everything = {}
Expand All @@ -159,4 +228,25 @@ def prune_images():
deleted_everything.update(deleted_volumes)
deleted_everything.update(deleted_images)

return deleted_everything
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()
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")
else:
raise HTTPException(status_code=exc.response.status_code, detail=exc.explanation)

return check_updates(yacht.image.tags[0])
2 changes: 2 additions & 0 deletions backend/api/db/schemas/templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ class TemplateRead(TemplateBase):
updated_at: datetime
created_at: datetime

class TemplateReadAll(TemplateBase):
items: List[TemplateItem] = []

class TemplateItems(TemplateRead):
items: List[TemplateItem] = []
Expand Down
14 changes: 11 additions & 3 deletions backend/api/routers/app_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ def export_settings(db: Session = Depends(get_db)):
def import_settings(db: Session = Depends(get_db), upload: UploadFile = File(...)):
return crud.import_settings(db=db, upload=upload)

@router.get("/prune", dependencies=[Depends(get_active_user)])
def prune_images():
return apps.prune_images()
@router.get("/prune/{resource}", dependencies=[Depends(get_active_user)])
def prune_resources(resource: str):
return apps.prune_resources(resource)

@router.get('/update', dependencies=[Depends(get_active_user)])
def update_self():
return apps.update_self()

@router.get('/check/update', dependencies=[Depends(get_active_user)])
def check_self_update():
return apps.check_self_update()
8 changes: 6 additions & 2 deletions backend/api/routers/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ def get_db():
def index():
return actions.get_apps()

@router.get('/updates', dependencies=[Depends(get_active_user)])
def check_updates():
return actions.check_app_updates()

@router.get("/{app_name}", dependencies=[Depends(get_active_user)])
def get_container_details(app_name):
Expand All @@ -51,6 +54,9 @@ def get_container_processes(app_name):
def get_container_logs(app_name):
return actions.get_app_logs(app_name=app_name)

@router.get("/{app_name}/update", dependencies=[Depends(get_active_user)])
def update_container(app_name):
return actions.app_update(app_name)

@router.get("/{app_name}/{action}", dependencies=[Depends(get_active_user)])
def container_actions(app_name, action):
Expand Down Expand Up @@ -116,7 +122,6 @@ async def stats(websocket: WebSocket, app_name: str):
cpu_percent = await calculate_cpu_percent(line)

full_stats = {
"time": line['read'],
"cpu_percent": cpu_percent,
"mem_current": mem_current,
"mem_total": mem_total,
Expand Down Expand Up @@ -174,7 +179,6 @@ async def process_container(name, stats, websocket):

full_stats = {
"name": name,
"time": line['read'],
"cpu_percent": cpu_percent,
"mem_current": mem_current,
"mem_total": mem_total,
Expand Down
36 changes: 34 additions & 2 deletions backend/api/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from .auth import user_db
from .settings import Settings
import aiodocker
import docker
import json
settings = Settings()

Expand Down Expand Up @@ -49,7 +50,7 @@ def conv_ports2dict(data: List[str]) -> List[Dict[str, str]]:
for port_data in data:
for label, port in port_data.items():
if not re.match(REGEXP_PORT_ASSIGN, port, flags=re.IGNORECASE):
raise ValueError('Malformed port assignment.')
raise HTTPException(status_code=500, detail='Malformed port assignment.'+port_data)

hport, cport = None, port
if delim in cport:
Expand All @@ -65,7 +66,7 @@ def conv_ports2dict(data: List[str]) -> List[Dict[str, str]]:
portlst = []
for port_data in data:
if not re.match(REGEXP_PORT_ASSIGN, port_data, flags=re.IGNORECASE):
raise ValueError('Malformed port assignment.')
raise HTTPException(status_code=500, detail='Malformed port assignment.'+port_data)

hport, cport = None, port_data
if delim in cport:
Expand Down Expand Up @@ -182,6 +183,14 @@ def conv_volumes2data(data):
def conv_env2data(data):
# Set is depracated. Name is the actual value. Label is the name of the field.
# Label is the label of the label field.
db = SessionLocal()
t_variables = db.query(models.TemplateVariables).all()

for i,variable in enumerate(data):
for t_var in t_variables:
if t_var.variable in variable.default:
new_var = data[i].default.replace(t_var.variable, t_var.replacement)
variable.default = new_var
delim = '='
return [delim.join((d.name, d.default)) for d in data]

Expand Down Expand Up @@ -337,3 +346,26 @@ async def get_app_stats(app_name):
"mem_percent": (mem_current / mem_total) * 100.0,
}
yield json.dumps(full_stats)

def get_update_ports(ports):
if ports:
portdir={}
for hport in ports:
for d in ports[hport]:
portdir.update({str(hport): d.get('HostPort') })
return portdir
else:
return None

def check_updates(tag):
if tag:
dclient = docker.from_env()
current = dclient.images.get(tag)
new = dclient.images.get_registry_data(tag)
if new.attrs['Descriptor']['digest'] in current.attrs['RepoDigests'][0]:
return False
else:
return True

else:
return False
38 changes: 19 additions & 19 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@
"chart.js": "^2.9.3",
"chartjs-plugin-crosshair": "^1.1.6",
"core-js": "^3.6.5",
"moment": "^2.28.0",
"vee-validate": "^3.3.11",
"moment": "^2.29.0",
"vee-validate": "^3.4.0",
"vue": "^2.6.12",
"vue-chartjs": "^3.5.1",
"vue-router": "^3.4.3",
"vuetify": "^2.3.10",
"vue-router": "^3.4.5",
"vuetify": "^2.3.12",
"vuex": "^3.4.0"
},
"devDependencies": {
Expand Down
Loading

0 comments on commit 7a5efb4

Please sign in to comment.