Skip to content

Commit 03fefaa

Browse files
author
João Silva
committed
!34 feat(CLI): [#76] Feedback for filters with no results Closes #76
1 parent 9ed06ff commit 03fefaa

15 files changed

Lines changed: 308 additions & 59 deletions

probely_cli/cli/commands/scans/cancel.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,12 @@ def scans_cancel_command_handler(args):
2323

2424
if filters:
2525
scan_list = list_scans(scans_filters=filters)
26-
scan_ids = [scan.get("id") for scan in scan_list]
26+
searched_scan_ids = [scan.get("id") for scan in scan_list]
27+
28+
if not searched_scan_ids:
29+
raise ProbelyCLIValidation("Selected Filters returned no results")
30+
31+
scan_ids = searched_scan_ids
2732

2833
logger.debug("Cancelling scan for scan ids: {}".format(scan_ids))
2934

probely_cli/cli/commands/scans/pause.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,12 @@ def scans_pause_command_handler(args):
2323

2424
if filters:
2525
scan_list = list_scans(scans_filters=filters)
26-
scan_ids = [scan.get("id") for scan in scan_list]
26+
searched_scan_ids = [scan.get("id") for scan in scan_list]
27+
28+
if not searched_scan_ids:
29+
raise ProbelyCLIValidation("Selected Filters returned no results")
30+
31+
scan_ids = searched_scan_ids
2732

2833
logger.debug("Pausing scan for scan ids: {}".format(scan_ids))
2934
scans = []

probely_cli/cli/commands/scans/resume.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,12 @@ def scans_resume_command_handler(args):
2525

2626
if filters:
2727
scan_list = list_scans(scans_filters=filters)
28-
scan_ids = [scan.get("id") for scan in scan_list]
28+
searched_scan_ids = [scan.get("id") for scan in scan_list]
29+
30+
if not searched_scan_ids:
31+
raise ProbelyCLIValidation("Selected Filters returned no results")
32+
33+
scan_ids = searched_scan_ids
2934

3035
logger.debug("Resuming scan for scan ids: {}".format(scan_ids))
3136
scans = []

probely_cli/cli/commands/targets/delete.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,11 @@ def targets_delete_command_handler(args):
1717
raise ProbelyCLIValidation("filters and Target IDs are mutually exclusive.")
1818

1919
if filters:
20-
targets_list = list_targets(targets_filters=filters)
21-
targets_ids = [target.get("id") for target in targets_list]
20+
searched_targets = list_targets(targets_filters=filters)
21+
if not searched_targets:
22+
raise ProbelyCLIValidation("Selected Filters returned no results")
23+
24+
targets_ids = [target.get("id") for target in searched_targets]
2225

2326
if len(targets_ids) == 1:
2427
target_id = delete_target(targets_ids[0])

probely_cli/cli/commands/targets/start_scan.py

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,17 @@
1111

1212
logger = logging.getLogger(__name__)
1313

14+
def validate_and_retrieve_extra_payload(args):
15+
extra_payload = validate_and_retrieve_yaml_content(args.yaml_file_path)
16+
17+
if "targets" in extra_payload:
18+
# NOTE: This is only for alpha version, specifying Target IDs in the file will be supported in the future
19+
raise ProbelyCLIValidation(
20+
"Target IDs should be provided only through CLI, not in the YAML file."
21+
)
22+
23+
return extra_payload
24+
1425

1526
def start_scans_command_handler(args):
1627
filters = target_filters_handler(args)
@@ -22,27 +33,16 @@ def start_scans_command_handler(args):
2233
if filters and targets_ids:
2334
raise ProbelyCLIValidation("filters and Target IDs are mutually exclusive.")
2435

25-
extra_payload = {}
26-
yaml_file_path = args.yaml_file_path
27-
if yaml_file_path:
28-
extra_payload = validate_and_retrieve_yaml_content(yaml_file_path)
29-
if "targets" in extra_payload:
30-
# NOTE: This is only for alpha version, specifying Target IDs in the file will be supported in the future
31-
raise ProbelyCLIValidation(
32-
"Target IDs should be provided only through CLI, not in the YAML file."
33-
)
34-
35-
if targets_ids:
36-
if len(targets_ids) == 1:
37-
scans = [start_scan(targets_ids[0], extra_payload)]
38-
else:
39-
scans = start_scans(targets_ids, extra_payload)
40-
display_scans_response_output(args, scans)
41-
return
42-
43-
# Fetch all Targets that match the filters and start Scans for them
44-
targets = list_targets(targets_filters=filters)
45-
targets_ids = [target["id"] for target in targets]
36+
extra_payload = validate_and_retrieve_extra_payload(args)
37+
38+
if filters:
39+
searched_targets = list_targets(targets_filters=filters)
40+
41+
if not searched_targets:
42+
raise ProbelyCLIValidation("Selected Filters returned no results")
43+
44+
targets_ids = [target["id"] for target in searched_targets]
45+
4646
if len(targets_ids) == 1:
4747
scans = [start_scan(targets_ids[0], extra_payload)]
4848
else:

probely_cli/cli/commands/targets/update.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@
99
from probely_cli.cli.common import validate_and_retrieve_yaml_content
1010
from probely_cli.cli.enums import OutputEnum
1111
from probely_cli.exceptions import ProbelyCLIValidation
12-
from probely_cli.sdk.targets import list_targets, update_target, update_targets
12+
from probely_cli.sdk.targets import (
13+
update_targets,
14+
list_targets,
15+
update_target,
16+
)
1317

1418
logger = logging.getLogger(__name__)
1519

@@ -66,7 +70,13 @@ def update_targets_command_handler(args):
6670

6771
# Fetch all Targets that match the filters and update them
6872
targets_for_update = list_targets(targets_filters=filters)
69-
target_ids = [target["id"] for target in targets_for_update]
73+
searched_targets_ids = [target["id"] for target in targets_for_update]
74+
75+
if not searched_targets_ids: # TODO test
76+
raise ProbelyCLIValidation("Selected Filters returned no results")
77+
78+
target_ids = searched_targets_ids
79+
7080
if len(target_ids) == 1:
7181
updated_targets = [update_target(target_ids[0], payload)]
7282
else:

probely_cli/settings.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ def _get_config(
9292
"PROBELY_API_URL_BASE",
9393
default="https://api.qa.probely.dev/",
9494
)
95-
# URLs
95+
9696
PROBELY_API_TARGETS_URL = PROBELY_API_URL_BASE + "targets/"
9797
PROBELY_API_TARGETS_RETRIEVE_URL = PROBELY_API_TARGETS_URL + "{id}/"
9898
PROBELY_API_TARGETS_DELETE_URL = PROBELY_API_TARGETS_URL + "{id}/"
@@ -104,10 +104,10 @@ def _get_config(
104104
PROBELY_API_SCANS_BULK_CANCEL_URL = PROBELY_API_SCANS_URL + "bulk/cancel/"
105105
PROBELY_API_SCANS_BULK_RESUME_URL = PROBELY_API_SCANS_URL + "bulk/resume/"
106106
PROBELY_API_SCANS_BULK_PAUSE_URL = PROBELY_API_SCANS_URL + "bulk/pause/"
107+
PROBELY_API_BULK_START_SCANS_URL = PROBELY_API_SCANS_URL + "bulk/start/"
107108
PROBELY_API_SCAN_PAUSE_URL = (
108109
PROBELY_API_TARGETS_URL + "{target_id}/scans/{scan_id}/pause/"
109110
)
110-
PROBELY_API_BULK_START_SCANS_URL = PROBELY_API_SCANS_URL + "bulk/start/"
111111
PROBELY_API_SCAN_CANCEL_URL = (
112112
PROBELY_API_TARGETS_URL + "{target_id}/scans/{scan_id}/cancel/"
113113
)

tests/cli/test_scans_cancel.py

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import json
22
from typing import Dict
3-
from unittest.mock import Mock, patch
3+
from unittest.mock import patch, Mock, MagicMock
44

55
import pytest
66
import yaml
@@ -9,7 +9,7 @@
99

1010

1111
@patch("probely_cli.cli.commands.scans.cancel.cancel_scans")
12-
def test_cancel_scans__command_handler(
12+
def test_scans_cancel__command_handler(
1313
sdk_cancel_scan_mock: Mock,
1414
valid_scans_cancel_api_response: Dict,
1515
probely_cli,
@@ -30,7 +30,7 @@ def test_cancel_scans__command_handler(
3030

3131

3232
@patch("probely_cli.cli.commands.scans.cancel.cancel_scan")
33-
def test_scans_cancel_request_with_exception(
33+
def test_scans_cancel__request_with_exception(
3434
sdk_cancel_scan_mock: Mock,
3535
probely_cli,
3636
):
@@ -99,19 +99,53 @@ def test_scans_cancel__no_arguments_passed(probely_cli):
9999
),
100100
],
101101
)
102-
@patch("probely_cli.cli.commands.scans.get.list_scans")
102+
@patch("probely_cli.cli.commands.scans.cancel.cancel_scan")
103+
@patch("probely_cli.cli.commands.scans.cancel.cancel_scans")
104+
@patch("probely_cli.cli.commands.scans.cancel.list_scans")
103105
def test_scans_cancel__arg_filters_success(
104-
sdk_list_scans_mock: Mock,
106+
sdk_list_scans_mock: MagicMock,
107+
_cancel_scans_mock: MagicMock,
108+
_cancel_scan_mock: MagicMock,
105109
filter_arg,
106110
expected_filter_request,
107111
probely_cli,
108112
):
109-
stdout, stderr = probely_cli("scans", "get", filter_arg, return_list=True)
113+
sdk_list_scans_mock.return_value = [{"id": "scan_id1"}]
114+
115+
stdout, stderr = probely_cli("scans", "cancel", filter_arg, return_list=True)
110116

111-
assert len(stderr) == 0, "Expected no errors"
117+
assert sdk_list_scans_mock.call_count == 1
118+
assert stderr == [], "Expected no errors"
112119
sdk_list_scans_mock.assert_called_once_with(scans_filters=expected_filter_request)
113120

114121

122+
@patch("probely_cli.cli.commands.scans.cancel.cancel_scan")
123+
@patch("probely_cli.cli.commands.scans.cancel.cancel_scans")
124+
@patch("probely_cli.cli.commands.scans.cancel.list_scans")
125+
def test_scans_cancel__filters_with_no_results(
126+
sdk_list_scans_mock: MagicMock,
127+
_cancel_scans_mock: MagicMock,
128+
_cancel_scan_mock: MagicMock,
129+
probely_cli,
130+
):
131+
132+
sdk_list_scans_mock.return_value = []
133+
134+
stdout_lines, stderr_lines = probely_cli(
135+
"scans",
136+
"cancel",
137+
"--f-search=test",
138+
return_list=True,
139+
)
140+
141+
assert stdout_lines == [], "Expected no output"
142+
143+
assert len(stderr_lines) == 1, "Expected error output"
144+
145+
expected_error = "probely scans cancel: error: Selected Filters returned no results"
146+
assert stderr_lines[-1] == expected_error
147+
148+
115149
@patch("probely_cli.cli.commands.scans.cancel.cancel_scans")
116150
def test_scans_cancel__output_argument_output(
117151
cancel_scans_mock, valid_scans_cancel_api_response: dict, probely_cli

tests/cli/test_scans_pause.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import json
22
from typing import Dict
3-
from unittest.mock import Mock, patch
3+
from unittest.mock import patch, Mock, MagicMock
44

55
import pytest
66
import yaml
@@ -129,6 +129,35 @@ def test_scans_pause_scans_with_filters(
129129
assert scan_id1 == stdout_lines[0]
130130

131131

132+
@patch("probely_cli.cli.commands.scans.pause.pause_scan")
133+
@patch("probely_cli.cli.commands.scans.pause.pause_scans")
134+
@patch("probely_cli.cli.commands.scans.pause.list_scans")
135+
def test_scans_pause__filters_with_no_results(
136+
sdk_list_scans_mock: MagicMock,
137+
pause_scans_mock: MagicMock,
138+
pause_scan_mock: MagicMock,
139+
probely_cli,
140+
):
141+
142+
sdk_list_scans_mock.return_value = []
143+
144+
stdout_lines, stderr_lines = probely_cli(
145+
"scans",
146+
"pause",
147+
"--f-search=test",
148+
return_list=True,
149+
)
150+
151+
assert stdout_lines == [], "Expected no output"
152+
assert len(stderr_lines) == 1, "Expected error output"
153+
154+
expected_error = "probely scans pause: error: Selected Filters returned no results"
155+
assert stderr_lines[-1] == expected_error
156+
157+
pause_scans_mock.assert_not_called()
158+
pause_scan_mock.assert_not_called()
159+
160+
132161
@patch("probely_cli.cli.commands.scans.pause.pause_scans")
133162
def test_scans_pause__output_argument_output(pause_scans_mock, probely_cli):
134163
scan_id0 = "scan_id0"

tests/cli/test_scans_resume.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import json
22
from typing import Dict
3-
from unittest.mock import Mock, patch
3+
from unittest.mock import patch, Mock, MagicMock
44

55
import yaml
66

@@ -75,6 +75,35 @@ def test_scans_resume_scans_with_filters(
7575
assert scan_id1 in stdout_lines
7676

7777

78+
@patch("probely_cli.cli.commands.scans.resume.resume_scan")
79+
@patch("probely_cli.cli.commands.scans.resume.resume_scans")
80+
@patch("probely_cli.cli.commands.scans.resume.list_scans")
81+
def test_scans_resume__filters_with_no_results(
82+
sdk_list_scans_mock: MagicMock,
83+
resume_scans_mock: MagicMock,
84+
resume_scan_mock: MagicMock,
85+
probely_cli,
86+
):
87+
88+
sdk_list_scans_mock.return_value = []
89+
90+
stdout_lines, stderr_lines = probely_cli(
91+
"scans",
92+
"resume",
93+
"--f-search=test",
94+
return_list=True,
95+
)
96+
97+
assert stdout_lines == [], "Expected no output"
98+
assert len(stderr_lines) == 1, "Expected error output"
99+
100+
expected_error = "probely scans resume: error: Selected Filters returned no results"
101+
assert stderr_lines[-1] == expected_error
102+
103+
resume_scans_mock.assert_not_called()
104+
resume_scan_mock.assert_not_called()
105+
106+
78107
@patch("probely_cli.cli.commands.scans.resume.resume_scan")
79108
def test_scans_resume_scans_with_ignore_blackout(
80109
resume_scans_mock: Mock,

0 commit comments

Comments
 (0)