Merge ~cjwatson/launchpad:charm-launchpad-admin into launchpad:master

Proposed by Colin Watson
Status: Merged
Approved by: Colin Watson
Approved revision: 43dd651ea33c4cd88cc6c39022b21baa4ec0a86e
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~cjwatson/launchpad:charm-launchpad-admin
Merge into: launchpad:master
Diff against target: 334 lines (+255/-1)
11 files modified
charm/Makefile (+6/-1)
charm/launchpad-admin/README.md (+22/-0)
charm/launchpad-admin/charmcraft.yaml (+58/-0)
charm/launchpad-admin/layer.yaml (+21/-0)
charm/launchpad-admin/metadata.yaml (+21/-0)
charm/launchpad-admin/reactive/launchpad-admin.py (+71/-0)
charm/launchpad-admin/templates/bash_aliases.j2 (+9/-0)
charm/launchpad-admin/templates/db-admin.j2 (+10/-0)
charm/launchpad-admin/templates/db-session.j2 (+10/-0)
charm/launchpad-admin/templates/db.j2 (+10/-0)
charm/launchpad-admin/templates/launchpad-admin-lazr.conf (+17/-0)
Reviewer Review Type Date Requested Status
Guruprasad Approve
Review via email: mp+439044@code.launchpad.net

Commit message

charm: Add a simple launchpad-admin charm

Description of the change

This is useful as a way to get hold of database superuser credentials in a charmed deployment, without having to SSH into a `postgresql` unit directly.

For now this is just for interactive use, but I can think of a couple of natural future extensions: we could do with an action to initialize a new Launchpad database, and it might well make sense to use this charm as a place to run our schema upgrade machinery.

To post a comment you must log in.
Revision history for this message
Guruprasad (lgp171188) wrote :

I don't understand some of the things very well since I haven't seen them in action, but the code changes look good to me. ๐Ÿ‘๐Ÿผ

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/charm/Makefile b/charm/Makefile
2index 24ac014..1b97cdd 100644
3--- a/charm/Makefile
4+++ b/charm/Makefile
5@@ -14,7 +14,9 @@ BUILD_LABEL = $(shell git rev-parse HEAD)
6 TARBALL = $(APP_NAME).tar.gz
7 ASSET = ../build/$(BUILD_LABEL)/$(TARBALL)
8
9-CHARMS := launchpad-appserver
10+CHARMS := \
11+ launchpad-admin \
12+ launchpad-appserver
13
14 all: ## alias to build
15 all: build
16@@ -29,6 +31,9 @@ $(BUILDDIR) $(TMPDIR):
17 build: ## build all the charms
18 build: $(foreach charm,$(CHARMS),build-$(charm))
19
20+build-launchpad-admin: ## build the launchpad-admin charm
21+build-launchpad-admin: dist/$(call charm_file,launchpad-admin)
22+
23 build-launchpad-appserver: ## build the launchpad-appserver charm
24 build-launchpad-appserver: dist/$(call charm_file,launchpad-appserver)
25
26diff --git a/charm/launchpad-admin/README.md b/charm/launchpad-admin/README.md
27new file mode 100644
28index 0000000..4241d3d
29--- /dev/null
30+++ b/charm/launchpad-admin/README.md
31@@ -0,0 +1,22 @@
32+# Launchpad administrative tools
33+
34+This charm provides administrative tools for use with a Launchpad
35+deployment.
36+
37+You will need the following relations:
38+
39+ juju relate launchpad-admin:db postgresql:db
40+ juju relate launchpad-admin:db-admin postgresql:db
41+ juju relate launchpad-admin:session-db postgresql:db
42+ juju relate launchpad-admin rabbitmq-server
43+
44+This will give you an environment you can SSH into for interactive database
45+tasks.
46+
47+The `db` and `db-admin` commands give you `launchpad_main` and
48+superuser-level PostgreSQL clients respectively connected to the main
49+database, while the `db-session` command gives you a PostgreSQL client
50+connected to the session database.
51+
52+You can run `/srv/launchpad/code/bin/iharness launchpad_main` to get an
53+interactive Python harness authenticated as `launchpad_main`.
54diff --git a/charm/launchpad-admin/charmcraft.yaml b/charm/launchpad-admin/charmcraft.yaml
55new file mode 100644
56index 0000000..f831b9f
57--- /dev/null
58+++ b/charm/launchpad-admin/charmcraft.yaml
59@@ -0,0 +1,58 @@
60+type: charm
61+bases:
62+ - build-on:
63+ - name: ubuntu
64+ channel: "20.04"
65+ run-on:
66+ - name: ubuntu
67+ channel: "20.04"
68+parts:
69+ charm-wheels:
70+ source: https://git.launchpad.net/~ubuntuone-hackers/ols-charm-deps/+git/wheels
71+ source-commit: "fe523e25521254c2034eea96e2fde079034b593a"
72+ source-submodules: []
73+ source-type: git
74+ plugin: dump
75+ organize:
76+ "*": charm-wheels/
77+ prime:
78+ - "-charm-wheels"
79+ ols-layers:
80+ source: https://git.launchpad.net/ols-charm-deps
81+ source-commit: "c2faacbd6d227b2ae40ee57ab162b28691e88ca6"
82+ source-submodules: []
83+ source-type: git
84+ plugin: dump
85+ organize:
86+ "*": layers/
87+ stage:
88+ - layers
89+ prime:
90+ - "-layers"
91+ launchpad-layers:
92+ after:
93+ - ols-layers
94+ source: https://git.launchpad.net/launchpad-layers
95+ source-commit: "624df58b5b21a34f8931bba12931e1e3a37ac7b5"
96+ source-submodules: []
97+ source-type: git
98+ plugin: dump
99+ organize:
100+ launchpad-base: layers/layer/launchpad-base
101+ stage:
102+ - layers
103+ prime:
104+ - "-layers"
105+ launchpad-admin:
106+ after:
107+ - charm-wheels
108+ - launchpad-layers
109+ source: .
110+ plugin: reactive
111+ build-snaps: [charm/2.x/stable]
112+ build-packages: [libpq-dev]
113+ build-environment:
114+ - CHARM_LAYERS_DIR: $CRAFT_STAGE/layers/layer
115+ - CHARM_INTERFACES_DIR: $CRAFT_STAGE/layers/interface
116+ - PIP_NO_INDEX: "true"
117+ - PIP_FIND_LINKS: $CRAFT_STAGE/charm-wheels
118diff --git a/charm/launchpad-admin/layer.yaml b/charm/launchpad-admin/layer.yaml
119new file mode 100644
120index 0000000..352e6d4
121--- /dev/null
122+++ b/charm/launchpad-admin/layer.yaml
123@@ -0,0 +1,21 @@
124+includes:
125+ - layer:launchpad-base
126+repo: https://git.launchpad.net/launchpad
127+options:
128+ apt:
129+ packages:
130+ - postgresql-client
131+ ols:
132+ # This charm is intended mainly for interactive use, so it's more
133+ # convenient to just use the `ubuntu` user.
134+ user: ubuntu
135+ ols-pg:
136+ databases:
137+ db:
138+ name: launchpad_dev
139+ roles: launchpad_main
140+ db-admin:
141+ name: launchpad_dev
142+ session-db:
143+ name: session_dev
144+ roles: session
145diff --git a/charm/launchpad-admin/metadata.yaml b/charm/launchpad-admin/metadata.yaml
146new file mode 100644
147index 0000000..974315f
148--- /dev/null
149+++ b/charm/launchpad-admin/metadata.yaml
150@@ -0,0 +1,21 @@
151+name: launchpad-admin
152+display-name: launchpad-admin
153+summary: Launchpad administrative tools
154+maintainer: Colin Watson <cjwatson@canonical.com>
155+description: |
156+ Launchpad is an open source suite of tools that help people and teams
157+ to work together on software projects.
158+
159+ This charm provides administrative tools for use with a Launchpad
160+ deployment.
161+tags:
162+ # https://juju.is/docs/charm-metadata#heading--charm-store-fields
163+ - network
164+series:
165+ - focal
166+subordinate: false
167+requires:
168+ db-admin:
169+ interface: pgsql
170+ session-db:
171+ interface: pgsql
172diff --git a/charm/launchpad-admin/reactive/launchpad-admin.py b/charm/launchpad-admin/reactive/launchpad-admin.py
173new file mode 100644
174index 0000000..0a31116
175--- /dev/null
176+++ b/charm/launchpad-admin/reactive/launchpad-admin.py
177@@ -0,0 +1,71 @@
178+# Copyright 2023 Canonical Ltd. This software is licensed under the
179+# GNU Affero General Public License version 3 (see the file LICENSE).
180+
181+import os.path
182+
183+from charmhelpers.core import hookenv, host, templating
184+from charms.launchpad.base import (
185+ configure_lazr,
186+ get_service_config,
187+ home_dir,
188+ strip_dsn_authentication,
189+ update_pgpass,
190+)
191+from charms.reactive import set_state, when, when_not
192+from ols import base, postgres
193+from psycopg2.extensions import make_dsn, parse_dsn
194+
195+
196+def strip_password(dsn):
197+ parsed_dsn = parse_dsn(dsn)
198+ parsed_dsn.pop("password", None)
199+ return make_dsn(**parsed_dsn)
200+
201+
202+@when(
203+ "launchpad.base.configured",
204+ "db.master.available",
205+ "db-admin.master.available",
206+ "session-db.master.available",
207+)
208+@when_not("service_configured")
209+def configure(db, db_admin, session_db):
210+ config = get_service_config()
211+ db_primary, _ = postgres.get_db_uris(db)
212+ db_admin_primary, _ = postgres.get_db_uris(db_admin)
213+ session_db_primary, _ = postgres.get_db_uris(session_db)
214+ update_pgpass(db_admin_primary)
215+ update_pgpass(session_db_primary)
216+ config["db_primary"] = strip_password(db_primary)
217+ config["db_admin_primary"] = strip_password(db_admin_primary)
218+ config["db_session_primary"] = strip_password(session_db_primary)
219+ config["db_session"] = strip_dsn_authentication(session_db_primary)
220+ config["db_session_user"] = parse_dsn(session_db_primary)["user"]
221+ configure_lazr(
222+ config,
223+ "launchpad-admin-lazr.conf",
224+ "launchpad-admin/launchpad-lazr.conf",
225+ )
226+ templating.render(
227+ "bash_aliases.j2",
228+ os.path.join(home_dir(), ".bash_aliases"),
229+ config,
230+ owner=base.user(),
231+ group=base.user(),
232+ perms=0o644,
233+ )
234+ bin_dir = os.path.join(home_dir(), "bin")
235+ host.mkdir(bin_dir, owner=base.user(), group=base.user(), perms=0o755)
236+ for script in ("db", "db-admin", "db-session"):
237+ script_path = os.path.join(bin_dir, script)
238+ templating.render(
239+ f"{script}.j2",
240+ script_path,
241+ config,
242+ owner=base.user(),
243+ group=base.user(),
244+ perms=0o755,
245+ )
246+
247+ set_state("service.configured")
248+ hookenv.status_set("active", "Ready")
249diff --git a/charm/launchpad-admin/templates/bash_aliases.j2 b/charm/launchpad-admin/templates/bash_aliases.j2
250new file mode 100644
251index 0000000..b5f4133
252--- /dev/null
253+++ b/charm/launchpad-admin/templates/bash_aliases.j2
254@@ -0,0 +1,9 @@
255+# Copyright 2023 Canonical Ltd. This software is licensed under the
256+# GNU Affero General Public License version 3 (see the file LICENSE).
257+
258+# Part of the launchpad-admin Juju charm.
259+
260+# This isn't an alias, but ~/.bash_aliases is conveniently already sourced
261+# by the default ~/.bashrc.
262+export LPCONFIG=launchpad-admin
263+
264diff --git a/charm/launchpad-admin/templates/db-admin.j2 b/charm/launchpad-admin/templates/db-admin.j2
265new file mode 100644
266index 0000000..aa0f73d
267--- /dev/null
268+++ b/charm/launchpad-admin/templates/db-admin.j2
269@@ -0,0 +1,10 @@
270+#! /bin/sh
271+# Copyright 2023 Canonical Ltd. This software is licensed under the
272+# GNU Affero General Public License version 3 (see the file LICENSE).
273+
274+# Part of the launchpad-admin Juju charm.
275+
276+set -e
277+
278+psql '{{ db_admin_primary }}'
279+
280diff --git a/charm/launchpad-admin/templates/db-session.j2 b/charm/launchpad-admin/templates/db-session.j2
281new file mode 100755
282index 0000000..4d776ae
283--- /dev/null
284+++ b/charm/launchpad-admin/templates/db-session.j2
285@@ -0,0 +1,10 @@
286+#! /bin/sh
287+# Copyright 2023 Canonical Ltd. This software is licensed under the
288+# GNU Affero General Public License version 3 (see the file LICENSE).
289+
290+# Part of the launchpad-admin Juju charm.
291+
292+set -e
293+
294+psql '{{ db_session_primary }}'
295+
296diff --git a/charm/launchpad-admin/templates/db.j2 b/charm/launchpad-admin/templates/db.j2
297new file mode 100644
298index 0000000..f07f7e8
299--- /dev/null
300+++ b/charm/launchpad-admin/templates/db.j2
301@@ -0,0 +1,10 @@
302+#! /bin/sh
303+# Copyright 2023 Canonical Ltd. This software is licensed under the
304+# GNU Affero General Public License version 3 (see the file LICENSE).
305+
306+# Part of the launchpad-admin Juju charm.
307+
308+set -e
309+
310+psql '{{ db_primary }}'
311+
312diff --git a/charm/launchpad-admin/templates/launchpad-admin-lazr.conf b/charm/launchpad-admin/templates/launchpad-admin-lazr.conf
313new file mode 100644
314index 0000000..b652e52
315--- /dev/null
316+++ b/charm/launchpad-admin/templates/launchpad-admin-lazr.conf
317@@ -0,0 +1,17 @@
318+# Public configuration data. The contents of this file may be freely shared
319+# with developers if needed for debugging.
320+
321+# A schema's sections, keys, and values are automatically inherited, except
322+# for '.optional' sections. Update this config to override key values.
323+# Values are strings, except for numbers that look like ints. The tokens
324+# true, false, and none are treated as True, False, and None.
325+
326+{% from "macros.j2" import opt -%}
327+
328+[meta]
329+extends: ../launchpad-base-lazr.conf
330+
331+[launchpad_session]
332+database: {{ db_session }}
333+dbuser: {{ db_session_user }}
334+

Subscribers

People subscribed via source and target branches

to status/vote changes: