Merge ~cjwatson/launchpad:charm-appserver-http-interface into launchpad:master

Proposed by Colin Watson
Status: Merged
Approved by: Colin Watson
Approved revision: c9b602eb5591aab4c736ce8bee146f31cbe051cb
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~cjwatson/launchpad:charm-appserver-http-interface
Merge into: launchpad:master
Diff against target: 161 lines (+106/-0)
5 files modified
charm/launchpad-appserver/README.md (+4/-0)
charm/launchpad-appserver/config.yaml (+24/-0)
charm/launchpad-appserver/layer.yaml (+1/-0)
charm/launchpad-appserver/metadata.yaml (+3/-0)
charm/launchpad-appserver/reactive/launchpad-appserver.py (+74/-0)
Reviewer Review Type Date Requested Status
Guruprasad Approve
Review via email: mp+444283@code.launchpad.net

Commit message

charm/launchpad-appserver: Add http interface support

Description of the change

This allows relating `launchpad-appserver` to a deployment of the `haproxy` charm to have it load-balance the various workers and expose them on the ports expected by other parts of Launchpad.

The code is based on the `ols-http` layer, but I had to write custom code for it because the appserver exposes two ports with different purposes (the main application, and XML-RPC); and the current production `haproxy` configuration uses slightly different options for those two, with special error page handling for the main application.

While this doesn't result in the exact same `haproxy` configuration that we have on production, I think it's equivalent.

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

