Merge lp:~timkuhlman/charms/trusty/grafana/grafana-update into lp:~canonical-is-sa/charms/trusty/grafana/grafana

Proposed by Tim Kuhlman
Status: Merged
Merged at revision: 5
Proposed branch: lp:~timkuhlman/charms/trusty/grafana/grafana-update
Merge into: lp:~canonical-is-sa/charms/trusty/grafana/grafana
Diff against target: 356 lines (+246/-3)
13 files modified
config.yaml (+6/-1)
hooks/relations/http/README.md (+68/-0)
hooks/relations/http/interface.yaml (+4/-0)
hooks/relations/http/provides.py (+23/-0)
hooks/relations/http/requires.py (+58/-0)
hooks/website-relation-broken (+19/-0)
hooks/website-relation-changed (+19/-0)
hooks/website-relation-departed (+19/-0)
hooks/website-relation-joined (+19/-0)
layer.yaml (+1/-0)
lib/charms/layer/basic.py (+2/-1)
metadata.yaml (+2/-0)
reactive/grafana.py (+6/-1)
To merge this branch: bzr merge lp:~timkuhlman/charms/trusty/grafana/grafana-update
Reviewer Review Type Date Requested Status
Tim Kuhlman (community) Approve
Review via email: mp+293552@code.launchpad.net

Description of the change

Charm Build of the latest layer changes, including revno 36.

To post a comment you must log in.
Revision history for this message
Tim Kuhlman (timkuhlman) wrote :

I'll merge this as it was pointed out that since the layer was approved and this is just the result of 'charm build' on that layer there isn't much to review.

Revision history for this message
Tim Kuhlman (timkuhlman) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'config.yaml'
2--- config.yaml 2016-04-27 16:21:44 +0000
3+++ config.yaml 2016-05-02 16:56:01 +0000
4@@ -55,8 +55,13 @@
5 "type": "string"
6 "description": |
7 Comma separated list of nagios servicegroups for the graphite check
8+ "port":
9+ "type": "string"
10+ "default": "3000"
11+ "description": |
12+ The port grafana will expose web services on.
13 "admin_password":
14- "default": !!null ""
15+ "default": ""
16 "type": "string"
17 "description": |
18 Grafana admin password. Default, pwgen(16) random password
19
20=== added directory 'hooks/relations/http'
21=== added file 'hooks/relations/http/README.md'
22--- hooks/relations/http/README.md 1970-01-01 00:00:00 +0000
23+++ hooks/relations/http/README.md 2016-05-02 16:56:01 +0000
24@@ -0,0 +1,68 @@
25+# Overview
26+
27+This interface layer implements the basic form of the `http` interface protocol,
28+which is used for things such as reverse-proxies, load-balanced servers, REST
29+service discovery, et cetera.
30+
31+# Usage
32+
33+## Provides
34+
35+By providing the `http` interface, your charm is providing an HTTP server that
36+can be load-balanced, reverse-proxied, used as a REST endpoint, etc.
37+
38+Your charm need only provide the port on which it is serving its content, as
39+soon as the `{relation_name}.available` state is set:
40+
41+```python
42+@when('website.available')
43+def configure_website(website):
44+ website.configure(port=hookenv.config('port'))
45+```
46+
47+## Requires
48+
49+By requiring the `http` interface, your charm is consuming one or more HTTP
50+servers, as a REST endpoint, to load-balance a set of servers, etc.
51+
52+Your charm should respond to the `{relation_name}.available` state, which
53+indicates that there is at least one HTTP server connected.
54+
55+The `services()` method returns a list of available HTTP services and their
56+associated hosts and ports.
57+
58+The return value is a list of dicts of the following form:
59+
60+```python
61+[
62+ {
63+ 'service_name': name_of_service,
64+ 'hosts': [
65+ {
66+ 'hostname': address_of_host,
67+ 'port': port_for_host,
68+ },
69+ # ...
70+ ],
71+ },
72+ # ...
73+]
74+```
75+
76+A trivial example of handling this interface would be:
77+
78+```python
79+from charms.reactive.helpers import data_changed
80+
81+@when('reverseproxy.available')
82+def update_reverse_proxy_config(reverseproxy):
83+ services = reverseproxy.services()
84+ if not data_changed('reverseproxy.services', services):
85+ return
86+ for service in services:
87+ for host in service['hosts']:
88+ hookenv.log('{} has a unit {}:{}'.format(
89+ services['service_name'],
90+ host['hostname'],
91+ host['port']))
92+```
93
94=== added file 'hooks/relations/http/__init__.py'
95=== added file 'hooks/relations/http/interface.yaml'
96--- hooks/relations/http/interface.yaml 1970-01-01 00:00:00 +0000
97+++ hooks/relations/http/interface.yaml 2016-05-02 16:56:01 +0000
98@@ -0,0 +1,4 @@
99+name: http
100+summary: Basic HTTP interface
101+version: 1
102+repo: https://git.launchpad.net/~bcsaller/charms/+source/http
103
104=== added file 'hooks/relations/http/provides.py'
105--- hooks/relations/http/provides.py 1970-01-01 00:00:00 +0000
106+++ hooks/relations/http/provides.py 2016-05-02 16:56:01 +0000
107@@ -0,0 +1,23 @@
108+from charmhelpers.core import hookenv
109+from charms.reactive import hook
110+from charms.reactive import RelationBase
111+from charms.reactive import scopes
112+
113+
114+class HttpProvides(RelationBase):
115+ scope = scopes.GLOBAL
116+
117+ @hook('{provides:http}-relation-{joined,changed}')
118+ def changed(self):
119+ self.set_state('{relation_name}.available')
120+
121+ @hook('{provides:http}-relation-{broken,departed}')
122+ def broken(self):
123+ self.remove_state('{relation_name}.available')
124+
125+ def configure(self, port):
126+ relation_info = {
127+ 'hostname': hookenv.unit_get('private-address'),
128+ 'port': port,
129+ }
130+ self.set_remote(**relation_info)
131
132=== added file 'hooks/relations/http/requires.py'
133--- hooks/relations/http/requires.py 1970-01-01 00:00:00 +0000
134+++ hooks/relations/http/requires.py 2016-05-02 16:56:01 +0000
135@@ -0,0 +1,58 @@
136+from charms.reactive import hook
137+from charms.reactive import RelationBase
138+from charms.reactive import scopes
139+
140+
141+class HttpRequires(RelationBase):
142+ scope = scopes.UNIT
143+
144+ @hook('{requires:http}-relation-{joined,changed}')
145+ def changed(self):
146+ conv = self.conversation()
147+ if conv.get_remote('port'):
148+ # this unit's conversation has a port, so
149+ # it is part of the set of available units
150+ conv.set_state('{relation_name}.available')
151+
152+ @hook('{requires:http}-relation-{departed,broken}')
153+ def broken(self):
154+ conv = self.conversation()
155+ conv.remove_state('{relation_name}.available')
156+
157+ def services(self):
158+ """
159+ Returns a list of available HTTP services and their associated hosts
160+ and ports.
161+
162+ The return value is a list of dicts of the following form::
163+
164+ [
165+ {
166+ 'service_name': name_of_service,
167+ 'hosts': [
168+ {
169+ 'hostname': address_of_host,
170+ 'port': port_for_host,
171+ },
172+ # ...
173+ ],
174+ },
175+ # ...
176+ ]
177+ """
178+ services = {}
179+ for conv in self.conversations():
180+ service_name = conv.scope.split('/')[0]
181+ service = services.setdefault(service_name, {
182+ 'service_name': service_name,
183+ 'hosts': [],
184+ })
185+ host = conv.get_remote('hostname') or \
186+ conv.get_remote('private-address')
187+ port = conv.get_remote('port')
188+ if host and port:
189+ service['hosts'].append({
190+ 'hostname': host,
191+ 'port': port,
192+ })
193+ return [s for s in services.values() if s['hosts']]
194
195=== added file 'hooks/website-relation-broken'
196--- hooks/website-relation-broken 1970-01-01 00:00:00 +0000
197+++ hooks/website-relation-broken 2016-05-02 16:56:01 +0000
198@@ -0,0 +1,19 @@
199+#!/usr/bin/env python3
200+
201+# Load modules from $CHARM_DIR/lib
202+import sys
203+sys.path.append('lib')
204+
205+from charms.layer import basic
206+basic.bootstrap_charm_deps()
207+basic.init_config_states()
208+
209+
210+# This will load and run the appropriate @hook and other decorated
211+# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
212+# and $CHARM_DIR/hooks/relations.
213+#
214+# See https://jujucharms.com/docs/stable/authors-charm-building
215+# for more information on this pattern.
216+from charms.reactive import main
217+main()
218
219=== added file 'hooks/website-relation-changed'
220--- hooks/website-relation-changed 1970-01-01 00:00:00 +0000
221+++ hooks/website-relation-changed 2016-05-02 16:56:01 +0000
222@@ -0,0 +1,19 @@
223+#!/usr/bin/env python3
224+
225+# Load modules from $CHARM_DIR/lib
226+import sys
227+sys.path.append('lib')
228+
229+from charms.layer import basic
230+basic.bootstrap_charm_deps()
231+basic.init_config_states()
232+
233+
234+# This will load and run the appropriate @hook and other decorated
235+# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
236+# and $CHARM_DIR/hooks/relations.
237+#
238+# See https://jujucharms.com/docs/stable/authors-charm-building
239+# for more information on this pattern.
240+from charms.reactive import main
241+main()
242
243=== added file 'hooks/website-relation-departed'
244--- hooks/website-relation-departed 1970-01-01 00:00:00 +0000
245+++ hooks/website-relation-departed 2016-05-02 16:56:01 +0000
246@@ -0,0 +1,19 @@
247+#!/usr/bin/env python3
248+
249+# Load modules from $CHARM_DIR/lib
250+import sys
251+sys.path.append('lib')
252+
253+from charms.layer import basic
254+basic.bootstrap_charm_deps()
255+basic.init_config_states()
256+
257+
258+# This will load and run the appropriate @hook and other decorated
259+# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
260+# and $CHARM_DIR/hooks/relations.
261+#
262+# See https://jujucharms.com/docs/stable/authors-charm-building
263+# for more information on this pattern.
264+from charms.reactive import main
265+main()
266
267=== added file 'hooks/website-relation-joined'
268--- hooks/website-relation-joined 1970-01-01 00:00:00 +0000
269+++ hooks/website-relation-joined 2016-05-02 16:56:01 +0000
270@@ -0,0 +1,19 @@
271+#!/usr/bin/env python3
272+
273+# Load modules from $CHARM_DIR/lib
274+import sys
275+sys.path.append('lib')
276+
277+from charms.layer import basic
278+basic.bootstrap_charm_deps()
279+basic.init_config_states()
280+
281+
282+# This will load and run the appropriate @hook and other decorated
283+# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
284+# and $CHARM_DIR/hooks/relations.
285+#
286+# See https://jujucharms.com/docs/stable/authors-charm-building
287+# for more information on this pattern.
288+from charms.reactive import main
289+main()
290
291=== modified file 'layer.yaml'
292--- layer.yaml 2016-04-27 15:11:18 +0000
293+++ layer.yaml 2016-05-02 16:56:01 +0000
294@@ -8,5 +8,6 @@
295 - "layer:basic"
296 - "interface:nrpe-external-master"
297 - "interface:grafana-source"
298+- "interface:http"
299 "ignore": [".*.swp"]
300 "is": "grafana"
301
302=== modified file 'lib/charms/layer/basic.py'
303--- lib/charms/layer/basic.py 2016-04-27 15:11:18 +0000
304+++ lib/charms/layer/basic.py 2016-05-02 16:56:01 +0000
305@@ -125,13 +125,14 @@
306 from charms.reactive import toggle_state
307 config = hookenv.config()
308 config_defaults = {}
309+ config_defs = {}
310 config_yaml = os.path.join(hookenv.charm_dir(), 'config.yaml')
311 if os.path.exists(config_yaml):
312 with open(config_yaml) as fp:
313 config_defs = yaml.load(fp).get('options', {})
314 config_defaults = {key: value.get('default')
315 for key, value in config_defs.items()}
316- for opt in config.keys():
317+ for opt in config_defs.keys():
318 if config.changed(opt):
319 set_state('config.changed')
320 set_state('config.changed.{}'.format(opt))
321
322=== modified file 'metadata.yaml'
323--- metadata.yaml 2016-04-27 15:11:18 +0000
324+++ metadata.yaml 2016-05-02 16:56:01 +0000
325@@ -14,4 +14,6 @@
326 "nrpe-external-master":
327 "interface": "nrpe-external-master"
328 "scope": "container"
329+ "website":
330+ "interface": "http"
331 "subordinate": !!bool "false"
332
333=== modified file 'reactive/grafana.py'
334--- reactive/grafana.py 2016-04-27 16:52:12 +0000
335+++ reactive/grafana.py 2016-05-02 16:56:01 +0000
336@@ -77,7 +77,7 @@
337 owner='root', group='grafana',
338 perms=0o640,
339 )
340- check_ports(config.get('port', '3000'))
341+ check_ports(config.get('port'))
342 set_state('grafana.start')
343 hookenv.status_set('active', 'Ready')
344
345@@ -148,6 +148,11 @@
346 pass
347
348
349+@when('website.available')
350+def configure_website(website):
351+ website.configure(port=hookenv.config('port'))
352+
353+
354 def validate_datasources():
355 """TODO: make sure datasources option is merged with
356 relation data

Subscribers

People subscribed via source and target branches

to all changes: