Skip to content
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

### Added

- Set `--show-all` to alias `--page-all`
- Add the ability to use a shortcut within `--page-size` to use pass `-1` or `*` to retrieve all pages i.e. `--page-size -1` or `--page-size *` (note the wildcard may require escaping in some shell environments)
- Added support for deny policy management commands (list, create, get, update, delete)

### Fixed
Expand Down
4 changes: 2 additions & 2 deletions cloudsmith_cli/cli/commands/entitlements.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def wrapper(ctx, *args, **kwargs):
return wrapper


def list_entitlements(ctx, opts, owner_repo, page, page_size, show_tokens, show_all):
def list_entitlements(ctx, opts, owner_repo, page, page_size, show_tokens, page_all):
"""
List entitlements for a repository.

Expand Down Expand Up @@ -103,7 +103,7 @@ def list_entitlements(ctx, opts, owner_repo, page, page_size, show_tokens, show_
with maybe_spinner(opts):
entitlements_, page_info = paginate_results(
api.list_entitlements,
show_all=show_all,
page_all=page_all,
page=page,
page_size=page_size,
owner=owner,
Expand Down
12 changes: 6 additions & 6 deletions cloudsmith_cli/cli/commands/list_.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ def entitlements_(*args, **kwargs): # pylint: disable=missing-docstring
help=("Sort packages by field. Prefix with '-' for descending order."),
)
@click.pass_context
def packages(ctx, opts, owner_repo, page, page_size, query, sort, show_all):
def packages(ctx, opts, owner_repo, page, page_size, query, sort, page_all):
"""
List packages for a repository.

Expand Down Expand Up @@ -220,7 +220,7 @@ def packages(ctx, opts, owner_repo, page, page_size, query, sort, show_all):
with maybe_spinner(opts):
packages_, page_info = paginate_results(
list_packages,
show_all=show_all,
page_all=page_all,
page=page,
page_size=page_size,
owner=owner,
Expand Down Expand Up @@ -262,9 +262,9 @@ def packages(ctx, opts, owner_repo, page, page_size, query, sort, show_all):
list_suffix = "package%s" % ("s" if num_results != 1 else "")
utils.pretty_print_list_info(
num_results=num_results,
page_info=None if show_all else page_info,
suffix=f"{list_suffix} retrieved" if show_all else f"{list_suffix} visible",
show_all=show_all,
page_info=None if page_all else page_info,
suffix=f"{list_suffix} retrieved" if page_all else f"{list_suffix} visible",
page_all=page_all,
)


Expand All @@ -282,7 +282,7 @@ def packages(ctx, opts, owner_repo, page, page_size, query, sort, show_all):
required=False,
)
@click.pass_context
def repos(ctx, opts, owner_repo, page, page_size, show_all):
def repos(ctx, opts, owner_repo, page, page_size, page_all):
"""
List repositories for a namespace (owner).

Expand Down
1 change: 1 addition & 0 deletions cloudsmith_cli/cli/commands/metrics/entitlements.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ def usage(ctx, opts, owner_repo, tokens, start, finish):
repo = None

context_msg = "Failed to get list of metrics!"
data = {}
with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
with maybe_spinner(opts):
if owner and repo:
Expand Down
8 changes: 4 additions & 4 deletions cloudsmith_cli/cli/commands/policy/deny.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def deny_policy(*args, **kwargs):
@decorators.initialise_api
@click.argument("owner")
@click.pass_context
def list_deny_policies(ctx, opts, owner, page, page_size, show_all):
def list_deny_policies(ctx, opts, owner, page, page_size, page_all):
"""List deny policies for an organization."""
use_stderr = opts.output != "pretty"
click.echo("Getting deny policies ... ", nl=False, err=use_stderr)
Expand All @@ -70,7 +70,7 @@ def list_deny_policies(ctx, opts, owner, page, page_size, show_all):
with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
with maybe_spinner(opts):
data, page_info = paginate_results(
orgs.list_deny_policies, show_all, page, page_size, owner=owner
orgs.list_deny_policies, page_all, page, page_size, owner=owner
)

click.secho("OK", fg="green", err=use_stderr)
Expand All @@ -86,9 +86,9 @@ def list_deny_policies(ctx, opts, owner, page, page_size, show_all):
list_suffix = "deny polic%s" % ("y" if num_results == 1 else "ies")
utils.pretty_print_list_info(
num_results=num_results,
page_info=None if show_all else page_info,
page_info=None if page_all else page_info,
suffix=list_suffix,
show_all=show_all,
page_all=page_all,
)


Expand Down
8 changes: 4 additions & 4 deletions cloudsmith_cli/cli/commands/policy/license.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def licence(*args, **kwargs):
"owner", metavar="OWNER", callback=validators.validate_owner, required=True
)
@click.pass_context
def ls(ctx, opts, owner, page, page_size, show_all):
def ls(ctx, opts, owner, page, page_size, page_all):
"""
List license policies.

