| import logging |
| |
| from . import model |
| |
| log = logging.getLogger(__name__) |
| |
| |
| class Endpoint: |
| def __init__(self, model, data): |
| self.model = model |
| self.data = data |
| |
| def __repr__(self): |
| return '<Endpoint {}:{}>'.format(self.application.name, self.name) |
| |
| @property |
| def application(self): |
| return self.model.applications[self.data['application-name']] |
| |
| @property |
| def name(self): |
| return self.data['relation']['name'] |
| |
| @property |
| def interface(self): |
| return self.data['relation']['interface'] |
| |
| @property |
| def role(self): |
| return self.data['relation']['role'] |
| |
| @property |
| def scope(self): |
| return self.data['relation']['scope'] |
| |
| |
| class Relation(model.ModelEntity): |
| def __repr__(self): |
| return '<Relation id={} {}>'.format(self.entity_id, self.key) |
| |
| @property |
| def endpoints(self): |
| return [Endpoint(self.model, data) |
| for data in self.safe_data['endpoints']] |
| |
| @property |
| def provides(self): |
| """ |
| The endpoint on the provides side of this relation, or None. |
| """ |
| for endpoint in self.endpoints: |
| if endpoint.role == 'provider': |
| return endpoint |
| return None |
| |
| @property |
| def requires(self): |
| """ |
| The endpoint on the requires side of this relation, or None. |
| """ |
| for endpoint in self.endpoints: |
| if endpoint.role == 'requirer': |
| return endpoint |
| return None |
| |
| @property |
| def peers(self): |
| """ |
| The peers endpoint of this relation, or None. |
| """ |
| for endpoint in self.endpoints: |
| if endpoint.role == 'peer': |
| return endpoint |
| return None |
| |
| @property |
| def is_subordinate(self): |
| return any(ep.scope == 'container' for ep in self.endpoints) |
| |
| @property |
| def is_peer(self): |
| return any(ep.role == 'peer' for ep in self.endpoints) |
| |
| def matches(self, *specs): |
| """ |
| Check if this relation matches relationship specs. |
| |
| Relation specs are strings that would be given to Juju to establish a |
| relation, and should be in the form ``<application>[:<endpoint_name>]`` |
| where the ``:<endpoint_name>`` suffix is optional. If the suffix is |
| omitted, this relation will match on any endpoint as long as the given |
| application is involved. |
| |
| In other words, this relation will match a spec if that spec could have |
| created this relation. |
| |
| :return: True if all specs match. |
| """ |
| for spec in specs: |
| if ':' in spec: |
| app_name, endpoint_name = spec.split(':') |
| else: |
| app_name, endpoint_name = spec, None |
| for endpoint in self.endpoints: |
| if app_name == endpoint.application.name and \ |
| endpoint_name in (endpoint.name, None): |
| # found a match for this spec, so move to next one |
| break |
| else: |
| # no match for this spec |
| return False |
| return True |
| |
| @property |
| def applications(self): |
| """ |
| All applications involved in this relation. |
| """ |
| return [ep.application for ep in self.endpoints] |
| |
| async def destroy(self): |
| raise NotImplementedError() |
| # TODO: destroy a relation |