62
def leader_get(attribute=None):
63
"""Wrapper to ensure that settings are migrated from the peer relation.
65
This is to support upgrading an environment that does not support
66
Juju leadership election to one that does.
68
If a setting is not extant in the leader-get but is on the relation-get
69
peer rel, it is migrated and marked as such so that it is not re-migrated.
71
migration_key = '__leader_get_migrated_settings__'
73
return _leader_get(attribute=attribute)
75
settings_migrated = False
76
leader_settings = _leader_get(attribute=attribute)
77
previously_migrated = _leader_get(attribute=migration_key)
79
if previously_migrated:
80
migrated = set(json.loads(previously_migrated))
85
if migration_key in leader_settings:
86
del leader_settings[migration_key]
91
if attribute in migrated:
92
return leader_settings
94
# If attribute not present in leader db, check if this unit has set
95
# the attribute in the peer relation
96
if not leader_settings:
97
peer_setting = relation_get(attribute=attribute, unit=local_unit())
99
leader_set(settings={attribute: peer_setting})
100
leader_settings = peer_setting
103
settings_migrated = True
104
migrated.add(attribute)
106
r_settings = relation_get(unit=local_unit())
108
for key in set(r_settings.keys()).difference(migrated):
109
# Leader setting wins
110
if not leader_settings.get(key):
111
leader_settings[key] = r_settings[key]
113
settings_migrated = True
116
if settings_migrated:
117
leader_set(**leader_settings)
119
if migrated and settings_migrated:
120
migrated = json.dumps(list(migrated))
121
leader_set(settings={migration_key: migrated})
123
return leader_settings
126
def relation_set(relation_id=None, relation_settings=None, **kwargs):
127
"""Attempt to use leader-set if supported in the current version of Juju,
128
otherwise falls back on relation-set.
130
Note that we only attempt to use leader-set if the provided relation_id is
131
a peer relation id or no relation id is provided (in which case we assume
132
we are within the peer relation context).
135
if relation_id in relation_ids('cluster'):
136
return leader_set(settings=relation_settings, **kwargs)
138
raise NotImplementedError
139
except NotImplementedError:
140
return _relation_set(relation_id=relation_id,
141
relation_settings=relation_settings, **kwargs)
144
def relation_get(attribute=None, unit=None, rid=None):
145
"""Attempt to use leader-get if supported in the current version of Juju,
146
otherwise falls back on relation-get.
148
Note that we only attempt to use leader-get if the provided rid is a peer
149
relation id or no relation id is provided (in which case we assume we are
150
within the peer relation context).
153
if rid in relation_ids('cluster'):
154
return leader_get(attribute)
156
raise NotImplementedError
157
except NotImplementedError:
158
return _relation_get(attribute=attribute, rid=rid, unit=unit)
57
161
def peer_retrieve(key, relation_name='cluster'):
58
162
"""Retrieve a named key from peer relation `relation_name`."""
59
163
cluster_rels = relation_ids(relation_name)
96
202
'peer relation {}'.format(relation_name))
99
def peer_echo(includes=None):
205
def peer_echo(includes=None, force=False):
100
206
"""Echo filtered attributes back onto the same relation for storage.
102
208
This is a requirement to use the peerstorage module - it needs to be called
103
209
from the peer relation's changed hook.
211
If Juju leader support exists this will be a noop unless force is True.
215
except NotImplementedError:
219
return # NOOP if leader-election is supported
221
# Use original non-leader calls
222
relation_get = _relation_get
223
relation_set = _relation_set
105
225
rdata = relation_get()
107
227
if includes is None: