Merge ~tcuthbert/turku/+git/turku-snap:development into turku:main

Proposed by Thomas Cuthbert
Status: Rejected
Rejected by: Haw Loeung
Proposed branch: ~tcuthbert/turku/+git/turku-snap:development
Merge into: turku:main
Diff against target: 356 lines (+302/-0) (has conflicts)
8 files modified
README.md (+51/-0)
snap/snapcraft.yaml (+115/-0)
src/hooks/bin/configure (+52/-0)
src/hooks/bin/install (+11/-0)
src/hooks/bin/turku-api-wrapper (+11/-0)
src/hooks/bin/turku-management (+49/-0)
src/turku-api/bin/turku-admin (+8/-0)
src/turku-api/config/local_settings.py (+5/-0)
Conflict in README.md
Reviewer Review Type Date Requested Status
Turku Pending
Review via email: mp+413679@code.launchpad.net
To post a comment you must log in.
0f78a8f... by Thomas Cuthbert

add: turku-storage and staticfiles compilation

Unmerged commits

0f78a8f... by Thomas Cuthbert

add: turku-storage and staticfiles compilation

bf1ae73... by Thomas Cuthbert

feat: initial turku-api snap config

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/README.md b/README.md
2index 2163b0b..c37c583 100644
3--- a/README.md
4+++ b/README.md
5@@ -1,3 +1,4 @@
6+<<<<<<< README.md
7 # turku-storage
8
9 ## About Turku
10@@ -102,3 +103,53 @@ This program is free software: you can redistribute it and/or modify it under th
11 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
14+=======
15+# Turku API Snap
16+
17+## Overview
18+
19+- installs turku-api from LP.
20+- sets PYTHONPATH order as:
21+ `$SNAP_DATA/turku-api:$SNAP/lib/python3.6/site-packages`
22+- copies the module into `$SNAP_DATA`, this works around turku's local settings
23+ import loading from `turku_api.local_settings`.
24+ - then it symlinks `$SNAP_COMMON/local_settings.py -> $SNAP_DATA/turku_api/local_settings.py`.
25+- gunicorn is included and is the snap app command.
26+- basic hooks:
27+ - bind (listener:port)
28+ - listener is validated via the rgxg package
29+ - workers
30+
31+## Build
32+
33+```
34+snapcraft clean
35+snapcraft
36+```
37+
38+## Install
39+
40+```
41+snap=
42+snap install "$snap" --dangerous --devmode
43+```
44+
45+## Configure
46+
47+```
48+listener=
49+port=
50+workers=
51+snap set turku-api bind.listener=$listener
52+snap set turku-api bind.port=$port
53+snap set turku-api workers=$workers
54+```
55+
56+## Todo
57+
58+- [ ] test that snap upgrades don't break things.
59+- [ ] test local_settings.py actually works.
60+- [ ] test when running upstream as an upstream server.
61+- [ ] not critical, but the `turku-api-wrapper` script should be called from
62+ `${SNAP}/bin`
63+>>>>>>> README.md
64diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml
65new file mode 100644
66index 0000000..e4c2443
67--- /dev/null
68+++ b/snap/snapcraft.yaml
69@@ -0,0 +1,115 @@
70+name: turku-api # you probably want to 'snapcraft register <name>'
71+base: core18
72+version: '0.1+git'
73+summary: Turku API
74+description: |
75+ Turku is an agent-based backup system where the server doing the backups has
76+ no direct access to the machine being backed up. Instead, the machine's
77+ agent coordinates with an API server and opens a reverse tunnel to the
78+ storage server when it is time to do a backup.
79+
80+grade: devel # must be 'stable' to release into candidate/stable channels
81+confinement: strict # use 'strict' once you have the right plugs and slots
82+
83+apps:
84+
85+ turku-api:
86+ daemon: simple
87+ plugs: [network-bind]
88+ environment:
89+ LC_ALL: C.UTF-8
90+ LANG: C.UTF-8
91+ PYTHONPATH: $SNAP_DATA/turku-api:$SNAP/lib/python3.6/site-packages
92+ command: snap/hooks/turku-api-wrapper
93+
94+ turku-admin:
95+ environment:
96+ LC_ALL: C.UTF-8
97+ LANG: C.UTF-8
98+ PYTHONPATH: $SNAP_DATA/turku-api:$SNAP/lib/python3.6/site-packages
99+ command: bin/turku-admin
100+
101+ turku-storage-ping:
102+ environment:
103+ LC_ALL: C.UTF-8
104+ LANG: C.UTF-8
105+ PYTHONPATH: $SNAP/lib/python3.6/python3.6/site-packages
106+ command: bin/turku-storage-ping
107+
108+ turku-storage-update-config:
109+ environment:
110+ LC_ALL: C.UTF-8
111+ LANG: C.UTF-8
112+ PYTHONPATH: $SNAP/lib/python3.6/python3.6/site-packages
113+ command: bin/turku-storage-update-config
114+
115+hooks:
116+ configure:
117+ plugs: [network-bind]
118+
119+parts:
120+
121+ turku-api:
122+ plugin: python
123+ source-type: git
124+ source: https://git.launchpad.net/~turku/turku/+git/turku-api
125+ source-branch: main
126+ python-version: python3
127+ python-packages: [psycopg2, gunicorn]
128+ requirements: [requirements.txt]
129+ prime:
130+ - -.venv
131+ - -venv
132+ - -env
133+ - -lib/python3.6/python3.6/site-packages/turku*
134+ build-packages:
135+ - libpq-dev
136+ stage-packages:
137+ - libpq5
138+ override-build: |
139+ snapcraftctl build
140+
141+ cp -r ./turku_api $SNAPCRAFT_PART_INSTALL/
142+
143+ override-stage: |
144+ snapcraftctl stage
145+
146+ export PYTHONPATH="$SNAPCRAFT_PART_INSTALL:$SNAPCRAFT_PART_INSTALL/lib/python3.6/site-packages"
147+ export DJANGO_SETTINGS_MODULE="turku_api.settings"
148+
149+ mkdir "static"
150+ printf '%s = "%s"\n' "STATIC_ROOT" "static" > "$SNAPCRAFT_PART_INSTALL/turku_api/local_settings.py"
151+ "$SNAPCRAFT_PART_INSTALL/bin/django-admin" collectstatic
152+ rm "$SNAPCRAFT_PART_INSTALL/turku_api/local_settings.py"
153+
154+ cp -r static "$SNAPCRAFT_PART_INSTALL/"
155+
156+ after: [turku-admin, hooks]
157+
158+ turku-storage:
159+ plugin: python
160+ source-type: git
161+ source: https://git.launchpad.net/turku
162+ source-branch: main
163+ python-version: python3
164+ requirements: [requirements.txt]
165+ prime:
166+ - -.venv
167+ - -venv
168+ - -env
169+ after: [turku-admin, hooks]
170+
171+ turku-admin:
172+ plugin: dump
173+ source: src/turku-api/
174+ stage:
175+ - bin/*
176+ - config/*
177+
178+ hooks:
179+ plugin: dump
180+ source: src/hooks/
181+ stage-packages:
182+ - rgxg
183+ organize:
184+ bin/: snap/hooks/
185diff --git a/src/hooks/bin/configure b/src/hooks/bin/configure
186new file mode 100755
187index 0000000..74f23fa
188--- /dev/null
189+++ b/src/hooks/bin/configure
190@@ -0,0 +1,52 @@
191+#!/bin/sh -e
192+
193+. "$SNAP/snap/hooks/turku-management"
194+
195+handle_port_config()
196+{
197+ http_port="$(http_port)"
198+
199+ # Validate HTTP port
200+ if ! expr "$http_port" : '^[0-9]\+$' > /dev/null; then
201+ echo "\"$http_port\" is not a valid HTTP port" >&2
202+ return 1
203+ fi
204+
205+ set_http_port "$http_port"
206+
207+ snapctl restart turku-api
208+}
209+
210+handle_listener_config()
211+{
212+ listener="$(listener)"
213+
214+ # Validate listener
215+ if ! rgxg cidr "$listener"/32; then
216+ echo "\"$listener\" is not a valid IP address" >&2
217+ return 1
218+ fi
219+
220+ set_listener "$listener"
221+
222+ snapctl restart turku-api
223+}
224+
225+handle_workers_config()
226+{
227+ workers="$(workers)"
228+
229+ # Validate gunicorn workers
230+ if ! expr "$workers" : '^[0-9]\+$' > /dev/null; then
231+ echo "\"$workers\" is not a valid number" >&2
232+ return 1
233+ fi
234+
235+ set_workers "$workers"
236+
237+ snapctl restart turku-api
238+}
239+
240+handle_port_config
241+handle_listener_config
242+handle_workers_config
243diff --git a/src/hooks/bin/install b/src/hooks/bin/install
244new file mode 100755
245index 0000000..17ee20d
246--- /dev/null
247+++ b/src/hooks/bin/install
248@@ -0,0 +1,11 @@
249+#!/bin/sh -e
250+
251+if [ ! -d "$SNAP_DATA/turku-api" ]; then
252+ mkdir -p "$SNAP_DATA/turku-api"
253+fi
254+
255+cp -r "$SNAP/turku_api" "$SNAP_DATA/turku-api/"
256+cp -r "$SNAP/static" "$SNAP_DATA/"
257+
258+touch "$SNAP_DATA/turku-api/turku_api/local_settings.py"
259+ln -fs "$SNAP_DATA/turku-api/turku_api/local_settings.py" "$SNAP_COMMON/local_settings.py"
260diff --git a/src/hooks/bin/turku-api-wrapper b/src/hooks/bin/turku-api-wrapper
261new file mode 100755
262index 0000000..9650198
263--- /dev/null
264+++ b/src/hooks/bin/turku-api-wrapper
265@@ -0,0 +1,11 @@
266+#!/bin/sh -eu
267+
268+. "$SNAP/snap/hooks/turku-management"
269+
270+TURKU_LISTENER="$(listener)"
271+TURKU_HTTP_PORT="$(http_port)"
272+TURKU_WORKERS="$(workers)"
273+
274+export GUNICORN_CMD_ARGS="--bind '${TURKU_LISTENER}:${TURKU_HTTP_PORT}' --workers '${TURKU_WORKERS}'"
275+
276+"$SNAP/bin/gunicorn" turku_api.wsgi
277diff --git a/src/hooks/bin/turku-management b/src/hooks/bin/turku-management
278new file mode 100755
279index 0000000..cc79356
280--- /dev/null
281+++ b/src/hooks/bin/turku-management
282@@ -0,0 +1,49 @@
283+#!/bin/sh
284+
285+DEFAULT_HTTP_PORT="8000"
286+DEFAULT_LISTENER="127.0.0.1" # gunicorn default
287+
288+http_port()
289+{
290+ port="$(snapctl get bind.port)"
291+ if [ -z "$port" ]; then
292+ port="$DEFAULT_HTTP_PORT"
293+ set_http_port $port
294+ fi
295+ echo "$port"
296+}
297+
298+set_http_port()
299+{
300+ snapctl set bind.port="$1"
301+}
302+
303+listener()
304+{
305+ listener="$(snapctl get bind.listener)"
306+ if [ -z "$listener" ]; then
307+ listener="$DEFAULT_LISTENER"
308+ set_listener $listener
309+ fi
310+ echo "$listener"
311+}
312+
313+set_listener()
314+{
315+ snapctl set bind.listener="$1"
316+}
317+
318+workers()
319+{
320+ workers="$(snapctl get workers)"
321+ if [ -z "$workers" ]; then
322+ workers="$(expr $(nproc) - 1)"
323+ set_workers $workers
324+ fi
325+ echo "$workers"
326+}
327+
328+set_workers()
329+{
330+ snapctl set workers="$1"
331+}
332diff --git a/src/turku-api/bin/turku-admin b/src/turku-api/bin/turku-admin
333new file mode 100755
334index 0000000..19da088
335--- /dev/null
336+++ b/src/turku-api/bin/turku-admin
337@@ -0,0 +1,8 @@
338+#!/bin/sh
339+
340+set -eu
341+
342+export PYTHONPATH="$SNAP_DATA/turku-api"
343+export DJANGO_SETTINGS_MODULE=turku_api.settings
344+
345+"$SNAP/bin/django-admin" "${@}"
346diff --git a/src/turku-api/config/local_settings.py b/src/turku-api/config/local_settings.py
347new file mode 100644
348index 0000000..84b9a63
349--- /dev/null
350+++ b/src/turku-api/config/local_settings.py
351@@ -0,0 +1,5 @@
352+import os
353+
354+BASE_DIR = os.path.dirname(os.path.dirname(__file__))
355+
356+STATIC_ROOT = os.path.join(BASE_DIR, "static")

Subscribers

People subscribed via source and target branches

to all changes: