Merge lp:~verterok/charms/trusty/telegraf/apache-support into lp:~ubuntuone-hackers/charms/trusty/telegraf/trunk

Proposed by Guillermo Gonzalez
Status: Merged
Merged at revision: 23
Proposed branch: lp:~verterok/charms/trusty/telegraf/apache-support
Merge into: lp:~ubuntuone-hackers/charms/trusty/telegraf/trunk
Diff against target: 303 lines (+132/-31)
6 files modified
README.md (+8/-2)
hooks/actions.py (+36/-5)
hooks/services.py (+1/-0)
hooks/tests/test_actions.py (+68/-24)
metadata.yaml (+3/-0)
templates/apache-server-status.tmpl (+16/-0)
To merge this branch: bzr merge lp:~verterok/charms/trusty/telegraf/apache-support
Reviewer Review Type Date Requested Status
Bret Barker (community) Approve
Review via email: mp+292658@code.launchpad.net

Commit message

Add apache input support via relation

Description of the change

Add apache input support via relation

To post a comment you must log in.
Revision history for this message
Bret Barker (noise) wrote :

+1

Discussed having a good way to know if mod status isn't disabled and thus not going to get apache metrics.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'README.md'
2--- README.md 2016-04-01 14:10:11 +0000
3+++ README.md 2016-04-22 15:53:25 +0000
4@@ -22,8 +22,6 @@
5
6 By default there is no output plugin configured, but a basic set of input plugins are setup, which can be overriden with inputs_config charm config.
7
8-The only output plugin supported via relation is influxdb, any other output plugin needs to be configured manually (via juju set)
9-
10 To configure any of the (default or via relation) plugins, the extra_options charm config can be used. It's string in yaml format, for example:
11
12 inputs:
13@@ -46,6 +44,14 @@
14
15 This extra options will only be applied to plugins defined in templates/base_inputs.conf and any other plugins configured via relations.
16
17+## Apache input
18+
19+For the apache input plugin, the charm provides the apache relation which uses apache-website interface. Current apache charm disables mod_status and in order to telegraf apache input to work 'status' should be removed from the list of disable_modules in the apache charm config.
20+
21+## Output
22+
23+The only output plugin supported via relation is influxdb, any other output plugin needs to be configured manually (via juju set)
24+
25 To use a different metrics storage, e.g: graphite. the plugin configuration needs to be set as a base64 string in outputs_config configuration.
26
27 For exmaple, save the following config to a file:
28
29=== modified file 'hooks/actions.py'
30--- hooks/actions.py 2016-04-18 16:08:00 +0000
31+++ hooks/actions.py 2016-04-22 15:53:25 +0000
32@@ -170,7 +170,7 @@
33 return json_vals
34
35
36-def render_extra_options(kind, name):
37+def render_extra_options(kind, name, extra_options=None):
38 template = """
39 {% if extra_options %}
40 {% for key, value in extra_options.items() %}
41@@ -188,7 +188,8 @@
42 {% endfor %}
43 {% endif %}
44 """
45- extra_options = get_extra_options()
46+ if extra_options is None:
47+ extra_options = get_extra_options()
48 context = {"extra_options": extra_options[kind].get(name, {}),
49 "kind": kind,
50 "name": name}
51@@ -243,7 +244,6 @@
52 addresses.append(address)
53 config_path = '{}/{}.conf'.format(CONFIG_DIR, 'memcached')
54 if addresses:
55- extra_options = get_extra_options()
56 context = {"servers": json.dumps(addresses)}
57 inputs.append(render_template(template, context) + \
58 render_extra_options("inputs", "memcached"))
59@@ -271,7 +271,6 @@
60 mongo_addresses.append(mongo_address)
61 config_path = '{}/{}.conf'.format(CONFIG_DIR, 'mongodb')
62 if mongo_addresses:
63- extra_options = get_extra_options()
64 context = {"servers": json.dumps(mongo_addresses)}
65 inputs.append(render_template(template, context) + \
66 render_extra_options("inputs", "mongodb"))
67@@ -288,7 +287,6 @@
68 """
69 required_keys = ['host', 'user', 'password', 'database']
70 rels = hookenv.relations_of_type('postgresql')
71- extra_options = get_extra_options()
72 inputs = []
73 for rel in rels:
74 if all([rel.get(key) for key in required_keys]) \
75@@ -342,6 +340,39 @@
76 os.unlink(config_path)
77
78
79+def apache_input(service_name):
80+ template = """
81+[[inputs.apache]]
82+ urls = {{ urls }}
83+"""
84+ config_path = '{}/{}.conf'.format(CONFIG_DIR, 'apache')
85+ port = '8080'
86+ vhost = render(source='apache-server-status.tmpl',
87+ target=None,
88+ context={'port': port})
89+ relation_info = {"ports": port,
90+ "domain": "apache-status",
91+ "enabled": True,
92+ "site_config": vhost,
93+ "site_modules": "status"}
94+ urls = []
95+ rels = hookenv.relations_of_type('apache')
96+ for rel in rels:
97+ hookenv.relation_set(rel['__relid__'], relation_settings=relation_info)
98+ addr = rel['private-address']
99+ url = 'http://{}:{}/server-status?auto'.format(addr, port)
100+ urls.append(url)
101+ inputs = []
102+ if urls:
103+ context = {"urls": json.dumps(urls)}
104+ inputs.append(render_template(template, context) + \
105+ render_extra_options("inputs", "apache"))
106+ hookenv.log("Updating {} plugin config file".format('apache'))
107+ host.write_file(config_path, '\n'.join(inputs))
108+ elif os.path.exists(config_path):
109+ os.unlink(config_path)
110+
111+
112 def influxdb_api_output(service_name):
113 required_keys = ['hostname', 'port', 'user', 'password']
114 rels = hookenv.relations_of_type('influxdb-api')
115
116=== added symlink 'hooks/apache-relation-joined'
117=== target is u'hooks.py'
118=== modified file 'hooks/services.py'
119--- hooks/services.py 2016-04-05 14:07:17 +0000
120+++ hooks/services.py 2016-04-22 15:53:25 +0000
121@@ -22,6 +22,7 @@
122 actions.memcached_input,
123 actions.postgresql_input,
124 actions.haproxy_input,
125+ actions.apache_input,
126 actions.influxdb_api_output,
127 actions.log_start,
128 ],
129
130=== modified file 'hooks/tests/test_actions.py'
131--- hooks/tests/test_actions.py 2016-04-06 00:25:14 +0000
132+++ hooks/tests/test_actions.py 2016-04-22 15:53:25 +0000
133@@ -1,6 +1,7 @@
134 """actions.py tests"""
135 import os
136 import getpass
137+import json
138
139 from functools import partial
140
141@@ -15,8 +16,28 @@
142 monkeypatch.setattr(actions.hookenv, 'charm_dir', lambda: charm_dir)
143 return charm_dir
144
145-
146-def test_render_extra_options(monkeypatch):
147+@pytest.fixture()
148+def config_dir(monkeypatch, tmpdir):
149+ p = tmpdir.mkdir("configs")
150+ monkeypatch.setattr(actions, 'CONFIG_DIR', p.strpath)
151+ return p
152+
153+
154+@pytest.fixture()
155+def host_write(monkeypatch):
156+ user = getpass.getuser()
157+ partial_write_file = partial(actions.host.write_file, owner=user, group=user)
158+ monkeypatch.setattr(actions.host, 'write_file', partial_write_file)
159+
160+
161+@pytest.fixture()
162+def config(monkeypatch):
163+ config = {'extra_options': ''}
164+ monkeypatch.setattr(actions.hookenv, 'config', lambda: config)
165+ return config
166+
167+
168+def test_render_extra_options(monkeypatch, config):
169 extra_options = """
170 inputs:
171 test:
172@@ -24,14 +45,29 @@
173 string: 10s
174 list: ["a", "b"]
175 """
176- config = {'extra_options': extra_options}
177- monkeypatch.setattr(actions.hookenv, 'config', lambda: config)
178+ config['extra_options'] = extra_options
179 content = actions.render_extra_options('inputs', 'test')
180 expected = """ boolean = true\n list = ["a", "b"]\n string = "10s"\n"""
181 assert sorted(content.split()) == sorted(expected.split())
182
183
184-def test_render_base_inputs(monkeypatch, charm_dir):
185+def test_render_extra_options_override(monkeypatch, config):
186+ extra_options = """
187+ inputs:
188+ test:
189+ boolean: true
190+ string: 10s
191+ list: ["a", "b"]
192+"""
193+ config['extra_options'] = extra_options
194+ # clone extra_options and use a modified version
195+ options = {'inputs': {'test': {'string': json.dumps("20s")}}}
196+ content = actions.render_extra_options('inputs', 'test', extra_options=options)
197+ expected = """ string = "20s"\n"""
198+ assert sorted(content.split()) == sorted(expected.split())
199+
200+
201+def test_render_base_inputs(monkeypatch, charm_dir, config):
202 base_inputs_opts = """
203 inputs:
204 cpu:
205@@ -41,8 +77,7 @@
206 tagpass:
207 cpu: ["cpu0"]
208 """
209- config = {'extra_options': base_inputs_opts}
210- monkeypatch.setattr(actions.hookenv, 'config', lambda: config)
211+ config['extra_options'] = base_inputs_opts
212 content = actions.render_base_inputs()
213 expected = """
214 # Read metrics about cpu usage
215@@ -56,27 +91,36 @@
216 assert content[:len(expected)] == expected
217
218
219-def test_memcached_input(monkeypatch, charm_dir, tmpdir):
220+def test_memcached_input(monkeypatch, charm_dir, config_dir, host_write, config):
221 relations = [{'host': '1.2.3.4', 'port': 1234}]
222 monkeypatch.setattr(actions.hookenv, 'relations_of_type', lambda n: relations)
223- p = tmpdir.mkdir("configs")
224- monkeypatch.setattr(actions, 'CONFIG_DIR', p.strpath)
225- config = {'extra_options': ''}
226- monkeypatch.setattr(actions.hookenv, 'config', lambda: config)
227- user = getpass.getuser()
228- partial_write_file = partial(actions.host.write_file, owner=user, group=user)
229- monkeypatch.setattr(actions.host, 'write_file', partial_write_file)
230 actions.memcached_input('test')
231 expected = """
232 [[inputs.memcached]]
233 servers = ["1.2.3.4:1234"]
234 """
235- assert p.join('memcached.conf').read().strip() == expected.strip()
236-
237-def test_memcached_input_no_relations(monkeypatch, charm_dir, tmpdir):
238- relations = []
239- monkeypatch.setattr(actions.hookenv, 'relations_of_type', lambda n: relations)
240- p = tmpdir.mkdir("configs")
241- monkeypatch.setattr(actions, 'CONFIG_DIR', p.strpath)
242- actions.memcached_input('test')
243- assert not p.join('memcached.conf').exists()
244+ assert config_dir.join('memcached.conf').read().strip() == expected.strip()
245+
246+def test_memcached_input_no_relations(monkeypatch, charm_dir, config_dir):
247+ relations = []
248+ monkeypatch.setattr(actions.hookenv, 'relations_of_type', lambda n: relations)
249+ actions.memcached_input('test')
250+ assert not config_dir.join('memcached.conf').exists()
251+
252+
253+def test_apache_input(monkeypatch, charm_dir, config_dir, host_write, config):
254+ relations = [{'__relid__': 'apache:0', 'private-address': '1.2.3.4'}]
255+ monkeypatch.setattr(actions.hookenv, 'relations_of_type', lambda n: relations)
256+ monkeypatch.setattr(actions.hookenv, 'relation_set', lambda *a, **kw: None)
257+ actions.apache_input('test')
258+ expected = """
259+[[inputs.apache]]
260+ urls = ["http://1.2.3.4:8080/server-status?auto"]
261+"""
262+ assert config_dir.join('apache.conf').read().strip() == expected.strip()
263+
264+def test_apache_input_no_relations(monkeypatch, charm_dir, config_dir):
265+ relations = []
266+ monkeypatch.setattr(actions.hookenv, 'relations_of_type', lambda n: relations)
267+ actions.memcached_input('test')
268+ assert not config_dir.join('apache.conf').exists()
269
270=== modified file 'metadata.yaml'
271--- metadata.yaml 2016-04-05 20:28:25 +0000
272+++ metadata.yaml 2016-04-22 15:53:25 +0000
273@@ -28,6 +28,9 @@
274 haproxy:
275 interface: statistics
276 scope: container
277+ apache:
278+ interface: apache-website
279+ scope: container
280 influxdb-api:
281 interface: influxdb-api
282 juju-info:
283
284=== added file 'templates/apache-server-status.tmpl'
285--- templates/apache-server-status.tmpl 1970-01-01 00:00:00 +0000
286+++ templates/apache-server-status.tmpl 2016-04-22 15:53:25 +0000
287@@ -0,0 +1,16 @@
288+<VirtualHost 127.0.0.1:8080>
289+ ServerName 127.0.0.1
290+ ServerAdmin webmaster@localhost
291+ DocumentRoot /var/www/html
292+ LogLevel info
293+ ErrorLog ${APACHE_LOG_DIR}/server-status-error.log
294+ CustomLog ${APACHE_LOG_DIR}/server-status-access.log combined
295+
296+ <Location /server-status>
297+ SetHandler server-status
298+ Order deny,allow
299+ Deny from all
300+ Allow from localhost
301+ </Location>
302+</VirtualHost>
303+

Subscribers

People subscribed via source and target branches