diff --git a/CBCClientHowTo.md b/CBCClientHowTo.md index 299cee9..6e9a11a 100644 --- a/CBCClientHowTo.md +++ b/CBCClientHowTo.md @@ -12,11 +12,14 @@ endpoint = '******' client_id = '*****' # CBC OAuth Key client_secret = '*****' +# CBC Extension App ID +app_id = '*****' client = CBCClient( endpoint=endpoint, oauth_key=client_id, oauth_secret=client_secret, + app_id=app_id, ) ``` diff --git a/connect_ext_ppr/client/client.py b/connect_ext_ppr/client/client.py index 5562f5e..7a218be 100644 --- a/connect_ext_ppr/client/client.py +++ b/connect_ext_ppr/client/client.py @@ -94,6 +94,7 @@ def execute_request( raise ClientError( message=f'{type(e).__name__} : {str(e)}', status_code=response.status_code, + response=response, cause=e, ) else: diff --git a/connect_ext_ppr/client/exception.py b/connect_ext_ppr/client/exception.py index 4b1c6a9..828cc4c 100644 --- a/connect_ext_ppr/client/exception.py +++ b/connect_ext_ppr/client/exception.py @@ -1,10 +1,15 @@ +from requests import Response + + class ClientError(RuntimeError): def __init__( self, message: str, status_code: int = None, + response: Response = None, cause: Exception = None, ): self.message = message + self.response = response self.status_code = status_code self.cause = cause diff --git a/connect_ext_ppr/client/ns.py b/connect_ext_ppr/client/ns.py index 82e6e16..b28832a 100644 --- a/connect_ext_ppr/client/ns.py +++ b/connect_ext_ppr/client/ns.py @@ -1,3 +1,5 @@ +from functools import cached_property + from connect_ext_ppr.client.mixin import ( ActionMixin, GetMixin, @@ -65,7 +67,15 @@ class Service( NSBase, ActionMixin, ): - def _get_service_path(self): + def __init__(self, client, aps_type: str, path: str): + super().__init__( + client=client, + path=path, + ) + self.aps_type = aps_type + + @cached_property + def service_path(self): aps_type_object = self.client.execute_request( method='GET', path=f'{self.path}/aps/2/resources/?implementing({self.aps_type})', @@ -79,13 +89,6 @@ def _get_service_path(self): service_id = aps_type_object[0]['aps']['id'] return f'{self.path}/aps/2/resources/{service_id}' - def __init__(self, client, aps_type: str, path: str): - super().__init__( - client=client, - path=path, - ) - self.aps_type = aps_type - def __getattr__(self, name): if '_' in name: name = name.replace('_', '-') @@ -101,7 +104,7 @@ def collection(self, name: str): return Collection( self.client, - f'{self._get_service_path()}/{name}', + f'{self.service_path}/{name}', ) def get(self, **kwargs): diff --git a/connect_ext_ppr/service.py b/connect_ext_ppr/service.py index 2c86c52..7b2f467 100644 --- a/connect_ext_ppr/service.py +++ b/connect_ext_ppr/service.py @@ -4,14 +4,11 @@ from connect_ext_ppr.errors import ExtensionValidationError from connect_ext_ppr.db import get_db_ctx_manager -from connect_ext_ppr.models.cbc_extenstion import HubCredential from connect_ext_ppr.models.deployment import Deployment from connect_ext_ppr.models.replicas import Product from connect_ext_ppr.utils import _parse_json_schema_error from connect_ext_ppr.constants import PPR_SCHEMA -from sqlalchemy import text - def insert_product_from_listing(db, listing_data, logger): product_data = listing_data['product'] @@ -93,31 +90,3 @@ def update_product(data, config, logger): product.version = data['version'] db.add(product) db.commit() - - -def get_hub_credentials(hub_id, db): - - query = text( - 'SELECT DISTINCT h.hub_id, g.app_instance_id, h.controller_uri, ' - 'c.oauth_key, c.oauth_secret ' - 'FROM hub_instances h ' - 'INNER JOIN global_app_configuration g ON g.hub_uuid = h.extension_resource_uid ' - 'INNER JOIN configuration c ON c.product_id = g.hub_uuid ' - 'WHERE h.hub_id = :hub_id', - ) - - query = query.columns( - HubCredential.hub_id, - HubCredential.app_id, - HubCredential.controller_url, - HubCredential.oauth_key, - HubCredential.oauth_secret, - ) - - return db.query( - HubCredential, - ).from_statement( - query, - ).params( - hub_id=hub_id, - ).first() diff --git a/connect_ext_ppr/services/__init__.py b/connect_ext_ppr/services/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/connect_ext_ppr/services/cbc_extension.py b/connect_ext_ppr/services/cbc_extension.py new file mode 100644 index 0000000..497e8f2 --- /dev/null +++ b/connect_ext_ppr/services/cbc_extension.py @@ -0,0 +1,37 @@ +from connect_ext_ppr.models.cbc_extenstion import HubCredential + +from sqlalchemy import text + + +HUB_CREDENTIAL_QUERY = ''' +SELECT DISTINCT h.hub_id, + g.app_instance_id, + h.controller_uri, + c.oauth_key, + c.oauth_secret +FROM hub_instances h +INNER JOIN global_app_configuration g ON g.hub_uuid = h.extension_resource_uid +INNER JOIN configuration c ON c.product_id = g.hub_uuid +WHERE h.hub_id = :hub_id +''' + + +def get_hub_credentials(hub_id, db): + + query = text(HUB_CREDENTIAL_QUERY) + + query = query.columns( + HubCredential.hub_id, + HubCredential.app_id, + HubCredential.controller_url, + HubCredential.oauth_key, + HubCredential.oauth_secret, + ) + + return db.query( + HubCredential, + ).from_statement( + query, + ).params( + hub_id=hub_id, + ).first() diff --git a/connect_ext_ppr/services/cbc_hub.py b/connect_ext_ppr/services/cbc_hub.py new file mode 100644 index 0000000..0e48206 --- /dev/null +++ b/connect_ext_ppr/services/cbc_hub.py @@ -0,0 +1,83 @@ +from functools import cached_property + +from connect_ext_ppr.client import CBCClient +from connect_ext_ppr.client.exception import ClientError +from connect_ext_ppr.models.cbc_extenstion import HubCredential + + +class CBCService: + + PLM_TYPE = 'http://com.odin.platform/inhouse-products/application' + SUBSCRIPTION_TYPE = 'http://parallels.com/aps/types/pa/subscription' + + def __init__(self, hub_credential: HubCredential, verify_certificate: bool = False): + self.hub_credential = hub_credential + self.__validate_hub_credentials_object() + + self.client = CBCClient( + endpoint=hub_credential.controller_url, + oauth_key=hub_credential.oauth_key, + oauth_secret=hub_credential.oauth_secret, + app_id=hub_credential.app_id, + verify_certificate=verify_certificate, + ) + self.__validate_client() + + def __validate_hub_credentials_object(self): + if not self.hub_credential: + raise ValueError('`hub_credential` must be not be empty.') + if not isinstance(self.hub_credential, HubCredential): + raise TypeError('`hub_credential` must be object of HubCredential.') + if not self.hub_credential.controller_url: + raise ValueError('`hub_credential.controller_url` must be not be empty.') + if not self.hub_credential.oauth_key: + raise ValueError('`hub_credential.oauth_key` must be not be empty.') + if not self.hub_credential.oauth_secret: + raise ValueError('`hub_credential.oauth_secret` must be not be empty.') + + def __validate_client(self): + try: + self.client.execute_request( + method='GET', + path=f'{self.hub_credential.controller_url}/aps', + ) + except ClientError: + raise ValueError('hub_credential are not valid!') + + @cached_property + def primary_subscription_id(self): + subscriptions = self.subscription_service.get( + subscriptionId=1, + ) + return subscriptions[0]['aps']['id'] + + @cached_property + def plm_service(self): + return self.client(self.PLM_TYPE) + + @cached_property + def subscription_service(self): + return self.client(self.SUBSCRIPTION_TYPE) + + def get_product_details(self, product_id: str): + return self.plm_service.appDetails[product_id].get( + fulfillmentSystem='connect', + ) + + def install_product(self, product_id: str): + self.plm_service.appDetails[product_id].action( + name='import', + payload={ + 'subscriptionId': self.primary_subscription_id, + 'fulfillmentSystem': 'connect', + }, + ) + + def update_product(self, product_id: str): + return self.plm_service.appDetails[product_id].action( + name='upgrade', + payload={ + 'subscriptionId': self.primary_subscription_id, + 'fulfillmentSystem': 'connect', + }, + ) diff --git a/tests/client/test_service.py b/tests/client/test_service.py index be31411..5f50073 100644 --- a/tests/client/test_service.py +++ b/tests/client/test_service.py @@ -91,7 +91,7 @@ def test_service_discovery_collection_with_underscore( @responses.activate -def test_service_discovery_collection_without_underscore( +def test_service_discovery_collection( cbc_endpoint, cbc_client, flat_catalog_type, @@ -104,10 +104,18 @@ def test_service_discovery_collection_without_underscore( json=flat_catalog_type_objects, ) - collection = cbc_client(flat_catalog_type).flatcatalog + service = cbc_client(flat_catalog_type) + + # First time - calls service discovery API + collection = service.flatcatalog assert collection.path == f'{cbc_endpoint}/aps/2/resources/{service_id}/flatcatalog' + # 2nd time - no call to service discovery API + collection = service.subscriptions + + assert collection.path == f'{cbc_endpoint}/aps/2/resources/{service_id}/subscriptions' + @responses.activate def test_service_discovery_collection_wrong_collection_value_type( diff --git a/tests/conftest.py b/tests/conftest.py index d6835f8..8eb75d0 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -26,6 +26,7 @@ from connect_ext_ppr.models.file import File from connect_ext_ppr.models.replicas import Product from connect_ext_ppr.models.ppr import PPRVersion +from connect_ext_ppr.services.cbc_extension import get_hub_credentials from connect_ext_ppr.webapp import ConnectExtensionXvsWebApplication @@ -524,7 +525,7 @@ def cbc_db_session(): " 'HB-000-000'," " '39deb31d-d6ad-48bb-ba0f-82e99a88a7e9'," " 'e4608f13-0582-4780-876f-224add5fa4fd'," - " 'https://www.cbc-instance.com'" + " 'https://example.com/api/v1'" ")", ] for query in queries: @@ -533,3 +534,155 @@ def cbc_db_session(): yield db transaction.rollback() + + +@pytest.fixture +def hub_credentials(cbc_db_session): + return get_hub_credentials( + 'HB-000-000', + cbc_db_session, + ) + + +@pytest.fixture +def aps_controller_details(): + return json.load(open('./tests/fixtures/aps_controller_details.json')) + + +@pytest.fixture +def product_details(): + return { + 'id': 'PRD-000-000-000', + 'name': 'Product F9', + 'vendor': "Adrian's Inc", + 'isImporting': False, + 'isInstalled': False, + 'isUpdateAvailable': False, + 'version': '1', + 'isSyndicated': False, + 'availableCountries': [], + 'category': 'Finance', + 'vendorLinks': [ + { + 'description': 'Admin Manual', + 'linkUrl': 'https://example.com/manual/admin', + }, + ], + 'releaseInformation': [ + { + 'version': '1', + 'releaseNotes': '', + }, + ], + } + + +@pytest.fixture +def get_product_details_not_found_response(): + return { + 'error': 'com.ingrammicro.imcp.library.aps.exception.APSError', + 'packageId': '04f3fca3-9a61-4af5-b722-dd0e8e25b51b', + 'message': '404 Not Found ' + 'ConnectError(error_code=CNCT_001, errors=[Not found.], params=null)', + 'http_request': 'GET https://inhouse-products:8081/rest/application/' + '4b4b65ec-149a-4a8c-9897-dc32f2e9e379/appDetails/' + 'PRD-361-577-149?fulfillmentSystem=connect', + } + + +@pytest.fixture +def import_product_not_found_response(): + return { + 'error': 'com.ingrammicro.imcp.library.aps.exception.APSError', + 'packageId': '04f3fca3-9a61-4af5-b722-dd0e8e25b51b', + 'message': 'java.lang.NullPointerException: Cannot invoke ' + '"com.odin.platform.application.rest.FulfillmentProduct.getFulfillmentSystem()"' + ' because "product" is null', + 'http_request': 'POST https://inhouse-products:8081/rest/application/' + '4b4b65ec-149a-4a8c-9897-dc32f2e9e379/appDetails/PRD-361-577-149/import', + } + + +@pytest.fixture +def update_product_response(): + return { + 'aps': { + 'id': '25ef793d-9a6e-4176-83b2-55d4849bdddb', + 'type': 'http://aps-standard.org/inhouse-products/connectProduct/1.0', + 'status': 'aps:ready', + 'revision': 5, + 'modified': '2023-07-13T09:05:21Z', + }, + 'productId': 'PRD-000-000-000', + 'version': 1, + 'paAccountId': '2fe324f0-68bc-45fa-91d6-d081c76f29d6', + 'subscriptionId': '7c83c18d-1d3d-40e5-973c-26a26c6eac4f', + 'cartValidation': False, + 'tierConfigValidation': False, + 'tierConfigUpdateValidation': False, + 'changeRequestValidation': False, + 'editableOrderingParameters': False, + 'payAsYouGo': False, + 'dynamicPAYG': False, + 'createNotificationId': 'f9650d3f-77da-49de-a240-5575ab4df3ec', + 'status': 'installed', + 'tenant': { + 'aps': { + 'id': '2c638143-bf4f-4520-90c0-981e36a15acb', + }, + }, + } + + +@pytest.fixture +def product_not_installed_response(): + return { + 'error': 'com.ingrammicro.imcp.library.aps.exception.APSError', + 'packageId': '04f3fca3-9a61-4af5-b722-dd0e8e25b51b', + 'message': 'java.lang.NullPointerException: Cannot invoke ' + '"com.odin.platform.application.rest.FulfillmentProduct.getFulfillmentSystem()"' + ' because "product" is null', + 'http_request': 'POST https://inhouse-products:8081/rest/application/' + '4b4b65ec-149a-4a8c-9897-dc32f2e9e379/appDetails/PRD-361-577-149/import', + } + + +@pytest.fixture +def subscriptions(): + return [ + { + 'name': 'License key', + 'trial': False, + 'oneTime': False, + 'disabled': False, + 'description': 'Parallels Automation License Key', + 'subscriptionId': 1, + 'serviceTemplateId': 0, + 'aps': { + 'modified': '2023-07-13T06:57:12Z', + 'id': '7c83c18d-1d3d-40e5-973c-26a26c6eac4f', + 'type': 'http://parallels.com/aps/types/pa/subscription/1.0', + 'status': 'aps:ready', + 'revision': 1, + }, + }, + ] + + +@pytest.fixture +def plm_service(): + return { + 'aps': + { + 'modified': '2023-07-13T07:01:38Z', + 'id': '4b4b65ec-149a-4a8c-9897-dc32f2e9e379', + 'type': 'http://com.odin.platform/inhouse-products/application/1.0', + 'status': 'aps:ready', + 'revision': 3, + }, + } + + +@pytest.fixture +def plm_services(plm_service): + return [plm_service] diff --git a/tests/fixtures/aps_controller_details.json b/tests/fixtures/aps_controller_details.json new file mode 100644 index 0000000..3467684 --- /dev/null +++ b/tests/fixtures/aps_controller_details.json @@ -0,0 +1,210 @@ +{ + "versions": { + "2.0": { + "features": { + "navigation": { + "vars": [ + "filter" + ] + }, + "async": { + "customOperation": true + }, + "rql": [ + "and()", + "or()", + "not()", + "eq()", + "ne()", + "ge()", + "le()", + "lt()", + "gt()", + "like()", + "in()", + "out()", + "true", + "false", + "true()", + "false()", + "empty()", + "null()", + "select()", + "limit()", + "sort()", + "implementing()", + "composing()" + ] + }, + "version": "2.0.0", + "href": "/aps/2.0" + }, + "2.1": { + "features": { + "navigation": { + "vars": [ + "filter", + "collection", + "required" + ] + }, + "async": { + "customOperation": true + }, + "rql": [ + "and()", + "or()", + "not()", + "eq()", + "ne()", + "ge()", + "le()", + "lt()", + "gt()", + "like()", + "in()", + "out()", + "true", + "false", + "true()", + "false()", + "empty()", + "null()", + "select()", + "limit()", + "sort()", + "implementing()", + "composing()" + ] + }, + "version": "2.1.0", + "href": "/aps/2.1" + }, + "2.2": { + "features": { + "navigation": { + "vars": [ + "filter", + "collection", + "required" + ], + "view-plugin": "true" + }, + "async": { + "customOperation": true + }, + "rql": [ + "and()", + "or()", + "not()", + "eq()", + "ne()", + "ge()", + "le()", + "lt()", + "gt()", + "like()", + "in()", + "out()", + "true", + "false", + "true()", + "false()", + "empty()", + "null()", + "select()", + "limit()", + "sort()", + "implementing()", + "composing()" + ] + }, + "version": "2.2.0", + "href": "/aps/2.2" + }, + "2.3": { + "features": { + "navigation": { + "vars": [ + "filter", + "collection", + "required" + ], + "view-plugin": "true" + }, + "async": { + "customOperation": true + }, + "rql": [ + "and()", + "or()", + "not()", + "eq()", + "ne()", + "ge()", + "le()", + "lt()", + "gt()", + "like()", + "in()", + "out()", + "true", + "false", + "true()", + "false()", + "empty()", + "null()", + "select()", + "limit()", + "sort()", + "implementing()", + "composing()" + ] + }, + "version": "2.3.0", + "href": "/aps/2.3" + }, + "21.12": { + "features": { + "navigation": { + "vars": [ + "filter", + "collection", + "required" + ], + "view-plugin": "true" + }, + "async": { + "customOperation": true + }, + "rql": [ + "and()", + "or()", + "not()", + "eq()", + "ne()", + "ge()", + "le()", + "lt()", + "gt()", + "like()", + "in()", + "out()", + "true", + "false", + "true()", + "false()", + "empty()", + "null()", + "select()", + "limit()", + "sort()", + "implementing()", + "composing()" + ] + }, + "version": "21.12.0", + "href": "/aps/21.12" + } + } +} diff --git a/tests/services/__init__.py b/tests/services/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/services/test_cbc_extension.py b/tests/services/test_cbc_extension.py new file mode 100644 index 0000000..2395f27 --- /dev/null +++ b/tests/services/test_cbc_extension.py @@ -0,0 +1,15 @@ +from connect_ext_ppr.services.cbc_extension import get_hub_credentials + + +def test_get_hub_credentials(cbc_db_session, logger): + hub_id = 'HB-000-000' + hub_credentials = get_hub_credentials(hub_id, cbc_db_session) + + assert hub_credentials + + +def test_get_hub_credentials_none(cbc_db_session, logger): + hub_id = 'HB-000-001' + hub_credentials = get_hub_credentials(hub_id, cbc_db_session) + + assert not hub_credentials diff --git a/tests/services/test_cbc_hub.py b/tests/services/test_cbc_hub.py new file mode 100644 index 0000000..9012592 --- /dev/null +++ b/tests/services/test_cbc_hub.py @@ -0,0 +1,284 @@ +from copy import deepcopy +from unittest import TestCase + +import pytest +import responses + +from connect_ext_ppr.client.exception import ClientError +from connect_ext_ppr.services.cbc_hub import CBCService + + +def __mock_common_services( + cbc_endpoint, + aps_controller_details, + plm_services, +): + responses.add( + method='GET', + url=f'{cbc_endpoint}/aps', + json=aps_controller_details, + ) + responses.add( + method='GET', + url=f'{cbc_endpoint}/aps/2/resources/?implementing({CBCService.PLM_TYPE})', + json=plm_services, + ) + + +@responses.activate +def test_get_product_details_positive( + hub_credentials, + cbc_endpoint, + plm_services, + aps_controller_details, + product_details, +): + product_id = 'PRD-000-000-000' + service_id = plm_services[0]['aps']['id'] + + __mock_common_services( + cbc_endpoint, + aps_controller_details, + plm_services, + ) + + responses.add( + method='GET', + url=f'{cbc_endpoint}/aps/2/resources/{service_id}/' + f'appDetails/{product_id}?fulfillmentSystem=connect', + json=product_details, + ) + + cbc_service = CBCService(hub_credentials) + product = cbc_service.get_product_details(product_id) + + TestCase().assertDictEqual(product, product_details) + + +@responses.activate +def test_get_product_details_not_found( + hub_credentials, + cbc_endpoint, + aps_controller_details, + plm_services, + get_product_details_not_found_response, +): + product_id = 'PRD-000-000-000' + service_id = plm_services[0]['aps']['id'] + + __mock_common_services( + cbc_endpoint, + aps_controller_details, + plm_services, + ) + + responses.add( + method='GET', + url=f'{cbc_endpoint}/aps/2/resources/{service_id}/' + f'appDetails/{product_id}?fulfillmentSystem=connect', + status=500, + json=get_product_details_not_found_response, + ) + + cbc_service = CBCService(hub_credentials) + with pytest.raises(ClientError): + cbc_service.get_product_details(product_id) + + +@responses.activate +def test_install_product_positive( + hub_credentials, + cbc_endpoint, + aps_controller_details, + plm_services, + subscriptions, +): + product_id = 'PRD-000-000-000' + service_id = plm_services[0]['aps']['id'] + + __mock_common_services( + cbc_endpoint, + aps_controller_details, + plm_services, + ) + responses.add( + method='GET', + url=f'{cbc_endpoint}/aps/2/resources/?' + f'implementing({CBCService.SUBSCRIPTION_TYPE})&subscriptionId=1', + json=subscriptions, + ) + responses.add( + method='POST', + url=f'{cbc_endpoint}/aps/2/resources/' + f'{service_id}/appDetails/{product_id}/import', + status=202, + ) + + cbc_service = CBCService(hub_credentials) + response = cbc_service.install_product(product_id) + + assert response is None + + +@responses.activate +def test_install_product_not_found( + hub_credentials, + cbc_endpoint, + aps_controller_details, + plm_services, + subscriptions, + import_product_not_found_response, +): + product_id = 'PRD-000-000-000' + service_id = plm_services[0]['aps']['id'] + + __mock_common_services( + cbc_endpoint, + aps_controller_details, + plm_services, + ) + responses.add( + method='GET', + url=f'{cbc_endpoint}/aps/2/resources/?' + f'implementing({CBCService.SUBSCRIPTION_TYPE})&subscriptionId=1', + json=subscriptions, + ) + responses.add( + method='POST', + url=f'{cbc_endpoint}/aps/2/resources/' + f'{service_id}/appDetails/{product_id}/import', + status=500, + json=import_product_not_found_response, + ) + + cbc_service = CBCService(hub_credentials) + with pytest.raises(ClientError): + cbc_service.install_product(product_id) + + +@responses.activate +def test_update_product_positive( + hub_credentials, + cbc_endpoint, + aps_controller_details, + plm_services, + subscriptions, + update_product_response, +): + product_id = 'PRD-000-000-000' + service_id = plm_services[0]['aps']['id'] + + __mock_common_services( + cbc_endpoint, + aps_controller_details, + plm_services, + ) + responses.add( + method='GET', + url=f'{cbc_endpoint}/aps/2/resources/?' + f'implementing({CBCService.SUBSCRIPTION_TYPE})&subscriptionId=1', + json=subscriptions, + ) + responses.add( + method='POST', + url=f'{cbc_endpoint}/aps/2/resources/' + f'{service_id}/appDetails/{product_id}/upgrade', + status=202, + json=update_product_response, + ) + + cbc_service = CBCService(hub_credentials) + response = cbc_service.update_product(product_id) + + TestCase().assertDictEqual(response, update_product_response) + + +@responses.activate +def test_update_product_negative_product_not_installed( + hub_credentials, + cbc_endpoint, + plm_services, + aps_controller_details, + subscriptions, + product_not_installed_response, +): + product_id = 'PRD-000-000-000' + service_id = plm_services[0]['aps']['id'] + + __mock_common_services( + cbc_endpoint, + aps_controller_details, + plm_services, + ) + responses.add( + method='GET', + url=f'{cbc_endpoint}/aps/2/resources/?' + f'implementing({CBCService.SUBSCRIPTION_TYPE})&subscriptionId=1', + json=subscriptions, + ) + responses.add( + method='POST', + url=f'{cbc_endpoint}/aps/2/resources/' + f'{service_id}/appDetails/{product_id}/upgrade', + status=500, + json=product_not_installed_response, + ) + + cbc_service = CBCService(hub_credentials) + with pytest.raises(ClientError): + cbc_service.update_product(product_id) + + +def test_hub_credential_validation_none(): + with pytest.raises(ValueError): + CBCService(None) + + +def test_hub_credential_validation_wrong_type(): + with pytest.raises(TypeError): + CBCService('Wrong_value') + + +def test_hub_credential_validation_empty_controller_url( + hub_credentials, +): + wrong_hub_credentials = deepcopy(hub_credentials) + wrong_hub_credentials.controller_url = None + + with pytest.raises(ValueError): + CBCService(wrong_hub_credentials) + + +def test_hub_credential_validation_empty_oauth_key( + hub_credentials, +): + wrong_hub_credentials = deepcopy(hub_credentials) + wrong_hub_credentials.oauth_key = None + + with pytest.raises(ValueError): + CBCService(wrong_hub_credentials) + + +def test_hub_credential_validation_empty_oauth_secret( + hub_credentials, +): + wrong_hub_credentials = deepcopy(hub_credentials) + wrong_hub_credentials.oauth_secret = None + + with pytest.raises(ValueError): + CBCService(wrong_hub_credentials) + + +@responses.activate +def test_client_validation_invalid( + cbc_endpoint, + hub_credentials, +): + responses.add( + method='GET', + url=f'{cbc_endpoint}/aps', + status=404, + ) + + with pytest.raises(ValueError): + CBCService(hub_credentials) diff --git a/tests/test_service.py b/tests/test_service.py index 0a9e6ac..04d2f6e 100644 --- a/tests/test_service.py +++ b/tests/test_service.py @@ -4,7 +4,6 @@ from connect_ext_ppr.models.deployment import Deployment from connect_ext_ppr.service import ( add_deployments, - get_hub_credentials, validate_ppr_schema, ) @@ -121,17 +120,3 @@ def test_extra_field_not_matching_pattern_allowed(ppr_valid_schema, not_allow): f"'Published', 'VendorTimezone', 'MPN']" ), ] - - -def test_get_hub_credentials(cbc_db_session, logger): - hub_id = 'HB-000-000' - hub_credentials = get_hub_credentials(hub_id, cbc_db_session) - - assert hub_credentials - - -def test_get_hub_credentials_none(cbc_db_session, logger): - hub_id = 'HB-000-001' - hub_credentials = get_hub_credentials(hub_id, cbc_db_session) - - assert not hub_credentials