353
363
"""Set relation information for the current unit"""
354
364
relation_settings = relation_settings if relation_settings else {}
355
365
relation_cmd_line = ['relation-set']
366
accepts_file = "--file" in subprocess.check_output(
367
relation_cmd_line + ["--help"], universal_newlines=True)
356
368
if relation_id is not None:
357
369
relation_cmd_line.extend(('-r', relation_id))
358
for k, v in (list(relation_settings.items()) + list(kwargs.items())):
360
relation_cmd_line.append('{}='.format(k))
362
relation_cmd_line.append('{}={}'.format(k, v))
363
subprocess.check_call(relation_cmd_line)
370
settings = relation_settings.copy()
371
settings.update(kwargs)
372
for key, value in settings.items():
373
# Force value to be a string: it always should, but some call
374
# sites pass in things like dicts or numbers.
375
if value is not None:
376
settings[key] = "{}".format(value)
378
# --file was introduced in Juju 1.23.2. Use it by default if
379
# available, since otherwise we'll break if the relation data is
380
# too big. Ideally we should tell relation-set to read the data from
381
# stdin, but that feature is broken in 1.23.2: Bug #1454678.
382
with tempfile.NamedTemporaryFile(delete=False) as settings_file:
383
settings_file.write(yaml.safe_dump(settings).encode("utf-8"))
384
subprocess.check_call(
385
relation_cmd_line + ["--file", settings_file.name])
386
os.remove(settings_file.name)
388
for key, value in settings.items():
390
relation_cmd_line.append('{}='.format(key))
392
relation_cmd_line.append('{}={}'.format(key, value))
393
subprocess.check_call(relation_cmd_line)
364
394
# Flush cache of any relation-gets for local unit
365
395
flush(local_unit())
398
def relation_clear(r_id=None):
399
''' Clears any relation data already set on relation r_id '''
400
settings = relation_get(rid=r_id,
402
for setting in settings:
403
if setting not in ['public-address', 'private-address']:
404
settings[setting] = None
405
relation_set(relation_id=r_id,
369
410
def relation_ids(reltype=None):
370
411
"""A list of relation_ids"""
606
652
The results set by action_set are preserved."""
607
653
subprocess.check_call(['action-fail', message])
656
def status_set(workload_state, message):
657
"""Set the workload state with a message
659
Use status-set to set the workload state with a message which is visible
660
to the user via juju status. If the status-set command is not found then
661
assume this is juju < 1.23 and juju-log the message unstead.
663
workload_state -- valid juju workload state.
664
message -- status update message
666
valid_states = ['maintenance', 'blocked', 'waiting', 'active']
667
if workload_state not in valid_states:
669
'{!r} is not a valid workload state'.format(workload_state)
671
cmd = ['status-set', workload_state, message]
673
ret = subprocess.call(cmd)
677
if e.errno != errno.ENOENT:
679
log_message = 'status-set failed: {} {}'.format(workload_state,
681
log(log_message, level='INFO')
685
"""Retrieve the previously set juju workload state
687
If the status-set command is not found then assume this is juju < 1.23 and
692
raw_status = subprocess.check_output(cmd, universal_newlines=True)
693
status = raw_status.rstrip()
696
if e.errno == errno.ENOENT:
702
def translate_exc(from_exc, to_exc):
703
def inner_translate_exc1(f):
704
def inner_translate_exc2(*args, **kwargs):
706
return f(*args, **kwargs)
710
return inner_translate_exc2
712
return inner_translate_exc1
715
@translate_exc(from_exc=OSError, to_exc=NotImplementedError)
717
"""Does the current unit hold the juju leadership
719
Uses juju to determine whether the current unit is the leader of its peers
721
cmd = ['is-leader', '--format=json']
722
return json.loads(subprocess.check_output(cmd).decode('UTF-8'))
725
@translate_exc(from_exc=OSError, to_exc=NotImplementedError)
726
def leader_get(attribute=None):
727
"""Juju leader get value(s)"""
728
cmd = ['leader-get', '--format=json'] + [attribute or '-']
729
return json.loads(subprocess.check_output(cmd).decode('UTF-8'))
732
@translate_exc(from_exc=OSError, to_exc=NotImplementedError)
733
def leader_set(settings=None, **kwargs):
734
"""Juju leader set value(s)"""
735
log("Juju leader-set '%s'" % (settings), level=DEBUG)
737
settings = settings or {}
738
settings.update(kwargs)
739
for k, v in settings.iteritems():
741
cmd.append('{}='.format(k))
743
cmd.append('{}={}'.format(k, v))
744
subprocess.check_call(cmd)