Expand All @@ -108,7 +108,7 @@ def ls(ctx, opts, owner, page, page_size, show_all):
with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
with maybe_spinner(opts):
policies, page_info = paginate_results(
api.list_license_policies, show_all, page, page_size, owner=owner
api.list_license_policies, page_all, page, page_size, owner=owner
)

click.secho("OK", fg="green", err=use_stderr)
Expand All @@ -124,9 +124,9 @@ def ls(ctx, opts, owner, page, page_size, show_all):
list_suffix = "license polic%s" % ("y" if num_results == 1 else "ies")
utils.pretty_print_list_info(
num_results=num_results,
page_info=None if show_all else page_info,
page_info=None if page_all else page_info,
suffix=list_suffix,
show_all=show_all,
page_all=page_all,
)


Expand Down
8 changes: 4 additions & 4 deletions cloudsmith_cli/cli/commands/policy/vulnerability.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def vulnerability(*args, **kwargs):
"owner", metavar="OWNER", callback=validators.validate_owner, required=True
)
@click.pass_context
def ls(ctx, opts, owner, page, page_size, show_all):
def ls(ctx, opts, owner, page, page_size, page_all):
"""
List vulnerability policies.

Expand All @@ -98,7 +98,7 @@ def ls(ctx, opts, owner, page, page_size, show_all):
with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
with maybe_spinner(opts):
policies, page_info = paginate_results(
api.list_vulnerability_policies, show_all, page, page_size, owner=owner
api.list_vulnerability_policies, page_all, page, page_size, owner=owner
)

click.secho("OK", fg="green", err=use_stderr)
Expand All @@ -114,9 +114,9 @@ def ls(ctx, opts, owner, page, page_size, show_all):
list_suffix = "vulnerability polic%s" % ("y" if num_results == 1 else "ies")
utils.pretty_print_list_info(
num_results=num_results,
page_info=None if show_all else page_info,
page_info=None if page_all else page_info,
suffix=list_suffix,
show_all=show_all,
page_all=page_all,
)


Expand Down
18 changes: 9 additions & 9 deletions cloudsmith_cli/cli/commands/repos.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from .main import main


def print_repositories(opts, data, page_info=None, show_list_info=True, show_all=False):
def print_repositories(opts, data, page_info=None, show_list_info=True, page_all=False):
"""Print repositories as a table or output in another format."""
headers = [
"Name",
Expand Down Expand Up @@ -56,9 +56,9 @@ def print_repositories(opts, data, page_info=None, show_list_info=True, show_all
list_suffix = "repositor%s" % ("ies" if num_results != 1 else "y")
utils.pretty_print_list_info(
num_results=num_results,
page_info=None if show_all else page_info,
suffix=f"{list_suffix} retrieved" if show_all else f"{list_suffix} visible",
show_all=show_all,
page_info=None if page_all else page_info,
suffix=f"{list_suffix} retrieved" if page_all else f"{list_suffix} visible",
page_all=page_all,
)


Expand Down Expand Up @@ -90,7 +90,7 @@ def repositories(ctx, opts): # pylink: disable=unused-argument
required=False,
)
@click.pass_context
def get(ctx, opts, owner_repo, page, page_size, show_all):
def get(ctx, opts, owner_repo, page, page_size, page_all):
"""
List repositories for a namespace (owner).

Expand Down Expand Up @@ -119,9 +119,9 @@ def get(ctx, opts, owner_repo, page, page_size, show_all):
owner = None
repo = None

