Native charm support
[osm/N2VC.git] / modules / libjuju / juju / relation.py
1 import logging
2
3 from . import model
4
5 log = logging.getLogger(__name__)
6
7
8 class Endpoint:
9 def __init__(self, model, data):
10 self.model = model
11 self.data = data
12
13 def __repr__(self):
14 return '<Endpoint {}:{}>'.format(self.application.name, self.name)
15
16 @property
17 def application(self):
18 return self.model.applications[self.data['application-name']]
19
20 @property
21 def name(self):
22 return self.data['relation']['name']
23
24 @property
25 def interface(self):
26 return self.data['relation']['interface']
27
28 @property
29 def role(self):
30 return self.data['relation']['role']
31
32 @property
33 def scope(self):
34 return self.data['relation']['scope']
35
36
37 class Relation(model.ModelEntity):
38 def __repr__(self):
39 return '<Relation id={} {}>'.format(self.entity_id, self.key)
40
41 @property
42 def endpoints(self):
43 return [Endpoint(self.model, data)
44 for data in self.safe_data['endpoints']]
45
46 @property
47 def provides(self):
48 """
49 The endpoint on the provides side of this relation, or None.
50 """
51 for endpoint in self.endpoints:
52 if endpoint.role == 'provider':
53 return endpoint
54 return None
55
56 @property
57 def requires(self):
58 """
59 The endpoint on the requires side of this relation, or None.
60 """
61 for endpoint in self.endpoints:
62 if endpoint.role == 'requirer':
63 return endpoint
64 return None
65
66 @property
67 def peers(self):
68 """
69 The peers endpoint of this relation, or None.
70 """
71 for endpoint in self.endpoints:
72 if endpoint.role == 'peer':
73 return endpoint
74 return None
75
76 @property
77 def is_subordinate(self):
78 return any(ep.scope == 'container' for ep in self.endpoints)
79
80 @property
81 def is_peer(self):
82 return any(ep.role == 'peer' for ep in self.endpoints)
83
84 def matches(self, *specs):
85 """
86 Check if this relation matches relationship specs.
87
88 Relation specs are strings that would be given to Juju to establish a
89 relation, and should be in the form ``<application>[:<endpoint_name>]``
90 where the ``:<endpoint_name>`` suffix is optional. If the suffix is
91 omitted, this relation will match on any endpoint as long as the given
92 application is involved.
93
94 In other words, this relation will match a spec if that spec could have
95 created this relation.
96
97 :return: True if all specs match.
98 """
99 for spec in specs:
100 if ':' in spec:
101 app_name, endpoint_name = spec.split(':')
102 else:
103 app_name, endpoint_name = spec, None
104 for endpoint in self.endpoints:
105 if app_name == endpoint.application.name and \
106 endpoint_name in (endpoint.name, None):
107 # found a match for this spec, so move to next one
108 break
109 else:
110 # no match for this spec
111 return False
112 return True
113
114 @property
115 def applications(self):
116 """
117 All applications involved in this relation.
118 """
119 return [ep.application for ep in self.endpoints]
120
121 async def destroy(self):
122 raise NotImplementedError()
123 # TODO: destroy a relation