Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
# Build artifacts
build/
.vscode/
__pycache__/
ferry_cli.egg-info/

# Development artifacts
result.json
.venv
.git
/tmp/*
__pycache__
.make_creds.sh
swagger.json
config/swagger.json

# Testing artifacts
/tmp/*
.make_creds.sh
remove
12 changes: 10 additions & 2 deletions ferry_cli/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class FerryCLI:
# pylint: disable=too-many-instance-attributes
def __init__(
self: "FerryCLI",
base_url: Optional[str] = None,
config_path: Optional[pathlib.Path] = None,
authorizer: Auth = Auth(),
print_help: bool = False,
Expand All @@ -53,6 +54,7 @@ def __init__(
Initializes the FerryCLI instance.

Args:
base_url (Optional[str]): The base URL for the Ferry API, if that should not come from the file specified by config_path.
config_path (Optional[pathlib.Path]): The path to the configuration file. If None,
a message will be printed indicating that a configuration file is required.
authorizer (Auth): An instance of the Auth class used for authorization. Defaults to a dummy Auth instance.
Expand Down Expand Up @@ -90,7 +92,11 @@ def __init__(
self.config_path = config_path
self.configs = self.__parse_config_file()
self.authorizer = authorizer
self.base_url = self._sanitize_base_url(self.base_url)
self.base_url = (
self._sanitize_base_url(self.base_url)
if base_url is None
else self._sanitize_base_url(base_url)
)
self.dev_url = self._sanitize_base_url(self.dev_url)

def get_arg_parser(self: "FerryCLI") -> FerryParser:
Expand Down Expand Up @@ -615,7 +621,9 @@ def main() -> None:
try:
auth_args, other_args = get_auth_args()
ferry_cli = FerryCLI(
config_path=config_path, authorizer=set_auth_from_args(auth_args)
config_path=config_path,
authorizer=set_auth_from_args(auth_args),
base_url=auth_args.server,
)
if auth_args.update or not os.path.exists(f"{CONFIG_DIR}/swagger.json"):
if auth_args.debug_level != DebugLevel.QUIET:
Expand Down
5 changes: 5 additions & 0 deletions ferry_cli/helpers/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,11 @@ def get_auth_parser() -> "FerryParser":
help="Get Ferry CLI support emails",
action=request_project_info("email"),
)
auth_parser.add_argument(
"-s",
"--server",
help="Server URL to use instead of configuration file api.base_url value",
)
auth_parser.add_argument(
"--version",
nargs=0,
Expand Down
121 changes: 96 additions & 25 deletions tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,39 +124,43 @@ def test_handle_show_configfile_envs_not_found(
assert "Mocked write_config_file" in captured.out


@pytest.mark.parametrize(
"args, expected_out_substr",
[
(
["-h"],
"--show-config-file",
), # If we pass -h, make sure --show-config-file shows up
(
["-h", "--show-config-file", "-e", "getAllGroups"],
"--show-config-file",
), # If we pass -h and --show-config-file, -h should win
(
["--show-config-file"],
"Configuration file",
), # Print out config file if we only pass --show-config-file
(
["--show-config-file", "-e", "getAllGroups"],
"Configuration file",
), # If we pass --show-config-file with other args, --show-config-file should print out the config file
],
)
@pytest.mark.unit
def test_show_configfile_flag_with_other_args(
tmp_path, monkeypatch, write_and_set_fake_config_file
tmp_path, monkeypatch, write_and_set_fake_config_file, args, expected_out_substr
):
# Since we have to handle --show-config-file outside of argparse, make sure we get the correct behavior given different combinations of args
bindir = f"{os.path.dirname(os.path.dirname(os.path.abspath(__file__)))}/bin"
exe = f"{bindir}/ferry-cli"

test_case = namedtuple("TestCase", ["args", "expected_out_substr"])

cases = (
test_case(
[sys.executable, exe, "-h"], "--show-config-file"
), # If we pass -h, make sure --show-config-file shows up
test_case(
[sys.executable, exe, "-h", "--show-config-file", "-e", "getAllGroups"],
"--show-config-file",
), # If we pass -h and --show-config-file, -h should win
test_case(
[sys.executable, exe, "--show-config-file"], "Configuration file"
), # Print out config file if we only pass --show-config-file
test_case(
[sys.executable, exe, "--show-config-file", "-e", "getAllGroups"],
"Configuration file",
), # If we pass --show-config-file with other args, --show-config-file should print out the config file
)
exe_args = [sys.executable, exe]
exe_args.extend(args)

for case in cases:
try:
proc = subprocess.run(case.args, capture_output=True)
except SystemExit:
pass
assert case.expected_out_substr in str(proc.stdout)
try:
proc = subprocess.run(exe_args, capture_output=True)
except SystemExit:
pass
assert expected_out_substr in str(proc.stdout)


@pytest.mark.unit
Expand Down Expand Up @@ -302,3 +306,70 @@ def test_handle_no_args_configfile_does_not_exist(

assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.value.code == 0


@pytest.mark.parametrize(
"base_url, expected_base_url",
[
(None, "https://example.com:12345/"), # Get base_url from config
(
"https://override_example.com:54321/",
"https://override_example.com:54321/",
), # Get base_url from override
],
)
@pytest.mark.unit
def test_override_base_url_FerryCLI(tmp_path, base_url, expected_base_url):
# Set up fake config
fake_config_text = """
[api]
base_url = https://example.com:12345/
dev_url = https://example.com:12345/

"""
fake_config = tmp_path / "config.ini"
fake_config.write_text(fake_config_text)

cli = FerryCLI(config_path=fake_config, base_url=base_url)
assert cli.base_url == expected_base_url


@pytest.mark.parametrize(
"args, expected_out_url",
[
([], "https://example.com:12345/"), # Get base_url from config
(
["--server", "https://override_example.com:54321/"],
"https://override_example.com:54321/",
), # Get base_url from override
],
)
@pytest.mark.test
def test_server_flag_main(tmp_path, monkeypatch, args, expected_out_url):
# Run ferry-cli with overridden base_url in dryrun mode to endpoint ping. Then see if we see the correct server in output
override_url = "https://override_example.com:54321/"
# Set up fake config
fake_config_text = """
[api]
base_url = https://example.com:12345/
dev_url = https://example.com:12345/

"""
# Fake config file
p = tmp_path
config_dir = p / "ferry_cli"
config_dir.mkdir()
config_file = config_dir / "config.ini"
config_file.write_text(fake_config_text)
monkeypatch.setenv("XDG_CONFIG_HOME", str(p.absolute()))

bindir = f"{os.path.dirname(os.path.dirname(os.path.abspath(__file__)))}/bin"
exe = f"{bindir}/ferry-cli"

exe_args = [sys.executable, exe]
exe_args.extend(args + ["--dryrun", "-e", "ping"])

proc = subprocess.run(exe_args, capture_output=True)
assert f"Would call endpoint: {expected_out_url}ping with params" in str(
proc.stdout
)