Merge ~xavpaice/charm-openstack-service-checks/+git/charm-openstack-service-checks:ssl-nagios-checks into ~canonical-bootstack/charm-openstack-service-checks:master

Proposed by Xav Paice
Status: Merged
Approved by: Xav Paice
Approved revision: 9b2192b8e8320f255264d7558c1544eabe8734a0
Merged at revision: 7895a97e4ee052c44971576a691e4ce23d6969f2
Proposed branch: ~xavpaice/charm-openstack-service-checks/+git/charm-openstack-service-checks:ssl-nagios-checks
Merge into: ~canonical-bootstack/charm-openstack-service-checks:master
Diff against target: 592 lines (+288/-92)
10 files modified
.gitignore (+10/-0)
Makefile (+7/-5)
README.md (+9/-5)
config.yaml (+25/-0)
files/plugins/check_nova_services.py (+7/-7)
layer.yaml (+11/-1)
reactive/service_checks.py (+173/-65)
templates/nagios.novarc (+6/-6)
test-requirements.txt (+9/-0)
tox.ini (+31/-3)
Reviewer Review Type Date Requested Status
Peter Sabaini (community) Approve
Joel Sing (community) +1 Approve
Alvaro Uria Pending
Andrea Ieri Pending
Review via email: mp+363689@code.launchpad.net

This proposal supersedes a proposal from 2019-02-25.

Commit message

Add NRPE checks for all API endpoints in the Keystone catalog

This change implements the first stage of spec https://code.launchpad.net/~xavpaice/bootstack-charm-specs/+git/bootstack-charm-specs/+ref/ssl-nagios-checks

The intent is to add an NRPE check to the openstack-services-checks unit, checking each endpoint found in the Keystone catalog using a healthcheck URL if known, otherwise the root URL found in the catalog. If the service is using TLS, then the expiry date of the certificate is also checked.

To post a comment you must log in.
Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote : Posted in a previous version of this proposal

This merge proposal is being monitored by mergebot. Change the status to Approved to merge.

Revision history for this message
Alvaro Uria (aluria) wrote : Posted in a previous version of this proposal

Please find comments inline. Other than that, I tested it in the charmlab and it looks good to me.

review: Needs Fixing
Revision history for this message
Xav Paice (xavpaice) wrote : Posted in a previous version of this proposal

Thanks for the review - couple of responses inline. Will update the actual change shortly.

Revision history for this message
Joel Sing (jsing) wrote : Posted in a previous version of this proposal

Please add an actual commit message to this merge proposal - what is this change doing and why?

Readability/standards review comments inline (mostly consistency related).

Revision history for this message
Andrea Ieri (aieri) wrote : Posted in a previous version of this proposal

A bunch of inline comments :)

review: Needs Fixing
Revision history for this message
Xav Paice (xavpaice) wrote : Posted in a previous version of this proposal

Thanks for the detailed review(s). Fresh commit coming.

Couple of inline responses.

Revision history for this message
Joel Sing (jsing) : Posted in a previous version of this proposal
Revision history for this message
Joel Sing (jsing) wrote : Posted in a previous version of this proposal

LGTM for a readability/standards review - couple of minor comments inline.

Please ensure you get a peer approval before merging.

review: Approve (+1)
Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote : Posted in a previous version of this proposal

This merge proposal is being monitored by mergebot. Change the status to Approved to merge.

Revision history for this message
Xav Paice (xavpaice) wrote : Posted in a previous version of this proposal

Review nits have been addressed, would appreciate review.

Revision history for this message
Joel Sing (jsing) wrote : Posted in a previous version of this proposal

LGTM for development standards - please see a handful of comments inline, mostly around doc strings and internal consistency.

review: Approve (+1)
Revision history for this message
Joel Sing (jsing) wrote : Posted in a previous version of this proposal

FWIW it also seems that peer review/approval is still needed.

Revision history for this message
Xav Paice (xavpaice) wrote : Posted in a previous version of this proposal

peer review would be good if someone can please.

Re the formatting nits, thanks for pointing them out. For these particular ones, I'll consider adding another commit - but I do want to avoid growing the scope any further than it already has grown due to catching formatting issues. We should do a separate PEP8 compliance commit for the rest of the code, plus another to add unit test coverage.

