234 lines
11 KiB
Python
234 lines
11 KiB
Python
#
|
|
# Copyright (c) 2023 Airbyte, Inc., all rights reserved.
|
|
#
|
|
|
|
import pytest
|
|
from click.testing import CliRunner
|
|
from octavia_cli._import import commands
|
|
|
|
|
|
@pytest.fixture
|
|
def patch_click(mocker):
|
|
mocker.patch.object(commands, "click")
|
|
|
|
|
|
@pytest.fixture
|
|
def context_object(mock_api_client, mock_telemetry_client):
|
|
return {
|
|
"PROJECT_IS_INITIALIZED": True,
|
|
"API_CLIENT": mock_api_client,
|
|
"WORKSPACE_ID": "workspace_id",
|
|
"TELEMETRY_CLIENT": mock_telemetry_client,
|
|
}
|
|
|
|
|
|
def test_build_help_message():
|
|
assert commands.build_help_message("source") == "Import an existing source to manage it with octavia-cli."
|
|
|
|
|
|
@pytest.mark.parametrize("ResourceClass", [commands.UnmanagedSource, commands.UnmanagedDestination])
|
|
def test_import_source_or_destination(mocker, context_object, ResourceClass):
|
|
resource_type = ResourceClass.__name__.lower()
|
|
mocker.patch.object(commands.click, "style")
|
|
mocker.patch.object(commands.click, "echo")
|
|
mocker.patch.object(commands, "get_json_representation")
|
|
mocker.patch.object(
|
|
commands.json,
|
|
"loads",
|
|
mocker.Mock(
|
|
return_value={
|
|
"name": "foo",
|
|
"connection_configuration": "bar",
|
|
f"{resource_type}_definition_id": f"{resource_type}_definition_id",
|
|
f"{resource_type}_id": f"my_{resource_type}_id",
|
|
}
|
|
),
|
|
)
|
|
mocker.patch.object(commands.definitions, "factory")
|
|
mocker.patch.object(commands.renderers, "ConnectorSpecificationRenderer")
|
|
expected_managed_resource, expected_state = (mocker.Mock(), mocker.Mock())
|
|
mocker.patch.object(
|
|
commands.resources,
|
|
"factory",
|
|
mocker.Mock(return_value=mocker.Mock(manage=mocker.Mock(return_value=(expected_managed_resource, expected_state)))),
|
|
)
|
|
commands.import_source_or_destination(context_object["API_CLIENT"], context_object["WORKSPACE_ID"], ResourceClass, "resource_to_get")
|
|
commands.get_json_representation.assert_called_with(
|
|
context_object["API_CLIENT"], context_object["WORKSPACE_ID"], ResourceClass, "resource_to_get"
|
|
)
|
|
commands.json.loads.assert_called_with(commands.get_json_representation.return_value)
|
|
remote_configuration = commands.json.loads.return_value
|
|
commands.definitions.factory.assert_called_with(
|
|
resource_type, context_object["API_CLIENT"], context_object["WORKSPACE_ID"], f"{resource_type}_definition_id"
|
|
)
|
|
commands.renderers.ConnectorSpecificationRenderer.assert_called_with("foo", commands.definitions.factory.return_value)
|
|
renderer = commands.renderers.ConnectorSpecificationRenderer.return_value
|
|
renderer.import_configuration.assert_called_with(project_path=".", configuration=remote_configuration["connection_configuration"])
|
|
commands.resources.factory.assert_called_with(
|
|
context_object["API_CLIENT"], context_object["WORKSPACE_ID"], renderer.import_configuration.return_value
|
|
)
|
|
commands.resources.factory.return_value.manage.assert_called_with(remote_configuration[f"{resource_type}_id"])
|
|
commands.click.style.assert_has_calls(
|
|
[
|
|
mocker.call(
|
|
f"✅ - Imported {resource_type} {expected_managed_resource.name} in {renderer.import_configuration.return_value}. State stored in {expected_state.path}",
|
|
fg="green",
|
|
),
|
|
mocker.call(f"⚠️ - Please update any secrets stored in {renderer.import_configuration.return_value}", fg="yellow"),
|
|
]
|
|
)
|
|
assert commands.click.echo.call_count == 2
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"source_exists, source_was_created, destination_exists, destination_was_created",
|
|
[
|
|
(True, True, True, True),
|
|
(False, False, False, False),
|
|
(True, False, True, False),
|
|
(True, True, False, False),
|
|
(True, True, True, False),
|
|
],
|
|
)
|
|
def test_import_connection(mocker, context_object, source_exists, source_was_created, destination_exists, destination_was_created):
|
|
mocker.patch.object(commands.click, "style")
|
|
mocker.patch.object(commands.click, "echo")
|
|
mocker.patch.object(commands, "get_json_representation")
|
|
mocker.patch.object(
|
|
commands.json,
|
|
"loads",
|
|
mocker.Mock(
|
|
return_value={
|
|
"source": {"name": "my_source"},
|
|
"destination": {"name": "my_destination"},
|
|
"name": "my_connection",
|
|
"connection_id": "my_connection_id",
|
|
}
|
|
),
|
|
)
|
|
remote_configuration = commands.json.loads.return_value
|
|
mocker.patch.object(commands.definitions, "factory")
|
|
mock_source_configuration_path = mocker.Mock(is_file=mocker.Mock(return_value=source_exists))
|
|
mock_destination_configuration_path = mocker.Mock(is_file=mocker.Mock(return_value=destination_exists))
|
|
|
|
mocker.patch.object(
|
|
commands.renderers.ConnectorSpecificationRenderer,
|
|
"get_output_path",
|
|
mocker.Mock(side_effect=[mock_source_configuration_path, mock_destination_configuration_path]),
|
|
)
|
|
mocker.patch.object(commands.renderers, "ConnectionRenderer")
|
|
mock_managed_source = mocker.Mock(was_created=source_was_created)
|
|
mock_managed_destination = mocker.Mock(was_created=destination_was_created)
|
|
mock_remote_connection, mock_connection_state = mocker.Mock(), mocker.Mock()
|
|
mock_managed_connection = mocker.Mock(manage=mocker.Mock(return_value=(mock_remote_connection, mock_connection_state)))
|
|
|
|
mocker.patch.object(
|
|
commands.resources, "factory", mocker.Mock(side_effect=[mock_managed_source, mock_managed_destination, mock_managed_connection])
|
|
)
|
|
if all([source_exists, destination_exists, source_was_created, destination_was_created]):
|
|
|
|
commands.import_connection(context_object["API_CLIENT"], context_object["WORKSPACE_ID"], "resource_to_get")
|
|
commands.get_json_representation.assert_called_with(
|
|
context_object["API_CLIENT"], context_object["WORKSPACE_ID"], commands.UnmanagedConnection, "resource_to_get"
|
|
)
|
|
commands.renderers.ConnectorSpecificationRenderer.get_output_path.assert_has_calls(
|
|
[
|
|
mocker.call(project_path=".", definition_type="source", resource_name="my_source"),
|
|
mocker.call(project_path=".", definition_type="destination", resource_name="my_destination"),
|
|
]
|
|
)
|
|
commands.resources.factory.assert_has_calls(
|
|
[
|
|
mocker.call(context_object["API_CLIENT"], context_object["WORKSPACE_ID"], mock_source_configuration_path),
|
|
mocker.call(context_object["API_CLIENT"], context_object["WORKSPACE_ID"], mock_destination_configuration_path),
|
|
mocker.call(
|
|
context_object["API_CLIENT"],
|
|
context_object["WORKSPACE_ID"],
|
|
commands.renderers.ConnectionRenderer.return_value.import_configuration.return_value,
|
|
),
|
|
]
|
|
)
|
|
commands.renderers.ConnectionRenderer.assert_called_with(
|
|
remote_configuration["name"], mock_managed_source, mock_managed_destination
|
|
)
|
|
commands.renderers.ConnectionRenderer.return_value.import_configuration.assert_called_with(".", remote_configuration)
|
|
new_configuration_path = commands.renderers.ConnectionRenderer.return_value.import_configuration.return_value
|
|
commands.click.style.assert_called_with(
|
|
f"✅ - Imported connection {mock_remote_connection.name} in {new_configuration_path}. State stored in {mock_connection_state.path}",
|
|
fg="green",
|
|
)
|
|
commands.click.echo.assert_called_with(commands.click.style.return_value)
|
|
if not source_exists or not destination_exists:
|
|
with pytest.raises(
|
|
commands.MissingResourceDependencyError,
|
|
match="is not managed by octavia-cli, please import and apply it before importing your connection.",
|
|
):
|
|
commands.import_connection(context_object["API_CLIENT"], context_object["WORKSPACE_ID"], "resource_to_get")
|
|
if source_exists and destination_exists and (not source_was_created or not destination_was_created):
|
|
with pytest.raises(commands.resources.NonExistingResourceError, match="Please run octavia apply before creating this connection."):
|
|
commands.import_connection(context_object["API_CLIENT"], context_object["WORKSPACE_ID"], "resource_to_get")
|
|
|
|
|
|
@pytest.mark.parametrize("command", [commands.source, commands.destination, commands.connection, commands.all])
|
|
def test_import_not_initialized(command):
|
|
runner = CliRunner()
|
|
result = runner.invoke(command, obj={"PROJECT_IS_INITIALIZED": False})
|
|
assert result.exit_code == 1
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"command, ResourceClass, import_function",
|
|
[
|
|
(commands.source, commands.UnmanagedSource, "import_source_or_destination"),
|
|
(commands.destination, commands.UnmanagedDestination, "import_source_or_destination"),
|
|
(commands.connection, None, "import_connection"),
|
|
],
|
|
)
|
|
def test_import_commands(mocker, context_object, ResourceClass, command, import_function):
|
|
runner = CliRunner()
|
|
mock_import_function = mocker.Mock()
|
|
mocker.patch.object(commands, import_function, mock_import_function)
|
|
result = runner.invoke(command, ["resource_to_import"], obj=context_object)
|
|
if import_function == "import_source_or_destination":
|
|
mock_import_function.assert_called_with(
|
|
context_object["API_CLIENT"], context_object["WORKSPACE_ID"], ResourceClass, "resource_to_import"
|
|
)
|
|
else:
|
|
mock_import_function.assert_called_with(context_object["API_CLIENT"], context_object["WORKSPACE_ID"], "resource_to_import")
|
|
assert result.exit_code == 0
|
|
|
|
|
|
def test_import_all(mocker, context_object):
|
|
runner = CliRunner()
|
|
mock_manager = mocker.Mock()
|
|
mocker.patch.object(commands, "import_source_or_destination", mock_manager.import_source_or_destination)
|
|
mocker.patch.object(commands, "import_connection", mock_manager.import_connection)
|
|
mocker.patch.object(
|
|
commands, "UnmanagedSources", return_value=mocker.Mock(get_listing=mocker.Mock(return_value=[("_", "_", "source_resource_id")]))
|
|
)
|
|
mocker.patch.object(
|
|
commands,
|
|
"UnmanagedDestinations",
|
|
return_value=mocker.Mock(get_listing=mocker.Mock(return_value=[("_", "_", "destination_resource_id")])),
|
|
)
|
|
mocker.patch.object(
|
|
commands,
|
|
"UnmanagedConnections",
|
|
return_value=mocker.Mock(get_listing=mocker.Mock(return_value=[("_", "connection_resource_id", "_", "_", "_")])),
|
|
)
|
|
result = runner.invoke(commands.all, obj=context_object)
|
|
|
|
commands.UnmanagedSources.return_value.get_listing.assert_called_once()
|
|
commands.UnmanagedDestinations.return_value.get_listing.assert_called_once()
|
|
commands.UnmanagedConnections.return_value.get_listing.assert_called_once()
|
|
assert result.exit_code == 0
|
|
assert mock_manager.mock_calls[0] == mocker.call.import_source_or_destination(
|
|
context_object["API_CLIENT"], "workspace_id", commands.UnmanagedSource, "source_resource_id"
|
|
)
|
|
assert mock_manager.mock_calls[1] == mocker.call.import_source_or_destination(
|
|
context_object["API_CLIENT"], "workspace_id", commands.UnmanagedDestination, "destination_resource_id"
|
|
)
|
|
assert mock_manager.mock_calls[2] == mocker.call.import_connection(
|
|
context_object["API_CLIENT"], "workspace_id", "connection_resource_id"
|
|
)
|