canonicalwebteam.store-api 5.0.0__py3-none-any.whl → 6.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- canonicalwebteam/store_api/base.py +68 -0
- canonicalwebteam/store_api/dashboard.py +647 -0
- canonicalwebteam/store_api/{store.py → devicegw.py} +126 -78
- canonicalwebteam/store_api/publishergw.py +832 -0
- {canonicalwebteam_store_api-5.0.0.dist-info → canonicalwebteam_store_api-6.0.0.dist-info}/METADATA +7 -7
- canonicalwebteam_store_api-6.0.0.dist-info/RECORD +11 -0
- {canonicalwebteam_store_api-5.0.0.dist-info → canonicalwebteam_store_api-6.0.0.dist-info}/WHEEL +1 -1
- canonicalwebteam/store_api/publisher.py +0 -420
- canonicalwebteam/store_api/stores/__init__.py +0 -0
- canonicalwebteam/store_api/stores/charmstore.py +0 -525
- canonicalwebteam/store_api/stores/snapstore.py +0 -770
- canonicalwebteam_store_api-5.0.0.dist-info/RECORD +0 -12
- /canonicalwebteam/{store_api/exceptions.py → exceptions.py} +0 -0
- {canonicalwebteam_store_api-5.0.0.dist-info → canonicalwebteam_store_api-6.0.0.dist-info}/LICENSE +0 -0
|
@@ -1,525 +0,0 @@
|
|
|
1
|
-
from os import getenv
|
|
2
|
-
|
|
3
|
-
import requests
|
|
4
|
-
|
|
5
|
-
from canonicalwebteam.store_api.store import Store
|
|
6
|
-
from canonicalwebteam.store_api.publisher import Publisher
|
|
7
|
-
|
|
8
|
-
CHARMSTORE_API_URL = getenv("CHARMSTORE_API_URL", "https://api.charmhub.io/")
|
|
9
|
-
CHARMSTORE_PUBLISHER_API_URL = getenv(
|
|
10
|
-
"CHARMSTORE_PUBLISHER_API_URL", "https://api.charmhub.io/"
|
|
11
|
-
)
|
|
12
|
-
CHARMSTORE_VALID_PACKAGE_TYPES = ["charm", "bundle"]
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class CharmStore(Store):
|
|
16
|
-
def __init__(self, session=requests.Session(), store=None):
|
|
17
|
-
super().__init__(session, store)
|
|
18
|
-
|
|
19
|
-
self.config = {
|
|
20
|
-
2: {"base_url": f"{CHARMSTORE_API_URL}v2/charms/"},
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
def find(
|
|
24
|
-
self,
|
|
25
|
-
query="",
|
|
26
|
-
category="",
|
|
27
|
-
publisher="",
|
|
28
|
-
type=None,
|
|
29
|
-
provides=[],
|
|
30
|
-
requires=[],
|
|
31
|
-
fields=[],
|
|
32
|
-
):
|
|
33
|
-
"""
|
|
34
|
-
Given a search term, return an array of matching search results.
|
|
35
|
-
v2 API only.
|
|
36
|
-
"""
|
|
37
|
-
url = self.get_endpoint_url("find", 2)
|
|
38
|
-
headers = self.config[2].get("headers")
|
|
39
|
-
params = {
|
|
40
|
-
"q": query,
|
|
41
|
-
"category": category,
|
|
42
|
-
"publisher": publisher,
|
|
43
|
-
"type": type,
|
|
44
|
-
}
|
|
45
|
-
if fields:
|
|
46
|
-
params["fields"] = ",".join(fields)
|
|
47
|
-
|
|
48
|
-
if provides:
|
|
49
|
-
params["provides"] = ",".join(provides)
|
|
50
|
-
|
|
51
|
-
if requires:
|
|
52
|
-
params["requires"] = ",".join(requires)
|
|
53
|
-
|
|
54
|
-
return self.process_response(
|
|
55
|
-
self.session.get(url, params=params, headers=headers)
|
|
56
|
-
)
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
class CharmPublisher(Publisher):
|
|
60
|
-
def __init__(self, session=requests.Session()):
|
|
61
|
-
super().__init__(session)
|
|
62
|
-
|
|
63
|
-
self.config = {
|
|
64
|
-
1: {"base_url": f"{CHARMSTORE_PUBLISHER_API_URL}v1/"},
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
self.session.headers.update({"Bakery-Protocol-Version": "2"})
|
|
68
|
-
|
|
69
|
-
def _get_authorization_header(self, publisher_auth):
|
|
70
|
-
"""
|
|
71
|
-
Return the formatted Authorization header for the publisher API.
|
|
72
|
-
"""
|
|
73
|
-
return {"Authorization": f"Macaroon {publisher_auth}"}
|
|
74
|
-
|
|
75
|
-
def get_macaroon(self):
|
|
76
|
-
"""
|
|
77
|
-
Return a bakery v2 macaroon from the publisher API to be discharged
|
|
78
|
-
Documentation: https://api.charmhub.io/docs/default.html#get_macaroon
|
|
79
|
-
Endpoint URL: [GET] https://api.charmhub.io/v1/tokens
|
|
80
|
-
"""
|
|
81
|
-
response = self.session.get(url=self.get_endpoint_url("tokens"))
|
|
82
|
-
|
|
83
|
-
return self.process_response(response)["macaroon"]
|
|
84
|
-
|
|
85
|
-
def issue_macaroon(self, permissions, description=None, ttl=None):
|
|
86
|
-
"""
|
|
87
|
-
Return a bakery v2 macaroon from the publisher API to be discharged
|
|
88
|
-
Documentation: https://api.charmhub.io/docs/default.html#issue_macaroon
|
|
89
|
-
Endpoint URL: [POST] https://api.charmhub.io/v1/tokens
|
|
90
|
-
"""
|
|
91
|
-
data = {"permissions": permissions}
|
|
92
|
-
|
|
93
|
-
if description:
|
|
94
|
-
data["description"] = description
|
|
95
|
-
|
|
96
|
-
if ttl:
|
|
97
|
-
data["ttl"] = ttl
|
|
98
|
-
|
|
99
|
-
response = self.session.post(
|
|
100
|
-
url=self.get_endpoint_url("tokens"),
|
|
101
|
-
json=data,
|
|
102
|
-
)
|
|
103
|
-
|
|
104
|
-
return self.process_response(response)["macaroon"]
|
|
105
|
-
|
|
106
|
-
def exchange_macaroons(self, issued_macaroon):
|
|
107
|
-
"""
|
|
108
|
-
Return an exchanged snapstore-only authentication macaroon.
|
|
109
|
-
Documentation:
|
|
110
|
-
https://api.charmhub.io/docs/default.html#exchange_macaroons
|
|
111
|
-
Endpoint URL: [POST] https://api.charmhub.io/v1/tokens/exchange
|
|
112
|
-
"""
|
|
113
|
-
|
|
114
|
-
response = self.session.post(
|
|
115
|
-
url=self.get_endpoint_url("tokens/exchange"),
|
|
116
|
-
headers={"Macaroons": issued_macaroon},
|
|
117
|
-
json={},
|
|
118
|
-
)
|
|
119
|
-
|
|
120
|
-
return self.process_response(response)["macaroon"]
|
|
121
|
-
|
|
122
|
-
def macaroon_info(self, publisher_auth):
|
|
123
|
-
"""
|
|
124
|
-
Return information about the authenticated macaroon token.
|
|
125
|
-
Documentation: https://api.charmhub.io/docs/default.html#macaroon_info
|
|
126
|
-
Endpoint URL: [GET] https://api.charmhub.io/v1/tokens/whoami
|
|
127
|
-
"""
|
|
128
|
-
response = self.session.get(
|
|
129
|
-
url=self.get_endpoint_url("tokens/whoami"),
|
|
130
|
-
headers=self._get_authorization_header(publisher_auth),
|
|
131
|
-
)
|
|
132
|
-
|
|
133
|
-
return self.process_response(response)
|
|
134
|
-
|
|
135
|
-
def whoami(self, publisher_auth):
|
|
136
|
-
"""
|
|
137
|
-
Return information about the authenticated macaroon token.
|
|
138
|
-
Documentation: 'DEPRECATED'
|
|
139
|
-
Endpoint URL: [GET] https://api.charmhub.io/v1/whoami
|
|
140
|
-
"""
|
|
141
|
-
response = self.session.get(
|
|
142
|
-
url=self.get_endpoint_url("whoami"),
|
|
143
|
-
headers=self._get_authorization_header(publisher_auth),
|
|
144
|
-
)
|
|
145
|
-
|
|
146
|
-
return self.process_response(response)
|
|
147
|
-
|
|
148
|
-
def get_account_packages(
|
|
149
|
-
self,
|
|
150
|
-
publisher_auth,
|
|
151
|
-
package_type,
|
|
152
|
-
include_collaborations=False,
|
|
153
|
-
status=None,
|
|
154
|
-
):
|
|
155
|
-
"""
|
|
156
|
-
Return publisher packages
|
|
157
|
-
Documentation: https://api.charmhub.io/docs/default.html
|
|
158
|
-
Endpoint URL: [GET] https://api.charmhub.io/v1/charm
|
|
159
|
-
|
|
160
|
-
Args:
|
|
161
|
-
publisher_auth: Serialized macaroon to consume the API.
|
|
162
|
-
package_type: Type of packages to obtain.
|
|
163
|
-
include_collaborations (optional): Include shared charms
|
|
164
|
-
status (optional): Only packages with the given status
|
|
165
|
-
|
|
166
|
-
Returns:
|
|
167
|
-
A list of packages
|
|
168
|
-
"""
|
|
169
|
-
|
|
170
|
-
if package_type not in CHARMSTORE_VALID_PACKAGE_TYPES:
|
|
171
|
-
raise ValueError(
|
|
172
|
-
"Invalid package type. Expected one of: %s"
|
|
173
|
-
% CHARMSTORE_VALID_PACKAGE_TYPES
|
|
174
|
-
)
|
|
175
|
-
|
|
176
|
-
params = {}
|
|
177
|
-
|
|
178
|
-
if include_collaborations:
|
|
179
|
-
params["include-collaborations"] = "true"
|
|
180
|
-
|
|
181
|
-
response = self.session.get(
|
|
182
|
-
url=self.get_endpoint_url(package_type),
|
|
183
|
-
headers=self._get_authorization_header(publisher_auth),
|
|
184
|
-
params=params,
|
|
185
|
-
)
|
|
186
|
-
packages = self.process_response(response)["results"]
|
|
187
|
-
|
|
188
|
-
if status:
|
|
189
|
-
packages = [p for p in packages if p["status"] == status]
|
|
190
|
-
|
|
191
|
-
return packages
|
|
192
|
-
|
|
193
|
-
def get_package_metadata(self, publisher_auth, package_type, name):
|
|
194
|
-
"""
|
|
195
|
-
Get general metadata for a package.
|
|
196
|
-
Documentation:
|
|
197
|
-
https://api.charmhub.io/docs/default.html#package_metadata
|
|
198
|
-
Endpoint URL: [GET] https://api.charmhub.io/v1/charm/<name>
|
|
199
|
-
namespace: charm for both charms and bundles
|
|
200
|
-
name: Package name
|
|
201
|
-
|
|
202
|
-
Args:
|
|
203
|
-
publisher_auth: Serialized macaroon to consume the API.
|
|
204
|
-
package_type: Type of packages to obtain.
|
|
205
|
-
|
|
206
|
-
Returns:
|
|
207
|
-
Package general metadata
|
|
208
|
-
"""
|
|
209
|
-
|
|
210
|
-
if package_type not in CHARMSTORE_VALID_PACKAGE_TYPES:
|
|
211
|
-
raise ValueError(
|
|
212
|
-
"Invalid package type. Expected one of: %s"
|
|
213
|
-
% CHARMSTORE_VALID_PACKAGE_TYPES
|
|
214
|
-
)
|
|
215
|
-
|
|
216
|
-
response = self.session.get(
|
|
217
|
-
url=self.get_endpoint_url(f"{package_type}/{name}"),
|
|
218
|
-
headers=self._get_authorization_header(publisher_auth),
|
|
219
|
-
)
|
|
220
|
-
|
|
221
|
-
return self.process_response(response)["metadata"]
|
|
222
|
-
|
|
223
|
-
def update_package_metadata(
|
|
224
|
-
self, publisher_auth, package_type, name, data
|
|
225
|
-
):
|
|
226
|
-
"""
|
|
227
|
-
Update general metadata for a package.
|
|
228
|
-
Documentation:
|
|
229
|
-
https://api.charmhub.io/docs/default.html#update_package_metadata
|
|
230
|
-
Endpoint URL: [PATCH]
|
|
231
|
-
https://api.charmhub.io/v1/charm/<name>
|
|
232
|
-
namespace: charm for both charms and bundles
|
|
233
|
-
name: Package name
|
|
234
|
-
|
|
235
|
-
Args:
|
|
236
|
-
publisher_auth: Serialized macaroon to consume the API.
|
|
237
|
-
package_type: Type of packages to obtain.
|
|
238
|
-
name: Package name
|
|
239
|
-
data: Dict with changes to apply
|
|
240
|
-
|
|
241
|
-
Returns:
|
|
242
|
-
Package general metadata with changes applied
|
|
243
|
-
"""
|
|
244
|
-
|
|
245
|
-
if package_type not in CHARMSTORE_VALID_PACKAGE_TYPES:
|
|
246
|
-
raise ValueError(
|
|
247
|
-
"Invalid package type. Expected one of: %s"
|
|
248
|
-
% CHARMSTORE_VALID_PACKAGE_TYPES
|
|
249
|
-
)
|
|
250
|
-
|
|
251
|
-
response = self.session.patch(
|
|
252
|
-
url=self.get_endpoint_url(f"{package_type}/{name}"),
|
|
253
|
-
headers=self._get_authorization_header(publisher_auth),
|
|
254
|
-
json=data,
|
|
255
|
-
)
|
|
256
|
-
|
|
257
|
-
return self.process_response(response)["metadata"]
|
|
258
|
-
|
|
259
|
-
def register_package_name(self, publisher_auth, data):
|
|
260
|
-
"""
|
|
261
|
-
Register a package name.
|
|
262
|
-
Documentation: https://api.charmhub.io/docs/default.html#register_name
|
|
263
|
-
Endpoint URL: [POST] https://api.charmhub.io/v1/charm
|
|
264
|
-
|
|
265
|
-
Args:
|
|
266
|
-
publisher_auth: Serialized macaroon to consume the API.
|
|
267
|
-
data: Dict with name, type and visibility of the package
|
|
268
|
-
|
|
269
|
-
Returns:
|
|
270
|
-
Newly registered name id
|
|
271
|
-
"""
|
|
272
|
-
|
|
273
|
-
response = self.session.post(
|
|
274
|
-
url=self.get_endpoint_url("charm"),
|
|
275
|
-
headers=self._get_authorization_header(publisher_auth),
|
|
276
|
-
json=data,
|
|
277
|
-
)
|
|
278
|
-
|
|
279
|
-
return self.process_response(response)
|
|
280
|
-
|
|
281
|
-
def unregister_package_name(self, publisher_auth, name):
|
|
282
|
-
"""
|
|
283
|
-
Unregister a package name.
|
|
284
|
-
Documentation:
|
|
285
|
-
https://api.charmhub.io/docs/default.html#unregister_package
|
|
286
|
-
Endpoint URL: [DELETE] https://api.charmhub.io/v1/charm/<name>
|
|
287
|
-
|
|
288
|
-
Args:
|
|
289
|
-
publisher_auth: Serialized macaroon to consume the API.
|
|
290
|
-
name: Name of the package to unregister
|
|
291
|
-
Returns:
|
|
292
|
-
The package name ID if successful
|
|
293
|
-
Otherwise, returns an error list
|
|
294
|
-
"""
|
|
295
|
-
url = self.get_endpoint_url(f"charm/{name}")
|
|
296
|
-
response = self.session.delete(
|
|
297
|
-
url=url,
|
|
298
|
-
headers=self._get_authorization_header(publisher_auth),
|
|
299
|
-
)
|
|
300
|
-
return response
|
|
301
|
-
|
|
302
|
-
def get_charm_libraries(self, charm_name):
|
|
303
|
-
"""
|
|
304
|
-
Get libraries for a charm.
|
|
305
|
-
Documentation:
|
|
306
|
-
https://api.charmhub.io/docs/libraries.html#fetch_libraries
|
|
307
|
-
Endpoint URL: [POST] https://api.charmhub.io/v1/charm/libraries/bulk
|
|
308
|
-
"""
|
|
309
|
-
response = self.session.post(
|
|
310
|
-
url=self.get_endpoint_url("charm/libraries/bulk"),
|
|
311
|
-
json=[{"charm-name": charm_name}],
|
|
312
|
-
)
|
|
313
|
-
|
|
314
|
-
return self.process_response(response)
|
|
315
|
-
|
|
316
|
-
def get_charm_library(self, charm_name, library_id, api_version=None):
|
|
317
|
-
"""
|
|
318
|
-
Get library metadata and content
|
|
319
|
-
Documentation:
|
|
320
|
-
https://api.charmhub.io/docs/libraries.html#fetch_library
|
|
321
|
-
Endpoint URL: [GET]
|
|
322
|
-
https://api.charmhub.io/v1/charm/libraries/<charm_name>/<library_id>
|
|
323
|
-
|
|
324
|
-
Args:
|
|
325
|
-
charm_name: Name of the charm
|
|
326
|
-
library_id: ID of the library
|
|
327
|
-
api_version: API version to use
|
|
328
|
-
"""
|
|
329
|
-
params = {}
|
|
330
|
-
|
|
331
|
-
if api_version is not None:
|
|
332
|
-
params["api"] = api_version
|
|
333
|
-
|
|
334
|
-
response = self.session.get(
|
|
335
|
-
url=self.get_endpoint_url(
|
|
336
|
-
f"charm/libraries/{charm_name}/{library_id}"
|
|
337
|
-
),
|
|
338
|
-
params=params,
|
|
339
|
-
)
|
|
340
|
-
|
|
341
|
-
return self.process_response(response)
|
|
342
|
-
|
|
343
|
-
def get_releases(self, publisher_auth, name):
|
|
344
|
-
"""
|
|
345
|
-
List of all releases for a package.
|
|
346
|
-
Documentation:
|
|
347
|
-
https://api.charmhub.io/docs/default.html#list_releases
|
|
348
|
-
Endpoint URL: [GET]
|
|
349
|
-
https://api.charmhub.io/v1/charm/<name>/releases
|
|
350
|
-
|
|
351
|
-
Args:
|
|
352
|
-
publisher_auth: Serialized macaroon to consume the API.
|
|
353
|
-
name: Name of the package
|
|
354
|
-
"""
|
|
355
|
-
response = self.session.get(
|
|
356
|
-
url=self.get_endpoint_url(f"charm/{name}/releases"),
|
|
357
|
-
headers=self._get_authorization_header(publisher_auth),
|
|
358
|
-
)
|
|
359
|
-
return self.process_response(response)
|
|
360
|
-
|
|
361
|
-
def get_collaborators(self, publisher_auth, name):
|
|
362
|
-
"""
|
|
363
|
-
Get collaborators (accepted invites) for the given package.
|
|
364
|
-
Documentation:
|
|
365
|
-
https://api.charmhub.io/docs/collaborator.html#get_collaborators
|
|
366
|
-
Endpoint URL: [GET]
|
|
367
|
-
https://api.charmhub.io/v1/charm/<name>/collaborators
|
|
368
|
-
|
|
369
|
-
Args:
|
|
370
|
-
publisher_auth: Serialized macaroon to consume the API.
|
|
371
|
-
name: Name of the package
|
|
372
|
-
"""
|
|
373
|
-
response = self.session.get(
|
|
374
|
-
url=self.get_endpoint_url(f"charm/{name}/collaborators"),
|
|
375
|
-
headers=self._get_authorization_header(publisher_auth),
|
|
376
|
-
)
|
|
377
|
-
return self.process_response(response)
|
|
378
|
-
|
|
379
|
-
def get_pending_invites(self, publisher_auth, name):
|
|
380
|
-
"""
|
|
381
|
-
Get pending collaborator invites for the given package.
|
|
382
|
-
Documentation:
|
|
383
|
-
https://api.charmhub.io/docs/collaborator.html#get_pending_invites
|
|
384
|
-
Endpoint URL: [GET]
|
|
385
|
-
https://api.charmhub.io/v1/charm/<name>/collaborators/invites
|
|
386
|
-
|
|
387
|
-
Args:
|
|
388
|
-
publisher_auth: Serialized macaroon to consume the API.
|
|
389
|
-
name: Name of the package
|
|
390
|
-
"""
|
|
391
|
-
response = self.session.get(
|
|
392
|
-
url=self.get_endpoint_url(f"charm/{name}/collaborators/invites"),
|
|
393
|
-
headers=self._get_authorization_header(publisher_auth),
|
|
394
|
-
)
|
|
395
|
-
return self.process_response(response)
|
|
396
|
-
|
|
397
|
-
def invite_collaborators(self, publisher_auth, name, emails):
|
|
398
|
-
"""
|
|
399
|
-
Invite one or more collaborators for a package.
|
|
400
|
-
Documentation:
|
|
401
|
-
https://api.charmhub.io/docs/collaborator.html#invite_collaborators
|
|
402
|
-
Endpoint URL: [POST]
|
|
403
|
-
https://api.charmhub.io/v1/charm/<name>/collaborators/invites
|
|
404
|
-
|
|
405
|
-
Args:
|
|
406
|
-
publisher_auth: Serialized macaroon to consume the API.
|
|
407
|
-
name: Name of the package
|
|
408
|
-
emails: List of emails to invite
|
|
409
|
-
"""
|
|
410
|
-
payload = {"invites": []}
|
|
411
|
-
|
|
412
|
-
for email in emails:
|
|
413
|
-
payload["invites"].append({"email": email})
|
|
414
|
-
|
|
415
|
-
response = self.session.post(
|
|
416
|
-
url=self.get_endpoint_url(f"charm/{name}/collaborators/invites"),
|
|
417
|
-
headers=self._get_authorization_header(publisher_auth),
|
|
418
|
-
json=payload,
|
|
419
|
-
)
|
|
420
|
-
return self.process_response(response)
|
|
421
|
-
|
|
422
|
-
def revoke_invites(self, publisher_auth, name, emails):
|
|
423
|
-
"""
|
|
424
|
-
Revoke invites to the specified emails for the package.
|
|
425
|
-
Documentation:
|
|
426
|
-
https://api.charmhub.io/docs/collaborator.html#revoke_invites
|
|
427
|
-
Endpoint URL: [POST]
|
|
428
|
-
https://api.charmhub.io/v1/charm/<name>/collaborators/invites/revoke
|
|
429
|
-
|
|
430
|
-
Args:
|
|
431
|
-
publisher_auth: Serialized macaroon to consume the API.
|
|
432
|
-
name: Name of the package
|
|
433
|
-
emails: List of emails to revoke
|
|
434
|
-
"""
|
|
435
|
-
payload = {"invites": []}
|
|
436
|
-
|
|
437
|
-
for email in emails:
|
|
438
|
-
payload["invites"].append({"email": email})
|
|
439
|
-
|
|
440
|
-
response = self.session.post(
|
|
441
|
-
url=self.get_endpoint_url(
|
|
442
|
-
f"charm/{name}/collaborators/invites/revoke"
|
|
443
|
-
),
|
|
444
|
-
headers=self._get_authorization_header(publisher_auth),
|
|
445
|
-
json=payload,
|
|
446
|
-
)
|
|
447
|
-
return response
|
|
448
|
-
|
|
449
|
-
def accept_invite(self, publisher_auth, name, token):
|
|
450
|
-
"""
|
|
451
|
-
Accept a collaborator invite.
|
|
452
|
-
Documentation:
|
|
453
|
-
https://api.charmhub.io/docs/collaborator.html#accept_invite
|
|
454
|
-
Endpoint URL: [POST]
|
|
455
|
-
https://api.charmhub.io/v1/charm/<name>/collaborators/invites/accept
|
|
456
|
-
|
|
457
|
-
Args:
|
|
458
|
-
publisher_auth: Serialized macaroon to consume the API.
|
|
459
|
-
name: Name of the package
|
|
460
|
-
token: Invite token
|
|
461
|
-
"""
|
|
462
|
-
response = self.session.post(
|
|
463
|
-
url=self.get_endpoint_url(
|
|
464
|
-
f"charm/{name}/collaborators/invites/accept"
|
|
465
|
-
),
|
|
466
|
-
headers=self._get_authorization_header(publisher_auth),
|
|
467
|
-
json={"token": token},
|
|
468
|
-
)
|
|
469
|
-
return response
|
|
470
|
-
|
|
471
|
-
def reject_invite(self, publisher_auth, name, token):
|
|
472
|
-
"""
|
|
473
|
-
Reject a collaborator invite.
|
|
474
|
-
Documentation:
|
|
475
|
-
https://api.charmhub.io/docs/collaborator.html#reject_invite
|
|
476
|
-
Endpoint URL: [POST]
|
|
477
|
-
https://api.charmhub.io/v1/charm/<name>/collaborators/invites/reject
|
|
478
|
-
|
|
479
|
-
Args:
|
|
480
|
-
publisher_auth: Serialized macaroon to consume the API.
|
|
481
|
-
name: Name of the package
|
|
482
|
-
token: Invite token
|
|
483
|
-
"""
|
|
484
|
-
response = self.session.post(
|
|
485
|
-
url=self.get_endpoint_url(
|
|
486
|
-
f"charm/{name}/collaborators/invites/reject"
|
|
487
|
-
),
|
|
488
|
-
headers=self._get_authorization_header(publisher_auth),
|
|
489
|
-
json={"token": token},
|
|
490
|
-
)
|
|
491
|
-
return response
|
|
492
|
-
|
|
493
|
-
def create_track(
|
|
494
|
-
self,
|
|
495
|
-
publisher_auth,
|
|
496
|
-
charm_name,
|
|
497
|
-
track_name,
|
|
498
|
-
version_pattern=None,
|
|
499
|
-
auto_phasing_percentage=None,
|
|
500
|
-
):
|
|
501
|
-
"""
|
|
502
|
-
Create a track for a charm base on the charm's guardrail pattern.
|
|
503
|
-
Documentation: https://api.charmhub.io/docs/default.html#create_tracks
|
|
504
|
-
Endpoint URL: [POST]
|
|
505
|
-
https://api.charmhub.io/v1/charm/<charm_name>/tracks
|
|
506
|
-
|
|
507
|
-
Args:
|
|
508
|
-
publisher_auth: Serialized macaroon to consume the API.
|
|
509
|
-
charm_name: Name of the charm
|
|
510
|
-
track_name: Name of the track
|
|
511
|
-
version_pattern: Version pattern for the track (optional)
|
|
512
|
-
auto_phasing_percentage: phasing percentage for track (optional)
|
|
513
|
-
"""
|
|
514
|
-
|
|
515
|
-
payload = {
|
|
516
|
-
"name": track_name,
|
|
517
|
-
"version-pattern": version_pattern,
|
|
518
|
-
"automatic-phasing-percentage": auto_phasing_percentage,
|
|
519
|
-
}
|
|
520
|
-
response = self.session.post(
|
|
521
|
-
url=self.get_endpoint_url(f"charm/{charm_name}/tracks"),
|
|
522
|
-
headers=self._get_authorization_header(publisher_auth),
|
|
523
|
-
json=[payload],
|
|
524
|
-
)
|
|
525
|
-
return response
|