auto sync charmhelpers
This commit is contained in:
parent
785a2a7b4c
commit
111e186e38
|
@ -20,11 +20,13 @@
|
||||||
# Authors:
|
# Authors:
|
||||||
# Charm Helpers Developers <juju@lists.ubuntu.com>
|
# Charm Helpers Developers <juju@lists.ubuntu.com>
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
import yaml
|
import yaml
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
import errno
|
||||||
from subprocess import CalledProcessError
|
from subprocess import CalledProcessError
|
||||||
|
|
||||||
import six
|
import six
|
||||||
|
@ -87,7 +89,18 @@ def log(message, level=None):
|
||||||
if not isinstance(message, six.string_types):
|
if not isinstance(message, six.string_types):
|
||||||
message = repr(message)
|
message = repr(message)
|
||||||
command += [message]
|
command += [message]
|
||||||
subprocess.call(command)
|
# Missing juju-log should not cause failures in unit tests
|
||||||
|
# Send log output to stderr
|
||||||
|
try:
|
||||||
|
subprocess.call(command)
|
||||||
|
except OSError as e:
|
||||||
|
if e.errno == errno.ENOENT:
|
||||||
|
if level:
|
||||||
|
message = "{}: {}".format(level, message)
|
||||||
|
message = "juju-log: {}".format(message)
|
||||||
|
print(message, file=sys.stderr)
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
class Serializable(UserDict):
|
class Serializable(UserDict):
|
||||||
|
@ -566,3 +579,29 @@ class Hooks(object):
|
||||||
def charm_dir():
|
def charm_dir():
|
||||||
"""Return the root directory of the current charm"""
|
"""Return the root directory of the current charm"""
|
||||||
return os.environ.get('CHARM_DIR')
|
return os.environ.get('CHARM_DIR')
|
||||||
|
|
||||||
|
|
||||||
|
@cached
|
||||||
|
def action_get(key=None):
|
||||||
|
"""Gets the value of an action parameter, or all key/value param pairs"""
|
||||||
|
cmd = ['action-get']
|
||||||
|
if key is not None:
|
||||||
|
cmd.append(key)
|
||||||
|
cmd.append('--format=json')
|
||||||
|
action_data = json.loads(subprocess.check_output(cmd).decode('UTF-8'))
|
||||||
|
return action_data
|
||||||
|
|
||||||
|
|
||||||
|
def action_set(values):
|
||||||
|
"""Sets the values to be returned after the action finishes"""
|
||||||
|
cmd = ['action-set']
|
||||||
|
for k, v in list(values.items()):
|
||||||
|
cmd.append('{}={}'.format(k, v))
|
||||||
|
subprocess.check_call(cmd)
|
||||||
|
|
||||||
|
|
||||||
|
def action_fail(message):
|
||||||
|
"""Sets the action status to failed and sets the error message.
|
||||||
|
|
||||||
|
The results set by action_set are preserved."""
|
||||||
|
subprocess.check_call(['action-fail', message])
|
||||||
|
|
|
@ -339,12 +339,16 @@ def lsb_release():
|
||||||
def pwgen(length=None):
|
def pwgen(length=None):
|
||||||
"""Generate a random pasword."""
|
"""Generate a random pasword."""
|
||||||
if length is None:
|
if length is None:
|
||||||
|
# A random length is ok to use a weak PRNG
|
||||||
length = random.choice(range(35, 45))
|
length = random.choice(range(35, 45))
|
||||||
alphanumeric_chars = [
|
alphanumeric_chars = [
|
||||||
l for l in (string.ascii_letters + string.digits)
|
l for l in (string.ascii_letters + string.digits)
|
||||||
if l not in 'l0QD1vAEIOUaeiou']
|
if l not in 'l0QD1vAEIOUaeiou']
|
||||||
|
# Use a crypto-friendly PRNG (e.g. /dev/urandom) for making the
|
||||||
|
# actual password
|
||||||
|
random_generator = random.SystemRandom()
|
||||||
random_chars = [
|
random_chars = [
|
||||||
random.choice(alphanumeric_chars) for _ in range(length)]
|
random_generator.choice(alphanumeric_chars) for _ in range(length)]
|
||||||
return(''.join(random_chars))
|
return(''.join(random_chars))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -139,7 +139,7 @@ class MysqlRelation(RelationContext):
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.required_keys = ['host', 'user', 'password', 'database']
|
self.required_keys = ['host', 'user', 'password', 'database']
|
||||||
super(HttpRelation).__init__(self, *args, **kwargs)
|
RelationContext.__init__(self, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class HttpRelation(RelationContext):
|
class HttpRelation(RelationContext):
|
||||||
|
@ -154,7 +154,7 @@ class HttpRelation(RelationContext):
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.required_keys = ['host', 'port']
|
self.required_keys = ['host', 'port']
|
||||||
super(HttpRelation).__init__(self, *args, **kwargs)
|
RelationContext.__init__(self, *args, **kwargs)
|
||||||
|
|
||||||
def provide_data(self):
|
def provide_data(self):
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -33,9 +33,9 @@ def bool_from_string(value):
|
||||||
|
|
||||||
value = value.strip().lower()
|
value = value.strip().lower()
|
||||||
|
|
||||||
if value in ['y', 'yes', 'true', 't']:
|
if value in ['y', 'yes', 'true', 't', 'on']:
|
||||||
return True
|
return True
|
||||||
elif value in ['n', 'no', 'false', 'f']:
|
elif value in ['n', 'no', 'false', 'f', 'off']:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
msg = "Unable to interpret string value '%s' as boolean" % (value)
|
msg = "Unable to interpret string value '%s' as boolean" % (value)
|
||||||
|
|
|
@ -443,7 +443,7 @@ class HookData(object):
|
||||||
data = hookenv.execution_environment()
|
data = hookenv.execution_environment()
|
||||||
self.conf = conf_delta = self.kv.delta(data['conf'], 'config')
|
self.conf = conf_delta = self.kv.delta(data['conf'], 'config')
|
||||||
self.rels = rels_delta = self.kv.delta(data['rels'], 'rels')
|
self.rels = rels_delta = self.kv.delta(data['rels'], 'rels')
|
||||||
self.kv.set('env', data['env'])
|
self.kv.set('env', dict(data['env']))
|
||||||
self.kv.set('unit', data['unit'])
|
self.kv.set('unit', data['unit'])
|
||||||
self.kv.set('relid', data.get('relid'))
|
self.kv.set('relid', data.get('relid'))
|
||||||
return conf_delta, rels_delta
|
return conf_delta, rels_delta
|
||||||
|
|
|
@ -118,6 +118,9 @@ class AmuletUtils(object):
|
||||||
longs, or can be a function that evaluate a variable and returns a
|
longs, or can be a function that evaluate a variable and returns a
|
||||||
bool.
|
bool.
|
||||||
"""
|
"""
|
||||||
|
self.log.debug('actual: {}'.format(repr(actual)))
|
||||||
|
self.log.debug('expected: {}'.format(repr(expected)))
|
||||||
|
|
||||||
for k, v in six.iteritems(expected):
|
for k, v in six.iteritems(expected):
|
||||||
if k in actual:
|
if k in actual:
|
||||||
if (isinstance(v, six.string_types) or
|
if (isinstance(v, six.string_types) or
|
||||||
|
@ -134,7 +137,6 @@ class AmuletUtils(object):
|
||||||
def validate_relation_data(self, sentry_unit, relation, expected):
|
def validate_relation_data(self, sentry_unit, relation, expected):
|
||||||
"""Validate actual relation data based on expected relation data."""
|
"""Validate actual relation data based on expected relation data."""
|
||||||
actual = sentry_unit.relation(relation[0], relation[1])
|
actual = sentry_unit.relation(relation[0], relation[1])
|
||||||
self.log.debug('actual: {}'.format(repr(actual)))
|
|
||||||
return self._validate_dict_data(expected, actual)
|
return self._validate_dict_data(expected, actual)
|
||||||
|
|
||||||
def _validate_list_data(self, expected, actual):
|
def _validate_list_data(self, expected, actual):
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
|
# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import six
|
import six
|
||||||
|
from collections import OrderedDict
|
||||||
from charmhelpers.contrib.amulet.deployment import (
|
from charmhelpers.contrib.amulet.deployment import (
|
||||||
AmuletDeployment
|
AmuletDeployment
|
||||||
)
|
)
|
||||||
|
@ -43,7 +44,7 @@ class OpenStackAmuletDeployment(AmuletDeployment):
|
||||||
Determine if the local branch being tested is derived from its
|
Determine if the local branch being tested is derived from its
|
||||||
stable or next (dev) branch, and based on this, use the corresonding
|
stable or next (dev) branch, and based on this, use the corresonding
|
||||||
stable or next branches for the other_services."""
|
stable or next branches for the other_services."""
|
||||||
base_charms = ['mysql', 'mongodb', 'rabbitmq-server']
|
base_charms = ['mysql', 'mongodb']
|
||||||
|
|
||||||
if self.stable:
|
if self.stable:
|
||||||
for svc in other_services:
|
for svc in other_services:
|
||||||
|
@ -100,12 +101,37 @@ class OpenStackAmuletDeployment(AmuletDeployment):
|
||||||
"""
|
"""
|
||||||
(self.precise_essex, self.precise_folsom, self.precise_grizzly,
|
(self.precise_essex, self.precise_folsom, self.precise_grizzly,
|
||||||
self.precise_havana, self.precise_icehouse,
|
self.precise_havana, self.precise_icehouse,
|
||||||
self.trusty_icehouse) = range(6)
|
self.trusty_icehouse, self.trusty_juno, self.trusty_kilo,
|
||||||
|
self.utopic_juno, self.vivid_kilo) = range(10)
|
||||||
releases = {
|
releases = {
|
||||||
('precise', None): self.precise_essex,
|
('precise', None): self.precise_essex,
|
||||||
('precise', 'cloud:precise-folsom'): self.precise_folsom,
|
('precise', 'cloud:precise-folsom'): self.precise_folsom,
|
||||||
('precise', 'cloud:precise-grizzly'): self.precise_grizzly,
|
('precise', 'cloud:precise-grizzly'): self.precise_grizzly,
|
||||||
('precise', 'cloud:precise-havana'): self.precise_havana,
|
('precise', 'cloud:precise-havana'): self.precise_havana,
|
||||||
('precise', 'cloud:precise-icehouse'): self.precise_icehouse,
|
('precise', 'cloud:precise-icehouse'): self.precise_icehouse,
|
||||||
('trusty', None): self.trusty_icehouse}
|
('trusty', None): self.trusty_icehouse,
|
||||||
|
('trusty', 'cloud:trusty-juno'): self.trusty_juno,
|
||||||
|
('trusty', 'cloud:trusty-kilo'): self.trusty_kilo,
|
||||||
|
('utopic', None): self.utopic_juno,
|
||||||
|
('vivid', None): self.vivid_kilo}
|
||||||
return releases[(self.series, self.openstack)]
|
return releases[(self.series, self.openstack)]
|
||||||
|
|
||||||
|
def _get_openstack_release_string(self):
|
||||||
|
"""Get openstack release string.
|
||||||
|
|
||||||
|
Return a string representing the openstack release.
|
||||||
|
"""
|
||||||
|
releases = OrderedDict([
|
||||||
|
('precise', 'essex'),
|
||||||
|
('quantal', 'folsom'),
|
||||||
|
('raring', 'grizzly'),
|
||||||
|
('saucy', 'havana'),
|
||||||
|
('trusty', 'icehouse'),
|
||||||
|
('utopic', 'juno'),
|
||||||
|
('vivid', 'kilo'),
|
||||||
|
])
|
||||||
|
if self.openstack:
|
||||||
|
os_origin = self.openstack.split(':')[1]
|
||||||
|
return os_origin.split('%s-' % self.series)[1].split('/')[0]
|
||||||
|
else:
|
||||||
|
return releases[self.series]
|
||||||
|
|
Loading…
Reference in New Issue