LGTM 👍

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/charm/launchpad-appserver/README.md b/charm/launchpad-appserver/README.md
2index 2222972..26a3afa 100644
3--- a/charm/launchpad-appserver/README.md
4+++ b/charm/launchpad-appserver/README.md
5@@ -9,5 +9,9 @@ You will need the following relations:
6 juju relate launchpad-appserver memcached
7 juju relate launchpad-appserver rabbitmq-server
8
9+You can also relate it to a load balancer:
10+
11+ juju relate launchpad-appserver:loadbalancer haproxy:reverseproxy
12+
13 By default the main application server runs on port 8085, and the XML-RPC
14 application server runs on port 8087.
15diff --git a/charm/launchpad-appserver/config.yaml b/charm/launchpad-appserver/config.yaml
16index f016031..2ff6762 100644
17--- a/charm/launchpad-appserver/config.yaml
18+++ b/charm/launchpad-appserver/config.yaml
19@@ -24,6 +24,30 @@ options:
20 Secret key for Git access tokens issued to Launchpad users. Any
21 random string of a reasonable size (64 characters) is ok.
22 default:
23+ haproxy_server_options:
24+ type: string
25+ description: Options to add to HAProxy "server" lines.
26+ default: check inter 5000 rise 2 fall 5 maxconn 16
27+ haproxy_service_options_main:
28+ type: string
29+ description: HAProxy options for the main port.
30+ default: |
31+ - mode http
32+ - option httplog
33+ - option httpchk HEAD /_status/ping
34+ - option http-server-close
35+ - http-check disable-on-404
36+ - balance roundrobin
37+ haproxy_service_options_xmlrpc:
38+ type: string
39+ description: HAProxy options for the XML-RPC port.
40+ default: |
41+ - mode http
42+ - option httplog
43+ - option httpchk HEAD /_status/ping
44+ - option http-server-close
45+ - http-check disable-on-404
46+ - balance roundrobin
47 internal_macaroon_secret_key:
48 type: string
49 description: >
50diff --git a/charm/launchpad-appserver/layer.yaml b/charm/launchpad-appserver/layer.yaml
51index 1401723..921b8a8 100644
52--- a/charm/launchpad-appserver/layer.yaml
53+++ b/charm/launchpad-appserver/layer.yaml
54@@ -1,6 +1,7 @@
55 includes:
56 - layer:launchpad-db
57 - layer:coordinator
58+ - interface:http
59 - interface:memcache
60 repo: https://git.launchpad.net/launchpad
61 options:
62diff --git a/charm/launchpad-appserver/metadata.yaml b/charm/launchpad-appserver/metadata.yaml
63index b56f0d6..8fcad01 100644
64--- a/charm/launchpad-appserver/metadata.yaml
65+++ b/charm/launchpad-appserver/metadata.yaml
66@@ -18,3 +18,6 @@ requires:
67 interface: pgsql
68 memcache:
69 interface: memcache
70+provides:
71+ loadbalancer:
72+ interface: http
73diff --git a/charm/launchpad-appserver/reactive/launchpad-appserver.py b/charm/launchpad-appserver/reactive/launchpad-appserver.py
74index ad4b439..1ceb82c 100644
75--- a/charm/launchpad-appserver/reactive/launchpad-appserver.py
76+++ b/charm/launchpad-appserver/reactive/launchpad-appserver.py
77@@ -5,6 +5,7 @@ import shlex
78 import subprocess
79 from multiprocessing import cpu_count
80
81+import yaml
82 from charmhelpers.core import hookenv, host, templating
83 from charms.coordinator import acquire
84 from charms.launchpad.base import configure_email, get_service_config
85@@ -206,3 +207,76 @@ def nrpe_available():
86 @when_not("nrpe-external-master.available")
87 def nrpe_unavailable():
88 clear_flag("launchpad.appserver.nrpe-external-master.published")
89+
90+
91+@when("loadbalancer.available", "service.configured")
92+@when_not("launchpad.loadbalancer.configured")
93+def configure_loadbalancer():
94+ config = hookenv.config()
95+
96+ try:
97+ service_options_main = yaml.safe_load(
98+ config["haproxy_service_options_main"]
99+ )
100+ except Exception:
101+ hookenv.log("Could not parse haproxy_service_options_main YAML")
102+ hookenv.status_set(
103+ "blocked", "Bad haproxy_service_options_main YAML configuration"
104+ )
105+ return
106+ try:
107+ service_options_xmlrpc = yaml.safe_load(
108+ config["haproxy_service_options_xmlrpc"]
109+ )
110+ except Exception:
111+ hookenv.log("Could not parse haproxy_service_options_xmlrpc YAML")
112+ hookenv.status_set(
113+ "blocked", "Bad haproxy_service_options_xmlrpc YAML configuration"
114+ )
115+ return
116+ server_options = config["haproxy_server_options"]
117+
118+ unit_name = hookenv.local_unit().replace("/", "-")
119+ unit_ip = hookenv.unit_private_ip()
120+ services = [
121+ {
122+ "service_name": "appserver-main",
123+ "service_port": config["port_main"],
124+ "service_host": "0.0.0.0",
125+ "service_options": list(service_options_main),
126+ "servers": [
127+ [
128+ f"main_{unit_name}",
129+ unit_ip,
130+ config["port_main"],
131+ server_options,
132+ ]
133+ ],
134+ },
135+ {
136+ "service_name": "appserver-xmlrpc",
137+ "service_port": config["port_xmlrpc"],
138+ "service_host": "0.0.0.0",
139+ "service_options": list(service_options_xmlrpc),
140+ "servers": [
141+ [
142+ f"xmlrpc_{unit_name}",
143+ unit_ip,
144+ config["port_xmlrpc"],
145+ server_options,
146+ ]
147+ ],
148+ },
149+ ]
150+ services_yaml = yaml.dump(services)
151+
152+ for rel in hookenv.relations_of_type("loadbalancer"):
153+ hookenv.relation_set(rel["__relid__"], services=services_yaml)
154+
155+ set_state("launchpad.loadbalancer.configured")
156+
157+
158+@when("launchpad.loadbalancer.configured")
159+@when_not_all("loadbalancer.available", "service.configured")
160+def deconfigure_loadbalancer():
161+ remove_state("launchpad.loadbalancer.configured")

Subscribers

People subscribed via source and target branches

to status/vote changes: