-
Notifications
You must be signed in to change notification settings - Fork 122
/
Copy pathjujucontext.py
229 lines (173 loc) · 6.92 KB
/
jujucontext.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
# Copyright 2024 Canonical Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""A helper to work with the Juju context and version."""
import dataclasses
from pathlib import Path
from typing import Any, Mapping, Optional, Set
from ops.jujuversion import JujuVersion
@dataclasses.dataclass(frozen=True)
class _JujuContext:
"""_JujuContext collects information from environment variables named 'JUJU_*'.
Source: https://juju.is/docs/juju/charm-environment-variables.
The HookVars function: https://github.com/juju/juju/blob/3.6/worker/uniter/runner/context/context.go#L1398.
Only a subset of the above source, because these are what are used in ops.
"""
action_name: Optional[str] = None
"""The action's name.
For example 'backup' (from JUJU_ACTION_NAME).
"""
action_uuid: Optional[str] = None
"""The action's uuid.
For example '1' (from JUJU_ACTION_UUID).
"""
charm_dir: Path = dataclasses.field(
default_factory=lambda: Path(f'{__file__}/../../..').resolve()
)
"""The root directory of the charm where it is running.
For example '/var/lib/juju/agents/unit-bare-0/charm' (from JUJU_CHARM_DIR).
If JUJU_CHARM_DIR is None or set to an empty string, use Path(f'{__file__}/../../..') as
default (assuming the '$JUJU_CHARM_DIR/lib/op/main.py' structure).
"""
debug: bool = False
"""Debug mode.
If true, write logs to stderr as well as to juju-log (from JUJU_DEBUG).
"""
debug_at: Set[str] = dataclasses.field(default_factory=set)
"""Where you want to stop when debugging.
For example 'all' (from JUJU_DEBUG_AT).
"""
dispatch_path: str = ''
"""The dispatch path in the format of 'actions/do-something'.
For example 'hooks/workload-pebble-ready' (from JUJU_DISPATCH_PATH).
"""
model_name: str = ''
"""The name of the model.
For example 'foo' (from JUJU_MODEL_NAME).
"""
model_uuid: str = ''
"""The uuid of the model.
For example 'cdac5656-2423-4388-8f30-41854b4cca7d' (from JUJU_MODEL_UUID).
"""
notice_id: Optional[str] = None
"""The ID of the notice.
For example '1', (from JUJU_NOTICE_ID).
"""
notice_key: Optional[str] = None
"""The key of the notice.
For example 'example.com/a', (from JUJU_NOTICE_KEY).
"""
notice_type: Optional[str] = None
"""The type of the notice.
For example 'custom' (from JUJU_NOTICE_TYPE).
"""
pebble_check_name: Optional[str] = None
"""The name of the pebble check.
For example 'http-check' (from JUJU_PEBBLE_CHECK_NAME).
"""
relation_departing_unit_name: Optional[str] = None
"""The unit that is departing a relation.
For example 'remote/42' (from JUJU_DEPARTING_UNIT).
"""
relation_name: Optional[str] = None
"""The name of the relation.
For example 'database' (from JUJU_RELATION).
"""
relation_id: Optional[int] = None
"""The id of the relation.
For example 1 (integer) if the original environment variable's value is 'database:1'
(from JUJU_RELATION_ID).
"""
remote_app_name: Optional[str] = None
"""The name of the remote app.
For example 'remoteapp1' (from JUJU_REMOTE_APP).
"""
remote_unit_name: Optional[str] = None
"""The name of the remote unit.
For example 'remoteapp1/0' (from JUJU_REMOTE_UNIT).
"""
secret_id: Optional[str] = None
"""The ID of the secret.
For example 'secret:dcc7aa9c-7202-4da6-8d5f-0fbbaa4e1a41' (from JUJU_SECRET_ID).
"""
secret_label: Optional[str] = None
"""The label of the secret.
For example 'db-password' (from JUJU_SECRET_LABEL).
"""
secret_revision: Optional[int] = None
"""The revision of the secret.
For example 42 (integer) (from JUJU_SECRET_REVISION).
"""
storage_name: Optional[str] = None
"""The storage name.
For example 'my-storage' if the original environment variable's value is 'my-storage/1'
(from JUJU_STORAGE_ID).
"""
unit_name: str = ''
"""The name of the unit.
For example 'myapp/0' (from JUJU_UNIT_NAME).
"""
version: JujuVersion = dataclasses.field(default_factory=lambda: JujuVersion('0.0.0'))
"""The version of Juju.
For example '3.4.0' (from JUJU_VERSION).
"""
workload_name: Optional[str] = None
"""The name of the workload.
For example 'workload' (from JUJU_WORKLOAD_NAME).
"""
@classmethod
def from_dict(cls, env: Mapping[str, Any]) -> '_JujuContext':
return _JujuContext(
action_name=env.get('JUJU_ACTION_NAME') or None,
action_uuid=env.get('JUJU_ACTION_UUID') or None,
charm_dir=(
Path(env['JUJU_CHARM_DIR']).resolve()
if env.get('JUJU_CHARM_DIR')
else Path(f'{__file__}/../../..').resolve()
),
debug='JUJU_DEBUG' in env,
debug_at=(
{x.strip() for x in env['JUJU_DEBUG_AT'].split(',')}
if env.get('JUJU_DEBUG_AT')
else set()
),
dispatch_path=env.get('JUJU_DISPATCH_PATH', ''),
model_name=env.get('JUJU_MODEL_NAME', ''),
model_uuid=env.get('JUJU_MODEL_UUID', ''),
notice_id=env.get('JUJU_NOTICE_ID') or None,
notice_key=env.get('JUJU_NOTICE_KEY') or None,
notice_type=env.get('JUJU_NOTICE_TYPE') or None,
pebble_check_name=env.get('JUJU_PEBBLE_CHECK_NAME') or None,
relation_departing_unit_name=env.get('JUJU_DEPARTING_UNIT') or None,
relation_name=env.get('JUJU_RELATION') or None,
relation_id=(
int(env['JUJU_RELATION_ID'].split(':')[-1])
if env.get('JUJU_RELATION_ID')
else None
),
remote_app_name=env.get('JUJU_REMOTE_APP') or None,
remote_unit_name=env.get('JUJU_REMOTE_UNIT') or None,
secret_id=env.get('JUJU_SECRET_ID') or None,
secret_label=env.get('JUJU_SECRET_LABEL') or None,
secret_revision=(
int(env['JUJU_SECRET_REVISION']) if env.get('JUJU_SECRET_REVISION') else None
),
storage_name=(
env.get('JUJU_STORAGE_ID', '').split('/')[0]
if env.get('JUJU_STORAGE_ID')
else None
),
unit_name=env.get('JUJU_UNIT_NAME', ''),
version=JujuVersion(env['JUJU_VERSION']),
workload_name=env.get('JUJU_WORKLOAD_NAME') or None,
)