if show_all and repo:
if page_all and repo:
raise click.UsageError(
"The --show-all option cannot be used when specifying a single repository (OWNER/REPO). Omit the repository slug or remove --show-all."
"The --page-all option cannot be used when specifying a single repository (OWNER/REPO). Omit the repository slug or remove --page-all."
)

click.echo("Getting list of repositories ... ", nl=False, err=use_stderr)
Expand All @@ -130,7 +130,7 @@ def get(ctx, opts, owner_repo, page, page_size, show_all):
with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
with maybe_spinner(opts):
repos_, page_info = paginate_results(
api.list_repos, show_all, page, page_size, owner=owner, repo=repo
api.list_repos, page_all, page, page_size, owner=owner, repo=repo
)

click.secho("OK", fg="green", err=use_stderr)
Expand All @@ -143,7 +143,7 @@ def get(ctx, opts, owner_repo, page, page_size, show_all):
data=repos_,
show_list_info=True,
page_info=page_info,
show_all=show_all,
page_all=page_all,
)


Expand Down
12 changes: 6 additions & 6 deletions cloudsmith_cli/cli/commands/upstream.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
]


def print_upstreams(upstreams, upstream_fmt, page_info=None, show_all=False):
def print_upstreams(upstreams, upstream_fmt, page_info=None, page_all=False):
"""Print upstreams as a table or output in another format."""

def build_row(u):
Expand Down Expand Up @@ -120,9 +120,9 @@ def build_row(u):
list_suffix = "upstream%s" % ("" if num_results == 1 else "s")
utils.pretty_print_list_info(
num_results=num_results,
page_info=None if show_all else page_info,
page_info=None if page_all else page_info,
suffix=list_suffix,
show_all=show_all,
page_all=page_all,
)


Expand Down Expand Up @@ -170,7 +170,7 @@ def build_upstream_list_command(upstream_fmt):
"owner_repo", metavar="OWNER/REPO", callback=validators.validate_owner_repo
)
@click.pass_context
def func(ctx, opts, owner_repo, page, page_size, show_all):
def func(ctx, opts, owner_repo, page, page_size, page_all):
owner, repo = owner_repo

