Merge ~cjwatson/launchpad-layers:payload-layer into launchpad-layers:main

Proposed by Colin Watson
Status: Merged
Merged at revision: 72b0393e9d3d34e29aaeddec5787e13ac826b277
Proposed branch: ~cjwatson/launchpad-layers:payload-layer
Merge into: launchpad-layers:main
Diff against target: 404 lines (+152/-102)
8 files modified
launchpad-base/config.yaml (+0/-11)
launchpad-base/layer.yaml (+1/-11)
launchpad-base/lib/charms/launchpad/base.py (+4/-46)
launchpad-base/reactive/launchpad-base.py (+9/-34)
launchpad-payload/config.yaml (+12/-0)
launchpad-payload/layer.yaml (+17/-0)
launchpad-payload/lib/charms/launchpad/payload.py (+66/-0)
launchpad-payload/reactive/launchpad-payload.py (+43/-0)
Reviewer Review Type Date Requested Status
Clinton Fung Approve
Guruprasad Approve
Review via email: mp+442013@code.launchpad.net

Commit message

Move part of launchpad-base into a new launchpad-payload layer

Description of the change

Some charms - at least the prospective `launchpad-assets`, which publishes CSS/JS etc. assets for use by frontends - only really need an unpacked Launchpad payload, and don't need the rest of `launchpad-base`. Extract that part into a separate layer.

To post a comment you must log in.
be89b3b... by Colin Watson

Add charms.launchpad.payload.get_service_config

This is useful in both the prospective `launchpad-assets` and
`launchpad-loggerhead` charms, so let's have it in common code for
charms that don't need database integration.

8a69d5d... by Colin Watson

Move LAZR config file handling to payload layer

It's useful for nearly any Launchpad deployment, and doesn't have
onerous dependencies.

b80ee57... by Colin Watson

Move crontab handling to payload layer

It's useful for nearly any Launchpad deployment, and doesn't have
onerous dependencies.

Revision history for this message
Guruprasad (lgp171188) wrote :

LGTM 👍🏼

review: Approve
Revision history for this message
Clinton Fung (clinton-fung) wrote :

Makes sense

review: Approve
Revision history for this message
Colin Watson (cjwatson) wrote :

Tweaked copyright years; landing.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/launchpad-base/config.yaml b/launchpad-base/config.yaml
2index 14feeca..b804392 100644
3--- a/launchpad-base/config.yaml
4+++ b/launchpad-base/config.yaml
5@@ -43,10 +43,6 @@ options:
6 type: string
7 description: URL of file used to control whether cron scripts run.
8 default: "file:cronscripts.ini"
9- cron_mailto:
10- type: string
11- description: Email address for output from cron jobs.
12- default: "error-reports@launchpad.test"
13 databases:
14 type: string
15 description: >
16@@ -274,10 +270,3 @@ options:
17 type: string
18 description: Outbound webhook request proxy URL.
19 default:
20- # layer-apt
21- install_sources:
22- default: |
23- - ppa:launchpad/ppa
24- install_keys:
25- default: |
26- - null # PPA keys securely added via Launchpad.
27diff --git a/launchpad-base/layer.yaml b/launchpad-base/layer.yaml
28index 32c0987..5abc6ac 100644
29--- a/launchpad-base/layer.yaml
30+++ b/launchpad-base/layer.yaml
31@@ -2,15 +2,5 @@ includes:
32 - layer:basic
33 - layer:ols-pg
34 - interface:rabbitmq
35-options:
36- apt:
37- packages:
38- - launchpad-dependencies
39- ols:
40- service_name: launchpad
41- config_filename: service.conf
42- user: launchpad
43- tarball_payload: true
44- symlink_switch_payload: true
45- python_bin: /usr/bin/python3
46+ - layer:launchpad-payload
47 repo: https://git.launchpad.net/launchpad-layers
48diff --git a/launchpad-base/lib/charms/launchpad/base.py b/launchpad-base/lib/charms/launchpad/base.py
49index 7768c9b..2d441de 100644
50--- a/launchpad-base/lib/charms/launchpad/base.py
51+++ b/launchpad-base/lib/charms/launchpad/base.py
52@@ -11,15 +11,14 @@ from email.utils import parseaddr
53 from urllib.parse import urlparse
54
55 from charmhelpers.core import hookenv, host, templating
56+from charms.launchpad.payload import config_file_path
57+from charms.launchpad.payload import get_service_config as get_payload_config
58+from charms.launchpad.payload import home_dir
59 from charms.reactive import endpoint_from_flag
60 from ols import base
61 from psycopg2.extensions import make_dsn, parse_dsn
62
63
64-def home_dir():
65- return os.path.join("/home", base.user())
66-
67-
68 def oopses_dir():
69 return os.path.join(base.base_dir(), "oopses")
70
71@@ -51,7 +50,6 @@ def ensure_lp_directories():
72 for dirpath in oopses_dir(), var_dir():
73 host.mkdir(dirpath, group=base.user(), perms=0o775)
74 host.mkdir(secrets_dir(), group=base.user(), perms=0o750)
75- host.mkdir(home_dir(), owner=base.user(), group=base.user(), perms=0o755)
76
77
78 def _get_first_rabbitmq_hostname(rabbitmq):
79@@ -64,17 +62,13 @@ def _get_first_rabbitmq_hostname(rabbitmq):
80
81
82 def get_service_config():
83- config = dict(hookenv.config())
84+ config = get_payload_config()
85 config.update(
86 {
87- "base_dir": base.base_dir(),
88- "code_dir": base.code_dir(),
89- "logs_dir": base.logs_dir(),
90 "oopses_dir": oopses_dir(),
91 # Used by some templates.
92 "parseaddr": parseaddr,
93 "secrets_dir": secrets_dir(),
94- "user": base.user(),
95 "var_dir": var_dir(),
96 }
97 )
98@@ -109,26 +103,6 @@ def get_service_config():
99 return config
100
101
102-def config_file_path(name, secret=False):
103- if secret:
104- config_dir = os.path.join(base.base_dir(), "secrets")
105- else:
106- config_dir = os.path.join(base.code_dir(), "production-configs")
107- return os.path.join(config_dir, name)
108-
109-
110-def configure_lazr(config, template, name, secret=False):
111- hookenv.log("Writing service configuration.")
112- templating.render(
113- template,
114- config_file_path(name, secret=secret),
115- config,
116- owner="root",
117- group=base.user(),
118- perms=0o440 if secret else 0o444,
119- )
120-
121-
122 def lazr_config_files():
123 return [
124 config_file_path("launchpad-base-lazr.conf"),
125@@ -266,19 +240,3 @@ def strip_dsn_authentication(dsn):
126 parsed_dsn = parse_dsn(dsn)
127 parsed_dsn.pop("password", None)
128 return make_dsn(**parsed_dsn)
129-
130-
131-def configure_cron(config, template):
132- hookenv.log("Writing crontab.")
133- crontab_path = os.path.join(home_dir(), "crontab")
134- templating.render(
135- template,
136- crontab_path,
137- config,
138- owner=base.user(),
139- group=base.user(),
140- perms=0o600,
141- )
142- subprocess.run(
143- ["sudo", "-H", "-u", base.user(), "crontab", crontab_path], check=True
144- )
145diff --git a/launchpad-base/reactive/launchpad-base.py b/launchpad-base/reactive/launchpad-base.py
146index adc40d7..186e7df 100644
147--- a/launchpad-base/reactive/launchpad-base.py
148+++ b/launchpad-base/reactive/launchpad-base.py
149@@ -1,18 +1,16 @@
150 # Copyright 2022 Canonical Ltd. This software is licensed under the
151 # GNU Affero General Public License version 3 (see the file LICENSE).
152
153-import subprocess
154-
155 from charmhelpers.core import hookenv
156 from charms.launchpad.base import (
157 change_shell,
158- configure_lazr,
159 configure_rsync,
160 ensure_lp_directories,
161 get_service_config,
162 strip_dsn_authentication,
163 update_pgpass,
164 )
165+from charms.launchpad.payload import configure_lazr
166 from charms.reactive import (
167 clear_flag,
168 endpoint_from_flag,
169@@ -27,18 +25,6 @@ from charms.reactive import (
170 from ols import base, postgres
171
172
173-# Monkey-patch layer:ols.
174-def create_virtualenv(wheels_dir, codedir, python_exe):
175- subprocess.run(
176- ["make", "compile", f"PYTHON={python_exe}"],
177- cwd=codedir,
178- check=True,
179- )
180-
181-
182-base.create_virtualenv = create_virtualenv
183-
184-
185 @when("rabbitmq.connected")
186 def prepare_rabbitmq():
187 rabbitmq = endpoint_from_flag("rabbitmq.connected")
188@@ -73,7 +59,11 @@ def rabbitmq_unavailable():
189 clear_flag("launchpad.rabbitmq.available")
190
191
192-@when("ols.configured", "db.master.available", "launchpad.rabbitmq.available")
193+@when(
194+ "launchpad.payload.configured",
195+ "db.master.available",
196+ "launchpad.rabbitmq.available",
197+)
198 @when_not("launchpad.base.configured")
199 def configure():
200 db = endpoint_from_flag("db.master.available")
201@@ -113,30 +103,15 @@ def configure():
202
203 @when("launchpad.base.configured")
204 @when_not_all(
205- "ols.configured", "db.master.available", "launchpad.rabbitmq.available"
206+ "launchpad.payload.configured",
207+ "db.master.available",
208+ "launchpad.rabbitmq.available",
209 )
210 def deconfigure():
211 clear_flag("launchpad.base.configured")
212 clear_flag("service.configured")
213
214
215-@hook("upgrade-charm")
216-def upgrade_charm():
217- # The ols layer takes care of removing the ols.service.installed,
218- # ols.configured, and service.configured states. Remove
219- # launchpad.base.configured as well so that we have an opportunity to
220- # rewrite base configuration files.
221- clear_flag("launchpad.base.configured")
222-
223-
224-@when("config.changed.build_label")
225-def build_label_changed():
226- clear_flag("ols.service.installed")
227- clear_flag("ols.configured")
228- clear_flag("launchpad.base.configured")
229- clear_flag("service.configured")
230-
231-
232 @when("config.changed")
233 def config_changed():
234 clear_flag("launchpad.base.configured")
235diff --git a/launchpad-payload/config.yaml b/launchpad-payload/config.yaml
236new file mode 100644
237index 0000000..bdb5437
238--- /dev/null
239+++ b/launchpad-payload/config.yaml
240@@ -0,0 +1,12 @@
241+options:
242+ cron_mailto:
243+ type: string
244+ description: Email address for output from cron jobs.
245+ default: "error-reports@launchpad.test"
246+ # layer-apt
247+ install_sources:
248+ default: |
249+ - ppa:launchpad/ppa
250+ install_keys:
251+ default: |
252+ - null # PPA keys securely added via Launchpad.
253diff --git a/launchpad-base/icon.svg b/launchpad-payload/icon.svg
254similarity index 100%
255rename from launchpad-base/icon.svg
256rename to launchpad-payload/icon.svg
257diff --git a/launchpad-payload/layer.yaml b/launchpad-payload/layer.yaml
258new file mode 100644
259index 0000000..970a981
260--- /dev/null
261+++ b/launchpad-payload/layer.yaml
262@@ -0,0 +1,17 @@
263+includes:
264+ - layer:basic
265+ - layer:ols
266+options:
267+ apt:
268+ packages:
269+ - launchpad-dependencies
270+ ols:
271+ service_name: launchpad
272+ config_filename: service.conf
273+ user: launchpad
274+ tarball_payload: true
275+ symlink_switch_payload: true
276+ python_bin: /usr/bin/python3
277+ launchpad-payload:
278+ build_target: compile
279+repo: https://git.launchpad.net/launchpad-layers
280diff --git a/launchpad-payload/lib/charms/launchpad/payload.py b/launchpad-payload/lib/charms/launchpad/payload.py
281new file mode 100644
282index 0000000..ba87457
283--- /dev/null
284+++ b/launchpad-payload/lib/charms/launchpad/payload.py
285@@ -0,0 +1,66 @@
286+# Copyright 2022-2023 Canonical Ltd. This software is licensed under the
287+# GNU Affero General Public License version 3 (see the file LICENSE).
288+
289+import os.path
290+import subprocess
291+
292+from charmhelpers.core import hookenv, host, templating
293+from ols import base
294+
295+
296+def home_dir():
297+ return os.path.join("/home", base.user())
298+
299+
300+def ensure_home_dir():
301+ host.mkdir(home_dir(), owner=base.user(), group=base.user(), perms=0o755)
302+
303+
304+def get_service_config():
305+ config = dict(hookenv.config())
306+ config.update(
307+ {
308+ "base_dir": base.base_dir(),
309+ "code_dir": base.code_dir(),
310+ "logs_dir": base.logs_dir(),
311+ "payloads_dir": base.payloads_dir(),
312+ "user": base.user(),
313+ }
314+ )
315+ return config
316+
317+
318+def config_file_path(name, secret=False):
319+ if secret:
320+ config_dir = os.path.join(base.base_dir(), "secrets")
321+ else:
322+ config_dir = os.path.join(base.code_dir(), "production-configs")
323+ return os.path.join(config_dir, name)
324+
325+
326+def configure_lazr(config, template, name, secret=False):
327+ hookenv.log("Writing service configuration.")
328+ templating.render(
329+ template,
330+ config_file_path(name, secret=secret),
331+ config,
332+ owner="root",
333+ group=base.user(),
334+ perms=0o440 if secret else 0o444,
335+ )
336+
337+
338+def configure_cron(config, template):
339+ hookenv.log("Writing crontab.")
340+ crontab_path = os.path.join(home_dir(), "crontab")
341+ templating.render(
342+ template,
343+ crontab_path,
344+ config,
345+ owner=base.user(),
346+ group=base.user(),
347+ perms=0o600,
348+ )
349+ subprocess.run(
350+ ["sudo", "-H", "-u", base.user(), "crontab", crontab_path], check=True
351+ )
352diff --git a/launchpad-payload/reactive/launchpad-payload.py b/launchpad-payload/reactive/launchpad-payload.py
353new file mode 100644
354index 0000000..0a77b45
355--- /dev/null
356+++ b/launchpad-payload/reactive/launchpad-payload.py
357@@ -0,0 +1,43 @@
358+# Copyright 2022-2023 Canonical Ltd. This software is licensed under the
359+# GNU Affero General Public License version 3 (see the file LICENSE).
360+
361+import subprocess
362+
363+from charms.launchpad.payload import ensure_home_dir
364+from charms.layer import options
365+from charms.reactive import clear_flag, set_flag, when, when_not
366+from ols import base
367+
368+
369+# Monkey-patch layer:ols.
370+def create_virtualenv(wheels_dir, codedir, python_exe):
371+ build_target = (
372+ options().get("launchpad-payload", {}).get("build_target", "compile")
373+ )
374+ subprocess.run(
375+ ["make", build_target, f"PYTHON={python_exe}"],
376+ cwd=codedir,
377+ check=True,
378+ )
379+
380+
381+base.create_virtualenv = create_virtualenv
382+
383+
384+@when("ols.configured")
385+@when_not("launchpad.payload.configured")
386+def configure():
387+ ensure_home_dir()
388+ set_flag("launchpad.payload.configured")
389+
390+
391+@when("launchpad.payload.configured")
392+@when_not("ols.configured")
393+def deconfigure():
394+ clear_flag("launchpad.payload.configured")
395+
396+
397+@when("config.changed.build_label")
398+def build_label_changed():
399+ clear_flag("ols.service.installed")
400+ clear_flag("ols.configured")
401diff --git a/launchpad-base/templates/macros.j2 b/launchpad-payload/templates/macros.j2
402similarity index 100%
403rename from launchpad-base/templates/macros.j2
404rename to launchpad-payload/templates/macros.j2

Subscribers

People subscribed via source and target branches