From 85af31dc4e70d3e84f590c3ec2f79bdbb30a265d Mon Sep 17 00:00:00 2001 From: SelfhostedPro Date: Mon, 28 Sep 2020 19:14:36 -0700 Subject: [PATCH 01/24] added separate buttons for purging and added snack for number of items deleted and space reclaimed --- backend/api/actions/apps.py | 7 +- backend/api/routers/app_settings.py | 6 +- backend/api/utils.py | 4 +- .../src/components/serverSettings/Prune.vue | 116 ++++++++++++++++++ .../serverSettings/ServerSettingsNav.vue | 4 + frontend/src/router/index.js | 6 + frontend/src/store/modules/snackbar.js | 7 ++ 7 files changed, 144 insertions(+), 6 deletions(-) create mode 100644 frontend/src/components/serverSettings/Prune.vue diff --git a/backend/api/actions/apps.py b/backend/api/actions/apps.py index 7c4f8d1c..e99f77a6 100644 --- a/backend/api/actions/apps.py +++ b/backend/api/actions/apps.py @@ -159,4 +159,9 @@ def prune_images(): deleted_everything.update(deleted_volumes) deleted_everything.update(deleted_images) - return deleted_everything \ No newline at end of file + return deleted_everything +def prune_resources(resource): + dclient = docker.from_env() + action = getattr(dclient, resource) + deleted_resource = action.prune() + return deleted_resource \ No newline at end of file diff --git a/backend/api/routers/app_settings.py b/backend/api/routers/app_settings.py index c0093039..20a2b661 100644 --- a/backend/api/routers/app_settings.py +++ b/backend/api/routers/app_settings.py @@ -37,6 +37,6 @@ 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() \ No newline at end of file +@router.get("/prune/{resource}", dependencies=[Depends(get_active_user)]) +def prune_resources(resource: str): + return apps.prune_resources(resource) \ No newline at end of file diff --git a/backend/api/utils.py b/backend/api/utils.py index b0878b9e..0ce815ed 100644 --- a/backend/api/utils.py +++ b/backend/api/utils.py @@ -49,7 +49,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: @@ -65,7 +65,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: diff --git a/frontend/src/components/serverSettings/Prune.vue b/frontend/src/components/serverSettings/Prune.vue new file mode 100644 index 00000000..582a5a0a --- /dev/null +++ b/frontend/src/components/serverSettings/Prune.vue @@ -0,0 +1,116 @@ + + + diff --git a/frontend/src/components/serverSettings/ServerSettingsNav.vue b/frontend/src/components/serverSettings/ServerSettingsNav.vue index e52e56f8..e25920c1 100644 --- a/frontend/src/components/serverSettings/ServerSettingsNav.vue +++ b/frontend/src/components/serverSettings/ServerSettingsNav.vue @@ -8,6 +8,10 @@ mdi-view-list-outlineTemplate Variables + + mdi-trash-can-outline + Prune + diff --git a/frontend/src/router/index.js b/frontend/src/router/index.js index 1b2d1954..88e3f4ee 100644 --- a/frontend/src/router/index.js +++ b/frontend/src/router/index.js @@ -20,6 +20,7 @@ import UserInfo from "../components/userSettings/UserInfo.vue"; import ServerSettings from "../views/ServerSettings.vue"; import ServerInfo from "../components/serverSettings/ServerInfo.vue"; import ServerVariables from "../components/serverSettings/ServerVariables.vue"; +import Prune from "../components/serverSettings/Prune.vue"; Vue.use(VueRouter); @@ -127,6 +128,11 @@ const routes = [ name: "Template Variables", path: "templateVariables", component: ServerVariables + }, + { + name: "Prune", + path: "prune", + component: Prune } ] }, diff --git a/frontend/src/store/modules/snackbar.js b/frontend/src/store/modules/snackbar.js index 45cc7e1a..32136867 100644 --- a/frontend/src/store/modules/snackbar.js +++ b/frontend/src/store/modules/snackbar.js @@ -29,6 +29,13 @@ const mutations = { state.btnColor = "black"; state.visible = true; }, + setMessage(state, message) { + state.content = message; + state.bottom = true; + state.color = "primary"; + state.btnColor = "black"; + state.visible = true; + }, clearSnack(state) { state.content = ""; (state.bottom = false), (state.btnColor = ""); From 8313a13e636916016daca76732ff99c98950b969 Mon Sep 17 00:00:00 2001 From: SelfhostedPro Date: Tue, 29 Sep 2020 09:19:41 -0700 Subject: [PATCH 02/24] removed purge from serverinfo --- .../components/serverSettings/ServerInfo.vue | 24 ------------------- 1 file changed, 24 deletions(-) diff --git a/frontend/src/components/serverSettings/ServerInfo.vue b/frontend/src/components/serverSettings/ServerInfo.vue index 9a6a1a67..13553504 100644 --- a/frontend/src/components/serverSettings/ServerInfo.vue +++ b/frontend/src/components/serverSettings/ServerInfo.vue @@ -47,17 +47,6 @@ >Export - - Prune - Delete unused images, volumes, and networks. - - Prune - - @@ -80,19 +69,6 @@ export default { setSuccess: "snackbar/setSuccess", setErr: "snackbar/setErr" }), - prune_images() { - axios({ - url: "/api/settings/prune", - method: "GET", - responseType: "text/json" - }) - .then(response => { - this.setSuccess(response); - }) - .catch(err => { - this.setErr(err); - }); - }, export_settings() { axios({ url: "/api/settings/export", From 1d920f5d7e350d2d6c4c317f3b982a63f2fd2cd1 Mon Sep 17 00:00:00 2001 From: SelfhostedPro Date: Tue, 29 Sep 2020 14:23:26 -0700 Subject: [PATCH 03/24] added updated button --- backend/api/actions/apps.py | 28 +++++ backend/api/routers/apps.py | 3 + .../applications/ApplicationsList.vue | 103 ++++++++++-------- 3 files changed, 87 insertions(+), 47 deletions(-) diff --git a/backend/api/actions/apps.py b/backend/api/actions/apps.py index e99f77a6..4d6cd5f1 100644 --- a/backend/api/actions/apps.py +++ b/backend/api/actions/apps.py @@ -148,6 +148,34 @@ def app_action(app_name, action): apps_list = get_apps() return apps_list +def app_update(app_name): + dclient = docker.from_env() + old = dclient.containers.get(app_name) + properties = { + 'name': old.name, + 'hostname': old.attrs['Config']['Hostname'], + 'user': old.attrs['Config']['User'], + 'detach': True, + 'domainname': old.attrs['Config']['Domainname'], + 'tty': old.attrs['Config']['Tty'], + 'ports': None if not old.attrs['Config'].get('ExposedPorts') else { + k:v if v else None for k,v in old.attrs['Config']['ExposedPorts'].items() + }, + 'volumes': None if not old.attrs['Config'].get('Volumes') else [ + v for v in old.attrs['Config']['Volumes'].keys() + ], + 'working_dir': old.attrs['Config']['WorkingDir'], + 'labels': old.attrs['Config']['Labels'], + 'entrypoint': old.attrs['Config']['Entrypoint'], + 'environment': old.attrs['Config']['Env'], + 'healthcheck': old.attrs['Config'].get('Healthcheck', None) + } + dclient.images.pull(old.image.tags[0]) + old.stop() + old.remove() + dclient.containers.run(old.image.tags[0], old.attrs['Config']['Cmd'], **properties) + return get_apps() + def prune_images(): dclient = docker.from_env() deleted_everything = {} diff --git a/backend/api/routers/apps.py b/backend/api/routers/apps.py index d8be06a9..87048950 100644 --- a/backend/api/routers/apps.py +++ b/backend/api/routers/apps.py @@ -51,6 +51,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): diff --git a/frontend/src/components/applications/ApplicationsList.vue b/frontend/src/components/applications/ApplicationsList.vue index 4ed287ac..d68afef0 100644 --- a/frontend/src/components/applications/ApplicationsList.vue +++ b/frontend/src/components/applications/ApplicationsList.vue @@ -1,5 +1,5 @@ + @@ -150,32 +150,36 @@ export default { value: "name", sortable: true, align: "start", - width: "30%" + width: "30%", }, { text: "Status", value: "status", sortable: true, - width: "10%" + width: "10%", }, { text: "Image", value: "image", - sortable: true + sortable: true, }, { text: "Ports", value: "ports", sortable: true, - width: "30%" + }, + { + text: "Created At", + value: "created", + sortable: true, } - ] + ], }; }, methods: { ...mapActions({ readApps: "apps/readApps", - AppAction: "apps/AppAction" + AppAction: "apps/AppAction", }), handleRowClick(appName) { this.$router.push({ path: `/apps${appName.Name}/info` }); @@ -195,14 +199,14 @@ export default { }, refresh() { this.readApps(); - } + }, }, computed: { - ...mapState("apps", ["apps", "isLoading"]) + ...mapState("apps", ["apps", "isLoading"]), }, mounted() { this.readApps(); - } + }, }; @@ -215,9 +219,14 @@ tr:hover { white-space: nowrap; text-overflow: ellipsis; } +.CreatedAt{ + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} .namecell { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } - + \ No newline at end of file From a788ffffcab568560fe9cf6315fdb335e202212d Mon Sep 17 00:00:00 2001 From: SelfhostedPro Date: Tue, 29 Sep 2020 14:30:16 -0700 Subject: [PATCH 04/24] added update button --- .../applications/ApplicationsList.vue | 58 ++++++++++++------- 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/frontend/src/components/applications/ApplicationsList.vue b/frontend/src/components/applications/ApplicationsList.vue index d68afef0..18d8de41 100644 --- a/frontend/src/components/applications/ApplicationsList.vue +++ b/frontend/src/components/applications/ApplicationsList.vue @@ -101,28 +101,42 @@ diff --git a/frontend/src/components/serverSettings/ServerUpdate.vue b/frontend/src/components/serverSettings/ServerUpdate.vue new file mode 100644 index 00000000..37b816f1 --- /dev/null +++ b/frontend/src/components/serverSettings/ServerUpdate.vue @@ -0,0 +1,62 @@ + + + diff --git a/frontend/src/router/index.js b/frontend/src/router/index.js index 88e3f4ee..5cec6e42 100644 --- a/frontend/src/router/index.js +++ b/frontend/src/router/index.js @@ -21,6 +21,7 @@ import ServerSettings from "../views/ServerSettings.vue"; import ServerInfo from "../components/serverSettings/ServerInfo.vue"; import ServerVariables from "../components/serverSettings/ServerVariables.vue"; import Prune from "../components/serverSettings/Prune.vue"; +import ServerUpdate from "../components/serverSettings/ServerUpdate.vue"; Vue.use(VueRouter); @@ -133,6 +134,11 @@ const routes = [ name: "Prune", path: "prune", component: Prune + }, + { + name: "Update Yacht", + path: "update", + component: ServerUpdate } ] }, From 6d34400777f1592d0dc33ad76f07e516c8e6666f Mon Sep 17 00:00:00 2001 From: SelfhostedPro Date: Wed, 30 Sep 2020 12:49:50 -0700 Subject: [PATCH 07/24] fixed update ports --- backend/api/actions/apps.py | 4 +--- backend/api/utils.py | 10 ++++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/backend/api/actions/apps.py b/backend/api/actions/apps.py index 65229037..d41dd72b 100644 --- a/backend/api/actions/apps.py +++ b/backend/api/actions/apps.py @@ -159,9 +159,7 @@ def app_update(app_name): 'detach': True, 'domainname': old.attrs['Config']['Domainname'], 'tty': old.attrs['Config']['Tty'], - 'ports': None if not old.attrs['Config'].get('ExposedPorts') else { - k:v if v else None for k,v in old.attrs['Config']['ExposedPorts'].items() - }, + 'ports': get_update_ports(old.ports), 'volumes': None if not old.attrs['Config'].get('Volumes') else [ v for v in old.attrs['Config']['Volumes'].keys() ], diff --git a/backend/api/utils.py b/backend/api/utils.py index 0ce815ed..ee6d1e62 100644 --- a/backend/api/utils.py +++ b/backend/api/utils.py @@ -337,3 +337,13 @@ 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 \ No newline at end of file From 7cf9c0b5fa584918da52b5b99d318d00a8cc40e6 Mon Sep 17 00:00:00 2001 From: SelfhostedPro Date: Wed, 30 Sep 2020 13:38:17 -0700 Subject: [PATCH 08/24] changed to using watchtower from custom solution --- backend/api/actions/apps.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/backend/api/actions/apps.py b/backend/api/actions/apps.py index d41dd72b..b3c2c4ae 100644 --- a/backend/api/actions/apps.py +++ b/backend/api/actions/apps.py @@ -180,12 +180,11 @@ def update_self(): bash_command = "head -1 /proc/self/cgroup|cut -d/ -f3" yacht_id = subprocess.check_output(['bash','-c', bash_command]).decode('UTF-8') print(yacht_id) - env = ['CONTAINER_ID='+yacht_id] volumes ={'/var/run/docker.sock': {'bind':'/var/run/docker.sock', 'mode': 'rw'}} dclient.containers.run( - image='selfhostedpro/docker-updater:latest', + image='containrrr/watchtower:latest', + command='--run-once '+yacht_id, remove=True, - environment=env, volumes=volumes ) return get_apps() From 873efdaea4249588f7df8595aed8f8b0b0213029 Mon Sep 17 00:00:00 2001 From: SelfhostedPro Date: Wed, 30 Sep 2020 15:02:07 -0700 Subject: [PATCH 09/24] changed updating to watchtower --- backend/api/actions/apps.py | 34 ++++++++++------------------------ 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/backend/api/actions/apps.py b/backend/api/actions/apps.py index b3c2c4ae..a4e5afe0 100644 --- a/backend/api/actions/apps.py +++ b/backend/api/actions/apps.py @@ -152,38 +152,24 @@ def app_action(app_name, action): def app_update(app_name): dclient = docker.from_env() old = dclient.containers.get(app_name) - properties = { - 'name': old.name, - 'hostname': old.attrs['Config']['Hostname'], - 'user': old.attrs['Config']['User'], - 'detach': True, - 'domainname': old.attrs['Config']['Domainname'], - 'tty': old.attrs['Config']['Tty'], - 'ports': get_update_ports(old.ports), - 'volumes': None if not old.attrs['Config'].get('Volumes') else [ - v for v in old.attrs['Config']['Volumes'].keys() - ], - 'working_dir': old.attrs['Config']['WorkingDir'], - 'labels': old.attrs['Config']['Labels'], - 'entrypoint': old.attrs['Config']['Entrypoint'], - 'environment': old.attrs['Config']['Env'], - 'healthcheck': old.attrs['Config'].get('Healthcheck', None) - } - dclient.images.pull(old.image.tags[0]) - old.stop() - old.remove() - dclient.containers.run(old.image.tags[0], old.attrs['Config']['Cmd'], **properties) + volumes ={'/var/run/docker.sock': {'bind':'/var/run/docker.sock', 'mode': 'rw'}} + dclient.containers.run( + image='containrrr/watchtower:latest', + command='--run-once '+old.name, + remove=True, + volumes=volumes + ) 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') - print(yacht_id) + yacht_id = subprocess.check_output(['bash','-c', bash_command]).decode('UTF-8').strip() + yacht = dclient.containers.get(yacht_id) volumes ={'/var/run/docker.sock': {'bind':'/var/run/docker.sock', 'mode': 'rw'}} dclient.containers.run( image='containrrr/watchtower:latest', - command='--run-once '+yacht_id, + command='--run-once '+yacht.name, remove=True, volumes=volumes ) From 3d6c91706d97aee42f2c7780131049b11342e968 Mon Sep 17 00:00:00 2001 From: SelfhostedPro Date: Wed, 30 Sep 2020 15:17:30 -0700 Subject: [PATCH 10/24] changed wording and attach to the running instance --- backend/api/actions/apps.py | 2 ++ frontend/src/components/serverSettings/ServerUpdate.vue | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/backend/api/actions/apps.py b/backend/api/actions/apps.py index a4e5afe0..6022779f 100644 --- a/backend/api/actions/apps.py +++ b/backend/api/actions/apps.py @@ -156,6 +156,7 @@ def app_update(app_name): dclient.containers.run( image='containrrr/watchtower:latest', command='--run-once '+old.name, + detach=False, remove=True, volumes=volumes ) @@ -170,6 +171,7 @@ def update_self(): dclient.containers.run( image='containrrr/watchtower:latest', command='--run-once '+yacht.name, + detach=False, remove=True, volumes=volumes ) diff --git a/frontend/src/components/serverSettings/ServerUpdate.vue b/frontend/src/components/serverSettings/ServerUpdate.vue index 37b816f1..fdf61296 100644 --- a/frontend/src/components/serverSettings/ServerUpdate.vue +++ b/frontend/src/components/serverSettings/ServerUpdate.vue @@ -1,10 +1,10 @@