Merge lp:~hopem/charms/trusty/keystone/sync-charm-helpers-get-bool-from-str into lp:~openstack-charmers-archive/charms/trusty/keystone/next

Proposed by Edward Hope-Morley
Status: Merged
Merged at revision: 119
Proposed branch: lp:~hopem/charms/trusty/keystone/sync-charm-helpers-get-bool-from-str
Merge into: lp:~openstack-charmers-archive/charms/trusty/keystone/next
Diff against target: 851 lines (+575/-41)
12 files modified
hooks/charmhelpers/contrib/openstack/amulet/deployment.py (+5/-2)
hooks/charmhelpers/contrib/python/packages.py (+2/-2)
hooks/charmhelpers/core/fstab.py (+2/-2)
hooks/charmhelpers/core/strutils.py (+42/-0)
hooks/charmhelpers/core/sysctl.py (+2/-2)
hooks/charmhelpers/core/unitdata.py (+477/-0)
hooks/charmhelpers/fetch/archiveurl.py (+10/-10)
hooks/charmhelpers/fetch/giturl.py (+1/-1)
hooks/keystone_context.py (+13/-4)
hooks/keystone_hooks.py (+6/-3)
hooks/keystone_utils.py (+10/-13)
tests/charmhelpers/contrib/openstack/amulet/deployment.py (+5/-2)
To merge this branch: bzr merge lp:~hopem/charms/trusty/keystone/sync-charm-helpers-get-bool-from-str
Reviewer Review Type Date Requested Status
Liam Young (community) Approve
Review via email: mp+249801@code.launchpad.net
To post a comment you must log in.
Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #2030 keystone-next for hopem mp249801
    LINT OK: passed

Build: http://10.245.162.77:8080/job/charm_lint_check/2030/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #1820 keystone-next for hopem mp249801
    UNIT OK: passed

Build: http://10.245.162.77:8080/job/charm_unit_test/1820/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #1968 keystone-next for hopem mp249801
    AMULET FAIL: amulet-test failed

AMULET Results (max last 2 lines):
  ERROR subprocess encountered error code 1
  make: *** [test] Error 1

Full amulet test output: http://paste.ubuntu.com/10254550/
Build: http://10.245.162.77:8080/job/charm_amulet_test/1968/

120. By Edward Hope-Morley

re-sync ch

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #2031 keystone-next for hopem mp249801
    LINT OK: passed

Build: http://10.245.162.77:8080/job/charm_lint_check/2031/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #1821 keystone-next for hopem mp249801
    UNIT OK: passed

Build: http://10.245.162.77:8080/job/charm_unit_test/1821/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #1969 keystone-next for hopem mp249801
    AMULET OK: passed

Build: http://10.245.162.77:8080/job/charm_amulet_test/1969/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #2033 keystone-next for hopem mp249801
    LINT OK: passed

Build: http://10.245.162.77:8080/job/charm_lint_check/2033/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #1823 keystone-next for hopem mp249801
    UNIT OK: passed

Build: http://10.245.162.77:8080/job/charm_unit_test/1823/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #1971 keystone-next for hopem mp249801
    AMULET OK: passed

Build: http://10.245.162.77:8080/job/charm_amulet_test/1971/

Revision history for this message
Liam Young (gnuoy) wrote :

Approve

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'hooks/charmhelpers/contrib/openstack/amulet/deployment.py'
2--- hooks/charmhelpers/contrib/openstack/amulet/deployment.py 2015-01-26 09:44:47 +0000
3+++ hooks/charmhelpers/contrib/openstack/amulet/deployment.py 2015-02-16 12:07:04 +0000
4@@ -71,16 +71,19 @@
5 services.append(this_service)
6 use_source = ['mysql', 'mongodb', 'rabbitmq-server', 'ceph',
7 'ceph-osd', 'ceph-radosgw']
8+ # Openstack subordinate charms do not expose an origin option as that
9+ # is controlled by the principle
10+ ignore = ['neutron-openvswitch']
11
12 if self.openstack:
13 for svc in services:
14- if svc['name'] not in use_source:
15+ if svc['name'] not in use_source + ignore:
16 config = {'openstack-origin': self.openstack}
17 self.d.configure(svc['name'], config)
18
19 if self.source:
20 for svc in services:
21- if svc['name'] in use_source:
22+ if svc['name'] in use_source and svc['name'] not in ignore:
23 config = {'source': self.source}
24 self.d.configure(svc['name'], config)
25
26
27=== modified file 'hooks/charmhelpers/contrib/python/packages.py'
28--- hooks/charmhelpers/contrib/python/packages.py 2015-01-26 09:44:47 +0000
29+++ hooks/charmhelpers/contrib/python/packages.py 2015-02-16 12:07:04 +0000
30@@ -17,8 +17,6 @@
31 # You should have received a copy of the GNU Lesser General Public License
32 # along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
33
34-__author__ = "Jorge Niedbalski <jorge.niedbalski@canonical.com>"
35-
36 from charmhelpers.fetch import apt_install, apt_update
37 from charmhelpers.core.hookenv import log
38
39@@ -29,6 +27,8 @@
40 apt_install('python-pip')
41 from pip import main as pip_execute
42
43+__author__ = "Jorge Niedbalski <jorge.niedbalski@canonical.com>"
44+
45
46 def parse_options(given, available):
47 """Given a set of options, check if available"""
48
49=== modified file 'hooks/charmhelpers/core/fstab.py'
50--- hooks/charmhelpers/core/fstab.py 2015-01-26 09:44:47 +0000
51+++ hooks/charmhelpers/core/fstab.py 2015-02-16 12:07:04 +0000
52@@ -17,11 +17,11 @@
53 # You should have received a copy of the GNU Lesser General Public License
54 # along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
55
56-__author__ = 'Jorge Niedbalski R. <jorge.niedbalski@canonical.com>'
57-
58 import io
59 import os
60
61+__author__ = 'Jorge Niedbalski R. <jorge.niedbalski@canonical.com>'
62+
63
64 class Fstab(io.FileIO):
65 """This class extends file in order to implement a file reader/writer
66
67=== added file 'hooks/charmhelpers/core/strutils.py'
68--- hooks/charmhelpers/core/strutils.py 1970-01-01 00:00:00 +0000
69+++ hooks/charmhelpers/core/strutils.py 2015-02-16 12:07:04 +0000
70@@ -0,0 +1,42 @@
71+#!/usr/bin/env python
72+# -*- coding: utf-8 -*-
73+
74+# Copyright 2014-2015 Canonical Limited.
75+#
76+# This file is part of charm-helpers.
77+#
78+# charm-helpers is free software: you can redistribute it and/or modify
79+# it under the terms of the GNU Lesser General Public License version 3 as
80+# published by the Free Software Foundation.
81+#
82+# charm-helpers is distributed in the hope that it will be useful,
83+# but WITHOUT ANY WARRANTY; without even the implied warranty of
84+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
85+# GNU Lesser General Public License for more details.
86+#
87+# You should have received a copy of the GNU Lesser General Public License
88+# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
89+
90+import six
91+
92+
93+def bool_from_string(value):
94+ """Interpret string value as boolean.
95+
96+ Returns True if value translates to True otherwise False.
97+ """
98+ if isinstance(value, six.string_types):
99+ value = six.text_type(value)
100+ else:
101+ msg = "Unable to interpret non-string value '%s' as boolean" % (value)
102+ raise ValueError(msg)
103+
104+ value = value.strip().lower()
105+
106+ if value in ['y', 'yes', 'true', 't']:
107+ return True
108+ elif value in ['n', 'no', 'false', 'f']:
109+ return False
110+
111+ msg = "Unable to interpret string value '%s' as boolean" % (value)
112+ raise ValueError(msg)
113
114=== modified file 'hooks/charmhelpers/core/sysctl.py'
115--- hooks/charmhelpers/core/sysctl.py 2015-02-03 12:56:40 +0000
116+++ hooks/charmhelpers/core/sysctl.py 2015-02-16 12:07:04 +0000
117@@ -17,8 +17,6 @@
118 # You should have received a copy of the GNU Lesser General Public License
119 # along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
120
121-__author__ = 'Jorge Niedbalski R. <jorge.niedbalski@canonical.com>'
122-
123 import yaml
124
125 from subprocess import check_call
126@@ -29,6 +27,8 @@
127 ERROR,
128 )
129
130+__author__ = 'Jorge Niedbalski R. <jorge.niedbalski@canonical.com>'
131+
132
133 def create(sysctl_dict, sysctl_file):
134 """Creates a sysctl.conf file from a YAML associative array
135
136=== added file 'hooks/charmhelpers/core/unitdata.py'
137--- hooks/charmhelpers/core/unitdata.py 1970-01-01 00:00:00 +0000
138+++ hooks/charmhelpers/core/unitdata.py 2015-02-16 12:07:04 +0000
139@@ -0,0 +1,477 @@
140+#!/usr/bin/env python
141+# -*- coding: utf-8 -*-
142+#
143+# Copyright 2014-2015 Canonical Limited.
144+#
145+# This file is part of charm-helpers.
146+#
147+# charm-helpers is free software: you can redistribute it and/or modify
148+# it under the terms of the GNU Lesser General Public License version 3 as
149+# published by the Free Software Foundation.
150+#
151+# charm-helpers is distributed in the hope that it will be useful,
152+# but WITHOUT ANY WARRANTY; without even the implied warranty of
153+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
154+# GNU Lesser General Public License for more details.
155+#
156+# You should have received a copy of the GNU Lesser General Public License
157+# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
158+#
159+#
160+# Authors:
161+# Kapil Thangavelu <kapil.foss@gmail.com>
162+#
163+"""
164+Intro
165+-----
166+
167+A simple way to store state in units. This provides a key value
168+storage with support for versioned, transactional operation,
169+and can calculate deltas from previous values to simplify unit logic
170+when processing changes.
171+
172+
173+Hook Integration
174+----------------
175+
176+There are several extant frameworks for hook execution, including
177+
178+ - charmhelpers.core.hookenv.Hooks
179+ - charmhelpers.core.services.ServiceManager
180+
181+The storage classes are framework agnostic, one simple integration is
182+via the HookData contextmanager. It will record the current hook
183+execution environment (including relation data, config data, etc.),
184+setup a transaction and allow easy access to the changes from
185+previously seen values. One consequence of the integration is the
186+reservation of particular keys ('rels', 'unit', 'env', 'config',
187+'charm_revisions') for their respective values.
188+
189+Here's a fully worked integration example using hookenv.Hooks::
190+
191+ from charmhelper.core import hookenv, unitdata
192+
193+ hook_data = unitdata.HookData()
194+ db = unitdata.kv()
195+ hooks = hookenv.Hooks()
196+
197+ @hooks.hook
198+ def config_changed():
199+ # Print all changes to configuration from previously seen
200+ # values.
201+ for changed, (prev, cur) in hook_data.conf.items():
202+ print('config changed', changed,
203+ 'previous value', prev,
204+ 'current value', cur)
205+
206+ # Get some unit specific bookeeping
207+ if not db.get('pkg_key'):
208+ key = urllib.urlopen('https://example.com/pkg_key').read()
209+ db.set('pkg_key', key)
210+
211+ # Directly access all charm config as a mapping.
212+ conf = db.getrange('config', True)
213+
214+ # Directly access all relation data as a mapping
215+ rels = db.getrange('rels', True)
216+
217+ if __name__ == '__main__':
218+ with hook_data():
219+ hook.execute()
220+
221+
222+A more basic integration is via the hook_scope context manager which simply
223+manages transaction scope (and records hook name, and timestamp)::
224+
225+ >>> from unitdata import kv
226+ >>> db = kv()
227+ >>> with db.hook_scope('install'):
228+ ... # do work, in transactional scope.
229+ ... db.set('x', 1)
230+ >>> db.get('x')
231+ 1
232+
233+
234+Usage
235+-----
236+
237+Values are automatically json de/serialized to preserve basic typing
238+and complex data struct capabilities (dicts, lists, ints, booleans, etc).
239+
240+Individual values can be manipulated via get/set::
241+
242+ >>> kv.set('y', True)
243+ >>> kv.get('y')
244+ True
245+
246+ # We can set complex values (dicts, lists) as a single key.
247+ >>> kv.set('config', {'a': 1, 'b': True'})
248+
249+ # Also supports returning dictionaries as a record which
250+ # provides attribute access.
251+ >>> config = kv.get('config', record=True)
252+ >>> config.b
253+ True
254+
255+
256+Groups of keys can be manipulated with update/getrange::
257+
258+ >>> kv.update({'z': 1, 'y': 2}, prefix="gui.")
259+ >>> kv.getrange('gui.', strip=True)
260+ {'z': 1, 'y': 2}
261+
262+When updating values, its very helpful to understand which values
263+have actually changed and how have they changed. The storage
264+provides a delta method to provide for this::
265+
266+ >>> data = {'debug': True, 'option': 2}
267+ >>> delta = kv.delta(data, 'config.')
268+ >>> delta.debug.previous
269+ None
270+ >>> delta.debug.current
271+ True
272+ >>> delta
273+ {'debug': (None, True), 'option': (None, 2)}
274+
275+Note the delta method does not persist the actual change, it needs to
276+be explicitly saved via 'update' method::
277+
278+ >>> kv.update(data, 'config.')
279+
280+Values modified in the context of a hook scope retain historical values
281+associated to the hookname.
282+
283+ >>> with db.hook_scope('config-changed'):
284+ ... db.set('x', 42)
285+ >>> db.gethistory('x')
286+ [(1, u'x', 1, u'install', u'2015-01-21T16:49:30.038372'),
287+ (2, u'x', 42, u'config-changed', u'2015-01-21T16:49:30.038786')]
288+
289+"""
290+
291+import collections
292+import contextlib
293+import datetime
294+import json
295+import os
296+import pprint
297+import sqlite3
298+import sys
299+
300+__author__ = 'Kapil Thangavelu <kapil.foss@gmail.com>'
301+
302+
303+class Storage(object):
304+ """Simple key value database for local unit state within charms.
305+
306+ Modifications are automatically committed at hook exit. That's
307+ currently regardless of exit code.
308+
309+ To support dicts, lists, integer, floats, and booleans values
310+ are automatically json encoded/decoded.
311+ """
312+ def __init__(self, path=None):
313+ self.db_path = path
314+ if path is None:
315+ self.db_path = os.path.join(
316+ os.environ.get('CHARM_DIR', ''), '.unit-state.db')
317+ self.conn = sqlite3.connect('%s' % self.db_path)
318+ self.cursor = self.conn.cursor()
319+ self.revision = None
320+ self._closed = False
321+ self._init()
322+
323+ def close(self):
324+ if self._closed:
325+ return
326+ self.flush(False)
327+ self.cursor.close()
328+ self.conn.close()
329+ self._closed = True
330+
331+ def _scoped_query(self, stmt, params=None):
332+ if params is None:
333+ params = []
334+ return stmt, params
335+
336+ def get(self, key, default=None, record=False):
337+ self.cursor.execute(
338+ *self._scoped_query(
339+ 'select data from kv where key=?', [key]))
340+ result = self.cursor.fetchone()
341+ if not result:
342+ return default
343+ if record:
344+ return Record(json.loads(result[0]))
345+ return json.loads(result[0])
346+
347+ def getrange(self, key_prefix, strip=False):
348+ stmt = "select key, data from kv where key like '%s%%'" % key_prefix
349+ self.cursor.execute(*self._scoped_query(stmt))
350+ result = self.cursor.fetchall()
351+
352+ if not result:
353+ return None
354+ if not strip:
355+ key_prefix = ''
356+ return dict([
357+ (k[len(key_prefix):], json.loads(v)) for k, v in result])
358+
359+ def update(self, mapping, prefix=""):
360+ for k, v in mapping.items():
361+ self.set("%s%s" % (prefix, k), v)
362+
363+ def unset(self, key):
364+ self.cursor.execute('delete from kv where key=?', [key])
365+ if self.revision and self.cursor.rowcount:
366+ self.cursor.execute(
367+ 'insert into kv_revisions values (?, ?, ?)',
368+ [key, self.revision, json.dumps('DELETED')])
369+
370+ def set(self, key, value):
371+ serialized = json.dumps(value)
372+
373+ self.cursor.execute(
374+ 'select data from kv where key=?', [key])
375+ exists = self.cursor.fetchone()
376+
377+ # Skip mutations to the same value
378+ if exists:
379+ if exists[0] == serialized:
380+ return value
381+
382+ if not exists:
383+ self.cursor.execute(
384+ 'insert into kv (key, data) values (?, ?)',
385+ (key, serialized))
386+ else:
387+ self.cursor.execute('''
388+ update kv
389+ set data = ?
390+ where key = ?''', [serialized, key])
391+
392+ # Save
393+ if not self.revision:
394+ return value
395+
396+ self.cursor.execute(
397+ 'select 1 from kv_revisions where key=? and revision=?',
398+ [key, self.revision])
399+ exists = self.cursor.fetchone()
400+
401+ if not exists:
402+ self.cursor.execute(
403+ '''insert into kv_revisions (
404+ revision, key, data) values (?, ?, ?)''',
405+ (self.revision, key, serialized))
406+ else:
407+ self.cursor.execute(
408+ '''
409+ update kv_revisions
410+ set data = ?
411+ where key = ?
412+ and revision = ?''',
413+ [serialized, key, self.revision])
414+
415+ return value
416+
417+ def delta(self, mapping, prefix):
418+ """
419+ return a delta containing values that have changed.
420+ """
421+ previous = self.getrange(prefix, strip=True)
422+ if not previous:
423+ pk = set()
424+ else:
425+ pk = set(previous.keys())
426+ ck = set(mapping.keys())
427+ delta = DeltaSet()
428+
429+ # added
430+ for k in ck.difference(pk):
431+ delta[k] = Delta(None, mapping[k])
432+
433+ # removed
434+ for k in pk.difference(ck):
435+ delta[k] = Delta(previous[k], None)
436+
437+ # changed
438+ for k in pk.intersection(ck):
439+ c = mapping[k]
440+ p = previous[k]
441+ if c != p:
442+ delta[k] = Delta(p, c)
443+
444+ return delta
445+
446+ @contextlib.contextmanager
447+ def hook_scope(self, name=""):
448+ """Scope all future interactions to the current hook execution
449+ revision."""
450+ assert not self.revision
451+ self.cursor.execute(
452+ 'insert into hooks (hook, date) values (?, ?)',
453+ (name or sys.argv[0],
454+ datetime.datetime.utcnow().isoformat()))
455+ self.revision = self.cursor.lastrowid
456+ try:
457+ yield self.revision
458+ self.revision = None
459+ except:
460+ self.flush(False)
461+ self.revision = None
462+ raise
463+ else:
464+ self.flush()
465+
466+ def flush(self, save=True):
467+ if save:
468+ self.conn.commit()
469+ elif self._closed:
470+ return
471+ else:
472+ self.conn.rollback()
473+
474+ def _init(self):
475+ self.cursor.execute('''
476+ create table if not exists kv (
477+ key text,
478+ data text,
479+ primary key (key)
480+ )''')
481+ self.cursor.execute('''
482+ create table if not exists kv_revisions (
483+ key text,
484+ revision integer,
485+ data text,
486+ primary key (key, revision)
487+ )''')
488+ self.cursor.execute('''
489+ create table if not exists hooks (
490+ version integer primary key autoincrement,
491+ hook text,
492+ date text
493+ )''')
494+ self.conn.commit()
495+
496+ def gethistory(self, key, deserialize=False):
497+ self.cursor.execute(
498+ '''
499+ select kv.revision, kv.key, kv.data, h.hook, h.date
500+ from kv_revisions kv,
501+ hooks h
502+ where kv.key=?
503+ and kv.revision = h.version
504+ ''', [key])
505+ if deserialize is False:
506+ return self.cursor.fetchall()
507+ return map(_parse_history, self.cursor.fetchall())
508+
509+ def debug(self, fh=sys.stderr):
510+ self.cursor.execute('select * from kv')
511+ pprint.pprint(self.cursor.fetchall(), stream=fh)
512+ self.cursor.execute('select * from kv_revisions')
513+ pprint.pprint(self.cursor.fetchall(), stream=fh)
514+
515+
516+def _parse_history(d):
517+ return (d[0], d[1], json.loads(d[2]), d[3],
518+ datetime.datetime.strptime(d[-1], "%Y-%m-%dT%H:%M:%S.%f"))
519+
520+
521+class HookData(object):
522+ """Simple integration for existing hook exec frameworks.
523+
524+ Records all unit information, and stores deltas for processing
525+ by the hook.
526+
527+ Sample::
528+
529+ from charmhelper.core import hookenv, unitdata
530+
531+ changes = unitdata.HookData()
532+ db = unitdata.kv()
533+ hooks = hookenv.Hooks()
534+
535+ @hooks.hook
536+ def config_changed():
537+ # View all changes to configuration
538+ for changed, (prev, cur) in changes.conf.items():
539+ print('config changed', changed,
540+ 'previous value', prev,
541+ 'current value', cur)
542+
543+ # Get some unit specific bookeeping
544+ if not db.get('pkg_key'):
545+ key = urllib.urlopen('https://example.com/pkg_key').read()
546+ db.set('pkg_key', key)
547+
548+ if __name__ == '__main__':
549+ with changes():
550+ hook.execute()
551+
552+ """
553+ def __init__(self):
554+ self.kv = kv()
555+ self.conf = None
556+ self.rels = None
557+
558+ @contextlib.contextmanager
559+ def __call__(self):
560+ from charmhelpers.core import hookenv
561+ hook_name = hookenv.hook_name()
562+
563+ with self.kv.hook_scope(hook_name):
564+ self._record_charm_version(hookenv.charm_dir())
565+ delta_config, delta_relation = self._record_hook(hookenv)
566+ yield self.kv, delta_config, delta_relation
567+
568+ def _record_charm_version(self, charm_dir):
569+ # Record revisions.. charm revisions are meaningless
570+ # to charm authors as they don't control the revision.
571+ # so logic dependnent on revision is not particularly
572+ # useful, however it is useful for debugging analysis.
573+ charm_rev = open(
574+ os.path.join(charm_dir, 'revision')).read().strip()
575+ charm_rev = charm_rev or '0'
576+ revs = self.kv.get('charm_revisions', [])
577+ if charm_rev not in revs:
578+ revs.append(charm_rev.strip() or '0')
579+ self.kv.set('charm_revisions', revs)
580+
581+ def _record_hook(self, hookenv):
582+ data = hookenv.execution_environment()
583+ self.conf = conf_delta = self.kv.delta(data['conf'], 'config')
584+ self.rels = rels_delta = self.kv.delta(data['rels'], 'rels')
585+ self.kv.set('env', data['env'])
586+ self.kv.set('unit', data['unit'])
587+ self.kv.set('relid', data.get('relid'))
588+ return conf_delta, rels_delta
589+
590+
591+class Record(dict):
592+
593+ __slots__ = ()
594+
595+ def __getattr__(self, k):
596+ if k in self:
597+ return self[k]
598+ raise AttributeError(k)
599+
600+
601+class DeltaSet(Record):
602+
603+ __slots__ = ()
604+
605+
606+Delta = collections.namedtuple('Delta', ['previous', 'current'])
607+
608+
609+_KV = None
610+
611+
612+def kv():
613+ global _KV
614+ if _KV is None:
615+ _KV = Storage()
616+ return _KV
617
618=== modified file 'hooks/charmhelpers/fetch/archiveurl.py'
619--- hooks/charmhelpers/fetch/archiveurl.py 2015-01-26 09:44:47 +0000
620+++ hooks/charmhelpers/fetch/archiveurl.py 2015-02-16 12:07:04 +0000
621@@ -18,6 +18,16 @@
622 import hashlib
623 import re
624
625+from charmhelpers.fetch import (
626+ BaseFetchHandler,
627+ UnhandledSource
628+)
629+from charmhelpers.payload.archive import (
630+ get_archive_handler,
631+ extract,
632+)
633+from charmhelpers.core.host import mkdir, check_hash
634+
635 import six
636 if six.PY3:
637 from urllib.request import (
638@@ -35,16 +45,6 @@
639 )
640 from urlparse import urlparse, urlunparse, parse_qs
641
642-from charmhelpers.fetch import (
643- BaseFetchHandler,
644- UnhandledSource
645-)
646-from charmhelpers.payload.archive import (
647- get_archive_handler,
648- extract,
649-)
650-from charmhelpers.core.host import mkdir, check_hash
651-
652
653 def splituser(host):
654 '''urllib.splituser(), but six's support of this seems broken'''
655
656=== modified file 'hooks/charmhelpers/fetch/giturl.py'
657--- hooks/charmhelpers/fetch/giturl.py 2015-01-26 09:44:47 +0000
658+++ hooks/charmhelpers/fetch/giturl.py 2015-02-16 12:07:04 +0000
659@@ -32,7 +32,7 @@
660 apt_install("python-git")
661 from git import Repo
662
663-from git.exc import GitCommandError
664+from git.exc import GitCommandError # noqa E402
665
666
667 class GitUrlFetchHandler(BaseFetchHandler):
668
669=== modified file 'hooks/keystone_context.py'
670--- hooks/keystone_context.py 2015-01-27 23:56:15 +0000
671+++ hooks/keystone_context.py 2015-02-16 12:07:04 +0000
672@@ -21,6 +21,10 @@
673 INFO,
674 )
675
676+from charmhelpers.core.strutils import (
677+ bool_from_string,
678+)
679+
680 from charmhelpers.contrib.hahelpers.apache import install_ca_cert
681
682 CA_CERT_PATH = '/usr/local/share/ca-certificates/keystone_juju_ca_cert.crt'
683@@ -179,8 +183,12 @@
684 singlenode_mode=True)
685 ctxt['public_port'] = determine_api_port(api_port('keystone-public'),
686 singlenode_mode=True)
687- ctxt['debug'] = config('debug') in ['yes', 'true', 'True']
688- ctxt['verbose'] = config('verbose') in ['yes', 'true', 'True']
689+
690+ debug = config('debug')
691+ ctxt['debug'] = debug and bool_from_string(debug)
692+ verbose = config('verbose')
693+ ctxt['verbose'] = verbose and bool_from_string(verbose)
694+
695 ctxt['identity_backend'] = config('identity-backend')
696 ctxt['assignment_backend'] = config('assignment-backend')
697 if config('identity-backend') == 'ldap':
698@@ -194,7 +202,8 @@
699 flags = context.config_flags_parser(ldap_flags)
700 ctxt['ldap_config_flags'] = flags
701
702- if config('enable-pki') not in ['false', 'False', 'no', 'No']:
703+ enable_pki = config('enable-pki')
704+ if enable_pki and bool_from_string(enable_pki):
705 ctxt['signing'] = True
706
707 # Base endpoint URL's which are used in keystone responses
708@@ -214,7 +223,7 @@
709 def __call__(self):
710 ctxt = {}
711 debug = config('debug')
712- if debug and debug.lower() in ['yes', 'true']:
713+ if debug and bool_from_string(debug):
714 ctxt['root_level'] = 'DEBUG'
715
716 return ctxt
717
718=== modified file 'hooks/keystone_hooks.py'
719--- hooks/keystone_hooks.py 2015-02-06 12:05:52 +0000
720+++ hooks/keystone_hooks.py 2015-02-16 12:07:04 +0000
721@@ -33,6 +33,10 @@
722 restart_on_change,
723 )
724
725+from charmhelpers.core.strutils import (
726+ bool_from_string,
727+)
728+
729 from charmhelpers.fetch import (
730 apt_install, apt_update,
731 filter_installed_packages
732@@ -65,7 +69,6 @@
733 CA_CERT_PATH,
734 ensure_permissions,
735 get_ssl_sync_request_units,
736- is_str_true,
737 is_ssl_cert_master,
738 is_db_ready,
739 clear_ssl_synced_units,
740@@ -301,10 +304,10 @@
741 """
742 unit = local_unit().replace('/', '-')
743 count = 0
744- if is_str_true(config('use-https')):
745+ if bool_from_string(config('use-https')):
746 count += 1
747
748- if is_str_true(config('https-service-endpoints')):
749+ if bool_from_string(config('https-service-endpoints')):
750 count += 2
751
752 if count:
753
754=== modified file 'hooks/keystone_utils.py'
755--- hooks/keystone_utils.py 2015-02-05 17:32:30 +0000
756+++ hooks/keystone_utils.py 2015-02-16 12:07:04 +0000
757@@ -48,6 +48,10 @@
758 write_file,
759 )
760
761+from charmhelpers.core.strutils import (
762+ bool_from_string,
763+)
764+
765 import charmhelpers.contrib.unison as unison
766
767 from charmhelpers.core.decorators import (
768@@ -226,13 +230,6 @@
769 }
770
771
772-def is_str_true(value):
773- if value and value.lower() in ['true', 'yes']:
774- return True
775-
776- return False
777-
778-
779 def resource_map():
780 '''
781 Dynamically generate a map of resources that will be managed for a single
782@@ -823,8 +820,8 @@
783
784 def is_ssl_enabled():
785 # Don't do anything if we are not in ssl/https mode
786- if (is_str_true(config('use-https')) or
787- is_str_true(config('https-service-endpoints'))):
788+ if (bool_from_string(config('use-https')) or
789+ bool_from_string(config('https-service-endpoints'))):
790 log("SSL/HTTPS is enabled", level=DEBUG)
791 return True
792
793@@ -906,13 +903,13 @@
794 """
795 paths_to_sync = [SYNC_FLAGS_DIR]
796
797- if is_str_true(config('https-service-endpoints')):
798+ if bool_from_string(config('https-service-endpoints')):
799 log("Syncing all endpoint certs since https-service-endpoints=True",
800 level=DEBUG)
801 paths_to_sync.append(SSL_DIR)
802 paths_to_sync.append(CA_CERT_PATH)
803
804- if is_str_true(config('use-https')):
805+ if bool_from_string(config('use-https')):
806 log("Syncing keystone-endpoint certs since use-https=True",
807 level=DEBUG)
808 paths_to_sync.append(SSL_DIR)
809@@ -1150,7 +1147,7 @@
810 relation_data["auth_port"] = config('admin-port')
811 relation_data["service_port"] = config('service-port')
812 relation_data["region"] = config('region')
813- if is_str_true(config('https-service-endpoints')):
814+ if bool_from_string(config('https-service-endpoints')):
815 # Pass CA cert as client will need it to
816 # verify https connections
817 ca = get_ca(user=SSH_USER)
818@@ -1290,7 +1287,7 @@
819 relation_data["auth_protocol"] = "http"
820 relation_data["service_protocol"] = "http"
821 # generate or get a new cert/key for service if set to manage certs.
822- if is_str_true(config('https-service-endpoints')):
823+ if bool_from_string(config('https-service-endpoints')):
824 ca = get_ca(user=SSH_USER)
825 # NOTE(jamespage) may have multiple cns to deal with to iterate
826 https_cns = set(https_cns)
827
828=== modified file 'tests/charmhelpers/contrib/openstack/amulet/deployment.py'
829--- tests/charmhelpers/contrib/openstack/amulet/deployment.py 2015-01-26 09:44:47 +0000
830+++ tests/charmhelpers/contrib/openstack/amulet/deployment.py 2015-02-16 12:07:04 +0000
831@@ -71,16 +71,19 @@
832 services.append(this_service)
833 use_source = ['mysql', 'mongodb', 'rabbitmq-server', 'ceph',
834 'ceph-osd', 'ceph-radosgw']
835+ # Openstack subordinate charms do not expose an origin option as that
836+ # is controlled by the principle
837+ ignore = ['neutron-openvswitch']
838
839 if self.openstack:
840 for svc in services:
841- if svc['name'] not in use_source:
842+ if svc['name'] not in use_source + ignore:
843 config = {'openstack-origin': self.openstack}
844 self.d.configure(svc['name'], config)
845
846 if self.source:
847 for svc in services:
848- if svc['name'] in use_source:
849+ if svc['name'] in use_source and svc['name'] not in ignore:
850 config = {'source': self.source}
851 self.d.configure(svc['name'], config)
852

Subscribers

People subscribed via source and target branches