Revision history for this message
Peter Sabaini (peter-sabaini) wrote : Posted in a previous version of this proposal

Comments inline -- one tox.ini issue and some nitpickings

A more general suggestion would be to add some logging to the charm and the service checks to aid in troubleshooting (charm currently has little logging and service checks none). Service checks could maybe just use a syslog handler

review: Needs Fixing
Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote :

This merge proposal is being monitored by mergebot. Change the status to Approved to merge.

Revision history for this message
Xav Paice (xavpaice) wrote :

I've addressed the latest round of review comments, and squashed commits to one to keep the history a bit cleaner.

Thanks Joel for the +1 earlier, all I've done here is address the nits and squash commits.

Re logging, that's a great plan for the next commit.

Revision history for this message
Joel Sing (jsing) wrote :

> I've addressed the latest round of review comments, and squashed commits to
> one to keep the history a bit cleaner.
>
> Thanks Joel for the +1 earlier, all I've done here is address the nits and
> squash commits.

Looks like the merge proposal has been resubmitted, so I'll +1 again without further review on this basis. FWIW you can squash and force push without resubmitting, which will avoid this.

> Re logging, that's a great plan for the next commit.

Revision history for this message
Joel Sing (jsing) wrote :

Reapproving without further review.

review: Approve (+1)
Revision history for this message
Peter Sabaini (peter-sabaini) wrote :

lgtm, cheers

review: Approve
Revision history for this message
Xav Paice (xavpaice) wrote :

got +1's from two folks, marking approved. Thanks!

Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote :

Change successfully merged at revision 7895a97e4ee052c44971576a691e4ce23d6969f2

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/.gitignore b/.gitignore
2new file mode 100644
3index 0000000..dccc0dc
4--- /dev/null
5+++ b/.gitignore
6@@ -0,0 +1,10 @@
7+*~
8+/bin
9+debian/files
10+/pkg
11+*.pyc
12+__pycache__
13+*.swp
14+.tox
15+.venv
16+.idea
17diff --git a/Makefile b/Makefile
18index a1ad3a5..27eeff6 100644
19--- a/Makefile
20+++ b/Makefile
21@@ -1,6 +1,6 @@
22 #!/usr/bin/make
23
24-all: lint unit_test
25+all: lint test
26
27
28 .PHONY: clean
29@@ -10,15 +10,17 @@ clean:
30 .PHONY: apt_prereqs
31 apt_prereqs:
32 @# Need tox, but don't install the apt version unless we have to (don't want to conflict with pip)
33- @which tox >/dev/null || (sudo apt-get install -y python-pip && sudo pip install tox)
34+ @which tox >/dev/null || (sudo apt-get install -y python3-pip && sudo pip3 install tox)
35
36 .PHONY: lint
37 lint: apt_prereqs
38- @tox --notest
39- @PATH=.tox/py34/bin:.tox/py35/bin flake8 $(wildcard hooks reactive lib unit_tests tests)
40+ @tox -e pep8
41 @charm proof
42
43-.PHONY: unit_test
44+.PHONY: test
45 unit_test: apt_prereqs
46 @echo Starting tests...
47 tox
48+
49+build:
50+ charm build
51diff --git a/README.md b/README.md
52index 24a4b54..b3159af 100644
53--- a/README.md
54+++ b/README.md
55@@ -2,7 +2,7 @@
56
57 This charm provides OpenStack services checks for Nagios
58
59- # Build
60+# Build
61 The fully built charm needs the following source branch
62 * https://git.launchpad.net/~canonical-bootstack/bootstack-ops/+git/charm-openstack-services-checks
63
64@@ -29,16 +29,20 @@ Build the charm, and symlink for juju-1 compatibility
65
66 juju deploy local:xenial/openstack-services-checks
67
68-This charm supports relating to keystone, but keystone-credentials interface
69-seems to be flaky, and hard to remove-relation, so the charm works around this
70-by adding 'os-credentials' setting (see setting description hints)
71+This charm supports relating to keystone via the keystone-credentials
72+interface. If you do not wish to use this, you can supply your own credential
73+set for Openstack by adding 'os-credentials' setting (see setting description
74+hints)
75
76 juju set openstack-services-checks os-credentials=" ... "
77-
78 juju add-relation openstack-services-checks nagios
79
80 With Keystone
81
82 juju add-relation openstack-services-checks:identity-credentials keystone:identity-credentials
83
84+If your OpenStack API endpoints have a common URL for the Admin, Public and
85+Internal addresses, you should consider disabling some endpoints which would be
86+duplicated otherwise, e.g.
87
88+ juju config openstack-service-checks check_internal_urls=False check_admin_urls=False
89diff --git a/config.yaml b/config.yaml
90index e4e8783..b71208c 100644
91--- a/config.yaml
92+++ b/config.yaml
93@@ -48,3 +48,28 @@ options:
94 default: false
95 description: |
96 An option to specify whether you want Warning alerts in nagios for disabled nova-compute hosts.
97+ tls_warn_days:
98+ type: int
99+ default: 30
100+ description: |
101+ Number of days left for the TLS certificate to expire before warning.
102+ tls_crit_days:
103+ type: int
104+ default: 14
105+ description: |
106+ Number of days left for the TLS certificate to expire before alerting Critical.
107+ check_public_urls:
108+ type: boolean
109+ default: True
110+ description: |
111+ If true, create NRPE checks matching all 'public' URLs in the Keystone catalog.
112+ check_internal_urls:
113+ type: boolean
114+ default: True
115+ description: |
116+ If true, create NRPE checks matching all 'internal' URLs in the Keystone catalog.
117+ check_admin_urls:
118+ type: boolean
119+ default: True
120+ description: |
121+ If true, create NRPE checks matching all 'admin' URLs in the Keystone catalog.
122diff --git a/files/plugins/check_nova_services.py b/files/plugins/check_nova_services.py
123index 1279c6a..6498542 100755
124--- a/files/plugins/check_nova_services.py
125+++ b/files/plugins/check_nova_services.py
126@@ -43,11 +43,11 @@ def check_hosts_up(args, aggregate, hosts, services_compute):
127 local_msg.append("Host Aggregate {} has {} hosts alive".format(
128 aggregate, counts['ok']))
129 nova_status = {
130- 'agg_name': aggregate,
131- 'msg_text': ", ".join(local_msg),
132- 'critical': status_crit,
133- 'warning': status_warn,
134- }
135+ 'agg_name': aggregate,
136+ 'msg_text': ", ".join(local_msg),
137+ 'critical': status_crit,
138+ 'warning': status_warn,
139+ }
140 return nova_status
141
142
143@@ -103,8 +103,8 @@ if __name__ == '__main__':
144 command = ['/bin/bash', '-c', "source {} && env".format(args.env)]
145 proc = subprocess.Popen(command, stdout=subprocess.PIPE)
146 for line in proc.stdout:
147- (key, _, value) = line.partition("=")
148- os.environ[key] = value.rstrip()
149+ (key, _, value) = line.partition(b'=')
150+ os.environ[key.decode('utf-8')] = value.rstrip().decode('utf-8')
151 proc.communicate()
152 nova = os_client_config.session_client('compute', cloud='envvars')
153 nagios_plugin.try_check(check_nova_services, args, nova)
154diff --git a/layer.yaml b/layer.yaml
155index f364d90..72f0af5 100644
156--- a/layer.yaml
157+++ b/layer.yaml
158@@ -1,6 +1,16 @@
159 includes:
160+ - 'layer:apt'
161 - 'layer:basic'
162- - 'interface:nrpe-external-master'
163 - 'interface:keystone-credentials'
164+ - 'interface:nrpe-external-master'
165 ignore: ['.*.swp' ]
166 repo: 'lp:~canonical-bootstack/+git/charm-openstack-service-checks'
167+options:
168+ basic:
169+ use_venv: true
170+ apt:
171+ packages:
172+ - nagios-nrpe-server
173+ - python3-keystoneclient
174+ - python3-openstackclient
175+ - python-openstackclient
176diff --git a/reactive/service_checks.py b/reactive/service_checks.py
177index 8341324..02a82d3 100644
178--- a/reactive/service_checks.py
179+++ b/reactive/service_checks.py
180@@ -17,112 +17,117 @@ from charmhelpers.core import (
181 unitdata,
182 )
183
184-from charmhelpers.fetch import (
185- apt_install,
186- apt_update,
187-)
188-
189 from charmhelpers.contrib.charmsupport.nrpe import NRPE
190+from urllib.parse import urlparse
191
192 config = hookenv.config()
193-install_packages = ['nagios-nrpe-server', 'python-openstackclient']
194+NOVARC = '/var/lib/nagios/nagios.novarc'
195+PLUGINS_DIR = '/usr/local/lib/nagios/plugins/'
196
197
198 @when_not('os-service-checks.installed')
199 def install_service_checks():
200- hookenv.status_set('maintenance', 'Installing software')
201- apt_update()
202- apt_install(install_packages)
203+ # Apt package installs are handled by the apt layer
204 set_state('os-service-checks.installed')
205 remove_state('os-service-checks.configured')
206 hookenv.status_set('active', 'Ready')
207-# setup openstack user
208
209
210 @when('identity-credentials.connected')
211-def configure_keystone_username(keystone):
212+def configure_ident_username(keystone):
213 username = 'nagios'
214 keystone.request_credentials(username)
215
216
217 @when('identity-credentials.available')
218 def save_creds(keystone):
219- creds = get_creds(keystone)
220- unitdata.kv().set('keystone-relation-creds', creds)
221- remove_state('os-service-checks.configured')
222-
223-
224-def get_creds(keystone):
225-
226+ """
227+ Collect and save credentials from Keystone relation.
228+
229+ Get credentials from the Keystone relation,
230+ reformat them into something the Keystone client
231+ can use, and save them into the unitdata.
232+ """
233+ creds = {
234+ 'username': keystone.credentials_username(),
235+ 'password': keystone.credentials_password(),
236+ 'region': keystone.region(),
237+ }
238 if keystone.api_version() == '3':
239 api_url = "v3"
240 try:
241 domain = keystone.domain()
242 except AttributeError:
243 domain = 'service_domain'
244- creds = {
245- 'credentials_username': keystone.credentials_username(),
246- 'credentials_password': keystone.credentials_password(),
247- 'credentials_project': keystone.credentials_project(),
248+ # keystone relation sends info back with funny names, fix here
249+ creds.update({
250+ 'project_name': keystone.credentials_project(),
251 'auth_version': '3',
252- 'region': keystone.region(),
253- 'credentials_user_domain': domain,
254- 'credentials_project_domain': domain
255- }
256+ 'user_domain_name': domain,
257+ 'project_domain_name': domain
258+ })
259 else:
260 api_url = "v2.0"
261- creds = {
262- 'credentials_username': keystone.credentials_username(),
263- 'credentials_password': keystone.credentials_password(),
264- 'credentials_project': keystone.credentials_project(),
265- 'region': keystone.region(),
266- }
267+ creds['tenant_name'] = keystone.credentials_project()
268
269 auth_url = "%s://%s:%s/%s" % (keystone.auth_protocol(),
270 keystone.auth_host(), keystone.auth_port(),
271 api_url)
272 creds['auth_url'] = auth_url
273- return creds
274+ unitdata.kv().set('keystonecreds', creds)
275+ remove_state('os-service-checks.configured')
276
277
278-# allow user to override credentials (and the need to be related to keystone)
279+# allow user to override credentials (and the need to be related to Keystone)
280 # with 'os-credentials'
281 def get_credentials():
282- keystone_creds = config_flags_parser(config.get('os-credentials'))
283- if keystone_creds:
284- if '/v3' in keystone_creds['auth_url']:
285- creds = {
286- 'credentials_username': keystone_creds['username'],
287- 'credentials_password': keystone_creds['password'],
288- 'credentials_project': keystone_creds['credentials_project'],
289- 'region': keystone_creds['region_name'],
290- 'auth_url': keystone_creds['auth_url'],
291+ """
292+ Get credential info from either config or relation data.
293+
294+ If config 'os-credentials' is set, return that info otherwise look for for a keystonecreds relation data.
295+
296+ :return: dictionary of credential information for Keystone.
297+ """
298+ ident_creds = config_flags_parser(config.get('os-credentials'))
299+ if ident_creds:
300+ creds = {
301+ 'username': ident_creds['username'],
302+ 'password': ident_creds['password'],
303+ 'region': ident_creds['region_name'],
304+ 'auth_url': ident_creds['auth_url'],
305+ }
306+ if '/v3' in ident_creds['auth_url']:
307+ creds.update({
308+ 'project_name': ident_creds['credentials_project'],
309 'auth_version': '3',
310- 'credentials_user_domain': keystone_creds['domain'],
311- 'credentials_project_domain': keystone_creds['domain'],
312- }
313+ 'user_domain_name': ident_creds['domain'],
314+ 'project_domain_name': ident_creds['domain'],
315+ })
316 else:
317- creds = {
318- 'credentials_username': keystone_creds['username'],
319- 'credentials_password': keystone_creds['password'],
320- 'credentials_project': keystone_creds['credentials_project'],
321- 'region': keystone_creds['region_name'],
322- 'auth_url': keystone_creds['auth_url'],
323- }
324+ creds['tenant_name'] = ident_creds['credentials_project']
325 else:
326 kv = unitdata.kv()
327- creds = kv.get('keystone-relation-creds')
328+ creds = kv.get('keystonecreds')
329+ old_creds = kv.get('keystone-relation-creds')
330+ if old_creds and not creds:
331+ # This set of creds needs an update to a newer format
332+ creds['username'] = old_creds.pop('credentials_username')
333+ creds['password'] = old_creds.pop('credentials_password')
334+ creds['project_name'] = old_creds.pop('credentials_project')
335+ creds['tenant_name'] = old_creds['project_name']
336+ creds['user_domain_name'] = old_creds.pop('credentials_user_domain', None)
337+ creds['project_domain_name'] = old_creds.pop('credentials_project_domain', None)
338+ kv.set('keystonecreds', creds)
339+ kv.update(creds, 'keystonecreds')
340 return creds
341
342
343 def render_checks():
344 nrpe = NRPE()
345- plugins_dir = '/usr/local/lib/nagios/plugins/'
346- if not os.path.exists(plugins_dir):
347- os.makedirs(plugins_dir)
348+ if not os.path.exists(PLUGINS_DIR):
349+ os.makedirs(PLUGINS_DIR)
350 charm_file_dir = os.path.join(hookenv.charm_dir(), 'files')
351 charm_plugin_dir = os.path.join(charm_file_dir, 'plugins')
352-
353 host.rsync(
354 charm_plugin_dir,
355 '/usr/local/lib/nagios/',
356@@ -133,9 +138,8 @@ def render_checks():
357 crit = config.get("nova_crit")
358 skip_disabled = config.get("skip-disabled")
359 check_dns = config.get("check-dns")
360-
361- check_command = plugins_dir + 'check_nova_services.py --warn ' \
362- + str(warn) + ' --crit ' + str(crit)
363+ nova_check_command = os.path.join(PLUGINS_DIR, 'check_nova_services.py')
364+ check_command = '{} --warn {} --crit {}'.format(nova_check_command, warn, crit)
365
366 if skip_disabled:
367 check_command = check_command + ' --skip-disabled'
368@@ -146,15 +150,18 @@ def render_checks():
369
370 nrpe.add_check(shortname='neutron_agents',
371 description='Check that enabled Neutron agents are up',
372- check_cmd=plugins_dir + 'check_neutron_agents.sh')
373+ check_cmd=os.path.join(PLUGINS_DIR, 'check_neutron_agents.sh'))
374
375 if len(check_dns):
376 nrpe.add_check(shortname='dns_multi',
377 description='Check DNS names are resolvable',
378- check_cmd=plugins_dir + 'check_dns_multi.sh ' + ' '.join(check_dns.split()))
379+ check_cmd=PLUGINS_DIR + 'check_dns_multi.sh ' + ' '.join(check_dns.split()))
380 else:
381 nrpe.remove_check(shortname='dns_multi')
382
383+ endpoint_checks = create_endpoint_checks()
384+ for check in endpoint_checks:
385+ nrpe.add_check(**check)
386 nrpe.write()
387
388
389@@ -171,8 +178,8 @@ def render_config():
390 hookenv.log('render_config: No credentials yet, skipping')
391 return
392 hookenv.log('render_config: Got credentials for username={}'.format(
393- creds['credentials_username']))
394- render('nagios.novarc', '/var/lib/nagios/nagios.novarc', creds,
395+ creds['username']))
396+ render('nagios.novarc', NOVARC, creds,
397 owner='nagios', group='nagios')
398 render_checks()
399 if config.get('trusted_ssl_ca', None):
400@@ -198,3 +205,104 @@ def fix_ssl():
401 with open(cert_file, 'w') as f:
402 print(cert_content, file=f)
403 subprocess.call(["/usr/sbin/update-ca-certificates"])
404+
405+
406+def create_endpoint_checks():
407+ """
408+ Create an NRPE check for each Keystone catalog endpoint.
409+
410+ Read the Keystone catalog, and create a check for each endpoint listed.
411+ If there is a healthcheck endpoint for the API, use that URL, otherwise check
412+ the url '/'.
413+ If SSL, add a check for the cert.
414+ """
415+ # provide URLs that can be used for healthcheck for some services
416+ # This also provides a nasty hack-ish way to add switches if we need
417+ # for some services.
418+ health_check_params = {
419+ 'keystone': '/healthcheck',
420+ 's3': '/healthcheck',
421+ 'swift': '/healthcheck',
422+ 'aodh': '/ -e Unauthorized -d x-openstack-request-id',
423+ 'cinderv3': '/v3 -e Unauthorized -d x-openstack-request-id',
424+ 'cinderv2': '/v2 -e Unauthorized -d x-openstack-request-id',
425+ 'cinderv1': '/v1 -e Unauthorized -d x-openstack-request-id',
426+ 'glance': '/healthcheck',
427+ 'nova': '/healthcheck',
428+ }
429+
430+ creds = get_credentials()
431+ keystone_client = get_keystone_client(creds)
432+ endpoints = keystone_client.endpoints.list()
433+ services = [x for x in keystone_client.services.list() if x.enabled]
434+ nrpe_checks = []
435+ for endpoint in endpoints:
436+ endpoint.service_names = [x.name for x in services if x.id == endpoint.service_id]
437+ service_name = endpoint.service_names[0]
438+ endpoint.healthcheck_url = health_check_params.get(service_name, '/')
439+ if config.get('check_{}_urls'.format(endpoint.interface)):
440+ cmd_params = ['/usr/lib/nagios/plugins/check_http ']
441+ check_url = urlparse(endpoint.url)
442+ host_port = check_url.netloc.split(':')
443+ cmd_params.append('-H {} -p {}'.format(host_port[0], host_port[1]))
444+ cmd_params.append('-u {}'.format(endpoint.healthcheck_url))
445+ # if this is https, we want to add a check for cert expiry
446+ # also need to tell check_http use use TLS
447+ if check_url.scheme == 'https':
448+ cmd_params.append('-S')
449+ # Add an extra check for TLS cert expiry
450+ cert_check = ['-C {},{}'.format(
451+ config.get('tls_warn_days'),
452+ config.get('tls_crit_days'))]
453+ nrpe_checks.append({
454+ 'shortname': "{}_{}_cert".format(
455+ service_name,
456+ endpoint.interface),
457+ 'description': 'Certificate expiry check for {} {}'.format(
458+ service_name,
459+ endpoint.interface),
460+ 'check_cmd': ' '.join(cmd_params + cert_check)
461+ })
462+ # Add the actual health check for the URL
463+ nrpe_checks.append({
464+ 'shortname': "{}_{}".format(
465+ service_name,
466+ endpoint.interface),
467+ 'description': 'Endpoint url check for {} {}'.format(
468+ service_name,
469+ endpoint.interface),
470+ 'check_cmd': (' '.join(cmd_params))})
471+ return nrpe_checks
472+
473+
474+def get_keystone_client(creds):
475+ """
476+ Import the appropriate Keystone client depending on API version.
477+
478+ Use credential info to determine the Keystone API version, and make a client session object that is to be
479+ used for authenticated communication with Keystone.
480+
481+ :returns: a keystoneclient Client object
482+ """
483+ from keystoneclient import session
484+ if int(creds['auth_version']) >= 3:
485+ from keystoneclient.v3 import client
486+ from keystoneclient.auth.identity import v3
487+ auth_fields = ['auth_url', 'password', 'username', 'user_domain_name',
488+ 'project_domain_name', 'project_name']
489+ auth_creds = {}
490+ for key in auth_fields:
491+ auth_creds[key] = creds[key]
492+ auth = v3.Password(**auth_creds)
493+
494+ else:
495+ from keystoneclient.v2_0 import client
496+ from keystoneclient.auth.identity import v2
497+ auth_fields = ['auth_url', 'password', 'username', 'tenant_name']
498+ auth_creds = {}
499+ for key in auth_fields:
500+ auth_creds[key] = creds[key]
501+ auth = v2.Password(**auth_creds)
502+
503+ sess = session.Session(auth=auth)
504+ return client.Client(session=sess)
505diff --git a/templates/nagios.novarc b/templates/nagios.novarc
506index e4c7e68..27f1c2a 100644
507--- a/templates/nagios.novarc
508+++ b/templates/nagios.novarc
509@@ -1,7 +1,7 @@
510-export OS_USERNAME={{ credentials_username }}
511-export OS_TENANT_NAME={{ credentials_project }}
512-export OS_PROJECT_NAME={{ credentials_project }}
513-export OS_PASSWORD={{ credentials_password }}
514+export OS_USERNAME={{ username }}
515+export OS_TENANT_NAME={{ tenant_name }}
516+export OS_PROJECT_NAME={{ project_name }}
517+export OS_PASSWORD={{ password }}
518 export OS_REGION_NAME={{ region }}
519 export OS_AUTH_URL={{ auth_url }}
520 {%- if cacert %}
521@@ -13,6 +13,6 @@ export HOME=${SNAP_COMMON}
522 {%- if auth_version %}
523 export OS_IDENTITY_API_VERSION={{ auth_version }}
524 export OS_AUTH_VERSION={{ auth_version }}
525-export OS_USER_DOMAIN_NAME={{ credentials_user_domain }}
526-export OS_PROJECT_DOMAIN_NAME={{ credentials_project_domain }}
527+export OS_USER_DOMAIN_NAME={{ user_domain_name }}
528+export OS_PROJECT_DOMAIN_NAME={{ project_domain_name }}
529 {%- endif %}
530diff --git a/test-requirements.txt b/test-requirements.txt
531new file mode 100644
532index 0000000..77ec3f5
533--- /dev/null
534+++ b/test-requirements.txt
535@@ -0,0 +1,9 @@
536+# Lint and unit test requirements
537+flake8>=2.2.4,<=2.4.1
538+os-testr>=0.4.1
539+requests>=2.18.4
540+charms.reactive
541+mock>=1.2
542+nose>=1.3.7
543+coverage>=3.6
544+netifaces
545diff --git a/tox.ini b/tox.ini
546index 0b8b27a..f4560b5 100644
547--- a/tox.ini
548+++ b/tox.ini
549@@ -1,12 +1,40 @@
550 [tox]
551 skipsdist=True
552-envlist = py34, py35
553+envlist = pep8
554 skip_missing_interpreters = True
555
556 [testenv]
557-commands = py.test -v
558+setenv = VIRTUAL_ENV={envdir}
559+ PYTHONHASHSEED=0
560+ TERM=linux
561+ LAYER_PATH={toxinidir}/layers
562+ INTERFACE_PATH={toxinidir}/interfaces
563+ JUJU_REPOSITORY={toxinidir}/build
564+passenv = http_proxy https_proxy
565+install_command =
566+ pip install {opts} {packages}
567 deps =
568 -r{toxinidir}/requirements.txt
569
570+[testenv:build]
571+basepython = python3
572+commands =
573+ charm-build --log-level DEBUG -o {toxinidir}/build src {posargs}
574+
575+[testenv:py3]
576+basepython = python3
577+deps = -r{toxinidir}/test-requirements.txt
578+commands = ostestr {posargs}
579+
580+[testenv:pep8]
581+basepython = python3
582+deps = -r{toxinidir}/test-requirements.txt
583+commands = flake8 {posargs} --max-complexity=10 --max-line-length=120 reactive files unit_tests
584+
585+[testenv:venv]
586+basepython = python3
587+commands = {posargs}
588+
589 [flake8]
590-exclude=docs
591+# E402 ignore necessary for path append before sys module import in actions
592+ignore = E402

Subscribers

People subscribed via source and target branches