Esempio n. 1
0
    def test_schedule(self, get, session, project, cli_runner,
                      schedule_service):
        TEST_DATE = "2010-01-01"
        get.return_value = TEST_DATE

        with mock.patch("meltano.cli.schedule.ScheduleService",
                        return_value=schedule_service):
            res = cli_runner.invoke(
                cli,
                [
                    "schedule",
                    "schedule-mock",
                    "tap-mock",
                    "target-mock",
                    "@eon",
                    "--transform",
                    "run",
                ],
            )

        assert_cli_runner(res)
        schedule = schedule_service.schedules()[0]

        assert schedule.name == "schedule-mock"
        assert schedule.extractor == "tap-mock"
        assert schedule.loader == "target-mock"
        assert schedule.transform == "run"
        assert schedule.interval == "@eon"  # not anytime soon ;)
        assert schedule.start_date == iso8601_datetime(TEST_DATE)
Esempio n. 2
0
    def test_ui_setup(self, project, cli_runner, monkeypatch):
        monkeypatch.setenv("MELTANO_UI_SECRET_KEY", "existing_secret_key")

        with mock.patch("meltano.cli.ui.secrets.token_hex",
                        return_value="fake_secret"):
            result = cli_runner.invoke(cli,
                                       ["ui", "setup", "meltano.example.com"])

        assert_cli_runner(result)

        assert (
            "Setting 'ui.secret_key' has already been set in the environment"
            in result.stdout)

        settings_service = ProjectSettingsService(project)

        assert settings_service.get_with_source("ui.server_name") == (
            "meltano.example.com",
            SettingValueStore.DOTENV,
        )
        assert settings_service.get_with_source("ui.secret_key") == (
            "existing_secret_key",
            SettingValueStore.ENV,
        )
        assert settings_service.get_with_source("ui.password_salt") == (
            "fake_secret",
            SettingValueStore.DOTENV,
        )
Esempio n. 3
0
    def test_carbon_intensity_sqlite(self, cli_runner, monkeypatch, project):
        # Directly run `meltano add loader target-sqlite` in a new project
        # So that the extractor and the loader are auto installed by meltano
        cli_args = ["elt", "tap-carbon-intensity", "target-sqlite"]
        result = cli_runner.invoke(cli, cli_args)

        assert_cli_runner(result)
Esempio n. 4
0
    def test_dump_loader_config(
        self,
        cli_runner,
        project,
        tap,
        target,
        project_plugins_service,
        plugin_settings_service_factory,
    ):
        job_id = "pytest_test_elt"
        args = [
            "elt",
            "--job_id",
            job_id,
            tap.name,
            target.name,
            "--dump",
            "loader-config",
        ]

        settings_service = plugin_settings_service_factory(target)

        with mock.patch(
                "meltano.cli.elt.ProjectPluginsService",
                return_value=project_plugins_service,
        ), mock.patch.object(SingerTap, "discover_catalog"), mock.patch.object(
                SingerTap, "apply_catalog_rules"):
            result = cli_runner.invoke(cli, args)
            assert_cli_runner(result)

            assert json.loads(result.stdout) == settings_service.as_dict(
                extras=False, process=True)
Esempio n. 5
0
    def test_carbon_intensity_postgres_dbt(
        self, cli_runner, monkeypatch, project, elt_context_builder, project_add_service
    ):
        with mock.patch(
            "meltano.cli.add.ProjectAddService", return_value=project_add_service
        ), mock.patch(
            "meltano.cli.elt.ELTContextBuilder", return_value=elt_context_builder
        ):
            cli_args = ["add", "extractor", "tap-carbon-intensity"]
            result = cli_runner.invoke(cli, cli_args)
            assert_cli_runner(result)

            cli_args = ["add", "loader", "target-postgres"]
            result = cli_runner.invoke(cli, cli_args)
            assert_cli_runner(result)

            cli_args = ["add", "transformer", "dbt"]
            result = cli_runner.invoke(cli, cli_args)
            assert_cli_runner(result)

            cli_args = ["add", "model", "model-carbon-intensity"]
            result = cli_runner.invoke(cli, cli_args)
            assert_cli_runner(result)

            cli_args = [
                "elt",
                "tap-carbon-intensity",
                "target-postgres",
                "--transform",
                "run",
            ]

            result = cli_runner.invoke(cli, cli_args)
            assert_cli_runner(result)
Esempio n. 6
0
    def test_elt_transform_only_with_transform(
        self,
        google_tracker,
        cli_runner,
        project,
        tap,
        target,
        dbt,
        tap_mock_transform,
        project_plugins_service,
    ):
        args = ["elt", tap.name, target.name, "--transform", "only"]

        with mock.patch(
                "meltano.cli.elt.ProjectPluginsService",
                return_value=project_plugins_service,
        ), mock.patch(
                "meltano.core.transform_add_service.ProjectPluginsService",
                return_value=project_plugins_service,
        ), mock.patch.object(DbtRunner, "run", new=CoroutineMock()):
            result = cli_runner.invoke(cli, args)
            assert_cli_runner(result)

            assert_lines(
                result.output,
                "meltano | Extract & load skipped.\n",
                "meltano | Running transformation...\n",
                "meltano | Transformation complete!\n",
            )
Esempio n. 7
0
    def test_upgrade_package(self, project, cli_runner):
        result = cli_runner.invoke(cli, ["upgrade", "package"])
        assert_cli_runner(result)

        assert ("The `meltano` package could not be upgraded automatically"
                in result.output)
        assert "run `meltano upgrade --skip-package`" not in result.output
Esempio n. 8
0
    def test_add_custom_variant(
        self, project, cli_runner, project_plugins_service, plugin_discovery_service
    ):
        with mock.patch(
            "meltano.cli.add.ProjectPluginsService",
            return_value=project_plugins_service,
        ), mock.patch("meltano.cli.add.install_plugins") as install_plugin_mock:
            install_plugin_mock.return_value = True
            res = cli_runner.invoke(
                cli,
                [
                    "add",
                    "--custom",
                    "extractor",
                    "tap-custom-variant",
                    "--variant",
                    "personal",
                ],
            )
            assert_cli_runner(res)

            plugin = project_plugins_service.find_plugin(
                plugin_type=PluginType.EXTRACTORS, plugin_name="tap-custom-variant"
            )
            plugin_def = plugin.custom_definition
            plugin_variant = plugin_def.variants[0]

            assert plugin.variant == plugin_variant.name == "personal"
Esempio n. 9
0
    def test_add_files_with_updates(
        self,
        project,
        cli_runner,
        project_plugins_service,
        plugin_settings_service_factory,
    ):
        result = cli_runner.invoke(cli, ["add", "files", "airflow"])
        assert_cli_runner(result)

        # Plugin has been added to meltano.yml
        plugin = project_plugins_service.find_plugin("airflow", PluginType.FILES)
        assert plugin

        # Automatic updating is enabled
        plugin_settings_service = plugin_settings_service_factory(plugin)
        update_config = plugin_settings_service.get("_update")
        assert update_config["orchestrate/dags/meltano.py"] == True

        # File has been created
        assert "Created orchestrate/dags/meltano.py" in result.output

        file_path = project.root_dir("orchestrate/dags/meltano.py")
        assert file_path.is_file()

        # File has "managed" header
        assert (
            "This file is managed by the 'airflow' file bundle" in file_path.read_text()
        )
Esempio n. 10
0
    def test_schedule(self, get_value, session, project, cli_runner,
                      schedule_service):
        TEST_DATE = "2010-01-01"
        get_value.return_value = (TEST_DATE, 0)

        res = cli_runner.invoke(
            cli,
            [
                "schedule",
                "schedule-mock",
                "tap-mock",
                "target-mock",
                "@eon",
                "--transform",
                "run",
            ],
        )

        assert_cli_runner(res)

        schedule = next(schedule_service.schedules())

        assert schedule.name == "schedule-mock"
        assert schedule.extractor == "tap-mock"
        assert schedule.loader == "target-mock"
        assert schedule.transform == "run"
        assert schedule.interval == "@eon"  # not anytime soon ;)
        assert schedule.start_date == iso8601_datetime(TEST_DATE)
Esempio n. 11
0
    def test_dump_catalog(
        self,
        cli_runner,
        project,
        tap,
        target,
        project_plugins_service,
        plugin_settings_service_factory,
    ):
        catalog = {"streams": []}
        with project.root.joinpath("catalog.json").open("w") as catalog_file:
            json.dump(catalog, catalog_file)

        job_id = "pytest_test_elt"
        args = [
            "elt",
            "--job_id",
            job_id,
            tap.name,
            target.name,
            "--catalog",
            "catalog.json",
            "--dump",
            "catalog",
        ]

        with mock.patch(
                "meltano.cli.elt.ProjectPluginsService",
                return_value=project_plugins_service,
        ):
            result = cli_runner.invoke(cli, args)
            assert_cli_runner(result)

            assert json.loads(result.stdout) == catalog
Esempio n. 12
0
def test_elt_transform_only(
    google_tracker,
    cli_runner,
    project,
    tap,
    target,
    dbt,
    plugin_discovery_service,
    plugin_settings_service,
):
    # exit cleanly when `meltano elt ... --transform only` runs for
    # a tap with no default transforms

    args = ["elt", tap.name, target.name, "--transform", "only"]

    # fmt: off
    with patch("meltano.cli.elt.add_plugin", return_value=None) as add_plugin, \
      patch("meltano.cli.elt.PluginDiscoveryService", return_value=plugin_discovery_service), \
      patch("meltano.core.elt_context.PluginDiscoveryService", return_value=plugin_discovery_service), \
      patch("meltano.core.elt_context.PluginSettingsService", return_value=plugin_settings_service), \
      patch.object(DbtRunner, "run", return_value=None):
        result = cli_runner.invoke(cli, args)
        assert_cli_runner(result)

        add_plugin.assert_called
Esempio n. 13
0
    def test_elt_transform_run(
        self,
        google_tracker,
        cli_runner,
        project,
        tap,
        target,
        dbt,
        tap_process,
        target_process,
        silent_dbt_process,
        dbt_process,
        tap_mock_transform,
        project_plugins_service,
    ):
        args = ["elt", tap.name, target.name, "--transform", "run"]

        invoke_async = CoroutineMock(side_effect=(
            tap_process,
            target_process,
            silent_dbt_process,  # dbt clean
            silent_dbt_process,  # dbt deps
            dbt_process,  # dbt run
        ))
        with mock.patch.object(
                PluginInvoker, "invoke_async",
                new=invoke_async) as invoke_async, mock.patch(
                    "meltano.cli.elt.ProjectPluginsService",
                    return_value=project_plugins_service,
                ), mock.patch(
                    "meltano.core.transform_add_service.ProjectPluginsService",
                    return_value=project_plugins_service,
                ):
            result = cli_runner.invoke(cli, args)
            assert_cli_runner(result)

            assert_lines(
                result.stdout,
                "meltano     | Running extract & load...\n",
                "meltano     | Extract & load complete!\n",
                "meltano     | Running transformation...\n",
                "meltano     | Transformation complete!\n",
            )

            assert_lines(
                result.stderr,
                "tap-mock    | Starting\n",
                "tap-mock    | Running\n",
                "tap-mock    | Done\n",
                "target-mock | Starting\n",
                "target-mock | Running\n",
                "target-mock | Done\n",
                "dbt         | Starting\n",
                "dbt         | Running\n",
                "dbt         | Done\n",
            )
Esempio n. 14
0
    def test_config(self, project, cli_runner, tap, project_plugins_service):
        with mock.patch(
                "meltano.cli.config.ProjectPluginsService",
                return_value=project_plugins_service,
        ):
            result = cli_runner.invoke(cli, ["config", tap.name])
            assert_cli_runner(result)

            json_config = json.loads(result.stdout)
            assert json_config["test"] == "mock"
Esempio n. 15
0
    def test_install(self, project, tap, tap_gitlab, target, dbt, cli_runner):
        with mock.patch(
                "meltano.cli.install.install_plugins") as install_plugin_mock:
            install_plugin_mock.return_value = True

            result = cli_runner.invoke(cli, ["install"])
            assert_cli_runner(result)

            install_plugin_mock.assert_called_once_with(
                project, [tap, tap_gitlab, target, dbt])
