cloudsmith-cli 1.20.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.
- cloudsmith_cli/__init__.py +10 -0
- cloudsmith_cli/__main__.py +8 -0
- cloudsmith_cli/cli/__init__.py +1 -0
- cloudsmith_cli/cli/command.py +160 -0
- cloudsmith_cli/cli/commands/__init__.py +33 -0
- cloudsmith_cli/cli/commands/auth.py +173 -0
- cloudsmith_cli/cli/commands/check.py +129 -0
- cloudsmith_cli/cli/commands/copy.py +98 -0
- cloudsmith_cli/cli/commands/credential_helper/__init__.py +39 -0
- cloudsmith_cli/cli/commands/credential_helper/docker.py +66 -0
- cloudsmith_cli/cli/commands/credential_helper/manage.py +299 -0
- cloudsmith_cli/cli/commands/delete.py +67 -0
- cloudsmith_cli/cli/commands/dependencies.py +108 -0
- cloudsmith_cli/cli/commands/docs.py +16 -0
- cloudsmith_cli/cli/commands/download.py +620 -0
- cloudsmith_cli/cli/commands/entitlements.py +819 -0
- cloudsmith_cli/cli/commands/help_.py +12 -0
- cloudsmith_cli/cli/commands/list_.py +317 -0
- cloudsmith_cli/cli/commands/login.py +99 -0
- cloudsmith_cli/cli/commands/logout.py +151 -0
- cloudsmith_cli/cli/commands/main.py +73 -0
- cloudsmith_cli/cli/commands/mcp.py +523 -0
- cloudsmith_cli/cli/commands/metadata.py +503 -0
- cloudsmith_cli/cli/commands/metrics/__init__.py +2 -0
- cloudsmith_cli/cli/commands/metrics/command.py +20 -0
- cloudsmith_cli/cli/commands/metrics/entitlements.py +148 -0
- cloudsmith_cli/cli/commands/metrics/packages.py +134 -0
- cloudsmith_cli/cli/commands/move.py +111 -0
- cloudsmith_cli/cli/commands/policy/__init__.py +3 -0
- cloudsmith_cli/cli/commands/policy/command.py +20 -0
- cloudsmith_cli/cli/commands/policy/deny.py +248 -0
- cloudsmith_cli/cli/commands/policy/license.py +335 -0
- cloudsmith_cli/cli/commands/policy/vulnerability.py +322 -0
- cloudsmith_cli/cli/commands/push.py +1323 -0
- cloudsmith_cli/cli/commands/quarantine.py +148 -0
- cloudsmith_cli/cli/commands/quota/__init__.py +2 -0
- cloudsmith_cli/cli/commands/quota/command.py +20 -0
- cloudsmith_cli/cli/commands/quota/history.py +122 -0
- cloudsmith_cli/cli/commands/quota/quota.py +107 -0
- cloudsmith_cli/cli/commands/repos.py +330 -0
- cloudsmith_cli/cli/commands/resync.py +90 -0
- cloudsmith_cli/cli/commands/status.py +92 -0
- cloudsmith_cli/cli/commands/tags.py +375 -0
- cloudsmith_cli/cli/commands/tokens.py +318 -0
- cloudsmith_cli/cli/commands/upstream.py +479 -0
- cloudsmith_cli/cli/commands/vulnerabilities.py +141 -0
- cloudsmith_cli/cli/commands/whoami.py +188 -0
- cloudsmith_cli/cli/config.py +635 -0
- cloudsmith_cli/cli/decorators.py +624 -0
- cloudsmith_cli/cli/exceptions.py +215 -0
- cloudsmith_cli/cli/metadata_common.py +146 -0
- cloudsmith_cli/cli/saml.py +109 -0
- cloudsmith_cli/cli/table.py +59 -0
- cloudsmith_cli/cli/types.py +14 -0
- cloudsmith_cli/cli/utils.py +267 -0
- cloudsmith_cli/cli/validators.py +378 -0
- cloudsmith_cli/cli/webserver.py +263 -0
- cloudsmith_cli/core/__init__.py +1 -0
- cloudsmith_cli/core/api/__init__.py +1 -0
- cloudsmith_cli/core/api/distros.py +31 -0
- cloudsmith_cli/core/api/entitlements.py +130 -0
- cloudsmith_cli/core/api/exceptions.py +57 -0
- cloudsmith_cli/core/api/files.py +131 -0
- cloudsmith_cli/core/api/init.py +109 -0
- cloudsmith_cli/core/api/metadata.py +217 -0
- cloudsmith_cli/core/api/metrics.py +78 -0
- cloudsmith_cli/core/api/orgs.py +201 -0
- cloudsmith_cli/core/api/packages.py +309 -0
- cloudsmith_cli/core/api/quota.py +64 -0
- cloudsmith_cli/core/api/rates.py +28 -0
- cloudsmith_cli/core/api/repos.py +81 -0
- cloudsmith_cli/core/api/status.py +27 -0
- cloudsmith_cli/core/api/upstreams.py +72 -0
- cloudsmith_cli/core/api/user.py +109 -0
- cloudsmith_cli/core/api/version.py +15 -0
- cloudsmith_cli/core/api/vulnerabilities.py +230 -0
- cloudsmith_cli/core/cache_utils.py +160 -0
- cloudsmith_cli/core/config.py +140 -0
- cloudsmith_cli/core/credentials/__init__.py +0 -0
- cloudsmith_cli/core/credentials/chain.py +69 -0
- cloudsmith_cli/core/credentials/models.py +44 -0
- cloudsmith_cli/core/credentials/oidc/__init__.py +6 -0
- cloudsmith_cli/core/credentials/oidc/cache.py +220 -0
- cloudsmith_cli/core/credentials/oidc/detectors/__init__.py +122 -0
- cloudsmith_cli/core/credentials/oidc/detectors/aws.py +85 -0
- cloudsmith_cli/core/credentials/oidc/detectors/azure_devops.py +70 -0
- cloudsmith_cli/core/credentials/oidc/detectors/base.py +26 -0
- cloudsmith_cli/core/credentials/oidc/detectors/bitbucket_pipelines.py +35 -0
- cloudsmith_cli/core/credentials/oidc/detectors/circleci.py +40 -0
- cloudsmith_cli/core/credentials/oidc/detectors/generic.py +42 -0
- cloudsmith_cli/core/credentials/oidc/detectors/github_actions.py +64 -0
- cloudsmith_cli/core/credentials/oidc/detectors/gitlab_ci.py +49 -0
- cloudsmith_cli/core/credentials/oidc/exchange.py +87 -0
- cloudsmith_cli/core/credentials/provider.py +17 -0
- cloudsmith_cli/core/credentials/providers/__init__.py +15 -0
- cloudsmith_cli/core/credentials/providers/cli_flag.py +24 -0
- cloudsmith_cli/core/credentials/providers/credentials_file.py +24 -0
- cloudsmith_cli/core/credentials/providers/env_var.py +24 -0
- cloudsmith_cli/core/credentials/providers/keyring_provider.py +59 -0
- cloudsmith_cli/core/credentials/providers/oidc_provider.py +115 -0
- cloudsmith_cli/core/download.py +594 -0
- cloudsmith_cli/core/keyring.py +171 -0
- cloudsmith_cli/core/mcp/__init__.py +0 -0
- cloudsmith_cli/core/mcp/data.py +17 -0
- cloudsmith_cli/core/mcp/server.py +786 -0
- cloudsmith_cli/core/pagination.py +131 -0
- cloudsmith_cli/core/ratelimits.py +88 -0
- cloudsmith_cli/core/rest.py +255 -0
- cloudsmith_cli/core/utils.py +95 -0
- cloudsmith_cli/core/version.py +20 -0
- cloudsmith_cli/credential_helpers/__init__.py +7 -0
- cloudsmith_cli/credential_helpers/backends.py +41 -0
- cloudsmith_cli/credential_helpers/common.py +111 -0
- cloudsmith_cli/credential_helpers/custom_domains.py +281 -0
- cloudsmith_cli/credential_helpers/docker/__init__.py +4 -0
- cloudsmith_cli/credential_helpers/docker/installer.py +349 -0
- cloudsmith_cli/credential_helpers/docker/runtime.py +117 -0
- cloudsmith_cli/credential_helpers/launchers.py +175 -0
- cloudsmith_cli/data/VERSION +1 -0
- cloudsmith_cli/data/config.ini +23 -0
- cloudsmith_cli/data/credentials.ini +14 -0
- cloudsmith_cli/templates/__init__.py +3 -0
- cloudsmith_cli/templates/auth_error.html +45 -0
- cloudsmith_cli/templates/auth_success.html +37 -0
- cloudsmith_cli-1.20.0.dist-info/METADATA +610 -0
- cloudsmith_cli-1.20.0.dist-info/RECORD +130 -0
- cloudsmith_cli-1.20.0.dist-info/WHEEL +5 -0
- cloudsmith_cli-1.20.0.dist-info/entry_points.txt +2 -0
- cloudsmith_cli-1.20.0.dist-info/licenses/LICENSE +201 -0
- cloudsmith_cli-1.20.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
"""API - Packages endpoints."""
|
|
2
|
+
|
|
3
|
+
import inspect
|
|
4
|
+
|
|
5
|
+
import cloudsmith_api
|
|
6
|
+
from cloudsmith_api.models import PackageQuarantineRequest
|
|
7
|
+
|
|
8
|
+
from .. import ratelimits, utils
|
|
9
|
+
from ..pagination import PageInfo
|
|
10
|
+
from .exceptions import catch_raise_api_exception
|
|
11
|
+
from .init import get_api_client
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def get_packages_api():
|
|
15
|
+
"""Get the packages API client."""
|
|
16
|
+
return get_api_client(cloudsmith_api.PackagesApi)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def make_create_payload(**kwargs):
|
|
20
|
+
"""Create payload for upload/check-upload operations."""
|
|
21
|
+
payload = {}
|
|
22
|
+
# Add non-empty arguments
|
|
23
|
+
for k, v in kwargs.items():
|
|
24
|
+
if v is not None:
|
|
25
|
+
payload[k] = v
|
|
26
|
+
|
|
27
|
+
return payload
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def create_package(package_format, owner, repo, **kwargs):
|
|
31
|
+
"""Create a new package in a repository."""
|
|
32
|
+
client = get_packages_api()
|
|
33
|
+
|
|
34
|
+
with catch_raise_api_exception():
|
|
35
|
+
upload = getattr(client, "packages_upload_%s_with_http_info" % package_format)
|
|
36
|
+
|
|
37
|
+
data, _, headers = upload(
|
|
38
|
+
owner=owner, repo=repo, data=make_create_payload(**kwargs)
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
ratelimits.maybe_rate_limit(client, headers)
|
|
42
|
+
return data.slug_perm, data.slug
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def validate_create_package(package_format, owner, repo, **kwargs):
|
|
46
|
+
"""Validate parameters for creating a package."""
|
|
47
|
+
client = get_packages_api()
|
|
48
|
+
|
|
49
|
+
with catch_raise_api_exception():
|
|
50
|
+
check = getattr(
|
|
51
|
+
client, "packages_validate_upload_%s_with_http_info" % package_format
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
_, _, headers = check(
|
|
55
|
+
owner=owner, repo=repo, data=make_create_payload(**kwargs)
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
ratelimits.maybe_rate_limit(client, headers)
|
|
59
|
+
return True
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def copy_package(owner, repo, identifier, destination):
|
|
63
|
+
"""Copy a package to another repository."""
|
|
64
|
+
client = get_packages_api()
|
|
65
|
+
|
|
66
|
+
with catch_raise_api_exception():
|
|
67
|
+
data, _, headers = client.packages_copy_with_http_info(
|
|
68
|
+
owner=owner,
|
|
69
|
+
repo=repo,
|
|
70
|
+
identifier=identifier,
|
|
71
|
+
data={"destination": destination},
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
ratelimits.maybe_rate_limit(client, headers)
|
|
75
|
+
return data.slug_perm, data.slug
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def move_package(owner, repo, identifier, destination):
|
|
79
|
+
"""Move a package to another repository."""
|
|
80
|
+
client = get_packages_api()
|
|
81
|
+
|
|
82
|
+
with catch_raise_api_exception():
|
|
83
|
+
data, _, headers = client.packages_move_with_http_info(
|
|
84
|
+
owner=owner,
|
|
85
|
+
repo=repo,
|
|
86
|
+
identifier=identifier,
|
|
87
|
+
data={"destination": destination},
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
ratelimits.maybe_rate_limit(client, headers)
|
|
91
|
+
return data.slug_perm, data.slug
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def delete_package(owner, repo, identifier):
|
|
95
|
+
"""Delete a package in a repository."""
|
|
96
|
+
client = get_packages_api()
|
|
97
|
+
|
|
98
|
+
with catch_raise_api_exception():
|
|
99
|
+
_, _, headers = client.packages_delete_with_http_info(
|
|
100
|
+
owner=owner, repo=repo, identifier=identifier
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
ratelimits.maybe_rate_limit(client, headers)
|
|
104
|
+
return True
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def resync_package(owner, repo, identifier):
|
|
108
|
+
"""Resync a package in a repository."""
|
|
109
|
+
client = get_packages_api()
|
|
110
|
+
|
|
111
|
+
with catch_raise_api_exception():
|
|
112
|
+
data, _, headers = client.packages_resync_with_http_info(
|
|
113
|
+
owner=owner, repo=repo, identifier=identifier
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
ratelimits.maybe_rate_limit(client, headers)
|
|
117
|
+
return data.slug_perm, data.slug
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def quarantine_package(owner, repo, identifier):
|
|
121
|
+
"""Quarantine a package."""
|
|
122
|
+
client = get_packages_api()
|
|
123
|
+
|
|
124
|
+
with catch_raise_api_exception():
|
|
125
|
+
data, _, headers = client.packages_quarantine_with_http_info(
|
|
126
|
+
owner=owner, repo=repo, identifier=identifier
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
ratelimits.maybe_rate_limit(client, headers)
|
|
130
|
+
return data.slug_perm, data.slug
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def quarantine_restore_package(owner, repo, identifier):
|
|
134
|
+
"""Restorea a package from quarantine."""
|
|
135
|
+
client = get_packages_api()
|
|
136
|
+
|
|
137
|
+
with catch_raise_api_exception():
|
|
138
|
+
data, _, headers = client.packages_quarantine_with_http_info(
|
|
139
|
+
owner=owner,
|
|
140
|
+
repo=repo,
|
|
141
|
+
identifier=identifier,
|
|
142
|
+
data=PackageQuarantineRequest(restore=True),
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
ratelimits.maybe_rate_limit(client, headers)
|
|
146
|
+
return data.slug_perm, data.slug
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def tag_package(owner, repo, identifier, data):
|
|
150
|
+
"""Manage tags for a package in a repository."""
|
|
151
|
+
client = get_packages_api()
|
|
152
|
+
|
|
153
|
+
with catch_raise_api_exception():
|
|
154
|
+
data, _, headers = client.packages_tag_with_http_info(
|
|
155
|
+
owner=owner, repo=repo, identifier=identifier, data=data
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
ratelimits.maybe_rate_limit(client, headers)
|
|
159
|
+
return data.tags, data.tags_immutable
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def get_package_status(owner, repo, identifier):
|
|
163
|
+
"""Get the status for a package in a repository."""
|
|
164
|
+
client = get_packages_api()
|
|
165
|
+
|
|
166
|
+
with catch_raise_api_exception():
|
|
167
|
+
data, _, headers = client.packages_status_with_http_info(
|
|
168
|
+
owner=owner, repo=repo, identifier=identifier
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
ratelimits.maybe_rate_limit(client, headers)
|
|
172
|
+
|
|
173
|
+
# pylint: disable=no-member
|
|
174
|
+
# Pylint detects the returned value as a tuple
|
|
175
|
+
return (
|
|
176
|
+
data.is_sync_completed,
|
|
177
|
+
data.is_sync_failed,
|
|
178
|
+
data.sync_progress,
|
|
179
|
+
data.status_str,
|
|
180
|
+
data.stage_str,
|
|
181
|
+
data.status_reason,
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def get_package_dependencies(owner, repo, identifier, **kwargs):
|
|
186
|
+
"""Get the direct dependencies for a package in a repository."""
|
|
187
|
+
client = get_packages_api()
|
|
188
|
+
|
|
189
|
+
with catch_raise_api_exception():
|
|
190
|
+
data, _, headers = client.packages_dependencies_with_http_info(
|
|
191
|
+
owner=owner, repo=repo, identifier=identifier, **kwargs
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
ratelimits.maybe_rate_limit(client, headers)
|
|
195
|
+
|
|
196
|
+
# pylint: disable=no-member
|
|
197
|
+
# Pylint detects the returned value as a tuple
|
|
198
|
+
page_info = PageInfo.from_headers(headers)
|
|
199
|
+
return [x.to_dict() for x in data.dependencies], page_info
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def get_package_tags(owner, repo, identifier):
|
|
203
|
+
"""Get the tags for a package in a repository."""
|
|
204
|
+
client = get_packages_api()
|
|
205
|
+
|
|
206
|
+
with catch_raise_api_exception():
|
|
207
|
+
data, _, headers = client.packages_read_with_http_info(
|
|
208
|
+
owner=owner, repo=repo, identifier=identifier
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
ratelimits.maybe_rate_limit(client, headers)
|
|
212
|
+
|
|
213
|
+
# pylint: disable=no-member
|
|
214
|
+
# Pylint detects the returned value as a tuple
|
|
215
|
+
return (data.tags, data.tags_immutable)
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def get_package_slug_perm(owner, repo, identifier):
|
|
219
|
+
"""Resolve a package's permanent slug from owner/repo/identifier.
|
|
220
|
+
|
|
221
|
+
Used by metadata commands that address packages by slug_perm.
|
|
222
|
+
"""
|
|
223
|
+
client = get_packages_api()
|
|
224
|
+
|
|
225
|
+
with catch_raise_api_exception():
|
|
226
|
+
data, _, headers = client.packages_read_with_http_info(
|
|
227
|
+
owner=owner, repo=repo, identifier=identifier
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
ratelimits.maybe_rate_limit(client, headers)
|
|
231
|
+
|
|
232
|
+
# pylint: disable=no-member
|
|
233
|
+
return data.slug_perm
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def list_packages(owner, repo, **kwargs):
|
|
237
|
+
"""List packages for a repository."""
|
|
238
|
+
client = get_packages_api()
|
|
239
|
+
|
|
240
|
+
api_kwargs = {}
|
|
241
|
+
api_kwargs.update(utils.get_page_kwargs(**kwargs))
|
|
242
|
+
api_kwargs.update(utils.get_query_kwargs(**kwargs))
|
|
243
|
+
api_kwargs.update(utils.get_sort_kwargs(**kwargs))
|
|
244
|
+
|
|
245
|
+
with catch_raise_api_exception():
|
|
246
|
+
data, _, headers = client.packages_list_with_http_info(
|
|
247
|
+
owner=owner, repo=repo, **api_kwargs
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
ratelimits.maybe_rate_limit(client, headers)
|
|
251
|
+
page_info = PageInfo.from_headers(headers)
|
|
252
|
+
return [x.to_dict() for x in data], page_info
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def get_package_formats():
|
|
256
|
+
"""Get the list of available package formats and parameters."""
|
|
257
|
+
|
|
258
|
+
# pylint: disable=fixme
|
|
259
|
+
# HACK: This obviously isn't great, and it is subject to change as
|
|
260
|
+
# the API changes, but it'll do for now as a interim method of
|
|
261
|
+
# introspection to get the parameters we need.
|
|
262
|
+
def get_parameters(cls):
|
|
263
|
+
"""Build parameters for a package format."""
|
|
264
|
+
params = {}
|
|
265
|
+
|
|
266
|
+
# Create a dummy instance so we can check if a parameter is required.
|
|
267
|
+
# As with the rest of this function, this is obviously hacky. We'll
|
|
268
|
+
# figure out a way to pull this information in from the API later.
|
|
269
|
+
dummy_kwargs = {k: "dummy" for k in cls.swagger_types}
|
|
270
|
+
instance = cls(**dummy_kwargs)
|
|
271
|
+
|
|
272
|
+
for k, v in cls.swagger_types.items():
|
|
273
|
+
attr = getattr(cls, k)
|
|
274
|
+
docs = [
|
|
275
|
+
doc.strip() for doc in attr.__doc__.strip().split("\n") if doc.strip()
|
|
276
|
+
]
|
|
277
|
+
doc = (docs[1] if docs[1] else docs[0]).strip()
|
|
278
|
+
|
|
279
|
+
try:
|
|
280
|
+
setattr(instance, k, None)
|
|
281
|
+
required = False
|
|
282
|
+
except ValueError:
|
|
283
|
+
required = True
|
|
284
|
+
|
|
285
|
+
params[cls.attribute_map.get(k)] = {
|
|
286
|
+
"type": v,
|
|
287
|
+
"help": doc,
|
|
288
|
+
"required": required,
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
return params
|
|
292
|
+
|
|
293
|
+
return {
|
|
294
|
+
key.replace("PackageUploadRequest", "").lower(): get_parameters(cls)
|
|
295
|
+
for key, cls in inspect.getmembers(cloudsmith_api.models)
|
|
296
|
+
if "PackageUploadRequest" in key
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
def get_package_format_names(predicate=None):
|
|
301
|
+
"""Get names for available package formats."""
|
|
302
|
+
return [
|
|
303
|
+
k for k, v in get_package_formats().items() if not predicate or predicate(k, v)
|
|
304
|
+
]
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
def get_package_format_names_with_distros():
|
|
308
|
+
"""Get names for package formats that support distributions."""
|
|
309
|
+
return get_package_format_names(lambda k, v: "distribution" in v)
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"""API - Quota endpoints."""
|
|
2
|
+
|
|
3
|
+
import cloudsmith_api
|
|
4
|
+
|
|
5
|
+
from .. import ratelimits
|
|
6
|
+
from .exceptions import catch_raise_api_exception
|
|
7
|
+
from .init import get_api_client
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def get_quota_api():
|
|
11
|
+
"""Get the Quota API client."""
|
|
12
|
+
return get_api_client(cloudsmith_api.QuotaApi)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def quota_limits(owner=None, oss=False, **kwargs):
|
|
16
|
+
"""Get Quota for namespace"""
|
|
17
|
+
client = get_quota_api()
|
|
18
|
+
|
|
19
|
+
api_kwargs = {}
|
|
20
|
+
api_kwargs.update(
|
|
21
|
+
{param: value for param, value in kwargs.items() if value is not None}
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
if oss:
|
|
25
|
+
if hasattr(client, "quota_oss_read_with_http_info"):
|
|
26
|
+
with catch_raise_api_exception():
|
|
27
|
+
res, _, headers = client.quota_oss_read_with_http_info(
|
|
28
|
+
owner=owner, **api_kwargs
|
|
29
|
+
)
|
|
30
|
+
elif not oss:
|
|
31
|
+
if hasattr(client, "quota_read_with_http_info"):
|
|
32
|
+
with catch_raise_api_exception():
|
|
33
|
+
res, _, headers = client.quota_read_with_http_info(
|
|
34
|
+
owner=owner, **api_kwargs
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
ratelimits.maybe_rate_limit(client, headers)
|
|
38
|
+
return res if not res else res
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def quota_history(owner=None, oss=False, **kwargs):
|
|
42
|
+
"""Get Quota history for namespace"""
|
|
43
|
+
client = get_quota_api()
|
|
44
|
+
|
|
45
|
+
api_kwargs = {}
|
|
46
|
+
api_kwargs.update(
|
|
47
|
+
{param: value for param, value in kwargs.items() if value is not None}
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
if oss:
|
|
51
|
+
if hasattr(client, "quota_oss_history_read_with_http_info"):
|
|
52
|
+
with catch_raise_api_exception():
|
|
53
|
+
res, _, headers = client.quota_oss_history_read_with_http_info(
|
|
54
|
+
owner=owner, **api_kwargs
|
|
55
|
+
)
|
|
56
|
+
elif not oss:
|
|
57
|
+
if hasattr(client, "quota_history_read_with_http_info"):
|
|
58
|
+
with catch_raise_api_exception():
|
|
59
|
+
res, _, headers = client.quota_history_read_with_http_info(
|
|
60
|
+
owner=owner, **api_kwargs
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
ratelimits.maybe_rate_limit(client, headers)
|
|
64
|
+
return res if not res else res
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""API - Status endpoints."""
|
|
2
|
+
|
|
3
|
+
import cloudsmith_api
|
|
4
|
+
|
|
5
|
+
from .. import ratelimits
|
|
6
|
+
from ..ratelimits import RateLimitsInfo
|
|
7
|
+
from .exceptions import catch_raise_api_exception
|
|
8
|
+
from .init import get_api_client
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def get_rates_api():
|
|
12
|
+
"""Get the status API client."""
|
|
13
|
+
return get_api_client(cloudsmith_api.RatesApi)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def get_rate_limits():
|
|
17
|
+
"""Retrieve status (and optionally) version from the API."""
|
|
18
|
+
client = get_rates_api()
|
|
19
|
+
|
|
20
|
+
with catch_raise_api_exception():
|
|
21
|
+
data, _, headers = client.rates_limits_list_with_http_info()
|
|
22
|
+
|
|
23
|
+
ratelimits.maybe_rate_limit(client, headers)
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
k: RateLimitsInfo.from_dict(v)
|
|
27
|
+
for k, v in data.to_dict().get("resources", {}).items()
|
|
28
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""API - Packages endpoints."""
|
|
2
|
+
|
|
3
|
+
import cloudsmith_api
|
|
4
|
+
|
|
5
|
+
from .. import ratelimits, utils
|
|
6
|
+
from ..pagination import PageInfo
|
|
7
|
+
from .exceptions import catch_raise_api_exception
|
|
8
|
+
from .init import get_api_client
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def get_repos_api():
|
|
12
|
+
"""Get the repos API client."""
|
|
13
|
+
return get_api_client(cloudsmith_api.ReposApi)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def list_repos(owner=None, **kwargs):
|
|
17
|
+
"""List repositories in a namespace."""
|
|
18
|
+
client = get_repos_api()
|
|
19
|
+
|
|
20
|
+
api_kwargs = {}
|
|
21
|
+
api_kwargs.update(utils.get_page_kwargs(**kwargs))
|
|
22
|
+
|
|
23
|
+
if owner:
|
|
24
|
+
repo = kwargs.get("repo", None)
|
|
25
|
+
if repo is not None:
|
|
26
|
+
if hasattr(client, "repos_read_with_http_info"):
|
|
27
|
+
with catch_raise_api_exception():
|
|
28
|
+
res, _, headers = client.repos_read_with_http_info(owner, repo)
|
|
29
|
+
res = [res]
|
|
30
|
+
else:
|
|
31
|
+
api_kwargs["owner"] = owner
|
|
32
|
+
|
|
33
|
+
if hasattr(client, "repos_namespace_list_with_http_info"):
|
|
34
|
+
with catch_raise_api_exception():
|
|
35
|
+
res, _, headers = client.repos_namespace_list_with_http_info(
|
|
36
|
+
**api_kwargs
|
|
37
|
+
)
|
|
38
|
+
else:
|
|
39
|
+
if hasattr(client, "repos_user_list_with_http_info"):
|
|
40
|
+
with catch_raise_api_exception():
|
|
41
|
+
res, _, headers = client.repos_user_list_with_http_info(**api_kwargs)
|
|
42
|
+
|
|
43
|
+
ratelimits.maybe_rate_limit(client, headers)
|
|
44
|
+
page_info = PageInfo.from_headers(headers)
|
|
45
|
+
return [x.to_dict() for x in res], page_info
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def create_repo(owner, repo_config):
|
|
49
|
+
"""Create a repository in a namespace."""
|
|
50
|
+
client = get_repos_api()
|
|
51
|
+
|
|
52
|
+
with catch_raise_api_exception():
|
|
53
|
+
data, _, headers = client.repos_create_with_http_info(
|
|
54
|
+
owner=owner, data=repo_config
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
ratelimits.maybe_rate_limit(client, headers)
|
|
58
|
+
return data.to_dict()
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def update_repo(owner, repo, repo_config):
|
|
62
|
+
"""Update a repo in a namespace."""
|
|
63
|
+
client = get_repos_api()
|
|
64
|
+
|
|
65
|
+
with catch_raise_api_exception():
|
|
66
|
+
data, _, headers = client.repos_partial_update_with_http_info(
|
|
67
|
+
owner, repo, data=repo_config
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
ratelimits.maybe_rate_limit(client, headers)
|
|
71
|
+
return data.to_dict()
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def delete_repo(owner, repo):
|
|
75
|
+
"""Delete a repo from a namespace."""
|
|
76
|
+
client = get_repos_api()
|
|
77
|
+
|
|
78
|
+
with catch_raise_api_exception():
|
|
79
|
+
_, _, headers = client.repos_delete_with_http_info(owner, repo)
|
|
80
|
+
|
|
81
|
+
ratelimits.maybe_rate_limit(client, headers)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""API - Status endpoints."""
|
|
2
|
+
|
|
3
|
+
import cloudsmith_api
|
|
4
|
+
|
|
5
|
+
from .. import ratelimits
|
|
6
|
+
from .exceptions import catch_raise_api_exception
|
|
7
|
+
from .init import get_api_client
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def get_status_api():
|
|
11
|
+
"""Get the status API client."""
|
|
12
|
+
return get_api_client(cloudsmith_api.StatusApi)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def get_status(with_version=False):
|
|
16
|
+
"""Retrieve status (and optionally) version from the API."""
|
|
17
|
+
client = get_status_api()
|
|
18
|
+
|
|
19
|
+
with catch_raise_api_exception():
|
|
20
|
+
data, _, headers = client.status_check_basic_with_http_info()
|
|
21
|
+
|
|
22
|
+
ratelimits.maybe_rate_limit(client, headers)
|
|
23
|
+
|
|
24
|
+
if with_version:
|
|
25
|
+
return data.detail, data.version
|
|
26
|
+
|
|
27
|
+
return data.detail
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"""API - Packages endpoints."""
|
|
2
|
+
|
|
3
|
+
import cloudsmith_api
|
|
4
|
+
|
|
5
|
+
from ...core import utils
|
|
6
|
+
from .. import ratelimits
|
|
7
|
+
from ..pagination import PageInfo
|
|
8
|
+
from .exceptions import catch_raise_api_exception
|
|
9
|
+
from .init import get_api_client
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def get_upstreams_api():
|
|
13
|
+
"""Get the upstreams API client."""
|
|
14
|
+
return get_api_client(cloudsmith_api.ReposApi)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def list_upstreams(owner, repo, upstream_format, page, page_size):
|
|
18
|
+
"""List upstreams by format in a repo."""
|
|
19
|
+
client = get_upstreams_api()
|
|
20
|
+
|
|
21
|
+
func = getattr(client, "repos_upstream_%s_list_with_http_info" % upstream_format)
|
|
22
|
+
|
|
23
|
+
with catch_raise_api_exception():
|
|
24
|
+
upstreams, _, headers = func(
|
|
25
|
+
owner, repo, **utils.get_page_kwargs(page=page, page_size=page_size)
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
ratelimits.maybe_rate_limit(client, headers)
|
|
29
|
+
page_info = PageInfo.from_headers(headers)
|
|
30
|
+
return [upstream.to_dict() for upstream in upstreams], page_info
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def create_upstream(owner, repo, upstream_format, upstream_config):
|
|
34
|
+
"""Create an upstream for a certain package format in a repo."""
|
|
35
|
+
client = get_upstreams_api()
|
|
36
|
+
|
|
37
|
+
func = getattr(client, "repos_upstream_%s_create_with_http_info" % upstream_format)
|
|
38
|
+
|
|
39
|
+
with catch_raise_api_exception():
|
|
40
|
+
upstream, _, headers = func(owner=owner, identifier=repo, data=upstream_config)
|
|
41
|
+
|
|
42
|
+
ratelimits.maybe_rate_limit(client, headers)
|
|
43
|
+
return upstream.to_dict()
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def update_upstream(owner, repo, slug_perm, upstream_format, upstream_config):
|
|
47
|
+
"""Update an upstream belonging to a repo."""
|
|
48
|
+
client = get_upstreams_api()
|
|
49
|
+
|
|
50
|
+
func = getattr(
|
|
51
|
+
client, "repos_upstream_%s_partial_update_with_http_info" % upstream_format
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
with catch_raise_api_exception():
|
|
55
|
+
upstream, _, headers = func(
|
|
56
|
+
owner=owner, identifier=repo, slug_perm=slug_perm, data=upstream_config
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
ratelimits.maybe_rate_limit(client, headers)
|
|
60
|
+
return upstream.to_dict()
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def delete_upstream(owner, repo, upstream_format, slug_perm):
|
|
64
|
+
"""Delete an upstream from a repo."""
|
|
65
|
+
client = get_upstreams_api()
|
|
66
|
+
|
|
67
|
+
func = getattr(client, "repos_upstream_%s_delete_with_http_info" % upstream_format)
|
|
68
|
+
|
|
69
|
+
with catch_raise_api_exception():
|
|
70
|
+
_, _, headers = func(owner, repo, slug_perm)
|
|
71
|
+
|
|
72
|
+
ratelimits.maybe_rate_limit(client, headers)
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"""API - User endpoints."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
|
|
5
|
+
import cloudsmith_api
|
|
6
|
+
from cloudsmith_api.rest import ApiException
|
|
7
|
+
|
|
8
|
+
from .. import ratelimits
|
|
9
|
+
from .exceptions import TwoFactorRequiredException, catch_raise_api_exception
|
|
10
|
+
from .init import get_api_client, unset_api_key
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def get_user_api():
|
|
14
|
+
"""Get the user API client."""
|
|
15
|
+
return get_api_client(cloudsmith_api.UserApi)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def get_user_token(login, password, totp_token=None, two_factor_token=None):
|
|
19
|
+
"""Retrieve user token from the API (via authentication)."""
|
|
20
|
+
client = get_user_api()
|
|
21
|
+
|
|
22
|
+
# Never use API key for the token endpoint
|
|
23
|
+
unset_api_key()
|
|
24
|
+
|
|
25
|
+
# Prepare data based on whether this is initial login or 2FA completion
|
|
26
|
+
if totp_token and two_factor_token:
|
|
27
|
+
data_dict = {
|
|
28
|
+
"totp_token": totp_token,
|
|
29
|
+
"two_factor_token": two_factor_token,
|
|
30
|
+
}
|
|
31
|
+
else:
|
|
32
|
+
data_dict = {
|
|
33
|
+
"email": login,
|
|
34
|
+
"password": password,
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
try:
|
|
38
|
+
data, _, headers = client.user_token_create_with_http_info(data=data_dict)
|
|
39
|
+
ratelimits.maybe_rate_limit(client, headers)
|
|
40
|
+
return data.token
|
|
41
|
+
except ApiException as e:
|
|
42
|
+
# Check for 2FA requirement
|
|
43
|
+
if e.status == 422 and e.body:
|
|
44
|
+
try:
|
|
45
|
+
response_data = json.loads(e.body)
|
|
46
|
+
if response_data.get("two_factor_required"):
|
|
47
|
+
two_factor_token = response_data.get("two_factor_token")
|
|
48
|
+
# Raise custom exception for 2FA requirement
|
|
49
|
+
raise TwoFactorRequiredException(two_factor_token)
|
|
50
|
+
except (ValueError, KeyError):
|
|
51
|
+
pass
|
|
52
|
+
|
|
53
|
+
# If not 2FA, use the context manager to handle other API exceptions
|
|
54
|
+
with catch_raise_api_exception():
|
|
55
|
+
raise
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def create_user_token_saml() -> dict:
|
|
59
|
+
"""Create a new user API token using SAML."""
|
|
60
|
+
client = get_user_api()
|
|
61
|
+
|
|
62
|
+
with catch_raise_api_exception():
|
|
63
|
+
data, _, headers = client.user_tokens_create_with_http_info()
|
|
64
|
+
|
|
65
|
+
ratelimits.maybe_rate_limit(client, headers)
|
|
66
|
+
return data
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def get_user_brief():
|
|
70
|
+
"""Retrieve brief for current user (if any)."""
|
|
71
|
+
client = get_user_api()
|
|
72
|
+
|
|
73
|
+
with catch_raise_api_exception():
|
|
74
|
+
data, _, headers = client.user_self_with_http_info()
|
|
75
|
+
|
|
76
|
+
ratelimits.maybe_rate_limit(client, headers)
|
|
77
|
+
return data.authenticated, data.slug, data.email, data.name
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def list_user_tokens() -> list[dict]:
|
|
81
|
+
"""List all user API tokens."""
|
|
82
|
+
client = get_user_api()
|
|
83
|
+
|
|
84
|
+
with catch_raise_api_exception():
|
|
85
|
+
data, _, headers = client.user_tokens_list_with_http_info()
|
|
86
|
+
|
|
87
|
+
ratelimits.maybe_rate_limit(client, headers)
|
|
88
|
+
return data.results
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def refresh_user_token(token_slug: str) -> dict:
|
|
92
|
+
"""Refresh user API token."""
|
|
93
|
+
client = get_user_api()
|
|
94
|
+
|
|
95
|
+
with catch_raise_api_exception():
|
|
96
|
+
data, _, headers = client.user_tokens_refresh_with_http_info(token_slug)
|
|
97
|
+
|
|
98
|
+
ratelimits.maybe_rate_limit(client, headers)
|
|
99
|
+
return data
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def get_token_metadata() -> dict | None:
|
|
103
|
+
"""Retrieve metadata for the user's first API token.
|
|
104
|
+
|
|
105
|
+
Raises ApiException on failure; callers should handle gracefully.
|
|
106
|
+
"""
|
|
107
|
+
if t := next(iter(list_user_tokens()), None):
|
|
108
|
+
return {"slug": t.slug_perm, "created": t.created}
|
|
109
|
+
return None
|