# Use stderr for messages if the output is something else (e.g. # JSON)
Expand All @@ -184,7 +184,7 @@ def func(ctx, opts, owner_repo, page, page_size, show_all):
with maybe_spinner(opts):
upstreams, page_info = paginate_results(
api.list_upstreams,
show_all,
page_all,
page,
page_size,
owner=owner,
Expand All @@ -198,7 +198,7 @@ def func(ctx, opts, owner_repo, page, page_size, show_all):
if utils.maybe_print_as_json(opts, upstreams, page_info):
return

print_upstreams(upstreams, upstream_fmt, page_info, show_all)
print_upstreams(upstreams, upstream_fmt, page_info, page_all)

func.__doc__ = f"""
List {upstream_fmt} upstreams for a repository.
Expand Down
19 changes: 14 additions & 5 deletions cloudsmith_cli/cli/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,8 @@ def common_cli_list_options(f):
"-l",
"--page-size",
default=30,
type=int,
help="The amount of items to view per page for lists.",
type=validators.IntOrWildcard(),
help="The amount of items to view per page for lists. Use '*' to show all results.",
callback=validators.validate_page_size,
)
@click.option(
Expand All @@ -163,6 +163,7 @@ def common_cli_list_options(f):
callback=validators.validate_page,
)
@click.option(
"--page-all",
"--show-all",
default=False,
is_flag=True,
Expand All @@ -173,10 +174,18 @@ def common_cli_list_options(f):
def wrapper(ctx, *args, **kwargs):
# pylint: disable=missing-docstring
opts = config.get_or_create_options(ctx)

# Handle wildcard page_size (converts to page_all behavior)
page_size = kwargs.get("page_size")
if page_size == -1:
kwargs["page_all"] = True
# Validate that wildcard isn't used with explicit --page
validators.enforce_page_all_exclusive(ctx, wildcard_used=True)

# Order-independent validation: perform after all options parsed.
show_all = kwargs.get("show_all")
if show_all:
validators.enforce_show_all_exclusive(ctx)
page_all = kwargs.get("page_all")
if page_all:
validators.enforce_page_all_exclusive(ctx)
kwargs["opts"] = opts
return ctx.invoke(f, *args, **kwargs)

Expand Down
6 changes: 3 additions & 3 deletions cloudsmith_cli/cli/tests/commands/policy/test_deny.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ def test_deny_policy_commands(runner, organization, tmp_path):
directory=tmp_path,
name=policy_name,
description=random_str(),
package_query_string="format:python and downloads:>50",
package_query_string=f"format:python and downloads:>50 and name:{random_str()}",
enabled=random_bool(),
)

Expand All @@ -107,7 +107,7 @@ def test_deny_policy_commands(runner, organization, tmp_path):

# Use the cli to get the policy
result = runner.invoke(
list_deny_policies, args=[organization, "--show-all"], catch_exceptions=False
list_deny_policies, args=[organization, "--page-all"], catch_exceptions=False
)
assert "Getting deny policies ... OK" in result.output
assert_output_matches_policy_config(result.output, policy_config_file_path)
Expand All @@ -117,7 +117,7 @@ def test_deny_policy_commands(runner, organization, tmp_path):
directory=tmp_path,
name=random_str(),
description=random_str(),
package_query_string="format:go and downloads:>15",
package_query_string=f"format:go and downloads:>15 and name:{random_str()}",
enabled=random_bool(),
)

Expand Down
4 changes: 2 additions & 2 deletions cloudsmith_cli/cli/tests/commands/policy/test_licence.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,14 +131,14 @@ def test_license_policy_commands(runner, organization, tmp_path):
)
assert result.exit_code == 0
assert "Getting license policies" in result.output
assert "Invalid value for '--show-all'" not in result.output
assert "Invalid value for '--page-all'" not in result.output

# Conflict: show-all with explicit page
conflict = runner.invoke(
ls, args=[organization, "--page", "1", "--show-all"], catch_exceptions=False
)
assert conflict.exit_code != 0
assert "Invalid value for '--show-all'" in conflict.output
assert "Invalid value for '--page-all'" in conflict.output
assert "Cannot be used with --page (-p) or --page-size (-l)." in conflict.output

# Change the values in the config file
Expand Down
12 changes: 6 additions & 6 deletions cloudsmith_cli/cli/tests/commands/policy/test_vulnerability.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,22 +127,22 @@ def test_vulnerability_policy_commands(runner, organization, tmp_path):
assert "Getting vulnerability policies ... OK" in result.output
assert_output_matches_policy_config(result.output, policy_config_file_path)

# Minimal show-all success (no pagination args besides flag)
# Minimal page-all using --page-size '*' - converts to `-1` (no pagination args besides flag)
result = runner.invoke(
ls, args=[organization, "--show-all"], catch_exceptions=False
ls, args=[organization, "--page-size", "*"], catch_exceptions=False
)
assert result.exit_code == 0
assert "Getting vulnerability policies" in result.output
assert "Invalid value for '--show-all'" not in result.output
assert "Invalid value for '--page-all'" not in result.output

# Conflict: show-all with explicit page
# Conflict: page-all with explicit page
conflict = runner.invoke(
ls,
args=[organization, "--show-all", "--page-size", "2"],
args=[organization, "--page-all", "--page-size", "2"],
catch_exceptions=False,
)
assert conflict.exit_code != 0
assert "Invalid value for '--show-all'" in conflict.output
assert "Invalid value for '--page-all'" in conflict.output
assert "Cannot be used with --page (-p) or --page-size (-l)." in conflict.output

# Change the values in the config file
Expand Down
4 changes: 2 additions & 2 deletions cloudsmith_cli/cli/tests/commands/test_package_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ def test_push_and_delete_raw_package(
small_file_data = data[0]
assert small_file_data["filename"] == pkg_file.name

# List packages with --show-all flag
# List packages with --page-all flag
result = runner.invoke(
list_, args=["pkgs", org_repo, "--show-all"], catch_exceptions=False
list_, args=["pkgs", org_repo, "--page-all"], catch_exceptions=False
)
assert "Getting list of packages ... OK" in result.output
assert "Results: 1 package retrieved" in result.output
Expand Down
Loading