Esempio n. 16
0
    def test_config_env(self, project, cli_runner, tap,
                        project_plugins_service):
        with mock.patch(
                "meltano.cli.config.ProjectPluginsService",
                return_value=project_plugins_service,
        ):
            result = cli_runner.invoke(cli,
                                       ["config", "--format=env", tap.name])
            assert_cli_runner(result)

            assert 'TAP_MOCK_TEST="mock"' in result.stdout
Esempio n. 17
0
    def test_add_files_that_already_exists(self, project, cli_runner,
                                           config_service):
        project.root_dir("transform/dbt_project.yml").write_text("Exists!")

        result = cli_runner.invoke(cli, ["add", "files", "dbt"])
        assert_cli_runner(result)

        assert (
            "File transform/dbt_project.yml already exists, keeping both versions"
            in result.output)
        assert "Created transform/dbt_project (dbt).yml" in result.output
        assert project.root_dir("transform/dbt_project (dbt).yml").is_file()
Esempio n. 18
0
    def test_config_meltano(self, project, cli_runner, engine_uri,
                            project_plugins_service):
        with mock.patch(
                "meltano.cli.config.ProjectPluginsService",
                return_value=project_plugins_service,
        ):
            result = cli_runner.invoke(cli, ["config", "meltano"])
            assert_cli_runner(result)

            json_config = json.loads(result.stdout)
            assert json_config["send_anonymous_usage_stats"] == False
            assert json_config["database_uri"] == engine_uri
            assert json_config["cli"]["log_level"] == "info"
Esempio n. 19
0
    def test_elt(
        self,
        google_tracker,
        cli_runner,
        project,
        tap,
        target,
        plugin_settings_service,
        plugin_discovery_service,
        job_logging_service,
    ):
        result = cli_runner.invoke(cli, ["elt"])
        assert result.exit_code == 2

        job_id = "pytest_test_elt"
        args = ["elt", "--job_id", job_id, tap.name, target.name]

        # exit cleanly when everything is fine
        # fmt: off
        with patch.object(SingerRunner, "run", return_value=None), \
        patch("meltano.cli.elt.install_missing_plugins", return_value=True), \
        patch("meltano.core.elt_context.PluginDiscoveryService", return_value=plugin_discovery_service), \
        patch("meltano.core.elt_context.PluginSettingsService", return_value=plugin_settings_service):
            result = cli_runner.invoke(cli, args)
            assert_cli_runner(result)
        # fmt: on

        # aborts when there is an exception
        with patch("meltano.cli.elt.install_missing_plugins",
                   return_value=None):
            result = cli_runner.invoke(cli, args)
            assert result.exit_code == 1

        job_logging_service.delete_all_logs(job_id)

        with patch.object(
                SingerRunner,
                "run",
                side_effect=Exception("This is a grave danger.")), patch(
                    "meltano.core.elt_context.PluginDiscoveryService",
                    return_value=plugin_discovery_service,
                ), patch(
                    "meltano.core.elt_context.PluginSettingsService",
                    return_value=plugin_settings_service,
                ):
            result = cli_runner.invoke(cli, args)
            assert result.exit_code == 1

            # ensure there is a log of this exception
            log = job_logging_service.get_latest_log(job_id)
            assert "This is a grave danger.\n" in log
Esempio n. 20
0
    def test_discover_extractors(self, project, cli_runner,
                                 plugin_discovery_service):
        with mock.patch(
                "meltano.cli.discovery.PluginDiscoveryService",
                return_value=plugin_discovery_service,
        ):
            result = cli_runner.invoke(cli, ["discover", "extractors"])
            assert_cli_runner(result)

            assert "Extractors" in result.output
            assert "tap-gitlab" in result.output
            assert "tap-mock" in result.output

            assert "Loaders" not in result.output
