Пример #1
0
def test_tenant_view_query_for_tenants_uses_where_in_query(monkeypatch):
    post = MagicMock(return_value={"data": {"tenant": [TENANT_DATA_1]}})
    monkeypatch.setattr("prefect.client.client.Client.post", post)

    TenantView._query_for_tenants(where={"foo": {"_eq": "bar"}})

    assert ('tenant(where: { foo: { _eq: "bar" } })'
            in post.call_args[1]["params"]["query"])
Пример #2
0
def test_tenant_view_query_for_tenants_uses_order_by_in_query(monkeypatch):
    post = MagicMock(return_value={"data": {"tenant": [TENANT_DATA_1]}})
    monkeypatch.setattr("prefect.client.client.Client.post", post)

    TenantView._query_for_tenants(where={}, order_by={"foo": EnumValue("asc")})

    assert ("tenant(where: {}, order_by: { foo: asc })"
            in post.call_args[1]["params"]["query"])
Пример #3
0
def test_tenant_view_from_tenant_id_where_clause(monkeypatch):
    post = MagicMock(return_value={"data": {"tenant": [TENANT_DATA_1]}})
    monkeypatch.setattr("prefect.client.client.Client.post", post)

    TenantView.from_tenant_id(tenant_id="id-1")

    assert ('tenant(where: { id: { _eq: "id-1" } })'
            in post.call_args[1]["params"]["query"])
Пример #4
0
def test_tenant_view_query_for_tenants_includes_all_required_data(monkeypatch):
    graphql = MagicMock(return_value={"data": {"tenant": [TENANT_DATA_1]}})
    monkeypatch.setattr("prefect.client.client.Client.graphql", graphql)

    TenantView._query_for_tenants(where={})

    query_dict = graphql.call_args[0][0]
    selection_set = query_dict["query"]["tenant(where: {})"]
    assert selection_set == {"id", "name", "slug"}
Пример #5
0
def test_tenant_view_from_returns_instance(patch_post, from_method,
                                           monkeypatch):
    patch_post({"data": {"tenant": [TENANT_DATA_1]}})

    if from_method == "tenant_id":
        tenant = TenantView.from_tenant_id("fake-id")
    elif from_method == "current_tenant":
        monkeypatch.setattr(
            "prefect.client.client.Client._get_auth_tenant",
            MagicMock(return_value="fake-id"),
        )
        tenant = TenantView.from_current_tenant()

    assert tenant.tenant_id == "id-1"
    assert tenant.name == "name-1"
    assert tenant.slug == "slug-1"
Пример #6
0
def login(key):
    """
    Login to Prefect Cloud

    Create an API key in the UI then login with it here:

        $ prefect auth login -k YOUR-KEY

    You will be switched to the default tenant associated with the key. After login,
    your available tenants can be seen with `prefect auth list-tenants` and you can
    change the default tenant on this machine using `prefect auth switch-tenants`.

    The given key will be stored on disk for later access. Prefect will default to using
    this key for all interaction with the API but frequently overrides can be passed to
    individual commands or functions. To remove your key from disk, see
    `prefect auth logout`.
    """
    if not key:
        raise TerminalError("You must supply an API key!")

    abort_on_config_api_key(
        "To log in with the CLI, remove the config key `prefect.cloud.api_key`"
    )

    # Ignore any tenant id that has been previously set via login
    client = Client(api_key=key)
    client._tenant_id = None

    try:
        tenant_id = client._get_auth_tenant()
    except AuthorizationError:
        raise TerminalError("Unauthorized. Invalid Prefect Cloud API key.")
    except ClientError:
        raise TerminalError(
            "Error attempting to communicate with Prefect Cloud.")
    else:
        client.tenant_id = tenant_id
        client.save_auth_to_disk()
        tenant = TenantView.from_tenant_id(tenant_id)
        click.secho(
            f"Logged in to Prefect Cloud tenant {tenant.name!r} ({tenant.slug})",
            fg="green",
        )
        return
Пример #7
0
def login(key, token):
    """
    Login to Prefect Cloud

    Create an API key in the UI then login with it here:

        $ prefect auth login -k YOUR-KEY

    You will be switched to the default tenant associated with the key. After login,
    your available tenants can be seen with `prefect auth list-tenants` and you can
    change the default tenant on this machine using `prefect auth switch-tenants`.

    The given key will be stored on disk for later access. Prefect will default to using
    this key for all interaction with the API but frequently overrides can be passed to
    individual commands or functions. To remove your key from disk, see
    `prefect auth logout`.

    This command has backwards compatibility support for API tokens, which are a
    deprecated form of authentication with Prefect Cloud
    """
    if not key and not token:
        raise TerminalError("You must supply an API key or token!")

    if key and token:
        raise TerminalError("You cannot supply both an API key and token")

    abort_on_config_api_key(
        "To log in with the CLI, remove the config key `prefect.cloud.api_key`"
    )

    # Attempt to treat the input like an API key even if it is passed as a token
    # Ignore any tenant id that has been previously set via login
    client = Client(api_key=key or token, tenant_id=None)

    try:
        tenant_id = client._get_auth_tenant()
    except AuthorizationError:
        if key:  # We'll catch an error again later if using a token
            raise TerminalError("Unauthorized. Invalid Prefect Cloud API key.")
    except ClientError:
        raise TerminalError(
            "Error attempting to communicate with Prefect Cloud.")
    else:
        if token:
            click.secho(
                "WARNING: You logged in with an API key using the `--token` flag "
                "which is deprecated. Please use `--key` instead.",
                fg="yellow",
            )
        client.tenant_id = tenant_id
        client.save_auth_to_disk()
        tenant = TenantView.from_tenant_id(tenant_id)
        click.secho(
            f"Logged in to Prefect Cloud tenant {tenant.name!r} ({tenant.slug})",
            fg="green",
        )
        return

        # If there's not a tenant id, we've been given an actual token, fallthrough to
        # the backwards compatibility token auth

    # Backwards compatibility for tokens
    if token:
        check_override_auth_token()
        client = Client(api_token=token)

        # Verify they're not also using an API key
        if client.api_key:
            raise TerminalError(
                "You have already logged in with an API key and cannot use a token."
            )

        click.secho(
            "WARNING: API tokens are deprecated. Please create an API key and use "
            "`prefect auth login --key <KEY>` to login instead.",
            fg="yellow",
        )

        # Verify login obtained a valid api token
        try:
            output = client.graphql(
                query={"query": {
                    "user": {
                        "default_membership": "tenant_id"
                    }
                }})

            # Log into default membership
            success_login = client.login_to_tenant(
                tenant_id=output.data.user[0].default_membership.tenant_id)

            if not success_login:
                raise AuthorizationError

        except AuthorizationError:
            click.secho(
                "Error attempting to use the given API token. "
                "Please check that you are providing a USER scoped Personal Access Token "
                "and consider switching API key.",
                fg="red",
            )
            return
        except ClientError:
            click.secho(
                "Error attempting to communicate with Prefect Cloud. "
                "Please check that you are providing a USER scoped Personal Access Token "
                "and consider switching API key.",
                fg="red",
            )
            return

        # save token
        client.save_api_token()

        click.secho("Login successful!", fg="green")
Пример #8
0
def test_tenant_view_query_for_tenant_unpacks_singleton_result(patch_post):
    patch_post({"data": {"tenant": [1]}})

    assert TenantView._query_for_tenant(where={}) == 1
Пример #9
0
def test_tenant_view_query_for_tenant_errors_on_multiple_tenants(patch_post):
    patch_post({"data": {"tenant": [1, 2]}})

    with pytest.raises(ValueError, match=r"multiple \(2\) tenants"):
        TenantView._query_for_tenant(where={})
Пример #10
0
def test_tenant_view_query_for_tenants_allows_returns_all_tenant_data(
        patch_post):
    patch_post({"data": {"tenant": [1, 2]}})

    assert TenantView._query_for_tenants(where={}) == [1, 2]
Пример #11
0
def test_tenant_view_query_for_tenants_allows_return_when_not_found(
        patch_post):
    patch_post({"data": {"tenant": []}})

    assert TenantView._query_for_tenants(where={}, error_on_empty=False) == []
Пример #12
0
def test_tenant_view_query_for_tenants_raises_when_not_found(patch_post):
    patch_post({"data": {"tenant": []}})

    with pytest.raises(ValueError,
                       match="No results found while querying for tenants"):
        TenantView._query_for_tenants(where={})
Пример #13
0
def test_tenant_view_query_for_tenants_raises_bad_responses(patch_post):
    patch_post({})

    with pytest.raises(ValueError,
                       match="bad result while querying for tenants"):
        TenantView._query_for_tenants(where={})