Ejemplo n.º 1
0
    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)
Ejemplo n.º 2
0
    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)
Ejemplo n.º 3
0
 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']
Ejemplo n.º 4
0
    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)
Ejemplo n.º 5
0
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)
Ejemplo n.º 6
0
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
Ejemplo n.º 7
0
 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"]