Esempio n. 21
0
    def test_add_variant(self, project, cli_runner, project_plugins_service):
        with mock.patch(
            "meltano.cli.add.ProjectPluginsService",
            return_value=project_plugins_service,
        ), mock.patch("meltano.cli.add.install_plugins") as install_plugin_mock:
            install_plugin_mock.return_value = True
            res = cli_runner.invoke(
                cli, ["add", "extractor", "tap-mock", "--variant", "singer-io"]
            )
            assert_cli_runner(res)

            plugin = project_plugins_service.find_plugin(
                plugin_type=PluginType.EXTRACTORS, plugin_name="tap-mock"
            )
            assert plugin.variant == "singer-io"
Esempio n. 22
0
    def test_install_multiple(
        self, project, tap, tap_gitlab, target, dbt, cli_runner, project_plugins_service
    ):
        with mock.patch(
            "meltano.cli.install.ProjectPluginsService",
            return_value=project_plugins_service,
        ), mock.patch("meltano.cli.install.install_plugins") as install_plugin_mock:
            install_plugin_mock.return_value = True

            result = cli_runner.invoke(
                cli, ["install", "extractors", tap.name, tap_gitlab.name]
            )
            assert_cli_runner(result)

            install_plugin_mock.assert_called_once_with(project, [tap_gitlab, tap])
Esempio n. 23
0
    def test_ui(self, project, cli_runner):
        with mock.patch("meltano.cli.ui.APIWorker.start"
                        ) as start_api_worker, mock.patch(
                            "meltano.cli.ui.MeltanoCompilerWorker.start"
                        ) as start_compiler, mock.patch(
                            "meltano.cli.ui.UIAvailableWorker.start"
                        ) as start_ui_available_worker, mock.patch.object(
                            GoogleAnalyticsTracker,
                            "track_meltano_ui") as track:
            result = cli_runner.invoke(cli, "ui")
            assert_cli_runner(result)

            assert start_api_worker.called
            assert start_ui_available_worker.called
            assert start_compiler.called
            assert track.called
Esempio n. 24
0
    def test_upgrade(self, project, cli_runner):
        result = cli_runner.invoke(cli, ["upgrade"])
        assert_cli_runner(result)

        assert ("The `meltano` package could not be upgraded automatically"
                in result.output)
        assert "run `meltano upgrade --skip-package`" in result.output

        with mock.patch("meltano.cli.upgrade.UpgradeService._upgrade_package"
                        ) as upgrade_package_mock:
            upgrade_package_mock.return_value = True

            result = cli_runner.invoke(cli, ["upgrade"])
            assert_cli_runner(result)

            assert ("Meltano and your Meltano project have been upgraded!"
                    in result.output)
Esempio n. 25
0
    def test_discover(self, project, cli_runner, plugin_discovery_service):
        with mock.patch(
                "meltano.cli.discovery.PluginDiscoveryService",
                return_value=plugin_discovery_service,
        ):
            result = cli_runner.invoke(cli, ["discover"])
            assert_cli_runner(result)

            assert "Extractors" in result.output
            assert "tap-gitlab" in result.output
            assert (
                "tap-mock, variants: meltano (default), singer-io (deprecated)"
                in result.output)

            assert "Loaders" in result.output
            assert "target-jsonl" in result.output
            assert "target-mock" in result.output
Esempio n. 26
0
    def test_add_files_without_updates(self, project, cli_runner,
                                       config_service):
        result = cli_runner.invoke(cli, ["add", "files", "docker-compose"])
        assert_cli_runner(result)

        # Plugin has not been added to meltano.yml
        with pytest.raises(PluginMissingError):
            config_service.find_plugin("docker-compose", PluginType.FILES)

        # File has been created
        assert "Created docker-compose.yml" in result.output

        file_path = project.root_dir("docker-compose.yml")
        assert file_path.is_file()

        # File does not have "managed" header
        assert "This file is managed" not in file_path.read_text()
