Skip to content

Commit

Permalink
Add filter parameters to task list
Browse files Browse the repository at this point in the history
fixes pulp#543

Co-authored-by: Grant Gainey <[email protected]>
  • Loading branch information
mdellweg and ggainey committed Sep 21, 2022
1 parent 8aaa087 commit 3a959d1
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 30 deletions.
1 change: 1 addition & 0 deletions CHANGES/543.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added task filtering options.
25 changes: 23 additions & 2 deletions pulpcore/cli/common/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import json
import sys
import time
from collections.abc import Iterable
from typing import Any, ClassVar, Dict, List, NamedTuple, Optional, Set, Type, Union

import click
Expand All @@ -27,6 +28,20 @@

DEFAULT_LIMIT = 25
BATCH_SIZE = 25
DATETIME_FORMATS = [
"%Y-%m-%dT%H:%M:%S.%fZ", # Pulp format
"%Y-%m-%d", # intl. format
"%Y-%m-%d %H:%M:%S", # ... with time
"%Y-%m-%dT%H:%M:%S", # ... with time and T as a separator
"%y/%m/%d", # US format
"%y/%m/%d %h:%M:%S %p", # ... with time
"%y/%m/%dT%h:%M:%S %p", # ... with time and T as a separator
"%y/%m/%d %H:%M:%S", # ... with time 24h
"%y/%m/%dT%H:%M:%S", # ... with time 24h and T as a separator
"%x", # local format
"%x %X", # ... with time
"%xT%X", # ... with time and T as a separator
]


class PreprocessedEntityDefinition(Dict[str, Any]):
Expand Down Expand Up @@ -64,9 +79,15 @@ def default(self, obj: Any) -> Any:
return super().default(obj)


def _preprocess_value(key: str, value: Any) -> Any:
def _preprocess_value(value: Any) -> Any:
if isinstance(value, str):
return value
if isinstance(value, PulpEntityContext):
return value.pulp_href
if isinstance(value, datetime.datetime):
return value.strftime(DATETIME_FORMATS[0])
if isinstance(value, Iterable):
return [_preprocess_value(item) for item in value]
return value


Expand All @@ -75,7 +96,7 @@ def preprocess_payload(payload: EntityDefinition) -> EntityDefinition:
return payload

return PreprocessedEntityDefinition(
{key: _preprocess_value(key, value) for key, value in payload.items() if value is not None}
{key: _preprocess_value(value) for key, value in payload.items() if value is not None}
)


Expand Down
8 changes: 7 additions & 1 deletion pulpcore/cli/core/context.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import datetime
import hashlib
import os
import sys
Expand Down Expand Up @@ -341,7 +342,11 @@ def scope(self) -> Dict[str, Any]:
else:
return {}

def purge(self, finished_before: Optional[str], states: Optional[List[str]]) -> Any:
def purge(
self,
finished_before: Optional[datetime.datetime],
states: Optional[List[str]],
) -> Any:
body: Dict[str, Any] = {}
if finished_before:
body["finished_before"] = finished_before
Expand Down Expand Up @@ -455,3 +460,4 @@ class PulpWorkerContext(PulpEntityContext):
ENTITIES = _("workers")
HREF = "worker_href"
ID_PREFIX = "workers"
HREF_PATTERN = r"workers/"
91 changes: 69 additions & 22 deletions pulpcore/cli/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@
import click

from pulpcore.cli.common.context import (
DATETIME_FORMATS,
PluginRequirement,
PulpContext,
PulpEntityContext,
pass_entity_context,
pass_pulp_context,
)
from pulpcore.cli.common.generic import list_command, pulp_group, pulp_option
from pulpcore.cli.common.generic import list_command, pulp_group, pulp_option, resource_option
from pulpcore.cli.common.i18n import get_translation
from pulpcore.cli.core.context import PulpTaskContext
from pulpcore.cli.core.context import PulpTaskContext, PulpWorkerContext

translation = get_translation(__name__)
_ = translation.gettext
Expand All @@ -22,27 +23,31 @@
# Generic reusable commands


def _task_group_filter_callback(
ctx: click.Context, param: click.Parameter, value: Optional[str]
) -> Optional[str]:
if value is not None:
pulp_ctx = ctx.find_object(PulpContext)
assert pulp_ctx is not None

