Skip to content

Commit

Permalink
Add pulp label commands
Browse files Browse the repository at this point in the history
fixes pulp#100
  • Loading branch information
David Davis committed Feb 2, 2021
1 parent fe74ca3 commit e3ec72f
Show file tree
Hide file tree
Showing 9 changed files with 168 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGES/100.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added label subcommands (set and unset).
17 changes: 17 additions & 0 deletions pulpcore/cli/common/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,23 @@ def update(
def delete(self, href: str) -> Any:
return self.pulp_ctx.call(self.DELETE_ID, parameters={self.HREF: href})

def set_label(self, href: str, key: str, value: str) -> Any:
entity = self.show(href)
entity["pulp_labels"][key] = value
return self.update(href, body=entity)

def unset_label(self, href: str, key: str) -> Any:
entity = self.show(href)
entity["pulp_labels"].pop(key)
return self.update(href, body=entity)

def show_label(self, href: str, key: str) -> Any:
entity = self.show(href)
try:
return entity["pulp_labels"][key]
except KeyError:
raise click.ClickException(f"Could not find label with key '{key}'.")

def find_repository(self, definition: RepositoryDefinition) -> Any:
name, repo_type = definition
if repo_type in self.REPOSITORY_FIND_IDS:
Expand Down
67 changes: 67 additions & 0 deletions pulpcore/cli/common/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,14 @@ def _version_callback(ctx: click.Context, param: click.Parameter, value: int) ->
expose_value=False,
)

label_select_option = click.option(
"--label-select",
"pulp_label_select",
help="Filter {entities} by a label search query.",
type=str,
cls=PulpOption,
)

##############################################################################
# Generic reusable commands