Esempio n. 27
0
    def test_install_type_name(self, project, tap, tap_gitlab, target, dbt,
                               cli_runner):
        with mock.patch(
                "meltano.cli.install.install_plugins") as install_plugin_mock:
            install_plugin_mock.return_value = True

            result = cli_runner.invoke(cli, ["install", "extractor", tap.name])
            assert_cli_runner(result)

            install_plugin_mock.assert_called_once_with(project, [tap])

        with mock.patch(
                "meltano.cli.install.install_plugins") as install_plugin_mock:
            install_plugin_mock.return_value = True

            result = cli_runner.invoke(cli, ["install", "loader", target.name])
            assert_cli_runner(result)

            install_plugin_mock.assert_called_once_with(project, [target])
Esempio n. 28
0
    def test_add_custom(self, project, cli_runner, project_plugins_service):
        pip_url = "-e path/to/tap-custom"
        executable = "tap-custom-bin"
        stdin = os.linesep.join(
            # namespace, pip_url, executable, capabilities, settings
            ["tap_custom", pip_url, executable, "foo,bar", "baz,qux"]
        )

        with mock.patch(
            "meltano.cli.add.ProjectPluginsService",
            return_value=project_plugins_service,
        ), mock.patch("meltano.cli.add.install_plugins") as install_plugin_mock:
            install_plugin_mock.return_value = True
            res = cli_runner.invoke(
                cli, ["add", "--custom", "extractor", "tap-custom"], input=stdin
            )
            assert_cli_runner(res)

            plugin = project_plugins_service.find_plugin(
                plugin_type=PluginType.EXTRACTORS, plugin_name="tap-custom"
            )
            assert plugin.name == "tap-custom"
            assert plugin.pip_url == pip_url

            plugin_def = plugin.custom_definition
            plugin_variant = plugin.custom_definition.variants[0]

            assert plugin_def.type == plugin.type
            assert plugin_def.name == plugin.name == "tap-custom"
            assert plugin_def.namespace == plugin.namespace == "tap_custom"

            assert plugin_variant.name is None

            assert plugin.pip_url == plugin_variant.pip_url == pip_url
            assert plugin.executable == plugin_variant.executable == executable
            assert plugin.capabilities == plugin_variant.capabilities == ["foo", "bar"]

            assert [s.name for s in plugin_variant.settings] == ["baz", "qux"]
            assert plugin.settings == plugin_variant.settings

            install_plugin_mock.assert_called_once_with(
                project, [plugin], reason=PluginInstallReason.ADD
            )
Esempio n. 29
0
    def test_add_transform(self, project, cli_runner):
        cli_runner.invoke(cli, ["add", "files", "dbt"])
        cli_runner.invoke(cli, ["install", "files", "dbt"])

        res = cli_runner.invoke(cli, ["add", "transform", "tap-google-analytics"])
        assert_cli_runner(res)

        with project.root_dir("transform/packages.yml").open() as packages_file:
            packages_yaml = yaml.safe_load(packages_file)

        with project.root_dir("transform/dbt_project.yml").open() as project_file:
            project_yaml = yaml.safe_load(project_file)

        assert {
            "git": "https://gitlab.com/meltano/dbt-tap-google-analytics.git"
        } in packages_yaml["packages"]

        assert "tap_google_analytics" in project_yaml["models"]
        assert project_yaml["models"]["tap_google_analytics"] == {
            "vars": {"schema": "{{ env_var('DBT_SOURCE_SCHEMA') }}"}
        }
Esempio n. 30
0
    def test_dump_state(
        self,
        session,
        cli_runner,
        project,
        tap,
        target,
        project_plugins_service,
        plugin_settings_service_factory,
    ):
        state = {"success": True}
        with project.root.joinpath("state.json").open("w") as state_file:
            json.dump(state, state_file)

        job_id = "pytest_test_elt"
        args = [
            "elt",
            "--job_id",
            job_id,
            tap.name,
            target.name,
            "--state",
            "state.json",
            "--dump",
            "state",
        ]

        with mock.patch(
                "meltano.cli.elt.ProjectPluginsService",
                return_value=project_plugins_service,
        ), mock.patch.object(SingerTap, "discover_catalog"), mock.patch.object(
                SingerTap, "apply_catalog_rules"):
            result = cli_runner.invoke(cli, args)
            assert_cli_runner(result)

            assert json.loads(result.stdout) == state