# Example: "/pulp/api/v3/task-groups/a69230d2-506e-44c7-9c46-e64a905f85e7/"
match = re.match(
rf"({pulp_ctx.api_path}task-groups/)?"
r"([0-9a-f]{8})-?([0-9a-f]{4})-?([0-9a-f]{4})-?([0-9a-f]{4})-?([0-9a-f]{12})/?",
value,
)
if match:
value = "{}task-groups/{}-{}-{}-{}-{}/".format(
pulp_ctx.api_path, *match.group(2, 3, 4, 5, 6)
class HrefOrUuidCallback:
def __init__(self, base_href: str) -> None:
self.base_href = base_href

def __call__(
self, ctx: click.Context, param: click.Parameter, value: Optional[str]
) -> Optional[str]:
if value is not None:
pulp_ctx = ctx.find_object(PulpContext)
assert pulp_ctx is not None

# Example: "/pulp/api/v3/tasks/a69230d2-506e-44c7-9c46-e64a905f85e7/"
href_match = re.match(
rf"({pulp_ctx.api_path}{self.base_href}/)?"
r"([0-9a-f]{8})-?([0-9a-f]{4})-?([0-9a-f]{4})-?([0-9a-f]{4})-?([0-9a-f]{12})/?",
value,
)
else:
raise click.ClickException(_("Either an href or a UUID must be provided."))
if href_match:
value = "{}{}/{}-{}-{}-{}-{}/".format(
pulp_ctx.api_path, self.base_href, *href_match.group(2, 3, 4, 5, 6)
)
else:
raise click.ClickException(_("Either an href or a UUID must be provided."))

return value
return value


task_filter = [
Expand All @@ -69,7 +74,49 @@ def _task_group_filter_callback(
click.option(
"--task-group",
help=_("List only tasks in this task group. Provide pulp_href or UUID."),
callback=_task_group_filter_callback,
callback=HrefOrUuidCallback("task-groups"),
),
click.option(
"--parent-task",
help=_("Parent task by uuid or href."),
callback=HrefOrUuidCallback("tasks"),
),
resource_option(
"--worker",
default_plugin="core",
default_type="none",
context_table={"core:none": PulpWorkerContext},
href_pattern=PulpWorkerContext.HREF_PATTERN,
help=_("Worker used to execute the task by name or href."),
),
click.option(
"--created-resource",
"created_resources",
help=_("Href of a resource created in the task."),
),
click.option(
"--started-after",
"started_at__gte",
help=_("Filter for tasks started at or after this ISO 8601 date"),
type=click.DateTime(formats=DATETIME_FORMATS),
),
click.option(
"--started-before",
"started_at__lte",
help=_("Filter for tasks started at or before this ISO 8601 date"),
type=click.DateTime(formats=DATETIME_FORMATS),
),
click.option(
"--finished-after",
"finished_at__gte",
help=_("Filter for tasks finished at or after this ISO 8601 date"),
type=click.DateTime(formats=DATETIME_FORMATS),
),
click.option(
"--finished-before",
"finished_at__lte",
help=_("Filter for tasks finished at or before this ISO 8601 date"),
type=click.DateTime(formats=DATETIME_FORMATS),
),
]

Expand Down
19 changes: 14 additions & 5 deletions pulpcore/cli/core/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import click

from pulpcore.cli.common.context import (
DATETIME_FORMATS,
PluginRequirement,
PulpContext,
PulpEntityContext,
Expand All @@ -27,8 +28,6 @@
translation = get_translation(__name__)
_ = translation.gettext

DATETIME_FORMATS = ["%Y-%m-%d", "%Y-%m-%dT%H:%M:%S"]


def _uuid_callback(
ctx: click.Context, param: click.Parameter, value: Optional[str]
Expand All @@ -55,7 +54,18 @@ def task(ctx: click.Context, pulp_ctx: PulpContext) -> None:
ctx.obj = PulpTaskContext(pulp_ctx)


task.add_command(list_command(decorators=task_filter))
task.add_command(
list_command(
decorators=task_filter
+ [
click.option(
"--reserved-resource",
"reserved_resources_record",
help=_("Href of a resource reserved by the task."),
),
]
)
)
task.add_command(destroy_command(decorators=[href_option, uuid_option]))
task.add_command(
role_command(
Expand Down Expand Up @@ -155,5 +165,4 @@ def purge(
) -> None:
pulp_ctx.needs_plugin(PluginRequirement("core", "3.17.0"))
state_list = list(state) if state else None
finished_str = finished.strftime(DATETIME_FORMATS[1]) if finished else None
task_ctx.purge(finished_str, state_list)
task_ctx.purge(finished, state_list)
10 changes: 10 additions & 0 deletions tests/scripts/pulpcore/test_task.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ trap cleanup EXIT
sync_task="pulp_file.app.tasks.synchronizing.synchronize"
expect_succ pulp task list --name $sync_task --state canceled
count="$(echo "$OUTPUT" | jq -r length)"
expect_succ pulp worker list --limit 1
worker="$(echo "$OUTPUT" | jq -r '.[0].pulp_href')"
worker_name="$(echo "$OUTPUT" | jq -r '.[0].name')"

expect_succ pulp file remote create --name "cli_test_file_remote" \
--url "$FILE_REMOTE_URL"
Expand All @@ -41,9 +44,16 @@ task=$(echo "$ERROUTPUT" | grep -E -o "${PULP_API_ROOT}api/v3/tasks/[-[:xdigit:]
task_uuid="${task%/}"
task_uuid="${task_uuid##*/}"
expect_succ pulp task show --wait --uuid "$task_uuid"
reserved_resource="$(echo "$OUTPUT" | jq -r '.reserved_resources_record[0]')"
created_resource="$(echo "$OUTPUT" | jq -r '.created_resources[0]')"
expect_succ test "$(echo "$OUTPUT" | jq -r '.state')" = "completed"

expect_succ pulp task list --name-contains file
expect_succ pulp task list --parent-task "$task" --worker "$worker"
expect_succ pulp task list --parent-task "$task_uuid" --worker "$worker_name"
expect_succ pulp task list --started-before "21/01/12" --started-after "22/01/06T00:00:00"
expect_succ pulp task list --finished-before "2021-12-01" --finished-after "2022-06-01 00:00:00"
expect_succ pulp task list --reserved-resource "$reserved_resource" --created-resource "$created_resource"

expect_fail pulp task list --state=cannotwork
expect_succ pulp task list --state=COmPLetED
Expand Down

0 comments on commit 3a959d1

Please sign in to comment.