def test_server_config_setup(self, mock_subprocess):
        # Pull current version information to test default values
        base_version = prefect.__version__.split("+")
        if len(base_version) > 1:
            default_tag = "master"
        else:
            default_tag = f"core-{base_version[0]}"

        expected_env = setup_compose_env(
            version=default_tag,
            ui_version=default_tag,
            ui_port=prefect.config.server.ui.host_port,
            hasura_port=prefect.config.server.hasura.host_port,
            graphql_port=prefect.config.server.graphql.host_port,
            postgres_port=prefect.config.server.database.host_port,
            server_port=prefect.config.server.host_port,
            no_upgrade=False,
            volume_path=prefect.config.server.database.volume_path,
        )

        CliRunner().invoke(server, ["config"])

        config_args, config_kwargs = get_command_call(
            mock_subprocess, ["docker-compose", "config"]
        )

        # Ensure the env is correct
        assert config_kwargs["env"] == expected_env

        # Ensure the docker-compose.yml exists at the tmpdir
        assert os.path.exists(os.path.join(config_kwargs["cwd"], "docker-compose.yml"))
    def test_warns_on_db_command_conflict(self):
        os.environ["PREFECT_SERVER_DB_CMD"] = "FOO"
        with pytest.warns(
            UserWarning,
            match="The database startup command has been set in the environment .* CLI",
        ):
            env = setup_compose_env(no_upgrade=True)

        assert env["PREFECT_SERVER_DB_CMD"] == "echo 'DATABASE MIGRATIONS SKIPPED'"
    def test_warns_on_ui_version_conflict(self):
        os.environ["PREFECT_UI_TAG"] = "FOO"
        with pytest.warns(
            UserWarning,
            match="The UI version has been set in the environment .* and the CLI",
        ):
            env = setup_compose_env(ui_version="BAR")

        assert env["PREFECT_UI_TAG"] == "BAR"
    def test_setup_env_for_external_postgres(
        self, monkeypatch, external_postgres, postgres_url, expected_postgres_url
    ):
        monkeypatch.delenv(
            "PREFECT_SERVER_DB_CMD", raising=False
        )  # Ensure this is not set
        with set_temporary_config(
            {
                "server.database.connection_url": "localhost/foo",
                "server.graphql.path": "/G",
                "server.telemetry.enabled": False,
            }
        ):
            env = setup_compose_env(
                version="A",
                ui_version="B",
                no_upgrade=False,
                external_postgres=external_postgres,
                postgres_url=postgres_url,
                hasura_port=2,
                graphql_port=3,
                ui_port=4,
                server_port=5,
                volume_path="C",
            )

        expected = {
            "APOLLO_HOST_PORT": "5",
            "APOLLO_URL": "http://localhost:4200/graphql",
            "DB_CONNECTION_URL": expected_postgres_url,
            "GRAPHQL_HOST_PORT": "3",
            "HASURA_API_URL": "http://hasura:2/v1alpha1/graphql",
            "HASURA_HOST_PORT": "2",
            "HASURA_WS_URL": "ws://hasura:2/v1alpha1/graphql",
            "PREFECT_API_HEALTH_URL": "http://graphql:3/health",
            "PREFECT_API_URL": f"http://graphql:3/G",
            "PREFECT_CORE_VERSION": prefect.__version__,
            "PREFECT_SERVER_DB_CMD": "prefect-server database upgrade -y",
            "PREFECT_SERVER_TAG": "A",
            "PREFECT_UI_TAG": "B",
            "UI_HOST_PORT": "4",
            "PREFECT_SERVER__TELEMETRY__ENABLED": "false",
        }

        for key, expected_value in expected.items():
            assert env[key] == expected_value

        # when using external postgres, we should not set these env vars
        not_expected = (
            "POSTGRES_DATA_PATH",
            "POSTGRES_DB",
            "POSTGRES_HOST_PORT",
            "POSTGRES_PASSWORD",
            "POSTGRES_USER",
        )
        assert all([key not in env for key in not_expected])
    def test_fills_env_with_values_from_config_and_args(self, monkeypatch):
        monkeypatch.delenv(
            "PREFECT_SERVER_DB_CMD", raising=False
        )  # Ensure this is not set
        with set_temporary_config(
            {
                "server.database.connection_url": "localhost/foo",
                "server.database.name": "D",
                "server.database.password": "******",
                "server.database.username": "******",
                "server.graphql.path": "/G",
                "server.telemetry.enabled": False,
            }
        ):
            env = setup_compose_env(
                version="A",
                ui_version="B",
                no_upgrade=False,
                postgres_port=1,
                hasura_port=2,
                graphql_port=3,
                ui_port=4,
                server_port=5,
                volume_path="C",
            )

        expected = {
            "APOLLO_HOST_PORT": "5",
            "APOLLO_URL": "http://localhost:4200/graphql",
            "DB_CONNECTION_URL": "postgres/foo",
            "GRAPHQL_HOST_PORT": "3",
            "HASURA_API_URL": "http://hasura:2/v1alpha1/graphql",
            "HASURA_HOST_PORT": "2",
            "HASURA_WS_URL": "ws://hasura:2/v1alpha1/graphql",
            "POSTGRES_DATA_PATH": "C",
            "POSTGRES_DB": "D",
            "POSTGRES_HOST_PORT": "1",
            "POSTGRES_PASSWORD": "******",
            "POSTGRES_USER": "******",
            "PREFECT_API_HEALTH_URL": "http://graphql:3/health",
            "PREFECT_API_URL": f"http://graphql:3/G",
            "PREFECT_CORE_VERSION": prefect.__version__,
            "PREFECT_SERVER_DB_CMD": "prefect-server database upgrade -y",
            "PREFECT_SERVER_TAG": "A",
            "PREFECT_UI_TAG": "B",
            "UI_HOST_PORT": "4",
            "PREFECT_SERVER__TELEMETRY__ENABLED": "false",
        }

        for key, expected_value in expected.items():
            assert env[key] == expected_value
    def test_server_start_setup_and_teardown(self, macos_platform, mock_subprocess):
        # Pull current version information to test default values
        base_version = prefect.__version__.split("+")
        if len(base_version) > 1:
            default_tag = "master"
        else:
            default_tag = f"core-{base_version[0]}"

        expected_env = setup_compose_env(
            version=default_tag,
            ui_version=default_tag,
            ui_port=prefect.config.server.ui.host_port,
            hasura_port=prefect.config.server.hasura.host_port,
            graphql_port=prefect.config.server.graphql.host_port,
            postgres_port=prefect.config.server.database.host_port,
            server_port=prefect.config.server.host_port,
            no_upgrade=False,
            volume_path=prefect.config.server.database.volume_path,
        )

        CliRunner().invoke(server, ["start"])

        pull_args, pull_kwargs = get_command_call(
            mock_subprocess, ["docker-compose", "pull"]
        )
        up_args, up_kwargs = get_command_call(mock_subprocess, ["docker-compose", "up"])
        down_args, down_kwargs = get_command_call(
            mock_subprocess, ["docker-compose", "down"]
        )

        # Ensure that cwd, env were passed and used consistently
        cwd = pull_kwargs.get("cwd")
        env = pull_kwargs.get("env")

        assert env is not None
        assert cwd is not None

        assert up_kwargs.get("cwd") == cwd
        assert up_kwargs.get("env") == env
        assert down_kwargs.get("cwd") == cwd
        assert down_kwargs.get("env") == env

        # Check the environment matches expected defaults
        assert env == expected_env

        # Ensure the docker-compose.yml exists at the tmpdir
        assert os.path.exists(os.path.join(cwd, "docker-compose.yml"))
 def test_server_start_image_versions(
     self, monkeypatch, version, expected, macos_platform
 ):
     monkeypatch.setattr(prefect, "__version__", version)
     assert setup_compose_env()["PREFECT_SERVER_TAG"] == expected
 def test_allows_db_command_override(self, monkeypatch):
     monkeypatch.setenv("PREFECT_SERVER_DB_CMD", "FOO")
     env = setup_compose_env(no_upgrade=False)
     assert env["PREFECT_SERVER_DB_CMD"] == "FOO"