Merge lp:~bac/charms/trusty/openstack-dashboard/apache-slugs into lp:~yellow/charms/trusty/openstack-dashboard/dashboard-plugin

Proposed by Brad Crittenden
Status: Merged
Merged at revision: 86
Proposed branch: lp:~bac/charms/trusty/openstack-dashboard/apache-slugs
Merge into: lp:~yellow/charms/trusty/openstack-dashboard/dashboard-plugin
Diff against target: 777 lines (+356/-24)
23 files modified
Makefile (+1/-2)
actions.yaml (+2/-0)
actions/openstack_upgrade.py (+34/-0)
config.yaml (+31/-2)
hooks/charmhelpers/contrib/openstack/utils.py (+48/-0)
hooks/horizon_contexts.py (+68/-2)
hooks/horizon_hooks.py (+11/-4)
hooks/horizon_utils.py (+8/-7)
hooks/install (+20/-0)
metadata.yaml (+1/-0)
templates/default (+2/-0)
templates/default-ssl (+2/-0)
templates/essex/local_settings.py (+2/-0)
templates/folsom/local_settings.py (+2/-0)
templates/grizzly/local_settings.py (+2/-0)
templates/havana/local_settings.py (+2/-0)
templates/icehouse/local_settings.py (+8/-0)
templates/juno/local_settings.py (+8/-0)
tests/00-setup (+1/-0)
tests/tests.yaml (+1/-1)
unit_tests/test_actions_openstack_upgrade.py (+53/-0)
unit_tests/test_horizon_contexts.py (+39/-3)
unit_tests/test_horizon_hooks.py (+10/-3)
To merge this branch: bzr merge lp:~bac/charms/trusty/openstack-dashboard/apache-slugs
Reviewer Review Type Date Requested Status
Jay R. Wren (community) Approve
j.c.sackett (community) Approve
Review via email: mp+274411@code.launchpad.net

Description of the change

Allow the ability to add controls to the end http and https configurations. Useful for things like rewrite stanzas.

To post a comment you must log in.
Revision history for this message
Brad Crittenden (bac) wrote :

This branch was started based on the 'next' version of the openstack-dashboard, so it brings our up-to-date with the latest.

Revision history for this message
j.c.sackett (jcsackett) wrote :

LGTM, thanks Brad.

review: Approve
Revision history for this message
Jay R. Wren (evarlast) wrote :

LGTM.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Makefile'
2--- Makefile 2015-08-22 04:13:34 +0000
3+++ Makefile 2015-10-14 14:39:53 +0000
4@@ -9,11 +9,10 @@
5 test:
6 @# Bundletester expects unit tests here.
7 @echo Starting tests...
8- @$(PYTHON) /usr/bin/nosetests --nologcapture --with-coverage unit_tests
9+ @$(PYTHON) /usr/bin/nosetests -v --nologcapture --with-coverage unit_tests
10
11 functional_test:
12 @echo Starting Amulet tests...
13- # https://bugs.launchpad.net/amulet/+bug/1320357
14 @juju test -v -p AMULET_HTTP_PROXY,AMULET_OS_VIP --timeout 2700
15
16 bin/charm_helpers_sync.py:
17
18=== modified file 'actions.yaml'
19--- actions.yaml 2015-04-07 13:58:41 +0000
20+++ actions.yaml 2015-10-14 14:39:53 +0000
21@@ -1,2 +1,4 @@
22 git-reinstall:
23 description: Reinstall openstack-dashboard from the openstack-origin-git repositories.
24+openstack-upgrade:
25+ description: Perform openstack upgrades. Config option action-managed-upgrade must be set to True.
26
27=== added symlink 'actions/openstack-upgrade'
28=== target is u'openstack_upgrade.py'
29=== added file 'actions/openstack_upgrade.py'
30--- actions/openstack_upgrade.py 1970-01-01 00:00:00 +0000
31+++ actions/openstack_upgrade.py 2015-10-14 14:39:53 +0000
32@@ -0,0 +1,34 @@
33+#!/usr/bin/python
34+import sys
35+
36+sys.path.append('hooks/')
37+
38+from charmhelpers.contrib.openstack.utils import (
39+ do_action_openstack_upgrade,
40+)
41+
42+from horizon_utils import (
43+ do_openstack_upgrade,
44+)
45+
46+from horizon_hooks import (
47+ config_changed,
48+ CONFIGS,
49+)
50+
51+
52+def openstack_upgrade():
53+ """Upgrade packages to config-set Openstack version.
54+
55+ If the charm was installed from source we cannot upgrade it.
56+ For backwards compatibility a config flag must be set for this
57+ code to run, otherwise a full service level upgrade will fire
58+ on config-changed."""
59+
60+ if do_action_openstack_upgrade('openstack-dashboard',
61+ do_openstack_upgrade,
62+ CONFIGS):
63+ config_changed()
64+
65+if __name__ == '__main__':
66+ openstack_upgrade()
67
68=== modified file 'config.yaml'
69--- config.yaml 2015-07-10 14:18:48 +0000
70+++ config.yaml 2015-10-14 14:39:53 +0000
71@@ -153,6 +153,14 @@
72 In order for this charm to function correctly, the privacy extension
73 must be disabled and a non-temporary address must be
74 configured/available on your network interface.
75+ endpoint-type:
76+ type: string
77+ default:
78+ description: |
79+ Specifies the endpoint types to use for endpoints in the Keystone
80+ service catalog. Valid values are 'publicURL', 'internalURL',
81+ and 'adminURL'. Both the primary and secondary endpoint types can
82+ be specified by providing multiple comma delimited values.
83 nagios_context:
84 default: "juju"
85 type: string
86@@ -163,7 +171,7 @@
87 .
88 juju-postgresql-0
89 .
90- If you're running multiple environments with the same services in them
91+ If you are running multiple environments with the same services in them
92 this allows you to differentiate between them.
93 nagios_check_http_params:
94 default: "-H localhost -I 127.0.0.1 -u '/' -e 200,301,302"
95@@ -175,4 +183,25 @@
96 description: |
97 A comma-separated list of nagios servicegroups. If left empty, the
98 nagios_context will be used as the servicegroup.
99-
100+ action-managed-upgrade:
101+ type: boolean
102+ default: False
103+ description: |
104+ If True enables openstack upgrades for this charm via juju actions.
105+ You will still need to set openstack-origin to the new repository but
106+ instead of an upgrade running automatically across all units, it will
107+ wait for you to execute the openstack-upgrade action for this charm on
108+ each unit. If False it will revert to existing behavior of upgrading
109+ all units on config change.
110+ apache_http_addendum:
111+ type: string
112+ default: ''
113+ description: |
114+ Extra stanzas to be inserted into the HTTP virtual host configuration.
115+ May be used to specify rewrite rules, for example.
116+ apache_https_addendum:
117+ type: string
118+ default: ''
119+ description: |
120+ Extra stanzas to be inserted into the HTTPS virtual host configuration.
121+ May be used to specify rewrite rules, for example.
122
123=== modified file 'hooks/charmhelpers/contrib/openstack/utils.py'
124--- hooks/charmhelpers/contrib/openstack/utils.py 2015-09-04 13:59:26 +0000
125+++ hooks/charmhelpers/contrib/openstack/utils.py 2015-10-14 14:39:53 +0000
126@@ -25,6 +25,7 @@
127 import re
128
129 import six
130+import traceback
131 import yaml
132
133 from charmhelpers.contrib.network import ip
134@@ -34,6 +35,8 @@
135 )
136
137 from charmhelpers.core.hookenv import (
138+ action_fail,
139+ action_set,
140 config,
141 log as juju_log,
142 charm_dir,
143@@ -114,6 +117,7 @@
144 ('2.2.1', 'kilo'),
145 ('2.2.2', 'kilo'),
146 ('2.3.0', 'liberty'),
147+ ('2.4.0', 'liberty'),
148 ])
149
150 # >= Liberty version->codename mapping
151@@ -748,3 +752,47 @@
152 return projects[key]
153
154 return None
155+
156+
157+def do_action_openstack_upgrade(package, upgrade_callback, configs):
158+ """Perform action-managed OpenStack upgrade.
159+
160+ Upgrades packages to the configured openstack-origin version and sets
161+ the corresponding action status as a result.
162+
163+ If the charm was installed from source we cannot upgrade it.
164+ For backwards compatibility a config flag (action-managed-upgrade) must
165+ be set for this code to run, otherwise a full service level upgrade will
166+ fire on config-changed.
167+
168+ @param package: package name for determining if upgrade available
169+ @param upgrade_callback: function callback to charm's upgrade function
170+ @param configs: templating object derived from OSConfigRenderer class
171+
172+ @return: True if upgrade successful; False if upgrade failed or skipped
173+ """
174+ ret = False
175+
176+ if git_install_requested():
177+ action_set({'outcome': 'installed from source, skipped upgrade.'})
178+ else:
179+ if openstack_upgrade_available(package):
180+ if config('action-managed-upgrade'):
181+ juju_log('Upgrading OpenStack release')
182+
183+ try:
184+ upgrade_callback(configs=configs)
185+ action_set({'outcome': 'success, upgrade completed.'})
186+ ret = True
187+ except:
188+ action_set({'outcome': 'upgrade failed, see traceback.'})
189+ action_set({'traceback': traceback.format_exc()})
190+ action_fail('do_openstack_upgrade resulted in an '
191+ 'unexpected error')
192+ else:
193+ action_set({'outcome': 'action-managed-upgrade config is '
194+ 'False, skipped upgrade.'})
195+ else:
196+ action_set({'outcome': 'no upgrade available.'})
197+
198+ return ret
199
200=== added symlink 'hooks/dashboard-plugin-relation-changed'
201=== target is u'horizon_hooks.py'
202=== added symlink 'hooks/dashboard-plugin-relation-joined'
203=== target is u'horizon_hooks.py'
204=== removed symlink 'hooks/dashboard-plugin-relation-joined'
205=== target was u'horizon_hooks.py'
206=== modified file 'hooks/horizon_contexts.py'
207--- hooks/horizon_contexts.py 2015-04-09 14:56:00 +0000
208+++ hooks/horizon_contexts.py 2015-10-14 14:39:53 +0000
209@@ -6,7 +6,8 @@
210 relation_get,
211 local_unit,
212 unit_get,
213- log
214+ log,
215+ ERROR,
216 )
217 from charmhelpers.contrib.openstack.context import (
218 OSContextGenerator,
219@@ -28,6 +29,12 @@
220 from base64 import b64decode
221 import os
222
223+VALID_ENDPOINT_TYPES = {
224+ 'PUBLICURL': 'publicURL',
225+ 'INTERNALURL': 'internalURL',
226+ 'ADMINURL': 'adminURL',
227+}
228+
229
230 class HorizonHAProxyContext(HAProxyContext):
231 def __call__(self):
232@@ -69,6 +76,22 @@
233 class IdentityServiceContext(OSContextGenerator):
234 interfaces = ['identity-service']
235
236+ def normalize(self, endpoint_type):
237+ """Normalizes the endpoint type values.
238+
239+ :param endpoint_type (string): the endpoint type to normalize.
240+ :raises: Exception if the endpoint type is not valid.
241+ :return (string): the normalized form of the endpoint type.
242+ """
243+ normalized_form = VALID_ENDPOINT_TYPES.get(endpoint_type.upper(), None)
244+ if not normalized_form:
245+ msg = ('Endpoint type specified %s is not a valid'
246+ ' endpoint type' % endpoint_type)
247+ log(msg, ERROR)
248+ raise Exception(msg)
249+
250+ return normalized_form
251+
252 def __call__(self):
253 log('Generating template context for identity-service')
254 ctxt = {}
255@@ -106,6 +129,21 @@
256 avail_regions = map(lambda r: {'endpoint': r[0], 'title': r[1]},
257 regions)
258 ctxt['regions'] = sorted(avail_regions)
259+
260+ # Allow the endpoint types to be specified via a config parameter.
261+ # The config parameter accepts either:
262+ # 1. a single endpoint type to be specified, in which case the
263+ # primary endpoint is configured
264+ # 2. a list of endpoint types, in which case the primary endpoint
265+ # is taken as the first entry and the secondary endpoint is
266+ # taken as the second entry. All subsequent entries are ignored.
267+ ep_types = config('endpoint-type')
268+ if ep_types:
269+ ep_types = [self.normalize(e) for e in ep_types.split(',')]
270+ ctxt['primary_endpoint'] = ep_types[0]
271+ if len(ep_types) > 1:
272+ ctxt['secondary_endpoint'] = ep_types[1]
273+
274 return ctxt
275
276
277@@ -134,7 +172,8 @@
278 ''' Grab cert and key from configuraton for SSL config '''
279 ctxt = {
280 'http_port': 70,
281- 'https_port': 433
282+ 'https_port': 433,
283+ 'apache_http_addendum': config("apache_http_addendum"),
284 }
285 return ctxt
286
287@@ -162,6 +201,8 @@
288 ctxt = {
289 'ssl_configured': False,
290 }
291+ ctxt['apache_https_addendum'] = config("apache_https_addendum")
292+
293 return ctxt
294
295
296@@ -172,3 +213,28 @@
297 'disable_router': False if config('profile') in ['cisco'] else True
298 }
299 return ctxt
300+
301+
302+class LocalSettingsContext(OSContextGenerator):
303+ def __call__(self):
304+ ''' Additional config stanzas to be appended to local_settings.py '''
305+
306+ relations = []
307+
308+ for rid in relation_ids("plugin"):
309+ try:
310+ unit = related_units(rid)[0]
311+ except IndexError:
312+ pass
313+ else:
314+ rdata = relation_get(unit=unit, rid=rid)
315+ if set(('local-settings', 'priority')) <= set(rdata.keys()):
316+ relations.append((unit, rdata))
317+
318+ ctxt = {
319+ 'settings': [
320+ '# {0}\n{1}'.format(u, rd['local-settings'])
321+ for u, rd in sorted(relations,
322+ key=lambda r: r[1]['priority'])]
323+ }
324+ return ctxt
325
326=== modified file 'hooks/horizon_hooks.py'
327--- hooks/horizon_hooks.py 2015-09-03 19:18:51 +0000
328+++ hooks/horizon_hooks.py 2015-10-14 14:39:53 +0000
329@@ -58,7 +58,7 @@
330 CONFIGS = register_configs()
331
332
333-@hooks.hook('install')
334+@hooks.hook('install.real')
335 def install():
336 execd_preinstall()
337 configure_installation_source(config('openstack-origin'))
338@@ -106,7 +106,7 @@
339 if git_install_requested():
340 if config_value_changed('openstack-origin-git'):
341 git_install(config('openstack-origin-git'))
342- else:
343+ elif not config('action-managed-upgrade'):
344 if openstack_upgrade_available('openstack-dashboard'):
345 do_openstack_upgrade(configs=CONFIGS)
346
347@@ -247,16 +247,23 @@
348
349
350 @hooks.hook('dashboard-plugin-relation-joined')
351-def update_dashboard_plugin(rel_id=None):
352+def plugin_relation_joined(rel_id=None):
353 if git_install_requested():
354 bin_path = git_pip_venv_dir(config('openstack-origin-git'))
355 else:
356 bin_path = '/usr/bin'
357- relation_set(relation_id=rel_id,
358+ relation_set(release=os_release("openstack-dashboard"),
359+ relation_id=rel_id,
360 bin_path=bin_path,
361 openstack_dir=INSTALL_DIR)
362
363
364+@hooks.hook('dashboard-plugin-relation-changed')
365+@restart_on_change(restart_map())
366+def update_plugin_config():
367+ CONFIGS.write(LOCAL_SETTINGS)
368+
369+
370 def main():
371 try:
372 hooks.execute(sys.argv)
373
374=== modified file 'hooks/horizon_utils.py'
375--- hooks/horizon_utils.py 2015-09-03 19:18:51 +0000
376+++ hooks/horizon_utils.py 2015-10-14 14:39:53 +0000
377@@ -101,7 +101,8 @@
378 (LOCAL_SETTINGS, {
379 'hook_contexts': [horizon_contexts.HorizonContext(),
380 horizon_contexts.IdentityServiceContext(),
381- context.SyslogContext()],
382+ context.SyslogContext(),
383+ horizon_contexts.LocalSettingsContext()],
384 'services': ['apache2']
385 }),
386 (APACHE_CONF, {
387@@ -262,12 +263,12 @@
388 raise Exception("IPv6 is not supported in the charms for Ubuntu "
389 "versions less than Trusty 14.04")
390
391- # NOTE(xianghui): Need to install haproxy(1.5.3) from trusty-backports
392- # to support ipv6 address, so check is required to make sure not
393- # breaking other versions, IPv6 only support for >= Trusty
394- if ubuntu_rel == 'trusty':
395- add_source('deb http://archive.ubuntu.com/ubuntu trusty-backports'
396- ' main')
397+ # Need haproxy >= 1.5.3 for ipv6 so for Trusty if we are <= Kilo we need to
398+ # use trusty-backports otherwise we can use the UCA.
399+ os_pkg = 'openstack-dashboard'
400+ if ubuntu_rel == 'trusty' and os_release(os_pkg) < 'liberty':
401+ add_source('deb http://archive.ubuntu.com/ubuntu trusty-backports '
402+ 'main')
403 apt_update()
404 apt_install('haproxy/trusty-backports', fatal=True)
405
406
407=== modified symlink 'hooks/install' (properties changed: -x to +x)
408=== target was u'horizon_hooks.py'
409--- hooks/install 1970-01-01 00:00:00 +0000
410+++ hooks/install 2015-10-14 14:39:53 +0000
411@@ -0,0 +1,20 @@
412+#!/bin/bash
413+# Wrapper to deal with newer Ubuntu versions that don't have py2 installed
414+# by default.
415+
416+declare -a DEPS=('apt' 'netaddr' 'netifaces' 'pip' 'yaml')
417+
418+check_and_install() {
419+ pkg="${1}-${2}"
420+ if ! dpkg -s ${pkg} 2>&1 > /dev/null; then
421+ apt-get -y install ${pkg}
422+ fi
423+}
424+
425+PYTHON="python"
426+
427+for dep in ${DEPS[@]}; do
428+ check_and_install ${PYTHON} ${dep}
429+done
430+
431+exec ./hooks/install.real
432
433=== added symlink 'hooks/install.real'
434=== target is u'horizon_hooks.py'
435=== modified file 'metadata.yaml'
436--- metadata.yaml 2015-09-10 20:38:16 +0000
437+++ metadata.yaml 2015-10-14 14:39:53 +0000
438@@ -15,6 +15,7 @@
439 interface: http
440 dashboard-plugin:
441 interface: dashboard-plugin
442+ scope: container
443 requires:
444 identity-service:
445 interface: keystone
446
447=== modified file 'templates/default'
448--- templates/default 2013-07-15 16:25:46 +0000
449+++ templates/default 2015-10-14 14:39:53 +0000
450@@ -29,4 +29,6 @@
451
452 CustomLog ${APACHE_LOG_DIR}/access.log combined
453
454+{{ apache_http_addendum }}
455+
456 </VirtualHost>
457
458=== modified file 'templates/default-ssl'
459--- templates/default-ssl 2013-07-15 16:25:46 +0000
460+++ templates/default-ssl 2015-10-14 14:39:53 +0000
461@@ -46,5 +46,7 @@
462 downgrade-1.0 force-response-1.0
463 BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
464
465+{{ apache_https_addendum }}
466+
467 </VirtualHost>
468 </IfModule>
469
470=== modified file 'templates/essex/local_settings.py'
471--- templates/essex/local_settings.py 2014-02-27 10:07:57 +0000
472+++ templates/essex/local_settings.py 2015-10-14 14:39:53 +0000
473@@ -118,3 +118,5 @@
474 }
475 }
476 }
477+
478+{{ settings|join('\n\n') }}
479
480=== modified file 'templates/folsom/local_settings.py'
481--- templates/folsom/local_settings.py 2014-05-28 16:05:37 +0000
482+++ templates/folsom/local_settings.py 2015-10-14 14:39:53 +0000
483@@ -167,3 +167,5 @@
484 # offline compression by default. To enable online compression, install
485 # the node-less package and enable the following option.
486 COMPRESS_OFFLINE = {{ compress_offline }}
487+
488+{{ settings|join('\n\n') }}
489\ No newline at end of file
490
491=== modified file 'templates/grizzly/local_settings.py'
492--- templates/grizzly/local_settings.py 2014-05-28 16:05:37 +0000
493+++ templates/grizzly/local_settings.py 2015-10-14 14:39:53 +0000
494@@ -263,3 +263,5 @@
495 }
496 }
497 }
498+
499+{{ settings|join('\n\n') }}
500
501=== modified file 'templates/havana/local_settings.py'
502--- templates/havana/local_settings.py 2014-07-22 07:18:55 +0000
503+++ templates/havana/local_settings.py 2015-10-14 14:39:53 +0000
504@@ -483,3 +483,5 @@
505 # installations should have this set accordingly. For more information
506 # see https://docs.djangoproject.com/en/dev/ref/settings/.
507 ALLOWED_HOSTS = '*'
508+
509+{{ settings|join('\n\n') }}
510\ No newline at end of file
511
512=== modified file 'templates/icehouse/local_settings.py'
513--- templates/icehouse/local_settings.py 2014-12-01 23:45:41 +0000
514+++ templates/icehouse/local_settings.py 2015-10-14 14:39:53 +0000
515@@ -212,6 +212,9 @@
516 # in the Keystone service catalog. Use this setting when Horizon is running
517 # external to the OpenStack environment. The default is 'publicURL'.
518 #OPENSTACK_ENDPOINT_TYPE = "publicURL"
519+{% if primary_endpoint -%}
520+OPENSTACK_ENDPOINT_TYPE = {{ primary_endpoint }}
521+{% endif -%}
522
523 # SECONDARY_ENDPOINT_TYPE specifies the fallback endpoint type to use in the
524 # case that OPENSTACK_ENDPOINT_TYPE is not present in the endpoints
525@@ -219,6 +222,9 @@
526 # external to the OpenStack environment. The default is None. This
527 # value should differ from OPENSTACK_ENDPOINT_TYPE if used.
528 #SECONDARY_ENDPOINT_TYPE = "publicURL"
529+{% if secondary_endpoint -%}
530+SECONDARY_ENDPOINT_TYPE = {{ secondary_endpoint }}
531+{% endif -%}
532
533 # The number of objects (Swift containers/objects or images) to display
534 # on a single page before providing a paging element (a "more" link)
535@@ -514,3 +520,5 @@
536 # installations should have this set accordingly. For more information
537 # see https://docs.djangoproject.com/en/dev/ref/settings/.
538 ALLOWED_HOSTS = '*'
539+
540+{{ settings|join('\n\n') }}
541\ No newline at end of file
542
543=== modified file 'templates/juno/local_settings.py'
544--- templates/juno/local_settings.py 2014-12-01 23:45:41 +0000
545+++ templates/juno/local_settings.py 2015-10-14 14:39:53 +0000
546@@ -250,6 +250,9 @@
547 # in the Keystone service catalog. Use this setting when Horizon is running
548 # external to the OpenStack environment. The default is 'publicURL'.
549 #OPENSTACK_ENDPOINT_TYPE = "publicURL"
550+{% if primary_endpoint -%}
551+OPENSTACK_ENDPOINT_TYPE = {{ primary_endpoint }}
552+{% endif -%}
553
554 # SECONDARY_ENDPOINT_TYPE specifies the fallback endpoint type to use in the
555 # case that OPENSTACK_ENDPOINT_TYPE is not present in the endpoints
556@@ -257,6 +260,9 @@
557 # external to the OpenStack environment. The default is None. This
558 # value should differ from OPENSTACK_ENDPOINT_TYPE if used.
559 #SECONDARY_ENDPOINT_TYPE = "publicURL"
560+{% if secondary_endpoint -%}
561+SECONDARY_ENDPOINT_TYPE = {{ secondary_endpoint }}
562+{% endif -%}
563
564 # The number of objects (Swift containers/objects or images) to display
565 # on a single page before providing a paging element (a "more" link)
566@@ -619,3 +625,5 @@
567 # installations should have this set accordingly. For more information
568 # see https://docs.djangoproject.com/en/dev/ref/settings/.
569 ALLOWED_HOSTS = '*'
570+
571+{{ settings|join('\n\n') }}
572\ No newline at end of file
573
574=== modified file 'tests/00-setup'
575--- tests/00-setup 2015-08-21 18:42:43 +0000
576+++ tests/00-setup 2015-10-14 14:39:53 +0000
577@@ -5,6 +5,7 @@
578 sudo add-apt-repository --yes ppa:juju/stable
579 sudo apt-get update --yes
580 sudo apt-get install --yes amulet \
581+ distro-info-data \
582 python-cinderclient \
583 python-distro-info \
584 python-glanceclient \
585
586=== modified file 'tests/tests.yaml'
587--- tests/tests.yaml 2015-08-21 18:42:43 +0000
588+++ tests/tests.yaml 2015-10-14 14:39:53 +0000
589@@ -8,7 +8,7 @@
590 - ppa:juju/stable
591 packages:
592 - amulet
593- - python-amulet
594+ - distro-info-data
595 - python-cinderclient
596 - python-distro-info
597 - python-glanceclient
598
599=== added file 'unit_tests/test_actions_openstack_upgrade.py'
600--- unit_tests/test_actions_openstack_upgrade.py 1970-01-01 00:00:00 +0000
601+++ unit_tests/test_actions_openstack_upgrade.py 2015-10-14 14:39:53 +0000
602@@ -0,0 +1,53 @@
603+from mock import patch
604+import os
605+
606+os.environ['JUJU_UNIT_NAME'] = 'openstack-dashboard'
607+
608+with patch('horizon_utils.register_configs') as register_configs:
609+ import openstack_upgrade
610+
611+from test_utils import (
612+ CharmTestCase
613+)
614+
615+TO_PATCH = [
616+ 'do_openstack_upgrade',
617+ 'config_changed',
618+]
619+
620+
621+class TestHorizonUpgradeActions(CharmTestCase):
622+
623+ def setUp(self):
624+ super(TestHorizonUpgradeActions, self).setUp(openstack_upgrade,
625+ TO_PATCH)
626+
627+ @patch('charmhelpers.contrib.openstack.utils.config')
628+ @patch('charmhelpers.contrib.openstack.utils.action_set')
629+ @patch('charmhelpers.contrib.openstack.utils.git_install_requested')
630+ @patch('charmhelpers.contrib.openstack.utils.openstack_upgrade_available')
631+ def test_openstack_upgrade_true(self, upgrade_avail, git_requested,
632+ action_set, config):
633+ git_requested.return_value = False
634+ upgrade_avail.return_value = True
635+ config.return_value = True
636+
637+ openstack_upgrade.openstack_upgrade()
638+
639+ self.assertTrue(self.do_openstack_upgrade.called)
640+ self.assertTrue(self.config_changed.called)
641+
642+ @patch('charmhelpers.contrib.openstack.utils.config')
643+ @patch('charmhelpers.contrib.openstack.utils.action_set')
644+ @patch('charmhelpers.contrib.openstack.utils.git_install_requested')
645+ @patch('charmhelpers.contrib.openstack.utils.openstack_upgrade_available')
646+ def test_openstack_upgrade_false(self, upgrade_avail, git_requested,
647+ action_set, config):
648+ git_requested.return_value = False
649+ upgrade_avail.return_value = True
650+ config.return_value = False
651+
652+ openstack_upgrade.openstack_upgrade()
653+
654+ self.assertFalse(self.do_openstack_upgrade.called)
655+ self.assertFalse(self.config_changed.called)
656
657=== modified file 'unit_tests/test_horizon_contexts.py'
658--- unit_tests/test_horizon_contexts.py 2015-04-09 14:34:44 +0000
659+++ unit_tests/test_horizon_contexts.py 2015-10-14 14:39:53 +0000
660@@ -47,19 +47,23 @@
661 self.pwgen.return_value = "secret"
662
663 def test_Apachecontext(self):
664+ self.test_config.set('apache_http_addendum', 'RewriteEngine on')
665 self.assertEquals(horizon_contexts.ApacheContext()(),
666- {'http_port': 70, 'https_port': 433})
667+ {'http_port': 70, 'https_port': 433,
668+ 'apache_http_addendum': 'RewriteEngine on'})
669
670 @patch.object(horizon_contexts, 'get_ca_cert', lambda: None)
671 @patch('os.chmod')
672 def test_ApacheSSLContext_enabled(self, _chmod):
673 self.get_cert.return_value = ('cert', 'key')
674 self.b64decode.side_effect = ['cert', 'key']
675+ self.test_config.set('apache_https_addendum', 'RewriteEngine off')
676 with patch_open() as (_open, _file):
677 self.assertEquals(horizon_contexts.ApacheSSLContext()(),
678 {'ssl_configured': True,
679 'ssl_cert': '/etc/ssl/certs/dashboard.cert',
680- 'ssl_key': '/etc/ssl/private/dashboard.key'})
681+ 'ssl_key': '/etc/ssl/private/dashboard.key',
682+ 'apache_https_addendum': 'RewriteEngine off'})
683 _open.assert_has_calls([
684 call('/etc/ssl/certs/dashboard.cert', 'w'),
685 call('/etc/ssl/private/dashboard.key', 'w')
686@@ -75,7 +79,8 @@
687 def test_ApacheSSLContext_disabled(self):
688 self.get_cert.return_value = (None, None)
689 self.assertEquals(horizon_contexts.ApacheSSLContext()(),
690- {'ssl_configured': False})
691+ {'ssl_configured': False,
692+ 'apache_https_addendum': ''})
693
694 def test_HorizonContext_defaults(self):
695 self.assertEquals(horizon_contexts.HorizonContext()(),
696@@ -212,6 +217,22 @@
697 {'endpoint': 'http://foo:5000/v2.0',
698 'title': 'regionTwo'}]})
699
700+ def test_IdentityServiceContext_endpoint_type(self):
701+ self.test_config.set('endpoint-type', 'internalURL')
702+ self.assertEqual(horizon_contexts.IdentityServiceContext()(),
703+ {'primary_endpoint': 'internalURL'})
704+
705+ def test_IdentityServiceContext_multi_endpoint_types(self):
706+ self.test_config.set('endpoint-type', 'internalURL,publicURL')
707+ self.assertEqual(horizon_contexts.IdentityServiceContext()(),
708+ {'primary_endpoint': 'internalURL',
709+ 'secondary_endpoint': 'publicURL'})
710+
711+ def test_IdentityServiceContext_invalid_endpoint_type(self):
712+ self.test_config.set('endpoint-type', 'this_is_bad')
713+ with self.assertRaises(Exception):
714+ horizon_contexts.IdentityServiceContext()()
715+
716 def test_HorizonHAProxyContext_no_cluster(self):
717 self.relation_ids.return_value = []
718 self.local_unit.return_value = 'openstack-dashboard/0'
719@@ -251,3 +272,18 @@
720 self.test_config.set('profile', None)
721 self.assertEquals(horizon_contexts.RouterSettingContext()(),
722 {'disable_router': True, })
723+
724+ def test_LocalSettingsContext(self):
725+ self.relation_ids.return_value = ['plugin:0', 'plugin-too:0']
726+ self.related_units.side_effect = [['horizon-plugin/0'],
727+ ['horizon-plugin-too/0']]
728+ self.relation_get.side_effect = [{'priority': 99,
729+ 'local-settings': 'FOO = True'},
730+ {'priority': 60,
731+ 'local-settings': 'BAR = False'}]
732+
733+ self.assertEquals(horizon_contexts.LocalSettingsContext()(),
734+ {'settings': ['# horizon-plugin-too/0\n'
735+ 'BAR = False',
736+ '# horizon-plugin/0\n'
737+ 'FOO = True']})
738
739=== modified file 'unit_tests/test_horizon_hooks.py'
740--- unit_tests/test_horizon_hooks.py 2015-09-04 15:16:58 +0000
741+++ unit_tests/test_horizon_hooks.py 2015-10-14 14:39:53 +0000
742@@ -308,25 +308,32 @@
743 self._call_hook('website-relation-joined')
744 self.relation_set.assert_called_with(port=70, hostname='192.168.1.1')
745
746+ @patch.object(hooks, 'os_release')
747 @patch.object(hooks, 'git_install_requested')
748- def test_dashboard_config_joined_not_git(self, _git_requested):
749+ def test_dashboard_config_joined_not_git(
750+ self, _git_requested, _os_release):
751 _git_requested.return_value = False
752+ _os_release.return_value = 'vivid'
753 self._call_hook('dashboard-plugin-relation-joined')
754 self.relation_set.assert_called_with(
755+ release='vivid',
756 bin_path='/usr/bin',
757 openstack_dir='/usr/share/openstack-dashboard',
758 relation_id=None
759 )
760
761+ @patch.object(hooks, 'os_release')
762 @patch.object(hooks, 'git_pip_venv_dir')
763 @patch.object(hooks, 'git_install_requested')
764- def test_dashboard_config_joined_git(self, _git_requested,
765- _git_pip_venv_dir):
766+ def test_dashboard_config_joined_git(
767+ self, _git_requested, _git_pip_venv_dir, _os_release):
768 expected_bin_path = '/mnt/fuji/venv'
769 _git_requested.return_value = True
770 _git_pip_venv_dir.return_value = expected_bin_path
771+ _os_release.return_value = 'wily'
772 self._call_hook('dashboard-plugin-relation-joined')
773 self.relation_set.assert_called_with(
774+ release='wily',
775 bin_path=expected_bin_path,
776 openstack_dir='/usr/share/openstack-dashboard',
777 relation_id=None

Subscribers

People subscribed via source and target branches

to all changes: