19
19
20
20
import ops
21
21
from ops ._tracing import _Config
22
+ from ops .charm import RelationRole
22
23
23
24
from .vendor .charms .certificate_transfer_interface .v1 .certificate_transfer import (
24
25
CertificateTransferRequires ,
44
45
# ```
45
46
# {"receivers": ["otlp_http"]}
46
47
# ```
47
- #
48
+ #
48
49
# - client reads this from remote_app_data:
49
50
# ```
50
51
# {"receivers": [
58
59
59
60
60
61
class Tracing (ops .Object ):
61
- """FIXME docstring ."""
62
+ """Tracing service ."""
62
63
63
64
_certificate_transfer : CertificateTransferRequires | None
64
65
@@ -69,46 +70,70 @@ def __init__(
69
70
ca_relation_name : str | None = None ,
70
71
ca_data : str | None = None ,
71
72
):
72
- """FIXME docstring.
73
-
74
- Include `ops[tracing]` in your dependencies.
75
-
76
- Declare the relations that the charm supports:
77
-
78
- ```yaml
79
- requires:
80
- charm-tracing:
81
- interface: tracing
82
- limit: 1
83
- optional: true
84
- send-ca-cert:
85
- interface: certificate_transfer
86
- limit: 1
87
- optional: true
88
- ```
89
-
90
- Initialise the tracing thing (FIXME) with the names of these relations.
91
-
92
- ```py
93
- import ops.tracing
94
-
95
- class SomeCharm(ops.CharmBase):
96
- def __init__(self, framework: ops.Framework):
97
- ...
98
- self._tracing = ops.tracing.Tracing(
99
- tracing_relation_name="charm-tracing",
100
- ca_relation_name="send-ca-cart",
101
- )
102
- ```
73
+ """Initialise the tracing service.
74
+
75
+ Args:
76
+ charm: your charm instange
77
+ tracing_relation_name: the name of the relation that provides the
78
+ destination to send tracing data to.
79
+ ca_relation_name: the name of the relation that provides the CA
80
+ list to validate the tracing destination against.
81
+ ca_data: a fixed CA list (PEM bundle, a multi-line string).
82
+
83
+ If the destination is resolved to an HTTPS URL, a CA list is required
84
+ to establish a secure connection.
85
+
86
+ The CA list can be provided over a relation via ``ca_relation_name=``
87
+ argument, as a fixed string via ``ca_data`` argument, or the system CA
88
+ list will be used if the earlier two are both ``None``.
89
+
90
+ Usage:
91
+ - Include ``ops[tracing]`` in your dependencies.
92
+ - Declare the relations that the charm supports.
93
+ - Initialise ``Tracing`` with the names of these relations.
94
+
95
+ Example::
96
+ # charmcraft.yaml
97
+ requires:
98
+ charm-tracing:
99
+ interface: tracing
100
+ limit: 1
101
+ optional: true
102
+ send-ca-cert:
103
+ interface: certificate_transfer
104
+ limit: 1
105
+ optional: true
106
+
107
+ # src/charm.py
108
+ import ops.tracing
109
+
110
+ class SomeCharm(ops.CharmBase):
111
+ def __init__(self, framework: ops.Framework):
112
+ ...
113
+ self.tracing = ops.tracing.Tracing(
114
+ tracing_relation_name="charm-tracing",
115
+ ca_relation_name="send-ca-cart",
116
+ )
103
117
"""
104
118
super ().__init__ (charm , f'{ tracing_relation_name } +{ ca_relation_name } ' )
105
119
self .charm = charm
106
120
self .tracing_relation_name = tracing_relation_name
107
121
self .ca_relation_name = ca_relation_name
108
122
self .ca_data = ca_data
109
123
110
- # FIXME: Pietro recommends inspecting charm meta to validate the interface name
111
- assert self .charm .meta .relations [tracing_relation_name ].interface_name == 'tracing'
124
+ # NOTE: Pietro recommends inspecting charm meta to validate the relation
125
+ # that way a badly written charm crashes in early testing.
126
+ if not (relation := self .charm .meta .relations .get (tracing_relation_name )):
127
+ raise ValueError (f'{ tracing_relation_name } is not declared in charm metadata' )
128
+ if (relation_role := relation .role ) is not RelationRole .requires :
129
+ raise ValueError (
130
+ f"{ tracing_relation_name } { relation_role = } when 'requires' is expected"
131
+ )
132
+ if (interface_name := relation .interface_name ) != 'tracing' :
133
+ raise ValueError (
134
+ f"{ tracing_relation_name = } { interface_name = } when 'tracing' is expected"
135
+ )
136
+
112
137
self ._tracing = TracingEndpointRequirer (
113
138
self .charm ,
114
139
tracing_relation_name ,
@@ -121,12 +146,7 @@ def __init__(self, framework: ops.Framework):
121
146
# RelationRoleMismatchError,
122
147
123
148
for event in (
124
- # FIXME: validate this
125
- # - the start event may happen after relation-joined?
126
- # - the k8s container died and got restarted
127
- # - the vm [smth] crashed and got restarted
128
149
self .charm .on .start ,
129
- # In case the previous charm version has a relation but didn't save the URL
130
150
self .charm .on .upgrade_charm ,
131
151
self ._tracing .on .endpoint_changed ,
132
152
self ._tracing .on .endpoint_removed ,
@@ -135,11 +155,20 @@ def __init__(self, framework: ops.Framework):
135
155
136
156
self ._certificate_transfer = None
137
157
if ca_relation_name :
158
+ if not (relation := self .charm .meta .relations .get (ca_relation_name )):
159
+ raise ValueError (f'{ ca_relation_name } is not declared in charm metadata' )
160
+ if (relation_role := relation .role ) is not RelationRole .requires :
161
+ raise ValueError (
162
+ f"{ ca_relation_name } { relation_role = } when 'requires' is expected"
163
+ )
164
+ if (interface_name := relation .interface_name ) != 'certificate_transfer' :
165
+ raise ValueError (
166
+ f"{ ca_relation_name = } { interface_name = } when 'certificate_transfer' "
167
+ 'is expected'
168
+ )
169
+
138
170
self ._certificate_transfer = CertificateTransferRequires (charm , ca_relation_name )
139
- assert (
140
- self .charm .meta .relations [ca_relation_name ].interface_name
141
- == 'certificate_transfer'
142
- )
171
+
143
172
for event in (
144
173
self ._certificate_transfer .on .certificate_set_updated ,
145
174
self ._certificate_transfer .on .certificates_removed ,
@@ -168,8 +197,8 @@ def _get_config(self) -> _Config:
168
197
ca_rel_id = ca_rel .id if ca_rel else None
169
198
170
199
if ca_rel and self ._certificate_transfer .is_ready (ca_rel ):
171
- return _Config (url , ' \n ' . join (
172
- sorted (self ._certificate_transfer .get_all_certificates (ca_rel_id ))
173
- ))
200
+ return _Config (
201
+ url , ' \n ' . join ( sorted (self ._certificate_transfer .get_all_certificates (ca_rel_id ) ))
202
+ )
174
203
else :
175
204
return _Config (None , None )
0 commit comments