def remove_state(self, state): """ Remove this conversation from the given state, and potentially deactivate the state if no more conversations are in it. The relation name will be interpolated in the state name, and it is recommended that it be included to avoid conflicts with states from other relations. For example:: conversation.remove_state('{relation_name}.state') If called from a converation handling the relation "foo", this will remove the conversation from the "foo.state" state, and, if no more conversations are in this the state, will deactivate it. """ state = state.format(relation_name=self.relation_name) value = _get_flag_value(state) if not value: return if self.key in value['conversations']: value['conversations'].remove(self.key) if value['conversations']: set_flag(state, value) else: clear_flag(state)
def set_state(self, state): """ Activate and put this conversation into the given state. The relation name will be interpolated in the state name, and it is recommended that it be included to avoid conflicts with states from other relations. For example:: conversation.set_state('{relation_name}.state') If called from a converation handling the relation "foo", this will activate the "foo.state" state, and will add this conversation to that state. Note: This uses :mod:`charmhelpers.core.unitdata` and requires that :meth:`~charmhelpers.core.unitdata.Storage.flush` be called. """ state = state.format(relation_name=self.relation_name) value = _get_flag_value(state, { 'relation': self.relation_name, 'conversations': [], }) if self.key not in value['conversations']: value['conversations'].append(self.key) set_flag(state, value)
def is_state(self, state): """ Test if this conversation is in the given state. """ state = state.format(relation_name=self.relation_name) value = _get_flag_value(state) if not value: return False return self.key in value['conversations']
def from_flag(cls, flag): """ Find relation implementation in the current charm, based on the name of an active flag. You should not use this method directly. Use :func:`endpoint_from_flag` instead. """ value = _get_flag_value(flag) if value is None: return None relation_name = value['relation'] conversations = Conversation.load(value['conversations']) return cls.from_name(relation_name, conversations)
def _migrate_conversations(): # noqa """ Due to issue #28 (https://github.com/juju-solutions/charms.reactive/issues/28), conversations needed to be updated to be namespaced per relation ID for SERVICE and UNIT scope. To ensure backwards compatibility, this updates all convs in the old format to the new. TODO: Remove in 2.0.0 """ for key, data in unitdata.kv().getrange('reactive.conversations.').items(): if 'local-data' in key: continue if 'namespace' in data: continue relation_name = data.pop('relation_name') if data['scope'] == scopes.GLOBAL: data['namespace'] = relation_name unitdata.kv().set(key, data) else: # split the conv based on the relation ID new_keys = [] for rel_id in hookenv.relation_ids(relation_name): new_key = Conversation._key(rel_id, data['scope']) new_units = set(hookenv.related_units(rel_id)) & set( data['units']) if new_units: unitdata.kv().set( new_key, { 'namespace': rel_id, 'scope': data['scope'], 'units': sorted(new_units), }) new_keys.append(new_key) unitdata.kv().unset(key) # update the states pointing to the old conv key to point to the # (potentially multiple) new key(s) for flag in get_flags(): value = _get_flag_value(flag) if not value: continue if key not in value['conversations']: continue value['conversations'].remove(key) value['conversations'].extend(new_keys) set_flag(flag, value)
def endpoint_from_flag(flag): """The object used for interacting with relations tied to a flag, or None. """ relation_name = None value = _get_flag_value(flag) if isinstance(value, dict) and 'relation' in value: # old-style RelationBase relation_name = value['relation'] elif flag.startswith('endpoint.'): # new-style Endpoint relation_name = flag.split('.')[1] elif '.' in flag: # might be an unprefixed new-style Endpoint relation_name = flag.split('.')[0] if relation_name not in hookenv.relation_types(): return None if relation_name: factory = relation_factory(relation_name) if factory: return factory.from_flag(flag) return None
def get_sshport(self): """Return the host used when configuring SSH access to GitLab.""" if _get_flag_value("reverseproxy.configured"): return self.charm_config["proxy_ssh_port"] return self.charm_config["ssh_port"]