Пример #1
0
    def test_graphql_uses_access_token_after_login(self, patch_post):
        tenant_id = str(uuid.uuid4())
        post = patch_post(
            {
                "data": {
                    "tenant": [{"id": tenant_id}],
                    "switch_tenant": {
                        "access_token": "ACCESS_TOKEN",
                        "expires_at": "2100-01-01",
                        "refresh_token": "REFRESH_TOKEN",
                    },
                }
            }
        )
        client = Client(api_token="api")
        client.graphql({})
        assert client.get_auth_token() == "api"
        assert post.call_args[1]["headers"] == {
            "Authorization": "Bearer api",
            "X-PREFECT-CORE-VERSION": str(prefect.__version__),
        }

        client.login_to_tenant(tenant_id=tenant_id)
        client.graphql({})
        assert client.get_auth_token() == "ACCESS_TOKEN"
        assert post.call_args[1]["headers"] == {
            "Authorization": "Bearer ACCESS_TOKEN",
            "X-PREFECT-CORE-VERSION": str(prefect.__version__),
        }
Пример #2
0
def test_graphql_errors_get_raised(patch_post):
    patch_post(dict(data="42", errors="GraphQL issue!"))

    with set_temporary_config(
        {"cloud.api": "http://my-cloud.foo", "cloud.auth_token": "secret_token"}
    ):
        client = Client()
    with pytest.raises(ClientError, match="GraphQL issue!"):
        client.graphql("query: {}")
Пример #3
0
 def test_tokens_are_passed_to_graphql(self, monkeypatch):
     post = MagicMock()
     session = MagicMock()
     session.return_value.post = post
     monkeypatch.setattr("requests.Session", session)
     with set_temporary_config({"cloud.graphql": "http://my-cloud.foo"}):
         client = Client()
     client.graphql("query {}", token="secret_token")
     assert post.called
     assert post.call_args[1]["headers"] == {"Authorization": "Bearer secret_token"}
Пример #4
0
def test_graphql_errors_get_raised(monkeypatch):
    post = MagicMock(return_value=MagicMock(json=MagicMock(
        return_value=dict(data="42", errors="GraphQL issue!"))))
    session = MagicMock()
    session.return_value.post = post
    monkeypatch.setattr("requests.Session", session)
    with set_temporary_config({
            "cloud.graphql": "http://my-cloud.foo",
            "cloud.auth_token": "secret_token"
    }):
        client = Client()
    with pytest.raises(ClientError, match="GraphQL issue!"):
        client.graphql("query: {}")
Пример #5
0
 def test_headers_are_passed_to_graphql(self, monkeypatch):
     post = MagicMock()
     session = MagicMock()
     session.return_value.post = post
     monkeypatch.setattr("requests.Session", session)
     with set_temporary_config(
         {"cloud.graphql": "http://my-cloud.foo", "cloud.auth_token": "secret_token"}
     ):
         client = Client()
     client.graphql("query {}", headers={"x": "y", "Authorization": "z"})
     assert post.called
     assert post.call_args[1]["headers"] == {
         "x": "y",
         "Authorization": "Bearer secret_token",
         "X-PREFECT-CORE-VERSION": str(prefect.__version__),
     }
Пример #6
0
    def get(self) -> Optional[Any]:
        """
        Retrieve the secret value.  If not found, returns `None`.

        If using local secrets, `Secret.get()` will attempt to call `json.loads` on the
        value pulled from context.  For this reason it is recommended to store local secrets as
        JSON documents to avoid ambiguous behavior.

        Returns:
            - Any: the value of the secret; if not found, returns `None`

        Raises:
            - ValueError: if `use_local_secrets=False` and the Client fails to retrieve your secret
        """
        if prefect.config.cloud.use_local_secrets is True:
            secrets = prefect.context.get("secrets", {})
            value = secrets.get(self.name)
            try:
                return json.loads(value)
            except (json.JSONDecodeError, TypeError):
                return value
        else:
            client = Client()
            result = client.graphql(
                """
                query($name: String!) {
                    secretValue(name: $name)
                }
                """,
                name=self.name,
            )  # type: Any
            return as_nested_dict(result.data.secretValue, dict)
Пример #7
0
    def get(self) -> Optional[Any]:
        """
        Retrieve the secret value.

        If not found, returns `None`.

        Returns:
            - Any: the value of the secret; if not found, returns `None`

        Raises:
            - ValueError: if `use_local_secrets=False` and the Client fails to retrieve your secret
        """
        if prefect.config.cloud.use_local_secrets is True:
            secrets = prefect.context.get("secrets", {})
            return secrets.get(self.name)
        else:
            client = Client()
            result = client.graphql(
                """
                query($name: String!) {
                    secretValue(name: $name)
                }
                """,
                name=self.name,
            )  # type: Any
            return as_nested_dict(result.data.secretValue, dict)
Пример #8
0
def test_client_posts_graphql_to_api_server(patch_post):
    post = patch_post(dict(data=dict(success=True)))

    with set_temporary_config(
        {"cloud.graphql": "http://my-cloud.foo", "cloud.auth_token": "secret_token"}
    ):
        client = Client()
    result = client.graphql("{projects{name}}")
    assert result.data == {"success": True}
    assert post.called
    assert post.call_args[0][0] == "http://my-cloud.foo"
Пример #9
0
def test_graphql_errors_get_raised(monkeypatch):
    post = MagicMock(return_value=MagicMock(json=MagicMock(
        return_value=dict(data="42", errors="GraphQL issue!"))))
    monkeypatch.setattr("requests.post", post)
    with set_temporary_config({
            "cloud.graphql": "http://my-cloud.foo",
            "cloud.auth_token": "secret_token"
    }):
        client = Client()
    with pytest.raises(ClientError) as exc:
        res = client.graphql("query: {}")
    assert "GraphQL issue!" in str(exc.value)
Пример #10
0
def test_client_posts_graphql_to_graphql_server(monkeypatch):
    post = MagicMock(return_value=MagicMock(json=MagicMock(return_value=dict(
        data=dict(success=True)))))
    monkeypatch.setattr("requests.post", post)
    with set_temporary_config({
            "cloud.graphql": "http://my-cloud.foo",
            "cloud.auth_token": "secret_token"
    }):
        client = Client()
    result = client.graphql("{projects{name}}")
    assert result.data == {"success": True}
    assert post.called
    assert post.call_args[0][0] == "http://my-cloud.foo"
Пример #11
0
    def get(self) -> Optional[Any]:
        """
        Retrieve the secret value.  If not found, returns `None`.

        If using local secrets, `Secret.get()` will attempt to call `json.loads` on the
        value pulled from context.  For this reason it is recommended to store local secrets as
        JSON documents to avoid ambiguous behavior.

        Returns:
            - Any: the value of the secret; if not found, raises an error

        Raises:
            - ValueError: if `.get()` is called within a Flow building context, or if `use_local_secrets=True`
                and your Secret doesn't exist
            - ClientError: if `use_local_secrets=False` and the Client fails to retrieve your secret
        """
        if isinstance(prefect.context.get("flow"), prefect.core.flow.Flow):
            raise ValueError(
                "Secrets should only be retrieved during a Flow run, not while building a Flow."
            )

        if prefect.context.config.cloud.use_local_secrets is True:
            secrets = prefect.context.get("secrets", {})
            try:
                value = secrets[self.name]
            except KeyError:
                raise ValueError('Local Secret "{}" was not found.'.format(
                    self.name)) from None
            try:
                return json.loads(value)
            except (json.JSONDecodeError, TypeError):
                return value
        else:
            client = Client()
            result = client.graphql(
                """
                query($name: String!) {
                    secretValue(name: $name)
                }
                """,
                variables=dict(name=self.name),
            )
            # the result object is a Box, so we recursively restore builtin
            # dict/list classes
            result_dict = result.to_dict()
            value = result_dict["data"]["secretValue"]
            try:
                return json.loads(value)
            except (json.JSONDecodeError, TypeError):
                return value
Пример #12
0
    def test_graphql_uses_access_token_after_login(self, patch_post):
        tenant_id = str(uuid.uuid4())
        post = patch_post(
            {
                "data": {
                    "tenant": [{"id": tenant_id}],
                    "switchTenant": {
                        "accessToken": "ACCESS_TOKEN",
                        "expiresIn": 600,
                        "refreshToken": "REFRESH_TOKEN",
                    },
                }
            }
        )
        client = Client(api_token="api")
        client.graphql({})
        assert client.get_auth_token() == "api"
        assert post.call_args[1]["headers"] == dict(Authorization="Bearer api")

        client.login_to_tenant(tenant_id=tenant_id)
        client.graphql({})
        assert client.get_auth_token() == "ACCESS_TOKEN"
        assert post.call_args[1]["headers"] == dict(Authorization="Bearer ACCESS_TOKEN")
Пример #13
0
def test_client_graphql_retries_if_token_needs_refreshing(monkeypatch):
    error = requests.HTTPError()
    error.response = MagicMock(status_code=401)  # unauthorized
    post = MagicMock(return_value=MagicMock(
        raise_for_status=MagicMock(side_effect=error),
        json=MagicMock(return_value=dict(token="new-token")),
    ))
    monkeypatch.setattr("requests.post", post)
    with set_temporary_config({
            "cloud.graphql": "http://my-cloud.foo",
            "cloud.auth_token": "secret_token"
    }):
        client = Client()
    with pytest.raises(requests.HTTPError) as exc:
        result = client.graphql("{}")
    assert exc.value is error
    assert post.call_count == 3  # first call -> refresh token -> last call
    assert post.call_args[0][0] == "http://my-cloud.foo"
    assert client.token == "new-token"