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,819 @@
|
|
|
1
|
+
"""CLI/Commands - Entitlements."""
|
|
2
|
+
|
|
3
|
+
import functools
|
|
4
|
+
from operator import itemgetter
|
|
5
|
+
|
|
6
|
+
import click
|
|
7
|
+
|
|
8
|
+
from ...core.api import entitlements as api
|
|
9
|
+
from ...core.pagination import paginate_results
|
|
10
|
+
from .. import command, decorators, utils, validators
|
|
11
|
+
from ..exceptions import handle_api_exceptions
|
|
12
|
+
from ..utils import fmt_datetime, maybe_spinner
|
|
13
|
+
from .main import main
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def validate_owner_repo_identifier(ctx, param, value):
|
|
17
|
+
"""Ensure that owner/repo/identifier is formatted correctly."""
|
|
18
|
+
# pylint: disable=unused-argument
|
|
19
|
+
form = "OWNER/REPO/IDENTIFIER"
|
|
20
|
+
return validators.validate_slashes(param, value, minimum=3, maximum=3, form=form)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def common_entitlements_options(f):
|
|
24
|
+
"""Add common options for entitlement commands."""
|
|
25
|
+
|
|
26
|
+
@click.option(
|
|
27
|
+
"--show-tokens",
|
|
28
|
+
default=False,
|
|
29
|
+
is_flag=True,
|
|
30
|
+
help="Show entitlement token string contents in output.",
|
|
31
|
+
)
|
|
32
|
+
@click.pass_context
|
|
33
|
+
@functools.wraps(f)
|
|
34
|
+
def wrapper(ctx, *args, **kwargs):
|
|
35
|
+
# pylint: disable=missing-docstring
|
|
36
|
+
return ctx.invoke(f, *args, **kwargs)
|
|
37
|
+
|
|
38
|
+
return wrapper
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@main.group(cls=command.AliasGroup, aliases=["ents"])
|
|
42
|
+
@decorators.common_cli_config_options
|
|
43
|
+
@decorators.common_cli_output_options
|
|
44
|
+
@decorators.common_api_auth_options
|
|
45
|
+
@decorators.initialise_api
|
|
46
|
+
@click.pass_context
|
|
47
|
+
def entitlements(ctx, opts): # pylint: disable=unused-argument
|
|
48
|
+
"""
|
|
49
|
+
Manage the entitlements for a repository.
|
|
50
|
+
|
|
51
|
+
See the help for subcommands for more information on each.
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def list_entitlements_options(f):
|
|
56
|
+
"""Options for list entitlements subcommand."""
|
|
57
|
+
|
|
58
|
+
@common_entitlements_options
|
|
59
|
+
@decorators.common_cli_config_options
|
|
60
|
+
@decorators.common_cli_list_options
|
|
61
|
+
@decorators.common_cli_output_options
|
|
62
|
+
@decorators.common_api_auth_options
|
|
63
|
+
@decorators.initialise_api
|
|
64
|
+
@click.argument(
|
|
65
|
+
"owner_repo", metavar="OWNER/REPO", callback=validators.validate_owner_repo
|
|
66
|
+
)
|
|
67
|
+
@click.pass_context
|
|
68
|
+
@functools.wraps(f)
|
|
69
|
+
def wrapper(ctx, *args, **kwargs):
|
|
70
|
+
# pylint: disable=missing-docstring
|
|
71
|
+
return ctx.invoke(f, *args, **kwargs)
|
|
72
|
+
|
|
73
|
+
return wrapper
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def list_entitlements(ctx, opts, owner_repo, page, page_size, show_tokens, page_all):
|
|
77
|
+
"""
|
|
78
|
+
List entitlements for a repository.
|
|
79
|
+
|
|
80
|
+
- OWNER/REPO: Specify the OWNER namespace (i.e. user or org), and the REPO
|
|
81
|
+
name where you want to list entitlements for. All separated by a slash.
|
|
82
|
+
|
|
83
|
+
Example: 'your-org/your-repo'
|
|
84
|
+
|
|
85
|
+
Full CLI example:
|
|
86
|
+
|
|
87
|
+
$ cloudsmith ents list your-org/your-repo
|
|
88
|
+
"""
|
|
89
|
+
owner, repo = owner_repo
|
|
90
|
+
|
|
91
|
+
# Use stderr for messages if the output is something else (e.g. # JSON)
|
|
92
|
+
use_stderr = utils.should_use_stderr(opts)
|
|
93
|
+
|
|
94
|
+
click.echo(
|
|
95
|
+
"Getting list of entitlements for the %(repository)s "
|
|
96
|
+
"repository ... " % {"repository": click.style(repo, bold=True)},
|
|
97
|
+
nl=False,
|
|
98
|
+
err=use_stderr,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
context_msg = "Failed to get list of entitlements!"
|
|
102
|
+
with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
|
|
103
|
+
with maybe_spinner(opts):
|
|
104
|
+
entitlements_, page_info = paginate_results(
|
|
105
|
+
api.list_entitlements,
|
|
106
|
+
page_all=page_all,
|
|
107
|
+
page=page,
|
|
108
|
+
page_size=page_size,
|
|
109
|
+
owner=owner,
|
|
110
|
+
repo=repo,
|
|
111
|
+
show_tokens=show_tokens,
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
click.secho("OK", fg="green", err=use_stderr)
|
|
115
|
+
|
|
116
|
+
print_entitlements(opts=opts, data=entitlements_, page_info=page_info)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
@entitlements.command(name="list", aliases=["ls"])
|
|
120
|
+
@list_entitlements_options
|
|
121
|
+
@functools.wraps(list_entitlements)
|
|
122
|
+
@click.pass_context
|
|
123
|
+
def list_(*args, **kwargs): # pylint: disable=missing-docstring
|
|
124
|
+
return list_entitlements(*args, **kwargs)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def print_entitlements(opts, data, page_info=None, show_list_info=True):
|
|
128
|
+
"""Print entitlements as a table or output in another format."""
|
|
129
|
+
if utils.maybe_print_as_json(opts, data, page_info):
|
|
130
|
+
return
|
|
131
|
+
|
|
132
|
+
headers = ["Name", "Token", "Created / Updated", "Identifier"]
|
|
133
|
+
|
|
134
|
+
rows = []
|
|
135
|
+
for entitlement in sorted(data, key=itemgetter("name")):
|
|
136
|
+
ent_updated_at = fmt_datetime(entitlement["updated_at"])
|
|
137
|
+
ent_created_at = fmt_datetime(entitlement["created_at"])
|
|
138
|
+
|
|
139
|
+
rows.append(
|
|
140
|
+
[
|
|
141
|
+
click.style(
|
|
142
|
+
"%(name)s (%(type)s)"
|
|
143
|
+
% {
|
|
144
|
+
"name": click.style(entitlement["name"], fg="cyan"),
|
|
145
|
+
"type": "user" if entitlement["user"] else "token",
|
|
146
|
+
}
|
|
147
|
+
),
|
|
148
|
+
click.style(entitlement["token"], fg="yellow"),
|
|
149
|
+
click.style(ent_updated_at or ent_created_at, fg="blue"),
|
|
150
|
+
click.style(entitlement["slug_perm"], fg="green"),
|
|
151
|
+
]
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
if data:
|
|
155
|
+
click.echo()
|
|
156
|
+
utils.pretty_print_table(headers, rows)
|
|
157
|
+
|
|
158
|
+
if not show_list_info:
|
|
159
|
+
return
|
|
160
|
+
|
|
161
|
+
click.echo()
|
|
162
|
+
|
|
163
|
+
num_results = len(data)
|
|
164
|
+
list_suffix = "entitlement%s" % ("s" if num_results != 1 else "")
|
|
165
|
+
utils.pretty_print_list_info(num_results=num_results, suffix=list_suffix)
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def print_entitlements_with_restrictions(
|
|
169
|
+
opts, data, page_info=None, show_list_info=True
|
|
170
|
+
):
|
|
171
|
+
# pylint: disable=too-many-locals
|
|
172
|
+
"""Print entitlements (with restrictions) as a table or output in another format."""
|
|
173
|
+
if utils.maybe_print_as_json(opts, data, page_info):
|
|
174
|
+
return
|
|
175
|
+
|
|
176
|
+
headers = [
|
|
177
|
+
"Identifier",
|
|
178
|
+
"Name",
|
|
179
|
+
"Created / Updated",
|
|
180
|
+
"Active",
|
|
181
|
+
"Limited",
|
|
182
|
+
"Valid From",
|
|
183
|
+
"Valid To",
|
|
184
|
+
"Reset",
|
|
185
|
+
"Clients",
|
|
186
|
+
"Downloads",
|
|
187
|
+
"Bandwidth",
|
|
188
|
+
"Package Query",
|
|
189
|
+
"Path Query",
|
|
190
|
+
]
|
|
191
|
+
|
|
192
|
+
rows = []
|
|
193
|
+
for entitlement in sorted(data, key=itemgetter("name")):
|
|
194
|
+
name = entitlement.get("name", "")
|
|
195
|
+
user = entitlement.get("user", "")
|
|
196
|
+
updated_at = fmt_datetime(entitlement.get("updated_at", ""))
|
|
197
|
+
created_at = fmt_datetime(entitlement.get("created_at", ""))
|
|
198
|
+
is_active = entitlement.get("is_active", "")
|
|
199
|
+
is_limited = entitlement.get("is_limited", "")
|
|
200
|
+
|
|
201
|
+
scheduled_reset_period = entitlement.get("scheduled_reset_period", "")
|
|
202
|
+
limit_bandwidth = entitlement.get("limit_bandwidth", "")
|
|
203
|
+
limit_bandwidth_unit = entitlement.get("limit_bandwidth_unit", "")
|
|
204
|
+
limit_num_clients = entitlement.get("limit_num_clients", "")
|
|
205
|
+
limit_num_downloads = entitlement.get("limit_num_downloads", "")
|
|
206
|
+
limit_date_range_from = fmt_datetime(
|
|
207
|
+
entitlement.get("limit_date_range_from", "")
|
|
208
|
+
)
|
|
209
|
+
limit_date_range_to = fmt_datetime(entitlement.get("limit_date_range_to", ""))
|
|
210
|
+
limit_package_query = entitlement.get("limit_package_query", "")
|
|
211
|
+
limit_path_query = entitlement.get("limit_path_query", "")
|
|
212
|
+
|
|
213
|
+
restricted_bandwidth = "-"
|
|
214
|
+
if limit_bandwidth and limit_bandwidth_unit:
|
|
215
|
+
restricted_bandwidth = f"{limit_bandwidth} {limit_bandwidth_unit}"
|
|
216
|
+
|
|
217
|
+
# format fields for rendering
|
|
218
|
+
scheduled_reset_period = (
|
|
219
|
+
str(scheduled_reset_period) if scheduled_reset_period else "-"
|
|
220
|
+
)
|
|
221
|
+
limit_bandwidth = str(limit_bandwidth) if limit_bandwidth else "-"
|
|
222
|
+
limit_bandwidth_unit = (
|
|
223
|
+
str(limit_bandwidth_unit) if limit_bandwidth_unit else "-"
|
|
224
|
+
)
|
|
225
|
+
limit_package_query = str(limit_package_query) if limit_package_query else "-"
|
|
226
|
+
limit_path_query = str(limit_path_query) if limit_path_query else "-"
|
|
227
|
+
limit_num_clients = str(limit_num_clients) if limit_num_clients else "-"
|
|
228
|
+
limit_num_downloads = str(limit_num_downloads) if limit_num_downloads else "-"
|
|
229
|
+
limit_date_range_from = limit_date_range_from if limit_date_range_from else "-"
|
|
230
|
+
limit_date_range_to = limit_date_range_to if limit_date_range_to else "-"
|
|
231
|
+
|
|
232
|
+
if limit_package_query:
|
|
233
|
+
if len(limit_package_query) > 20:
|
|
234
|
+
limit_package_query = limit_package_query[0:20] + "..."
|
|
235
|
+
else:
|
|
236
|
+
limit_package_query = "-"
|
|
237
|
+
|
|
238
|
+
if limit_path_query:
|
|
239
|
+
if len(limit_path_query) > 20:
|
|
240
|
+
limit_path_query = limit_path_query[0:20] + " ..."
|
|
241
|
+
else:
|
|
242
|
+
limit_path_query = "-"
|
|
243
|
+
|
|
244
|
+
rows.append(
|
|
245
|
+
[
|
|
246
|
+
click.style(entitlement["slug_perm"], fg="green"),
|
|
247
|
+
click.style(
|
|
248
|
+
"%(name)s (%(type)s)"
|
|
249
|
+
% {
|
|
250
|
+
"name": click.style(name, fg="cyan"),
|
|
251
|
+
"type": "user" if user else "token",
|
|
252
|
+
}
|
|
253
|
+
),
|
|
254
|
+
click.style(updated_at or created_at, fg="white"),
|
|
255
|
+
click.style("yes" if is_active else "no", fg="yellow"),
|
|
256
|
+
click.style("yes" if is_limited else "no", fg="yellow"),
|
|
257
|
+
click.style(limit_date_range_from, fg="yellow"),
|
|
258
|
+
click.style(limit_date_range_to, fg="yellow"),
|
|
259
|
+
click.style(scheduled_reset_period, fg="yellow"),
|
|
260
|
+
click.style(limit_num_clients, fg="magenta"),
|
|
261
|
+
click.style(limit_num_downloads, fg="magenta"),
|
|
262
|
+
click.style(restricted_bandwidth, fg="magenta"),
|
|
263
|
+
click.style(limit_package_query, fg="magenta"),
|
|
264
|
+
click.style(limit_path_query, fg="magenta"),
|
|
265
|
+
]
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
if data:
|
|
269
|
+
click.echo()
|
|
270
|
+
utils.pretty_print_table(headers, rows)
|
|
271
|
+
|
|
272
|
+
if not show_list_info:
|
|
273
|
+
return
|
|
274
|
+
|
|
275
|
+
click.echo()
|
|
276
|
+
|
|
277
|
+
num_results = len(data)
|
|
278
|
+
list_suffix = "entitlement%s" % ("s" if num_results != 1 else "")
|
|
279
|
+
utils.pretty_print_list_info(num_results=num_results, suffix=list_suffix)
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
@entitlements.command(aliases=["new"])
|
|
283
|
+
@common_entitlements_options
|
|
284
|
+
@decorators.common_cli_config_options
|
|
285
|
+
@decorators.common_cli_output_options
|
|
286
|
+
@decorators.common_api_auth_options
|
|
287
|
+
@decorators.initialise_api
|
|
288
|
+
@click.argument(
|
|
289
|
+
"owner_repo", metavar="OWNER/REPO", callback=validators.validate_owner_repo
|
|
290
|
+
)
|
|
291
|
+
@click.option(
|
|
292
|
+
"--name",
|
|
293
|
+
type=str,
|
|
294
|
+
required=True,
|
|
295
|
+
help=(
|
|
296
|
+
"A name that identifies the token. This must be unique, as it both identifies "
|
|
297
|
+
"the user/client of the token, and is also usable as a username for "
|
|
298
|
+
"authentication in some contexts. * Note: May not apply to older repositories."
|
|
299
|
+
),
|
|
300
|
+
)
|
|
301
|
+
@click.option(
|
|
302
|
+
"--token",
|
|
303
|
+
type=str,
|
|
304
|
+
required=False,
|
|
305
|
+
help="The entitlement token value. Must be exactly 16 characters in "
|
|
306
|
+
"length and only contain alphanumerics. If not specified then "
|
|
307
|
+
"an entitlement token will be automatically generated.",
|
|
308
|
+
)
|
|
309
|
+
@click.pass_context
|
|
310
|
+
def create(ctx, opts, owner_repo, show_tokens, name, token):
|
|
311
|
+
"""
|
|
312
|
+
Create a new entitlement in a repository.
|
|
313
|
+
|
|
314
|
+
- OWNER/REPO: Specify the OWNER namespace (i.e. user or org), and the REPO
|
|
315
|
+
name where you want to create an entitlement. All separated by a slash.
|
|
316
|
+
|
|
317
|
+
Example: 'your-org/your-repo'
|
|
318
|
+
|
|
319
|
+
Full CLI example:
|
|
320
|
+
|
|
321
|
+
$ cloudsmith ents create your-org/your-repo --name 'Foobar'
|
|
322
|
+
"""
|
|
323
|
+
owner, repo = owner_repo
|
|
324
|
+
|
|
325
|
+
# Use stderr for messages if the output is something else (e.g. # JSON)
|
|
326
|
+
use_stderr = utils.should_use_stderr(opts)
|
|
327
|
+
|
|
328
|
+
click.secho(
|
|
329
|
+
"Creating %(name)s entitlement for the %(repository)s "
|
|
330
|
+
"repository ... "
|
|
331
|
+
% {
|
|
332
|
+
"name": click.style(name, bold=True),
|
|
333
|
+
"repository": click.style(repo, bold=True),
|
|
334
|
+
},
|
|
335
|
+
nl=False,
|
|
336
|
+
err=use_stderr,
|
|
337
|
+
)
|
|
338
|
+
|
|
339
|
+
context_msg = "Failed to create the entitlement!"
|
|
340
|
+
with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
|
|
341
|
+
with maybe_spinner(opts):
|
|
342
|
+
entitlement = api.create_entitlement(
|
|
343
|
+
owner=owner, repo=repo, name=name, token=token, show_tokens=show_tokens
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
click.secho("OK", fg="green", err=use_stderr)
|
|
347
|
+
|
|
348
|
+
print_entitlements(opts=opts, data=[entitlement], show_list_info=False)
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
@entitlements.command(aliases=["rm"])
|
|
352
|
+
@decorators.common_cli_config_options
|
|
353
|
+
@decorators.common_cli_output_options
|
|
354
|
+
@decorators.common_api_auth_options
|
|
355
|
+
@decorators.initialise_api
|
|
356
|
+
@click.argument(
|
|
357
|
+
"owner_repo_identifier",
|
|
358
|
+
metavar="OWNER/REPO/IDENTIFIER",
|
|
359
|
+
callback=validate_owner_repo_identifier,
|
|
360
|
+
)
|
|
361
|
+
@click.option(
|
|
362
|
+
"-y",
|
|
363
|
+
"--yes",
|
|
364
|
+
default=False,
|
|
365
|
+
is_flag=True,
|
|
366
|
+
help="Assume yes as default answer to questions (this is dangerous!)",
|
|
367
|
+
)
|
|
368
|
+
@click.pass_context
|
|
369
|
+
def delete(ctx, opts, owner_repo_identifier, yes):
|
|
370
|
+
"""
|
|
371
|
+
Delete an entitlement from a repository.
|
|
372
|
+
|
|
373
|
+
- OWNER/REPO/IDENTIFIER: Specify the OWNER namespace (i.e. user or org),
|
|
374
|
+
and the REPO name that has an entitlement identified by IDENTIFIER. All
|
|
375
|
+
separated by a slash.
|
|
376
|
+
|
|
377
|
+
Example: 'your-org/your-repo/abcdef123456'
|
|
378
|
+
|
|
379
|
+
Full CLI example:
|
|
380
|
+
|
|
381
|
+
$ cloudsmith ents delete your-org/your-repo/abcdef123456
|
|
382
|
+
"""
|
|
383
|
+
owner, repo, identifier = owner_repo_identifier
|
|
384
|
+
|
|
385
|
+
delete_args = {
|
|
386
|
+
"identifier": click.style(identifier, bold=True),
|
|
387
|
+
"repository": click.style(repo, bold=True),
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
prompt = (
|
|
391
|
+
"delete the %(identifier)s entitlement from the %(repository)s "
|
|
392
|
+
"repository" % delete_args
|
|
393
|
+
)
|
|
394
|
+
|
|
395
|
+
use_stderr = utils.should_use_stderr(opts)
|
|
396
|
+
|
|
397
|
+
if not utils.confirm_operation(prompt, assume_yes=yes, err=use_stderr):
|
|
398
|
+
return
|
|
399
|
+
|
|
400
|
+
click.secho(
|
|
401
|
+
"Deleting %(identifier)s entitlement from the %(repository)s "
|
|
402
|
+
"repository ... " % delete_args,
|
|
403
|
+
nl=False,
|
|
404
|
+
err=use_stderr,
|
|
405
|
+
)
|
|
406
|
+
|
|
407
|
+
context_msg = "Failed to delete the entitlement!"
|
|
408
|
+
with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
|
|
409
|
+
with maybe_spinner(opts):
|
|
410
|
+
api.delete_entitlement(owner=owner, repo=repo, identifier=identifier)
|
|
411
|
+
|
|
412
|
+
click.secho("OK", fg="green")
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
@entitlements.command(aliases=["set"])
|
|
416
|
+
@common_entitlements_options
|
|
417
|
+
@decorators.common_cli_config_options
|
|
418
|
+
@decorators.common_cli_output_options
|
|
419
|
+
@decorators.common_api_auth_options
|
|
420
|
+
@decorators.initialise_api
|
|
421
|
+
@click.argument(
|
|
422
|
+
"owner_repo_identifier",
|
|
423
|
+
metavar="OWNER/REPO/IDENTIFIER",
|
|
424
|
+
callback=validate_owner_repo_identifier,
|
|
425
|
+
)
|
|
426
|
+
@click.option(
|
|
427
|
+
"--name",
|
|
428
|
+
type=str,
|
|
429
|
+
required=False,
|
|
430
|
+
help=(
|
|
431
|
+
"A name that identifies the token. This must be unique, as it both identifies "
|
|
432
|
+
"the user/client of the token, and is also usable as a username for "
|
|
433
|
+
"authentication in some contexts. * Note: May not apply to older repositories."
|
|
434
|
+
),
|
|
435
|
+
)
|
|
436
|
+
@click.option(
|
|
437
|
+
"--token",
|
|
438
|
+
type=str,
|
|
439
|
+
required=False,
|
|
440
|
+
help="The entitlement token value. Must be exactly 16 characters in "
|
|
441
|
+
"length and only contain alphanumerics.",
|
|
442
|
+
)
|
|
443
|
+
@click.pass_context
|
|
444
|
+
def update(ctx, opts, owner_repo_identifier, show_tokens, name, token):
|
|
445
|
+
"""
|
|
446
|
+
Update (set) a entitlement in a repository.
|
|
447
|
+
|
|
448
|
+
- OWNER/REPO/IDENTIFIER: Specify the OWNER namespace (i.e. user or org),
|
|
449
|
+
and the REPO name that has an entitlement identified by IDENTIFIER. All
|
|
450
|
+
separated by a slash.
|
|
451
|
+
|
|
452
|
+
Example: 'your-org/your-repo/abcdef123456'
|
|
453
|
+
|
|
454
|
+
Full CLI example:
|
|
455
|
+
|
|
456
|
+
$ cloudsmith ents update your-org/your-repo/abcdef123456 --name 'Newly'
|
|
457
|
+
"""
|
|
458
|
+
owner, repo, identifier = owner_repo_identifier
|
|
459
|
+
|
|
460
|
+
# Use stderr for messages if the output is something else (e.g. # JSON)
|
|
461
|
+
use_stderr = utils.should_use_stderr(opts)
|
|
462
|
+
|
|
463
|
+
click.secho(
|
|
464
|
+
"Updating %(identifier)s entitlement for the %(repository)s "
|
|
465
|
+
"repository ... "
|
|
466
|
+
% {
|
|
467
|
+
"identifier": click.style(identifier, bold=True),
|
|
468
|
+
"repository": click.style(repo, bold=True),
|
|
469
|
+
},
|
|
470
|
+
nl=False,
|
|
471
|
+
err=use_stderr,
|
|
472
|
+
)
|
|
473
|
+
|
|
474
|
+
context_msg = "Failed to update the entitlement!"
|
|
475
|
+
with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
|
|
476
|
+
with maybe_spinner(opts):
|
|
477
|
+
entitlement = api.update_entitlement(
|
|
478
|
+
owner=owner,
|
|
479
|
+
repo=repo,
|
|
480
|
+
identifier=identifier,
|
|
481
|
+
name=name,
|
|
482
|
+
token=token,
|
|
483
|
+
show_tokens=show_tokens,
|
|
484
|
+
)
|
|
485
|
+
|
|
486
|
+
click.secho("OK", fg="green", err=use_stderr)
|
|
487
|
+
|
|
488
|
+
print_entitlements(opts=opts, data=[entitlement], show_list_info=False)
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
@entitlements.command()
|
|
492
|
+
@common_entitlements_options
|
|
493
|
+
@decorators.common_cli_config_options
|
|
494
|
+
@decorators.common_cli_output_options
|
|
495
|
+
@decorators.common_api_auth_options
|
|
496
|
+
@decorators.initialise_api
|
|
497
|
+
@click.argument(
|
|
498
|
+
"owner_repo_identifier",
|
|
499
|
+
metavar="OWNER/REPO/IDENTIFIER",
|
|
500
|
+
callback=validate_owner_repo_identifier,
|
|
501
|
+
)
|
|
502
|
+
@click.option(
|
|
503
|
+
"-y",
|
|
504
|
+
"--yes",
|
|
505
|
+
default=False,
|
|
506
|
+
is_flag=True,
|
|
507
|
+
help="Assume yes as default answer to questions (this is dangerous!)",
|
|
508
|
+
)
|
|
509
|
+
@click.pass_context
|
|
510
|
+
def refresh(ctx, opts, owner_repo_identifier, show_tokens, yes):
|
|
511
|
+
"""
|
|
512
|
+
Refresh an entitlement in a repository.
|
|
513
|
+
|
|
514
|
+
Note that this changes the token associated with the entitlement.
|
|
515
|
+
|
|
516
|
+
- OWNER/REPO/IDENTIFIER: Specify the OWNER namespace (i.e. user or org),
|
|
517
|
+
and the REPO name that has an entitlement identified by IDENTIFIER. All
|
|
518
|
+
separated by a slash.
|
|
519
|
+
|
|
520
|
+
Example: 'your-org/your-repo/abcdef123456'
|
|
521
|
+
|
|
522
|
+
Full CLI example:
|
|
523
|
+
|
|
524
|
+
$ cloudsmith ents refresh your-org/your-repo/abcdef123456
|
|
525
|
+
"""
|
|
526
|
+
owner, repo, identifier = owner_repo_identifier
|
|
527
|
+
|
|
528
|
+
refresh_args = {
|
|
529
|
+
"identifier": click.style(identifier, bold=True),
|
|
530
|
+
"repository": click.style(repo, bold=True),
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
# Use stderr for messages if the output is something else (e.g. # JSON)
|
|
534
|
+
use_stderr = utils.should_use_stderr(opts)
|
|
535
|
+
|
|
536
|
+
prompt = (
|
|
537
|
+
"refresh the %(identifier)s entitlement for the %(repository)s "
|
|
538
|
+
"repository" % refresh_args
|
|
539
|
+
)
|
|
540
|
+
if not utils.confirm_operation(prompt, assume_yes=yes, err=use_stderr):
|
|
541
|
+
return
|
|
542
|
+
|
|
543
|
+
click.secho(
|
|
544
|
+
"Refreshing %(identifier)s entitlement for the %(repository)s "
|
|
545
|
+
"repository ... " % refresh_args,
|
|
546
|
+
nl=False,
|
|
547
|
+
err=use_stderr,
|
|
548
|
+
)
|
|
549
|
+
|
|
550
|
+
context_msg = "Failed to refresh the entitlement!"
|
|
551
|
+
with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
|
|
552
|
+
with maybe_spinner(opts):
|
|
553
|
+
entitlement = api.refresh_entitlement(
|
|
554
|
+
owner=owner, repo=repo, identifier=identifier, show_tokens=show_tokens
|
|
555
|
+
)
|
|
556
|
+
|
|
557
|
+
click.secho("OK", fg="green", err=use_stderr)
|
|
558
|
+
|
|
559
|
+
print_entitlements(opts=opts, data=[entitlement], show_list_info=False)
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
@entitlements.command()
|
|
563
|
+
@common_entitlements_options
|
|
564
|
+
@decorators.common_cli_config_options
|
|
565
|
+
@decorators.common_cli_output_options
|
|
566
|
+
@decorators.common_api_auth_options
|
|
567
|
+
@decorators.initialise_api
|
|
568
|
+
@click.argument(
|
|
569
|
+
"owner_repo", metavar="OWNER/REPO", callback=validators.validate_owner_repo
|
|
570
|
+
)
|
|
571
|
+
@click.argument("source", metavar="SOURCE", default=str)
|
|
572
|
+
@click.option(
|
|
573
|
+
"-y",
|
|
574
|
+
"--yes",
|
|
575
|
+
default=False,
|
|
576
|
+
is_flag=True,
|
|
577
|
+
help="Assume yes as default answer to questions (this is dangerous!)",
|
|
578
|
+
)
|
|
579
|
+
@click.pass_context
|
|
580
|
+
def sync(ctx, opts, owner_repo, show_tokens, source, yes):
|
|
581
|
+
"""
|
|
582
|
+
Sync entitlements from another repository.
|
|
583
|
+
|
|
584
|
+
***WARNING*** This will DELETE ALL of the existing entitlements in the
|
|
585
|
+
repository and replace them with entitlements from the source repository.
|
|
586
|
+
|
|
587
|
+
- OWNER/REPO: Specify the OWNER namespace (i.e. user or org), and the REPO
|
|
588
|
+
name where you want to sync entitlements to. All separated by a slash.
|
|
589
|
+
|
|
590
|
+
Example: 'your-org/your-repo'
|
|
591
|
+
|
|
592
|
+
- SOURCE: Specify the SOURCE repository to copy the entitlements from.
|
|
593
|
+
This *must* be in the same namespace as the destination repository.
|
|
594
|
+
|
|
595
|
+
Example: 'source-repo'
|
|
596
|
+
|
|
597
|
+
Full CLI example:
|
|
598
|
+
|
|
599
|
+
$ cloudsmith ents sync your-org/your-repo source-repo
|
|
600
|
+
"""
|
|
601
|
+
owner, repo = owner_repo
|
|
602
|
+
|
|
603
|
+
sync_args = {
|
|
604
|
+
"source": click.style(source, bold=True),
|
|
605
|
+
"dest": click.style(repo, bold=True),
|
|
606
|
+
"warning": click.style("*** WARNING ***", fg="yellow"),
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
# Use stderr for messages if the output is something else (e.g. # JSON)
|
|
610
|
+
use_stderr = utils.should_use_stderr(opts)
|
|
611
|
+
|
|
612
|
+
if not yes:
|
|
613
|
+
click.secho(
|
|
614
|
+
"%(warning)s This will DELETE ALL of the existing entitlements "
|
|
615
|
+
"in the %(dest)s repository and replace them with entitlements "
|
|
616
|
+
"from the %(source)s repository." % sync_args,
|
|
617
|
+
fg="yellow",
|
|
618
|
+
err=use_stderr,
|
|
619
|
+
)
|
|
620
|
+
click.echo()
|
|
621
|
+
|
|
622
|
+
prompt = (
|
|
623
|
+
"sync entitlements from the %(source)s repository to the "
|
|
624
|
+
"%(dest)s repository" % sync_args
|
|
625
|
+
)
|
|
626
|
+
if not utils.confirm_operation(prompt, assume_yes=yes, err=use_stderr):
|
|
627
|
+
return
|
|
628
|
+
|
|
629
|
+
click.secho(
|
|
630
|
+
"Syncing entitlements from the %(source)s repository to the "
|
|
631
|
+
"%(dest)s repository" % sync_args,
|
|
632
|
+
nl=False,
|
|
633
|
+
err=use_stderr,
|
|
634
|
+
)
|
|
635
|
+
|
|
636
|
+
context_msg = "Failed to sync the entitlements!"
|
|
637
|
+
with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
|
|
638
|
+
with maybe_spinner(opts):
|
|
639
|
+
entitlements_, page_info = api.sync_entitlements(
|
|
640
|
+
owner=owner, repo=repo, source=source, show_tokens=show_tokens
|
|
641
|
+
)
|
|
642
|
+
|
|
643
|
+
click.secho("OK", fg="green", err=use_stderr)
|
|
644
|
+
|
|
645
|
+
print_entitlements(opts=opts, data=entitlements_, page_info=page_info)
|
|
646
|
+
|
|
647
|
+
|
|
648
|
+
@entitlements.command()
|
|
649
|
+
@decorators.common_cli_config_options
|
|
650
|
+
@decorators.common_cli_output_options
|
|
651
|
+
@decorators.common_api_auth_options
|
|
652
|
+
@decorators.initialise_api
|
|
653
|
+
@click.argument(
|
|
654
|
+
"owner_repo_identifier",
|
|
655
|
+
metavar="OWNER/REPO/IDENTIFIER",
|
|
656
|
+
callback=validate_owner_repo_identifier,
|
|
657
|
+
)
|
|
658
|
+
@click.option(
|
|
659
|
+
"--refresh-token",
|
|
660
|
+
type=str,
|
|
661
|
+
required=False,
|
|
662
|
+
help="The unit of bandwidth used to calculate the restrictions applied to the entitlement token (e.g. "
|
|
663
|
+
"Never reset, Daily, Weekly, Fortnightly, Monthly, Bi-Monthly, Quarterly, Every 6 months, Annual).",
|
|
664
|
+
callback=validators.validate_scheduled_reset_period,
|
|
665
|
+
)
|
|
666
|
+
@click.option(
|
|
667
|
+
"--limit-num-clients",
|
|
668
|
+
type=int,
|
|
669
|
+
required=False,
|
|
670
|
+
help="The maximum number of unique clients allowed for the token. Please note that since clients are "
|
|
671
|
+
"calculated asynchronously (after the download happens), the limit may not be imposed immediately but "
|
|
672
|
+
"at a later point.",
|
|
673
|
+
)
|
|
674
|
+
@click.option(
|
|
675
|
+
"--limit-num-downloads",
|
|
676
|
+
type=int,
|
|
677
|
+
required=False,
|
|
678
|
+
help="The maximum number of downloads allowed for the token. Please note that since downloads are calculated "
|
|
679
|
+
"asynchronously (after the download happens), the limit may not be imposed immediately but at a later point.",
|
|
680
|
+
)
|
|
681
|
+
@click.option(
|
|
682
|
+
"--limit-bandwidth",
|
|
683
|
+
type=int,
|
|
684
|
+
required=False,
|
|
685
|
+
help="The maximum download bandwidth allowed for the token. Values are expressed as integers to express a "
|
|
686
|
+
"number of bandwidth units. Please note that since downloads are calculated asynchronously (after"
|
|
687
|
+
"the download happens), the limit may not be imposed immediately but at a later point",
|
|
688
|
+
)
|
|
689
|
+
@click.option(
|
|
690
|
+
"--limit-bandwidth-unit",
|
|
691
|
+
type=str,
|
|
692
|
+
required=False,
|
|
693
|
+
help="The unit of bandwidth used to calculate the restrictions applied to the entitlement token (e.g. "
|
|
694
|
+
"Byte, Kilobyte, Megabyte, Gigabyte, Terabyte, Petabyte)",
|
|
695
|
+
callback=validators.validate_bandwidth_unit,
|
|
696
|
+
)
|
|
697
|
+
@click.option(
|
|
698
|
+
"--limit-package-query",
|
|
699
|
+
type=str,
|
|
700
|
+
required=False,
|
|
701
|
+
help="The package-based search query to apply to restrict downloads to. This uses the same syntax as the "
|
|
702
|
+
"standard search used for repositories (see Searching / Filtering for more details). This will still allow "
|
|
703
|
+
"access to non-package files, such as metadata. For package formats that support dynamic metadata indexes, "
|
|
704
|
+
"the contents of the metadata will also be filtered.",
|
|
705
|
+
)
|
|
706
|
+
@click.option(
|
|
707
|
+
"--limit-path-query",
|
|
708
|
+
type=str,
|
|
709
|
+
required=False,
|
|
710
|
+
help="The path-based search query to apply to restrict downloads to. This supports boolean logic operators "
|
|
711
|
+
"such as OR/AND/NOT and parentheses for grouping. The path evaluated does not include the domain name, the "
|
|
712
|
+
"namespace, the entitlement code used, the package format, etc. and it always starts with a forward slash.",
|
|
713
|
+
)
|
|
714
|
+
@click.option(
|
|
715
|
+
"--limit-date-range-from",
|
|
716
|
+
type=str,
|
|
717
|
+
required=False,
|
|
718
|
+
help="A UTC timestamp used to specify the valid 'from' date for this entitlement token.",
|
|
719
|
+
callback=validators.validate_optional_timestamp,
|
|
720
|
+
)
|
|
721
|
+
@click.option(
|
|
722
|
+
"--limit-date-range-to",
|
|
723
|
+
type=str,
|
|
724
|
+
required=False,
|
|
725
|
+
help="A UTC timestamp used to specify the valid 'to' date for this entitlement token.",
|
|
726
|
+
callback=validators.validate_optional_timestamp,
|
|
727
|
+
)
|
|
728
|
+
@click.pass_context
|
|
729
|
+
def restrict(
|
|
730
|
+
ctx,
|
|
731
|
+
opts,
|
|
732
|
+
owner_repo_identifier,
|
|
733
|
+
refresh_token,
|
|
734
|
+
limit_num_clients,
|
|
735
|
+
limit_num_downloads,
|
|
736
|
+
limit_bandwidth,
|
|
737
|
+
limit_bandwidth_unit,
|
|
738
|
+
limit_package_query,
|
|
739
|
+
limit_path_query,
|
|
740
|
+
limit_date_range_from,
|
|
741
|
+
limit_date_range_to,
|
|
742
|
+
):
|
|
743
|
+
"""
|
|
744
|
+
Restrict an Entitlement Token using the provided limits.
|
|
745
|
+
|
|
746
|
+
***WARNING*** This will restrict a an existing entitlement token and will
|
|
747
|
+
prevent entitlement token users from downloading packages if a limit has
|
|
748
|
+
been exceeded.
|
|
749
|
+
|
|
750
|
+
- OWNER/REPO/IDENTIFIER: Specify the OWNER namespace (i.e. user or org),
|
|
751
|
+
and the REPO name that has an entitlement identified by IDENTIFIER. All
|
|
752
|
+
separated by a slash.
|
|
753
|
+
|
|
754
|
+
Example: 'your-org/your-repo/abcdef123456'
|
|
755
|
+
|
|
756
|
+
CLI example:
|
|
757
|
+
|
|
758
|
+
$ cloudsmith entitlements restrict your-org/your-repo/your-token-identifier
|
|
759
|
+
|
|
760
|
+
Full CLI example:
|
|
761
|
+
|
|
762
|
+
$ cloudsmith entitlements restrict cloudsmith/testing-private/9xGSdAxlIqIV \
|
|
763
|
+
--limit-bandwidth=1 \
|
|
764
|
+
--limit-bandwidth-unit=gigabyte \
|
|
765
|
+
--limit-num-clients=10 \
|
|
766
|
+
--limit-num-downloads=1000 \
|
|
767
|
+
--limit-package-query="package-darwin-amd64 OR package-windows-amd64 OR package-linux-amd64" \
|
|
768
|
+
--limit-path-query=tag:latest \
|
|
769
|
+
--limit-date-range-from=2020-01-01T00:00:00Z \
|
|
770
|
+
--limit-date-range-to=2077-01-01T00:00:00Z
|
|
771
|
+
"""
|
|
772
|
+
owner, repo, identifier = owner_repo_identifier
|
|
773
|
+
|
|
774
|
+
# Use stderr for messages if the output is something else (e.g. # JSON)
|
|
775
|
+
use_stderr = utils.should_use_stderr(opts)
|
|
776
|
+
|
|
777
|
+
click.secho(
|
|
778
|
+
"Updating %(identifier)s entitlement for the %(repository)s "
|
|
779
|
+
"repository ... "
|
|
780
|
+
% {
|
|
781
|
+
"identifier": click.style(identifier, bold=True),
|
|
782
|
+
"repository": click.style(repo, bold=True),
|
|
783
|
+
},
|
|
784
|
+
nl=False,
|
|
785
|
+
err=use_stderr,
|
|
786
|
+
)
|
|
787
|
+
|
|
788
|
+
data = {}
|
|
789
|
+
if refresh_token:
|
|
790
|
+
data["scheduled_reset_period"] = refresh_token
|
|
791
|
+
if limit_num_clients:
|
|
792
|
+
data["limit_num_clients"] = limit_num_clients
|
|
793
|
+
if limit_num_downloads:
|
|
794
|
+
data["limit_num_downloads"] = limit_num_downloads
|
|
795
|
+
if limit_bandwidth:
|
|
796
|
+
data["limit_bandwidth"] = limit_bandwidth
|
|
797
|
+
if limit_bandwidth_unit:
|
|
798
|
+
data["limit_bandwidth_unit"] = limit_bandwidth_unit
|
|
799
|
+
if limit_package_query:
|
|
800
|
+
data["limit_package_query"] = limit_package_query
|
|
801
|
+
if limit_path_query:
|
|
802
|
+
data["limit_path_query"] = limit_path_query
|
|
803
|
+
if limit_date_range_from:
|
|
804
|
+
data["limit_date_range_from"] = limit_date_range_from
|
|
805
|
+
if limit_date_range_to:
|
|
806
|
+
data["limit_date_range_to"] = limit_date_range_to
|
|
807
|
+
|
|
808
|
+
context_msg = "Failed to update the entitlement!"
|
|
809
|
+
with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
|
|
810
|
+
with maybe_spinner(opts):
|
|
811
|
+
entitlement = api.restrict_entitlement(
|
|
812
|
+
owner=owner, repo=repo, identifier=identifier, data=data
|
|
813
|
+
)
|
|
814
|
+
|
|
815
|
+
click.secho("OK", fg="green", err=use_stderr)
|
|
816
|
+
|
|
817
|
+
print_entitlements_with_restrictions(
|
|
818
|
+
opts=opts, data=[entitlement], show_list_info=False
|
|
819
|
+
)
|