Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump fastapi[all] from 0.82.0 to 0.89.1 #2246

Merged
merged 22 commits into from
Mar 6, 2023
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
2785c90
Bump fastapi[all] from 0.82.0 to 0.89.1
dependabot[bot] Jan 31, 2023
1180960
fix: FastAPIresponse bug
ThomasLaPiana Feb 2, 2023
9ea8171
Merge branch 'main' into dependabot/pip/fastapi-all--0.89.1
ThomasLaPiana Feb 13, 2023
9595b8a
fix: update return types
ThomasLaPiana Feb 13, 2023
763e318
fix: mypy
ThomasLaPiana Feb 14, 2023
fc012c4
fix: small refactor and test update to get version comparison working…
ThomasLaPiana Feb 14, 2023
bfad1c5
fix: update httpx client usage and refactor version comparison
ThomasLaPiana Feb 14, 2023
788da9a
fix: final ops unit test fix
ThomasLaPiana Feb 14, 2023
610c566
Merge branch 'main' into dependabot/pip/fastapi-all--0.89.1
ThomasLaPiana Mar 2, 2023
2920ec6
feat: replace requests with httpx in the fides client
ThomasLaPiana Mar 2, 2023
75084ed
fix: test_authenticated_request
ThomasLaPiana Mar 2, 2023
39808b2
feat: replace try blocks with "is_success" in the fides client
ThomasLaPiana Mar 2, 2023
414382b
fix: tests that inspected httpx Request content
ThomasLaPiana Mar 2, 2023
2bc3d75
fix: test_retrieve_data
ThomasLaPiana Mar 2, 2023
bd0b8e1
fix: static checks
ThomasLaPiana Mar 2, 2023
7da1112
fix: remove the tuple test now that tuples aren't supported
ThomasLaPiana Mar 2, 2023
b19bf97
use fides connector polling_timeout config to drive http client timeout
adamsachs Mar 2, 2023
92ed420
fix: add a default `connection_read_timeout`
ThomasLaPiana Mar 3, 2023
789132e
dummy commit to trigger external saas tests
adamsachs Mar 3, 2023
5c29021
remove unrecognized --rm flag from docker exec commands
adamsachs Mar 3, 2023
64563d4
fix: add login step to the external ctl tests
ThomasLaPiana Mar 6, 2023
2610956
fix: set the ctl external tests to --wait for application startup bef…
ThomasLaPiana Mar 6, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ colorama>=0.4.3
cryptography==38.0.3
dask==2022.9.2
deepdiff==5.8.1
fastapi[all]==0.82.0
fastapi[all]==0.89.1
fastapi-caching[redis]==0.3.0
fastapi-pagination[sqlalchemy]~= 0.10.0
fideslang==1.3.3
Expand Down
1 change: 1 addition & 0 deletions src/fides/api/ops/api/v1/endpoints/connection_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ def patch_connections(
CONNECTION_BY_KEY,
dependencies=[Security(verify_oauth_client, scopes=[CONNECTION_DELETE])],
status_code=HTTP_204_NO_CONTENT,
response_model=None,
)
def delete_connection(
connection_key: FidesKey, *, db: Session = Depends(deps.get_db)
Expand Down
1 change: 1 addition & 0 deletions src/fides/api/ops/api/v1/endpoints/user_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ def update_user_password(
urls.USER_FORCE_PASSWORD_RESET,
dependencies=[Security(verify_oauth_client, scopes=[USER_PASSWORD_RESET])],
status_code=HTTP_200_OK,
response_model=UserResponse,
)
def force_update_password(
*,
Expand Down
35 changes: 19 additions & 16 deletions src/fides/api/ops/service/connectors/fides/fides_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

from typing import Any, Dict, List, Optional

import requests
import httpx
from httpx import AsyncClient
from loguru import logger
from requests import PreparedRequest, Request, RequestException, Session
from httpx import Request, RequestError, Client, HTTPStatusError

from fides.api.ctl.utils.errors import FidesError
from fides.api.ops.api.v1 import urn_registry as urls
Expand Down Expand Up @@ -41,7 +41,7 @@ def __init__(
username: str,
password: str,
):
self.session = Session()
self.session = Client(timeout=5.0)
adamsachs marked this conversation as resolved.
Show resolved Hide resolved
self.uri = uri
self.username = username
self.password = password
Expand All @@ -55,14 +55,14 @@ def login(self) -> None:
self.username,
)
try:
response = requests.post(
response = httpx.post(
f"{self.uri}{urls.V1_URL_PREFIX}{urls.LOGIN}", json=ul.dict()
)
except RequestException as e:
except RequestError as e:
logger.error("Error logging in on remote Fides {}: {}", self.uri, str(e))
raise e

if response.ok:
if response.is_success:
self.token = response.json()["token_data"]["access_token"]
logger.info(
"Successfully logged in to remote fides {} with username '{}'",
Expand All @@ -81,21 +81,21 @@ def authenticated_request(
query_params: Optional[Dict[str, Any]] = {},
data: Optional[Any] = None,
json: Optional[Any] = None,
) -> PreparedRequest:
) -> Request:

if not self.token:
raise FidesError(
f"Unable to create authenticated request. No token for Fides connector for server {self.uri}"
)

req: PreparedRequest = Request(
req: Request = self.session.build_request(
method=method,
url=f"{self.uri}{path}",
headers=headers,
params=query_params,
data=data,
json=json,
).prepare()
)
req.headers["Authorization"] = f"Bearer {self.token}"
return req

Expand All @@ -117,15 +117,17 @@ def create_privacy_request(
external_id,
self.uri,
)
request: PreparedRequest = self.authenticated_request(
request: Request = self.authenticated_request(
method="POST",
path=urls.V1_URL_PREFIX + urls.PRIVACY_REQUEST_AUTHENTICATED,
json=[pr.dict()],
)
response = self.session.send(request)
if not response.ok:

if not response.is_success:
logger.error("Error creating privacy request on remote Fides {}", self.uri)
response.raise_for_status()

if response.json()["failed"]:
# TODO better handle errored state here?
raise FidesError(
Expand Down Expand Up @@ -199,7 +201,7 @@ async def poll_for_request_completion(
f"Privacy request [{privacy_request_id}] on remote Fides {self.uri} is in an unknown state. Look at the remote Fides for more information."
)

def request_status(self, privacy_request_id: str = None) -> List[Dict[str, Any]]:
def request_status(self, privacy_request_id: str = "") -> List[Dict[str, Any]]:
"""
Return privacy request object that tracks its status
"""
Expand All @@ -215,15 +217,16 @@ def request_status(self, privacy_request_id: str = None) -> List[Dict[str, Any]]
self.uri,
)

request: PreparedRequest = self.authenticated_request(
request: Request = self.authenticated_request(
method="GET",
path=urls.V1_URL_PREFIX + urls.PRIVACY_REQUESTS,
query_params={"request_id": privacy_request_id}
if privacy_request_id
else None,
)
response = self.session.send(request, timeout=5)
if not response.ok:
response = self.session.send(request)

if not response.is_success:
logger.error(
"Error retrieving status of privacy request [{}] on remote Fides {}",
privacy_request_id,
Expand Down Expand Up @@ -266,7 +269,7 @@ def retrieve_request_results(
headers={"Authorization": f"Bearer {self.token}"},
)
response = self.session.send(request)
except requests.exceptions.HTTPError as e:
except HTTPStatusError as e:
logger.error(
"Error retrieving data from child server for privacy request {}: {}",
privacy_request_id,
Expand Down
9 changes: 7 additions & 2 deletions src/fides/cli/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ def check_server_health(server_url: str, verbose: bool = True) -> requests.Respo
return health_response


def compare_application_versions(server_version: str, cli_version: str) -> bool:
"""Normalize and compare application versions."""
normalize_version = lambda v: str(v).replace(".dirty", "", 1)
return normalize_version(server_version) == normalize_version(cli_version)


def check_server(cli_version: str, server_url: str, quiet: bool = False) -> None:
"""Runs a health check and a version check against the server."""

Expand All @@ -82,8 +88,7 @@ def check_server(cli_version: str, server_url: str, quiet: bool = False) -> None
raise SystemExit(1)

server_version = health_response.json()["version"]
normalize_version = lambda v: str(v).replace(".dirty", "", 1)
if normalize_version(server_version) == normalize_version(cli_version):
if compare_application_versions(server_version, cli_version):
if not quiet:
echo_green(
"Server is reachable and the client/server application versions match."
Expand Down
4 changes: 3 additions & 1 deletion src/fides/lib/oauth/schemas/oauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ def __init__(
)

async def __call__(self, request: Request) -> Optional[str]:
authorization: str = request.headers.get("Authorization")
authorization: Optional[str] = request.headers.get("Authorization")
if not authorization:
raise InvalidAuthorizationSchemeError()
scheme, param = get_authorization_scheme_param(authorization)
if not authorization or scheme.lower() != "bearer":
if self.auto_error:
Expand Down
33 changes: 10 additions & 23 deletions tests/ctl/cli/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@

import click
import pytest
from requests_mock import Mocker

import fides.cli.utils as utils
from fides.core.config import FidesConfig, get_config
from fides.core.config import FidesConfig
from tests.ctl.conftest import orig_requests_get


Expand All @@ -24,42 +23,30 @@ def test_check_server_bad_ping(test_client, monkeypatch) -> None:

@pytest.mark.unit
@pytest.mark.parametrize(
"server_version, cli_version, expected_output, quiet",
"server_version, cli_version, expected_result",
[
("1.6.0+7.ge953df5", "1.6.0+7.ge953df5", "application versions match", False),
("1.6.0+7.ge953df5", "1.6.0+9.ge953df5", "Mismatched versions!", False),
("1.6.0+7.ge953df5", "1.6.0+7.ge953df5", True),
("1.6.0+7.ge953df5", "1.6.0+9.ge953df5", False),
(
"1.6.0+7.ge953df5",
"1.6.0+7.ge953df5.dirty",
"application versions match",
False,
True,
),
(
"1.6.0+7.ge953df5.dirty",
"1.6.0+7.ge953df5",
"application versions match",
False,
True,
),
("1.6.0+7.ge953df5", "1.6.0+7.ge953df5.dirty", None, True),
],
)
def test_check_server_version_comparisons(
requests_mock: Mocker,
capsys: pytest.CaptureFixture,
server_version: str,
cli_version: str,
expected_output: str,
quiet: bool,
expected_result: str,
) -> None:
"""Check that comparing versions works"""
fake_url = "http://fake_address:8080"
requests_mock.get(f"{fake_url}/health", json={"version": server_version})
utils.check_server(cli_version, "http://fake_address:8080", quiet=quiet)
captured = capsys.readouterr()
if expected_output is None:
assert captured.out == ""
else:
assert expected_output in captured.out
"""Check that version comparison works."""
actual_result = utils.compare_application_versions(server_version, cli_version)
assert expected_result == actual_result


@pytest.mark.unit
Expand Down
14 changes: 9 additions & 5 deletions tests/ctl/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,22 @@

@pytest.fixture(scope="session")
def monkeysession():
"""monkeypatch fixture at the session level instead of the function level"""
"""
Monkeypatch at the session level instead of the function level.
Automatically undoes the monkeypatching when the session finishes.
"""
mpatch = MonkeyPatch()
yield mpatch
mpatch.undo()


@pytest.fixture(autouse=True, scope="session")
def monkeypatch_requests(test_client, monkeysession) -> None:
"""The requests library makes requests against the running webserver
which talks to the application db. This monkeypatching operation
makes `requests` calls from src/fides/core/api.py in a test
context talk to the test db instead"""
"""
Some places within the application, for example `fides.core.api`, use the `requests`
library to interact with the webserver. This fixture patches those `requests` calls
so that all of those tests instead interact with the test instance.
"""
monkeysession.setattr(requests, "get", test_client.get)
monkeysession.setattr(requests, "post", test_client.post)
monkeysession.setattr(requests, "put", test_client.put)
Expand Down
3 changes: 2 additions & 1 deletion tests/ops/api/v1/endpoints/test_config_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,8 @@ def test_get_application_config(

# then we test that we can GET them
auth_header = generate_auth_header([scopes.CONFIG_READ])
response = api_client.get(
response = api_client.request(
"GET",
url,
headers=auth_header,
params={"api_set": True},
Expand Down
6 changes: 4 additions & 2 deletions tests/ops/api/v1/endpoints/test_consent_request_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,8 @@ class TestGetConsentUnverified:
def test_consent_unverified_no_consent_request_id(self, api_client):
data = {"code": "12345"}

response = api_client.get(
response = api_client.request(
"GET",
f"{V1_URL_PREFIX}{CONSENT_REQUEST_PREFERENCES_WITH_ID.format(consent_request_id='non_existent_consent_id')}",
json=data,
)
Expand All @@ -387,7 +388,8 @@ def test_consent_unverified_no_consent_request_id(self, api_client):
def test_consent_unverified_verification_error(self, api_client):
data = {"code": "12345"}

response = api_client.get(
response = api_client.request(
"GET",
f"{V1_URL_PREFIX}{CONSENT_REQUEST_PREFERENCES_WITH_ID.format(consent_request_id='non_existent_consent_id')}",
json=data,
)
Expand Down
2 changes: 1 addition & 1 deletion tests/ops/api/v1/endpoints/test_oauth_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,7 @@ def test_callback_for_valid_state(
response = api_client.get(
callback_url, params={"code": "abc", "state": "new_request"}
)
assert response.ok
response.raise_for_status()
get_access_token_mock.assert_called_once()

authentication_request.delete(db)
Expand Down
6 changes: 4 additions & 2 deletions tests/ops/api/v1/endpoints/test_privacy_request_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -1534,7 +1534,8 @@ def test_sort_privacy_request_by_due_date(
api_client.post(url, json=data)

auth_header = generate_auth_header(scopes=[PRIVACY_REQUEST_READ])
resp = api_client.get(
resp = api_client.request(
"GET",
f"{url}?sort_direction=asc&sort_field=due_date",
json=data,
headers=auth_header,
Expand All @@ -1544,7 +1545,8 @@ def test_sort_privacy_request_by_due_date(
for i, request in enumerate(asc_response_data):
assert request["days_left"] == days_left_values[i]

resp = api_client.get(
resp = api_client.request(
"GET",
f"{url}?sort_direction=desc&sort_field=due_date",
json=data,
headers=auth_header,
Expand Down
2 changes: 1 addition & 1 deletion tests/ops/api/v1/endpoints/test_saas_config_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -450,5 +450,5 @@ def test_get_authorize_url(
authorization_url_mock.return_value = authorization_url
auth_header = generate_auth_header([CONNECTION_AUTHORIZE])
response = api_client.get(authorize_url, headers=auth_header)
assert response.ok
response.raise_for_status()
assert response.text == f'"{authorization_url}"'
Loading