Expand Down Expand Up @@ -233,6 +241,65 @@ def repair(
return callback


def label_command(**kwargs: Any) -> click.Command:
"""A factory that creates a label command group."""

if "name" not in kwargs:
kwargs["name"] = "label"
decorators = kwargs.pop("decorators", [])
lookup_decorators = kwargs.pop("lookup_decorators", [name_option, href_option])

@click.group(**kwargs)
@pass_entity_context
@pass_pulp_context
@click.pass_context
def label_group(
ctx: click.Context, entity_ctx: PulpEntityContext, pulp_ctx: PulpContext
) -> None:
pass

for option in decorators:
# Decorate callback
label_group = option(label_group)

@click.command(name="set")
@click.option("--key", required=True, help="Key of the label")
@click.option("--value", required=True, help="Value of the label")
@pass_entity_context
@pass_pulp_context
def label_set(
pulp_ctx: PulpContext, entity_ctx: PulpEntityContext, key: str, value: str
) -> None:
"""Add or update a label"""
href = entity_ctx.entity["pulp_href"]
entity_ctx.set_label(href, key, value)

@click.command(name="unset")
@click.option("--key", required=True, help="Key of the label")
@pass_entity_context
@pass_pulp_context
def label_unset(pulp_ctx: PulpContext, entity_ctx: PulpEntityContext, key: str) -> None:
"""Remove a label with a given key"""
href = entity_ctx.entity["pulp_href"]
entity_ctx.unset_label(href, key)

@click.command(name="show")
@click.option("--key", required=True, help="Key of the label")
@pass_entity_context
@pass_pulp_context
def label_show(pulp_ctx: PulpContext, entity_ctx: PulpEntityContext, key: str) -> None:
"""Show the value for a particular label key"""
href = entity_ctx.entity["pulp_href"]
click.echo(entity_ctx.show_label(href, key))

for subcmd in [label_set, label_unset, label_show]:
for decorator in lookup_decorators:
subcmd = decorator(subcmd)
label_group.add_command(subcmd)

return label_group


@click.command(name="list")
@limit_option
@offset_option
Expand Down
5 changes: 4 additions & 1 deletion pulpcore/cli/file/distribution.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
from pulpcore.cli.common.generic import (
destroy_command,
href_option,
label_command,
label_select_option,
list_command,
name_option,
show_command,
Expand All @@ -32,9 +34,10 @@ def distribution(ctx: click.Context, pulp_ctx: PulpContext, distribution_type: s

lookup_options = [href_option, name_option]

distribution.add_command(list_command())
distribution.add_command(list_command(decorators=[label_select_option]))
distribution.add_command(show_command(decorators=lookup_options))
distribution.add_command(destroy_command(decorators=lookup_options))
distribution.add_command(label_command())


@distribution.command()
Expand Down
5 changes: 4 additions & 1 deletion pulpcore/cli/file/remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
from pulpcore.cli.common.generic import (
destroy_command,
href_option,
label_command,
label_select_option,
list_command,
name_option,
show_command,
Expand All @@ -30,9 +32,10 @@ def remote(ctx: click.Context, pulp_ctx: PulpContext, remote_type: str) -> None:

lookup_options = [href_option, name_option]

remote.add_command(list_command())
remote.add_command(list_command(decorators=[label_select_option]))
remote.add_command(show_command(decorators=lookup_options))
remote.add_command(destroy_command(decorators=lookup_options))
remote.add_command(label_command())


@remote.command()
Expand Down
5 changes: 4 additions & 1 deletion pulpcore/cli/file/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
from pulpcore.cli.common.generic import (
destroy_command,
href_option,
label_command,
label_select_option,
list_command,
name_option,
show_command,
Expand Down Expand Up @@ -43,10 +45,11 @@ def repository(ctx: click.Context, pulp_ctx: PulpContext, repo_type: str) -> Non

lookup_options = [href_option, name_option]

repository.add_command(list_command())
repository.add_command(list_command(decorators=[label_select_option]))
repository.add_command(show_command(decorators=lookup_options))
repository.add_command(destroy_command(decorators=lookup_options))
repository.add_command(version_command())
repository.add_command(label_command())


@repository.command()
Expand Down
23 changes: 19 additions & 4 deletions tests/scripts/config.source
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ settings="$(dirname "$(realpath "$0")")/config/pulp/settings.toml"
PULP_BASE_URL="$(sed -n -e 's/^base_url\s*=\s*"\(\S*\)"\s*$/\1/p' "$settings")"
VERIFY_SSL="$(sed -n -e 's/^verify_ssl\s*=\s*\(\S*\)\s*$/\1/p' "$settings")"

# Configure path to config
export XDG_CONFIG_HOME="$(dirname "$(realpath "$0")")/config"

# Constants used in tests
PULPCORE_VERSION=$(http "$PULP_BASE_URL/pulp/api/v3/status/" | jq -r '.versions | .[] | select(.component=="pulpcore").version')
PULPCORE_VERSION=$(pulp status | jq -r '.versions | .[] | select(.component=="pulpcore").version')
PULP_FIXTURES_URL="${PULP_FIXTURES_URL:-https://fixtures.pulpproject.org}"
FILE_REMOTE_URL="${PULP_FIXTURES_URL}/file/PULP_MANIFEST"
CONTAINER_REMOTE_URL="https://registry-1.docker.io"
Expand All @@ -13,9 +16,6 @@ RPM_REMOTE_URL="${PULP_FIXTURES_URL}/rpm-unsigned"
ANSIBLE_COLLECTION_REMOTE_URL="https://galaxy.ansible.com/"
ANSIBLE_ROLE_REMOTE_URL="https://galaxy.ansible.com/api/v1/roles/?namespace__name=elastic"

# Configure path to config
export XDG_CONFIG_HOME="$(dirname "$(realpath "$0")")/config"

# Library for test helper functions

TMP="$(mktemp -d)"
Expand Down Expand Up @@ -67,4 +67,19 @@ expect_fail () {
fi
}

# Returns true if $PULPCORE_VERSION >= $1, false otherwise
require_min_pulp () {
if [ -z "${PULPCORE_VERSION+x}" ]
then
echo "Error: require_min_pulp called without \$PULPCORE_VERSION defined."
exit 1
fi

if [ "$1" != "`printf "$PULPCORE_VERSION\n$1" | sort -V | head -n1`" ]
then
echo "Skipping $0"
exit 3 # skip exit code
fi
}

set -eu
50 changes: 50 additions & 0 deletions tests/scripts/test_label.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#!/bin/sh

# shellcheck source=tests/scripts/config.source
. "$(dirname "$(realpath "$0")")/config.source"

require_min_pulp "3.10.0"

cleanup() {
pulp file repository destroy --name "cli_test_file_repo" || true
}
trap cleanup EXIT

name="cli_test_file_repo"
expect_succ pulp file repository create --name "$name"
expect_succ pulp file repository label set --name "$name" --key "atani" --value "hurin"
expect_succ pulp file repository label set --name "$name" --key "ainur" --value "ulmo"

expect_succ pulp file repository show --name "$name"
test "$(echo "$OUTPUT" | jq -r -c .pulp_labels)" = '{"atani":"hurin","ainur":"ulmo"}'

# update a label
expect_succ pulp file repository label set --name "$name" --key "atani" --value "beor"
expect_succ pulp file repository show --name "$name"
test "$(echo "$OUTPUT" | jq -r -c .pulp_labels)" = '{"ainur":"ulmo","atani":"beor"}'
expect_succ pulp file repository label show --name "$name" --key "atani"
test "$OUTPUT" = "beor"

# remove a label
expect_succ pulp file repository label unset --name "$name" --key "atani"
expect_succ pulp file repository show --name "$name"
test "$(echo "$OUTPUT" | jq -r -c .pulp_labels)" = '{"ainur":"ulmo"}'
expect_fail pulp file repository label show --name "$name"

# filtering
expect_succ pulp file repository list --label-select "ainur"
test "$(echo "$OUTPUT" | jq length)" -eq 1
expect_succ pulp file repository list --label-select "!ainur"
test "$(echo "$OUTPUT" | jq length)" -eq 0
expect_succ pulp file repository list --label-select "ainur=ulmo"
test "$(echo "$OUTPUT" | jq length)" -eq 1
expect_succ pulp file repository list --label-select "ainur!=ulmo"
test "$(echo "$OUTPUT" | jq length)" -eq 0
expect_succ pulp file repository list --label-select "ainur~lm"
test "$(echo "$OUTPUT" | jq length)" -eq 1

expect_succ pulp file repository label set --name "$name" --key "istar" --value "olorin"
expect_succ pulp file repository list --label-select "ainur=ulmo,istar!=curumo"
test "$(echo "$OUTPUT" | jq length)" -eq 1
expect_succ pulp file repository list --label-select "ainur=ulmo,istar=olorin"
test "$(echo "$OUTPUT" | jq length)" -eq 1
2 changes: 2 additions & 0 deletions tests/test_scripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,6 @@
@pytest.mark.parametrize("test_name", TEST_NAMES)
def test_script(test_name):
run = subprocess.run([os.path.join("tests", "scripts", "test_" + test_name + ".sh")])
if run.returncode == 3:
pytest.skip("Skipped as requested by the script.")
assert run.returncode == 0

0 comments on commit e3ec72f

Please sign in to comment.