From d81eae960de4bec4f922dfb2496021bf3404d363 Mon Sep 17 00:00:00 2001 From: Martin Kudlej Date: Fri, 5 Apr 2024 14:32:40 +0200 Subject: [PATCH] fix flake and pylint errors --- Pipfile | 1 + tests/integration/asserts.py | 18 +- tests/integration/conftest.py | 421 ++-- .../integration/test_integration_accounts.py | 39 +- .../test_integration_activedocs.py | 24 +- .../test_integration_application.py | 27 +- .../test_integration_application_plan.py | 22 +- .../test_integration_backend_mapping_rules.py | 53 +- .../test_integration_backend_metrics.py | 75 +- .../test_integration_backend_usages.py | 9 +- .../integration/test_integration_backends.py | 13 +- .../test_integration_custom_tenant.py | 15 +- tests/integration/test_integration_limit.py | 28 +- .../test_integration_mapping_rules.py | 47 +- tests/integration/test_integration_methods.py | 3 + tests/integration/test_integration_metrics.py | 17 +- .../integration/test_integration_openapis.py | 14 +- .../integration/test_integration_policies.py | 44 +- .../test_integration_policy_registry.py | 26 +- .../test_integration_pricing_rules.py | 22 +- .../integration/test_integration_promotes.py | 14 +- .../integration/test_integration_services.py | 89 +- tests/test_3scale_api_client.py | 20 +- threescale_api_crd/__init__.py | 2 +- threescale_api_crd/client.py | 43 +- threescale_api_crd/constants.py | 777 +++--- threescale_api_crd/defaults.py | 353 ++- threescale_api_crd/resources.py | 2212 ++++++++++------- 28 files changed, 2630 insertions(+), 1798 deletions(-) diff --git a/Pipfile b/Pipfile index 7ece735..e479585 100644 --- a/Pipfile +++ b/Pipfile @@ -2,6 +2,7 @@ flake8 = "*" mypy = "*" pylint = "*" +black = "*" pytest = "<8.0.0" python-dotenv = "*" backoff = "*" diff --git a/tests/integration/asserts.py b/tests/integration/asserts.py index ee74d1c..1304daa 100644 --- a/tests/integration/asserts.py +++ b/tests/integration/asserts.py @@ -11,18 +11,24 @@ def assert_resource(resource: threescale_api.defaults.DefaultResource): assert resource.entity is not None -def assert_errors_contains(resource: threescale_api.defaults.DefaultClient, fields: List[str]): - errors = resource['errors'] +def assert_errors_contains( + resource: threescale_api.defaults.DefaultClient, fields: List[str] +): + errors = resource["errors"] assert errors is not None for field in fields: assert field in errors -def assert_resource_params(obj: threescale_api.defaults.DefaultResource, params: dict, allowed=None): - for (key, val) in params.items(): +def assert_resource_params( + obj: threescale_api.defaults.DefaultResource, params: dict, allowed=None +): + for key, val in params.items(): if allowed is not None and key in allowed: - assert obj[key] == val, f"Resource value for key \"{key}\" should be correct." - assert obj.entity[key] == val, "Entity value for key \"{key}\" should be correct." + assert obj[key] == val, f'Resource value for key "{key}" should be correct.' + assert ( + obj.entity[key] == val + ), 'Entity value for key "{key}" should be correct.' def assert_http_ok(response: requests.Response): diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index fd743fa..8e96626 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -4,21 +4,36 @@ import pytest from dotenv import load_dotenv + # from threescale_api import errors import threescale_api import threescale_api_crd from threescale_api.resources import Application -from threescale_api_crd.resources import (Service, Metric, BackendUsage, BackendMappingRule, - Backend, ActiveDoc, PolicyRegistry, MappingRule, - Limit, ApplicationPlan, Proxy, PricingRule) +from threescale_api_crd.resources import ( + Service, + Metric, + BackendUsage, + BackendMappingRule, + Backend, + ActiveDoc, + PolicyRegistry, + MappingRule, + Limit, + ApplicationPlan, + Proxy, + PricingRule, +) + load_dotenv() def cleanup(resource): resource.delete() assert not resource.exists() + + # pass @@ -26,169 +41,197 @@ def get_suffix() -> str: return secrets.token_urlsafe(8) -@pytest.fixture(scope='session') +@pytest.fixture(scope="session") def url() -> str: - return os.getenv('THREESCALE_PROVIDER_URL') + return os.getenv("THREESCALE_PROVIDER_URL") -@pytest.fixture(scope='session') +@pytest.fixture(scope="session") def token() -> str: - return os.getenv('THREESCALE_PROVIDER_TOKEN') + return os.getenv("THREESCALE_PROVIDER_TOKEN") -@pytest.fixture(scope='session') +@pytest.fixture(scope="session") def master_url() -> str: - return os.getenv('THREESCALE_MASTER_URL') + return os.getenv("THREESCALE_MASTER_URL") -@pytest.fixture(scope='session') +@pytest.fixture(scope="session") def master_token() -> str: - return os.getenv('THREESCALE_MASTER_TOKEN') + return os.getenv("THREESCALE_MASTER_TOKEN") @pytest.fixture(scope="session") def ssl_verify() -> bool: - ssl_verify = os.getenv('THREESCALE_SSL_VERIFY', 'false') + ssl_verify = os.getenv("THREESCALE_SSL_VERIFY", "false") ssl_verify = bool(strtobool(ssl_verify)) if not ssl_verify: import urllib3 + urllib3.disable_warnings() return ssl_verify -@pytest.fixture(scope='session') +@pytest.fixture(scope="session") def api_backend() -> str: - return os.getenv('TEST_API_BACKEND', 'http://www.httpbin.org:80') + return os.getenv("TEST_API_BACKEND", "http://www.httpbin.org:80") -@pytest.fixture(scope='session') +@pytest.fixture(scope="session") def ocp_provider_ref() -> str: - return os.getenv('OCP_PROVIDER_ACCOUNT_REF') + return os.getenv("OCP_PROVIDER_ACCOUNT_REF") -@pytest.fixture(scope='session') -def api(url: str, token: str, - ssl_verify: bool, ocp_provider_ref: str) -> threescale_api_crd.ThreeScaleClientCRD: - return threescale_api_crd.ThreeScaleClientCRD(url=url, token=token, - ssl_verify=ssl_verify, - ocp_provider_ref=ocp_provider_ref) +@pytest.fixture(scope="session") +def api( + url: str, token: str, ssl_verify: bool, ocp_provider_ref: str +) -> threescale_api_crd.ThreeScaleClientCRD: + return threescale_api_crd.ThreeScaleClientCRD( + url=url, token=token, ssl_verify=ssl_verify, ocp_provider_ref=ocp_provider_ref + ) -@pytest.fixture(scope='session') -def api_origin(url: str, token: str, - ssl_verify: bool, ocp_provider_ref: str) -> threescale_api.ThreeScaleClient: - return threescale_api.ThreeScaleClient(url=url, token=token, - ssl_verify=ssl_verify) +@pytest.fixture(scope="session") +def api_origin( + url: str, token: str, ssl_verify: bool, ocp_provider_ref: str +) -> threescale_api.ThreeScaleClient: + return threescale_api.ThreeScaleClient(url=url, token=token, ssl_verify=ssl_verify) -@pytest.fixture(scope='session') -def master_api(master_url: str, master_token: str, - ssl_verify: bool, ocp_provider_ref: str) -> threescale_api_crd.ThreeScaleClientCRD: - return threescale_api_crd.ThreeScaleClientCRD(url=master_url, token=master_token, - ssl_verify=ssl_verify, ocp_provider_ref=ocp_provider_ref) +@pytest.fixture(scope="session") +def master_api( + master_url: str, master_token: str, ssl_verify: bool, ocp_provider_ref: str +) -> threescale_api_crd.ThreeScaleClientCRD: + return threescale_api_crd.ThreeScaleClientCRD( + url=master_url, + token=master_token, + ssl_verify=ssl_verify, + ocp_provider_ref=ocp_provider_ref, + ) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def apicast_http_client(application, proxy, ssl_verify): proxy.deploy() return application.api_client(verify=ssl_verify) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def service_params(): suffix = get_suffix() return dict(name=f"test-{suffix}") -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def service(service_params, api) -> Service: service = api.services.create(params=service_params) yield service cleanup(service) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def account_params(): suffix = get_suffix() name = f"testacc{suffix}" - return dict(name=name, username=name, org_name=name, monthly_billing_enabled=False, - monthly_charging_enabled=False, email=f"{name}@name.none") + return dict( + name=name, + username=name, + org_name=name, + monthly_billing_enabled=False, + monthly_charging_enabled=False, + email=f"{name}@name.none", + ) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def account(api, account_params): acc = api.accounts.create(params=account_params) - account_params.update(account_name=acc['name']) + account_params.update(account_name=acc["name"]) yield acc cleanup(acc) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def acc_user(account): return account.users.list()[-1] -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def acc_user2_params(account, acc_user): - name = acc_user['username'] + '2' - return dict(username=name, email=f"{name}@name.none", role='member', account_name=account['name']) + name = acc_user["username"] + "2" + return dict( + username=name, + email=f"{name}@name.none", + role="member", + account_name=account["name"], + ) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def acc_user2(account, acc_user, acc_user2_params): return account.users.create(acc_user2_params) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def application_plan_params(service) -> dict: suffix = get_suffix() - return dict(name=f"test-{suffix}", setup_fee="1.00", state_event="publish", cost_per_month="3.00") + return dict( + name=f"test-{suffix}", + setup_fee="1.00", + state_event="publish", + cost_per_month="3.00", + ) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def application_plan(api, service, application_plan_params) -> ApplicationPlan: resource = service.app_plans.create(params=application_plan_params) yield resource cleanup(resource) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def application_params(application_plan, service, account): suffix = get_suffix() name = f"test-{suffix}" - return dict(name=name, description=name, plan_id=application_plan['id'], - service_id=service['id'], account_id=account['id']) + return dict( + name=name, + description=name, + plan_id=application_plan["id"], + service_id=service["id"], + account_id=account["id"], + ) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def application(service, application_plan, application_params, account) -> Application: resource = account.applications.create(params=application_params) yield resource cleanup(resource) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def proxy(service) -> Proxy: return service.proxy.list() -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def backend_usage_params(service, backend): return { - 'service_id': service['id'], - 'backend_id': backend['id'], - 'path': '/', + "service_id": service["id"], + "backend_id": backend["id"], + "path": "/", } -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def backend_updated_usage_params(backend_usage_params): ret = backend_usage_params.copy() - ret['path'] = '/post' + ret["path"] = "/post" return ret -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def backend_usage(service, backend, backend_usage_params) -> BackendUsage: service = service.read() resource = service.backend_usages.create(params=backend_usage_params) @@ -196,126 +239,123 @@ def backend_usage(service, backend, backend_usage_params) -> BackendUsage: cleanup(resource) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def metric_params(service): suffix = get_suffix() - friendly_name = f'test-metric-{suffix}' - name = f'{friendly_name}'.replace('-', '_') - return dict(friendly_name=friendly_name, system_name=name, unit='count') + friendly_name = f"test-metric-{suffix}" + name = f"{friendly_name}".replace("-", "_") + return dict(friendly_name=friendly_name, system_name=name, unit="count") -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def backend_metric_params(): suffix = get_suffix() - friendly_name = f'test-metric-{suffix}' - name = f'{friendly_name}'.replace('-', '') - return dict(friendly_name=friendly_name, - system_name=name, unit='count') + friendly_name = f"test-metric-{suffix}" + name = f"{friendly_name}".replace("-", "") + return dict(friendly_name=friendly_name, system_name=name, unit="count") -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def updated_metric_params(metric_params): suffix = get_suffix() - friendly_name = f'test-updated-metric-{suffix}' - metric_params['friendly_name'] = f'/get/{friendly_name}' + friendly_name = f"test-updated-metric-{suffix}" + metric_params["friendly_name"] = f"/get/{friendly_name}" return metric_params -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def backend_updated_metric_params(backend_metric_params): updated = backend_metric_params.copy() suffix = get_suffix() - friendly_name = f'test-updated-metric-{suffix}' - updated['friendly_name'] = f'/get/{friendly_name}' + friendly_name = f"test-updated-metric-{suffix}" + updated["friendly_name"] = f"/get/{friendly_name}" return updated -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def metric(service, metric_params) -> Metric: resource = service.metrics.create(params=metric_params) yield resource cleanup(resource) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def method_params(): suffix = get_suffix() - friendly_name = f'test-method-{suffix}' - system_name = f'{friendly_name}'.replace('-', '_') + friendly_name = f"test-method-{suffix}" + system_name = f"{friendly_name}".replace("-", "_") return dict(friendly_name=friendly_name, system_name=system_name) # 'friendly_name' is id in CRD for methods -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def updated_method_params(method_params): suffix = get_suffix() - description = f'test-updated-method-{suffix}' - method_params['description'] = description + description = f"test-updated-method-{suffix}" + method_params["description"] = description return method_params -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def method(hits_metric, method_params): resource = hits_metric.methods.create(params=method_params) yield resource cleanup(resource) - #service.proxy.deploy() + # service.proxy.deploy() -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def hits_metric(service): - return service.metrics.read_by(system_name='hits') + return service.metrics.read_by(system_name="hits") def get_mapping_rule_pattern(): suffix = get_suffix() - pattern = f'test-{suffix}'.replace('_', '-') + pattern = f"test-{suffix}".replace("_", "-") return pattern -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def mapping_rule_params(service): """ Fixture for getting paramteres for mapping rule for product/service. """ - hits_metric = service.metrics.read_by_name('hits') - return dict(http_method='GET', pattern='/get', metric_id=hits_metric['id'], - delta=1) + hits_metric = service.metrics.read_by_name("hits") + return dict(http_method="GET", pattern="/get", metric_id=hits_metric["id"], delta=1) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def backend_mapping_rule_params(backend, backend_metric): """ Fixture for getting paramteres for mapping rule for backend. """ - back = backend_metric['id'] - return dict(http_method='GET', pattern='/anything/get/ida', metric_id=back, - delta=1) + back = backend_metric["id"] + return dict(http_method="GET", pattern="/anything/get/ida", metric_id=back, delta=1) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def updated_mapping_rules_params(mapping_rule_params): """ Fixture for updating mapping rule for product/service. """ pattern = get_mapping_rule_pattern() params = mapping_rule_params.copy() - params['pattern'] = f'/anything/get/{pattern}' + params["pattern"] = f"/anything/get/{pattern}" return params -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def updated_backend_mapping_rules_params(backend_mapping_rule_params): """ Fixture for updating mapping rule for backend. """ pattern = get_mapping_rule_pattern() params = backend_mapping_rule_params.copy() - params['pattern'] = f'/anything/get/{pattern}' + params["pattern"] = f"/anything/get/{pattern}" return params -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def mapping_rule(service, mapping_rule_params, proxy) -> MappingRule: """ Fixture for getting mapping rule for product/service. @@ -326,8 +366,10 @@ def mapping_rule(service, mapping_rule_params, proxy) -> MappingRule: proxy.deploy() -@pytest.fixture(scope='module') -def backend_mapping_rule(backend, backend_metric, backend_mapping_rule_params, service, proxy, backend_usage) -> BackendMappingRule: +@pytest.fixture(scope="module") +def backend_mapping_rule( + backend, backend_metric, backend_mapping_rule_params, service, proxy, backend_usage +) -> BackendMappingRule: """ Fixture for getting mapping rule for backend. """ @@ -338,7 +380,7 @@ def backend_mapping_rule(backend, backend_metric, backend_mapping_rule_params, s proxy.deploy() -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def create_mapping_rule(service): """ Fixture for creating mapping rule for product/service. @@ -346,10 +388,13 @@ def create_mapping_rule(service): rules = [] def _create(metric, http_method, path): - params = dict(service_id=service['id'], - http_method=http_method, - pattern=f'/anything{path}', - delta=1, metric_id=metric['id']) + params = dict( + service_id=service["id"], + http_method=http_method, + pattern=f"/anything{path}", + delta=1, + metric_id=metric["id"], + ) rule = service.mapping_rules.create(params=params) rules.append(rule) return rule @@ -362,7 +407,7 @@ def _create(metric, http_method, path): # cleanup(rule) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def create_backend_mapping_rule(backend): """ Fixture for creating mapping rule for backend. @@ -370,10 +415,13 @@ def create_backend_mapping_rule(backend): rules = [] def _create(backend_metric, http_method, path): - params = dict(backend_id=backend['id'], - http_method=http_method, - pattern=f'/anything{path}', - delta=1, metric_id=backend_metric['id']) + params = dict( + backend_id=backend["id"], + http_method=http_method, + pattern=f"/anything{path}", + delta=1, + metric_id=backend_metric["id"], + ) rule = backend.mapping_rules.create(params=params) rules.append(rule) return rule @@ -385,18 +433,18 @@ def _create(backend_metric, http_method, path): cleanup(rule) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def backend_params(api_backend): """ Fixture for getting backend parameters. """ suffix = get_suffix() - return dict(name=f"test-backend-{suffix}", - private_endpoint=api_backend, - description='111') + return dict( + name=f"test-backend-{suffix}", private_endpoint=api_backend, description="111" + ) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def backend(backend_params, api) -> Backend: """ Fixture for getting backend. @@ -406,7 +454,7 @@ def backend(backend_params, api) -> Backend: cleanup(backend) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def backend_metric(backend, backend_metric_params) -> Metric: """ Fixture for getting backend metric. @@ -431,20 +479,22 @@ def tenant_params(): """ Params for custom tenant """ - return dict(username=f"tenant{get_suffix()}", - admin_password="123456", - email=f"e{get_suffix()}@invalid.invalid", - org_name="org") + return dict( + username=f"tenant{get_suffix()}", + admin_password="123456", + email=f"e{get_suffix()}@invalid.invalid", + org_name="org", + ) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def active_docs_body(): return """{"openapi":"3.0.0","info":{"version":"1.0.0","title":"example"},"paths":{ "/pets":{"get":{"summary":"List all pets","operationId":"listPets","responses": {"200":{"description":"A paged array of pets"}}}}},"components":{}}""" -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def active_docs_params(active_docs_body): suffix = get_suffix() name = f"test-{suffix}" @@ -452,36 +502,37 @@ def active_docs_params(active_docs_body): return dict(name=name, body=active_docs_body, description=des) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def active_doc(api, service, active_docs_params) -> ActiveDoc: """ Fixture for getting active doc. """ acs = active_docs_params.copy() - acs['service_id'] = service['id'] + acs["service_id"] = service["id"] resource = api.active_docs.create(params=acs) yield resource cleanup(resource) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def openapi_params(active_docs_body): suffix = get_suffix() name = f"test-{suffix}" params = dict( name=name, - productionPublicBaseURL='http://productionPublicBaseURL', - stagingPublicBaseURL='http://stagingPublicBaseURL', - productSystemName='PrOdUcTsYsTeMnAmE', - privateBaseURL='http://privateBaseURL', + productionPublicBaseURL="http://productionPublicBaseURL", + stagingPublicBaseURL="http://stagingPublicBaseURL", + productSystemName="PrOdUcTsYsTeMnAmE", + privateBaseURL="http://privateBaseURL", prefixMatching=True, - privateAPIHostHeader='privateAPIHostHeader', - privateAPISecretToken='privateAPISecretToken', - body=active_docs_body) + privateAPIHostHeader="privateAPIHostHeader", + privateAPISecretToken="privateAPISecretToken", + body=active_docs_body, + ) return params -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def openapi(api, openapi_params): """ Fixture for getting OpenApi. @@ -491,32 +542,52 @@ def openapi(api, openapi_params): cleanup(resource) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def webhook(api): return api.webhooks -@pytest.fixture(scope='session') +@pytest.fixture(scope="session") def policy_registry_schema(): - return {"summary": "This is just an example.", "description": ["This policy is just an example\ - how to write your custom policy.\nAnd this is next line", "And next item."], - "name": "APIcast Example Policy", "$schema": - "http://apicast.io/policy-v1/schema#manifest#", "version": "0.1", "configuration": { - "properties": {"property1": {"description": "list of properties1", "items": { - "properties": {"value1": {"description": "Value1", "type": "string"}, "value2": { - "description": "Value2", "type": "string"}}, "required": ["value1"], "type": "object" - }, "type": "array"}}, "type": "object"}} + return { + "summary": "This is just an example.", + "description": [ + "This policy is just an example\ + how to write your custom policy.\nAnd this is next line", + "And next item.", + ], + "name": "APIcast Example Policy", + "$schema": "http://apicast.io/policy-v1/schema#manifest#", + "version": "0.1", + "configuration": { + "properties": { + "property1": { + "description": "list of properties1", + "items": { + "properties": { + "value1": {"description": "Value1", "type": "string"}, + "value2": {"description": "Value2", "type": "string"}, + }, + "required": ["value1"], + "type": "object", + }, + "type": "array", + } + }, + "type": "object", + }, + } -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def policy_registry_params(policy_registry_schema): - """ Params for policy registry. """ + """Params for policy registry.""" suffix = get_suffix() name = f"test-{suffix}" - return dict(name=name, version='0.1', schema=policy_registry_schema) + return dict(name=name, version="0.1", schema=policy_registry_schema) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def policy_registry(api, policy_registry_params) -> PolicyRegistry: """ Fixture for getting policy registry. @@ -527,13 +598,13 @@ def policy_registry(api, policy_registry_params) -> PolicyRegistry: cleanup(resource) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def limit_params(metric): - """ Params for limit. """ + """Params for limit.""" return dict(metric_id=metric["id"], period="minute", value=10) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def limit(service, application, application_plan, metric, limit_params) -> Limit: """ Fixture for getting limit. @@ -543,14 +614,21 @@ def limit(service, application, application_plan, metric, limit_params) -> Limit resource.delete() -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def backend_limit_params(backend_metric): - """ Params for limit. """ + """Params for limit.""" return dict(metric_id=backend_metric["id"], period="minute", value=10) -@pytest.fixture(scope='module') -def backend_limit(service, application, application_plan, backend_metric, backend_limit_params, backend_usage) -> Limit: +@pytest.fixture(scope="module") +def backend_limit( + service, + application, + application_plan, + backend_metric, + backend_limit_params, + backend_usage, +) -> Limit: """ Fixture for getting limit for backend metric. """ @@ -559,13 +637,13 @@ def backend_limit(service, application, application_plan, backend_metric, backen resource.delete() -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def prule_params(metric): - """ Params for prule. """ + """Params for prule.""" return dict(metric_id=metric["id"], min=10, max=100, cost_per_unit="10") -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def prule(service, application, application_plan, metric, prule_params) -> PricingRule: """ Fixture for getting prule. @@ -575,31 +653,40 @@ def prule(service, application, application_plan, metric, prule_params) -> Prici resource.delete() -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def backend_prule_params(backend_metric): - """ Params for prule. """ + """Params for prule.""" return dict(metric_id=backend_metric["id"], min=10, max=100, cost_per_unit=10) -@pytest.fixture(scope='module') -def backend_prule(service, application, application_plan, backend_metric, backend_prule_params, backend_usage) -> PricingRule: +@pytest.fixture(scope="module") +def backend_prule( + service, + application, + application_plan, + backend_metric, + backend_prule_params, + backend_usage, +) -> PricingRule: """ Fixture for getting prule for backend metric. """ - resource = application_plan.pricing_rules(backend_metric).create(backend_prule_params) + resource = application_plan.pricing_rules(backend_metric).create( + backend_prule_params + ) yield resource resource.delete() -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def promote_params(api, service): """ Promote params for service. """ - return dict(productCRName=service.crd.as_dict()['metadata']['name']) + return dict(productCRName=service.crd.as_dict()["metadata"]["name"]) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def promote(api, service, backend, backend_usage, promote_params): """ Promote object for service. diff --git a/tests/integration/test_integration_accounts.py b/tests/integration/test_integration_accounts.py index 869a181..8727834 100644 --- a/tests/integration/test_integration_accounts.py +++ b/tests/integration/test_integration_accounts.py @@ -2,10 +2,12 @@ # tests important for CRD - CRU + list + def test_accounts_list(api, account, acc_user): accounts = api.accounts.list() assert len(accounts) >= 1 + def test_account_can_be_created(api, account, account_params, acc_user): asserts.assert_resource(account) asserts.assert_resource_params(account, account_params) @@ -18,29 +20,43 @@ def test_account_can_be_read(api, account, account_params, acc_user): def test_account_can_be_read_by_name(api, account, account_params, acc_user): - account_name = account['org_name'] + account_name = account["org_name"] read = api.accounts[account_name] asserts.assert_resource(read) asserts.assert_resource_params(read, account_params) + def test_account_can_be_updated(api, account, acc_user): - account['monthly_charging_enabled'] = True + account["monthly_charging_enabled"] = True acc_updated = account.update() - assert account['monthly_charging_enabled'] == True == acc_updated['monthly_charging_enabled'] + assert ( + account["monthly_charging_enabled"] + == True + == acc_updated["monthly_charging_enabled"] + ) updated = account.read() - assert updated['monthly_charging_enabled'] == True == account['monthly_charging_enabled'] + assert ( + updated["monthly_charging_enabled"] + == True + == account["monthly_charging_enabled"] + ) + # end of tests important for CRD - CRU + list # tests important for CRD - CRU + list + def test_users_list(api, account, acc_user): users = account.users.list() assert len(users) >= 1 users = api.account_users.list() assert len(users) >= 1 -def test_user_can_be_created(api, account, account_params, acc_user, acc_user2, acc_user2_params): + +def test_user_can_be_created( + api, account, account_params, acc_user, acc_user2, acc_user2_params +): asserts.assert_resource(acc_user) asserts.assert_resource_params(acc_user, account_params) @@ -59,23 +75,24 @@ def test_user_can_be_read(api, account, account_params, acc_user): def test_user_can_be_read_by_name(api, account, account_params, acc_user): - user_name = acc_user['username'] + user_name = acc_user["username"] read = account.users[user_name] asserts.assert_resource(read) asserts.assert_resource_params(read, account_params) - + read = api.account_users[user_name] asserts.assert_resource(read) asserts.assert_resource_params(read, account_params) + def test_user_can_be_updated(api, account, acc_user2): - acc_user2['role'] = 'admin' + acc_user2["role"] = "admin" user2_updated = acc_user2.update() - assert acc_user2['role'] == 'admin' == user2_updated['role'] + assert acc_user2["role"] == "admin" == user2_updated["role"] updated = acc_user2.read() - assert updated['role'] == 'admin' == acc_user2['role'] + assert updated["role"] == "admin" == acc_user2["role"] + # end of tests important for CRD - CRU + list # TODO - implement and create unit tests for user states and permissions - diff --git a/tests/integration/test_integration_activedocs.py b/tests/integration/test_integration_activedocs.py index 28b2d06..9a0570c 100644 --- a/tests/integration/test_integration_activedocs.py +++ b/tests/integration/test_integration_activedocs.py @@ -5,14 +5,17 @@ # tests important for CRD - CRU + list + def test_activedocs_list(api, active_doc): active_docs = api.active_docs.list() assert len(active_docs) >= 1 + def test_activedoc_can_be_created(api, active_docs_params, active_doc): assert_resource(active_doc) assert_resource_params(active_doc, active_docs_params) + def test_activedoc_can_be_read(api, active_docs_params, active_doc): read = api.active_docs.read(int(active_doc.entity_id)) asserts.assert_resource(read) @@ -20,32 +23,35 @@ def test_activedoc_can_be_read(api, active_docs_params, active_doc): def test_activedoc_can_be_read_by_name(api, active_docs_params, active_doc): - account_name = active_doc['system_name'] + account_name = active_doc["system_name"] read = api.active_docs[account_name] asserts.assert_resource(read) asserts.assert_resource_params(read, active_docs_params) + def test_activedoc_can_be_updated(api, active_doc): - des_changed = (active_doc['description'] or '') + '_changed' - active_doc['description'] = des_changed + des_changed = (active_doc["description"] or "") + "_changed" + active_doc["description"] = des_changed gg = active_doc.update() - assert active_doc['description'] == des_changed + assert active_doc["description"] == des_changed updated = active_doc.read() - assert updated['description'] == des_changed - assert active_doc['description'] == des_changed + assert updated["description"] == des_changed + assert active_doc["description"] == des_changed + # end of tests important for CRD - CRU + list # tests to compare data in CRD and in 3scale + def test_data(api, api_origin, active_doc): for acd in api.active_docs.list(): - acd_origin = api_origin.active_docs.read(int(acd['id'])) + acd_origin = api_origin.active_docs.read(int(acd["id"])) for att in acd.entity: # exclude CRD specific keys - if att not in ['activeDocOpenAPIRef']: + if att not in ["activeDocOpenAPIRef"]: # body should be processed because 3scale processes json - if att == 'body': + if att == "body": body = json.loads(acd.entity[att]) body_origin = json.loads(acd_origin.entity[att]) assert body == body_origin diff --git a/tests/integration/test_integration_application.py b/tests/integration/test_integration_application.py index fce76c2..9495c25 100644 --- a/tests/integration/test_integration_application.py +++ b/tests/integration/test_integration_application.py @@ -27,30 +27,35 @@ def test_application_can_be_read(api, application_params, application): def test_application_can_be_read_by_name(api, application_params, application): - app_name = application['name'] + app_name = application["name"] read = api.applications[app_name] asserts.assert_resource(read) asserts.assert_resource_params(read, application_params) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def application_plan_params2(): suffix = secrets.token_urlsafe(8) - return dict(name=f"test-{suffix}", setup_fee="1.00", state_event='publish', cost_per_month="3.00") + return dict( + name=f"test-{suffix}", + setup_fee="1.00", + state_event="publish", + cost_per_month="3.00", + ) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def application_plan2(service, application_plan_params2): resource = service.app_plans.create(params=application_plan_params2) yield resource resource.delete() -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def update_application_params(application_plan2): suffix = secrets.token_urlsafe(8) name = f"updated-{suffix}" - return dict(name=name, description=name, plan_id=application_plan2['id']) + return dict(name=name, description=name, plan_id=application_plan2["id"]) def test_application_update(update_application_params, application): @@ -58,12 +63,14 @@ def test_application_update(update_application_params, application): asserts.assert_resource(updated_application) asserts.assert_resource_params(updated_application, update_application_params) + # tests important for CRD - CRU + list # changing application state tests + def test_application_set_state(application): - application = application.set_state('suspend') - assert application['state'] == 'suspended' - application = application.set_state('resume') - assert application['state'] == 'live' + application = application.set_state("suspend") + assert application["state"] == "suspended" + application = application.set_state("resume") + assert application["state"] == "live" diff --git a/tests/integration/test_integration_application_plan.py b/tests/integration/test_integration_application_plan.py index 8df477b..88e15a5 100644 --- a/tests/integration/test_integration_application_plan.py +++ b/tests/integration/test_integration_application_plan.py @@ -3,32 +3,41 @@ from tests.integration import asserts + # tests important for CRD - CRU + list def test_application_plans_list(service): app_plans = service.app_plans.list() assert len(app_plans) == 1 -def test_application_plan_can_be_created(service, application_plan_params, application_plan): + +def test_application_plan_can_be_created( + service, application_plan_params, application_plan +): asserts.assert_resource(application_plan) asserts.assert_resource_params(application_plan, application_plan_params) + # IDs cannot be used in nested objects -#def test_application_plan_can_be_read(service, application_plan_params, application_plan): +# def test_application_plan_can_be_read(service, application_plan_params, application_plan): # read = service.app_plans.read(int(application_plan.entity_id)) # asserts.assert_resource(read) # asserts.assert_resource_params(read, application_plan) -def test_application_plan_can_be_read_by_name(service, application_plan_params, application_plan): - name = application_plan['system_name'] +def test_application_plan_can_be_read_by_name( + service, application_plan_params, application_plan +): + name = application_plan["system_name"] read = service.app_plans[name] asserts.assert_resource(read) asserts.assert_resource_params(read, application_plan) -@pytest.fixture(scope='module') + +@pytest.fixture(scope="module") def update_params(): suffix = secrets.token_urlsafe(8) - return dict(cost_per_month='12.00', setup_fee='50.00', state_event='publish') + return dict(cost_per_month="12.00", setup_fee="50.00", state_event="publish") + def test_application_plan_can_be_updated(service, application_plan, update_params): lcount = len(service.app_plans.list()) @@ -37,4 +46,5 @@ def test_application_plan_can_be_updated(service, application_plan, update_param asserts.assert_resource_params(updated_app_plan, update_params) assert len(service.app_plans.list()) == lcount + # end of tests important for CRD - CRU + list diff --git a/tests/integration/test_integration_backend_mapping_rules.py b/tests/integration/test_integration_backend_mapping_rules.py index ce99562..a5a5408 100644 --- a/tests/integration/test_integration_backend_mapping_rules.py +++ b/tests/integration/test_integration_backend_mapping_rules.py @@ -5,64 +5,89 @@ # tests important for CRD - CRU + list + def test_should_list_mapping_rules(backend, backend_mapping_rule): resource = backend.mapping_rules.list() assert resource + def test_should_create_mapping_rule(backend_mapping_rule, backend_mapping_rule_params): asserts.assert_resource(backend_mapping_rule) asserts.assert_resource_params(backend_mapping_rule, backend_mapping_rule_params) + def test_should_read_mapping_rule(backend_mapping_rule, backend_mapping_rule_params): resource = backend_mapping_rule.read() asserts.assert_resource(resource) asserts.assert_resource_params(resource, backend_mapping_rule_params) -def test_should_update_mapping_rule(service, backend, backend_usage, backend_mapping_rule, - updated_backend_mapping_rules_params, application, apicast_http_client): + +def test_should_update_mapping_rule( + service, + backend, + backend_usage, + backend_mapping_rule, + updated_backend_mapping_rules_params, + application, + apicast_http_client, +): resource = backend.mapping_rules.create(updated_backend_mapping_rules_params) lcount = backend.mapping_rules.list() delta = 11 - resource['delta'] = delta + resource["delta"] = delta resource.update() updated_resource = resource.read() - assert updated_resource['delta'] == delta + assert updated_resource["delta"] == delta assert len(lcount) == len(backend.mapping_rules.list()) service.proxy.deploy() - response = apicast_http_client.get(path=resource['pattern']) + response = apicast_http_client.get(path=resource["pattern"]) asserts.assert_http_ok(response) resource.delete() service.proxy.deploy() + # end of tests important for CRD - CRU + list -def test_should_mapping_rule_endpoint_return_ok(service, backend, - backend_usage, backend_mapping_rule, application, apicast_http_client): +def test_should_mapping_rule_endpoint_return_ok( + service, + backend, + backend_usage, + backend_mapping_rule, + application, + apicast_http_client, +): response = apicast_http_client.get(path=f"{backend_mapping_rule['pattern']}") asserts.assert_http_ok(response) -def test_stop_processing_mapping_rules_once_first_one_is_met(service, - backend, backend_usage, updated_backend_mapping_rules_params, application, - apicast_http_client): +def test_stop_processing_mapping_rules_once_first_one_is_met( + service, + backend, + backend_usage, + updated_backend_mapping_rules_params, + application, + apicast_http_client, +): params_first = updated_backend_mapping_rules_params.copy() - params_first['pattern'] = '/anything/search' + params_first["pattern"] = "/anything/search" resource_first = backend.mapping_rules.create(params=params_first) assert resource_first.exists() params_second = updated_backend_mapping_rules_params.copy() - params_second['pattern'] = '/anything/{id}' + params_second["pattern"] = "/anything/{id}" resource_second = backend.mapping_rules.create(params=params_second) assert resource_second.exists() service.proxy.deploy() - response = apicast_http_client.get(path=f"{params_first['pattern']}/{service['id']}") + response = apicast_http_client.get( + path=f"{params_first['pattern']}/{service['id']}" + ) asserts.assert_http_ok(response) - assert params_first['pattern'] in response.url + assert params_first["pattern"] in response.url resource_first.delete() resource_second.delete() diff --git a/tests/integration/test_integration_backend_metrics.py b/tests/integration/test_integration_backend_metrics.py index 16b1759..458cf60 100644 --- a/tests/integration/test_integration_backend_metrics.py +++ b/tests/integration/test_integration_backend_metrics.py @@ -7,57 +7,76 @@ # tests important for CRD - CRU + list + def test_should_list_metrics(backend, backend_metric): resources = backend.metrics.list() assert len(resources) > 0 + def test_should_create_metric(backend_metric, backend_metric_params): asserts.assert_resource(backend_metric) asserts.assert_resource_params(backend_metric, backend_metric_params) + def test_should_read_metric(backend_metric, backend_metric_params): resource = backend_metric.read() asserts.assert_resource(resource) asserts.assert_resource_params(resource, backend_metric_params) -def test_should_update_metric(backend, backend_metric, backend_metric_params, backend_updated_metric_params): + +def test_should_update_metric( + backend, backend_metric, backend_metric_params, backend_updated_metric_params +): lcount = len(backend.metrics.list()) resource = backend_metric.update(params=backend_updated_metric_params) asserts.assert_resource(resource) asserts.assert_resource_params(resource, backend_updated_metric_params) assert lcount == len(backend.metrics.list()) + # end of tests important for CRD - CRU + list -#def test_should_fields_be_required(backend): +# def test_should_fields_be_required(backend): # resource = backend.metrics.create(params={}, throws=False) # asserts.assert_errors_contains(resource, ['friendly_name', 'unit']) -#def test_should_system_name_be_invalid(backend, backend_metric_params): +# def test_should_system_name_be_invalid(backend, backend_metric_params): # backend_metric_params['system_name'] = 'invalid name whitespaces' # resource = backend.metrics.create(params=backend_metric_params, throws=False) # asserts.assert_errors_contains(resource, ['system_name']) -#def test_should_raise_exception(backend): +# def test_should_raise_exception(backend): # with pytest.raises(ApiClientError): # backend.metrics.create(params={}) + def test_should_apicast_return_403_when_metric_is_disabled( - service, backend, backend_usage, backend_metric_params, application_plan, - application, apicast_http_client): + service, + backend, + backend_usage, + backend_metric_params, + application_plan, + application, + apicast_http_client, +): """Metric is disabled when its limit is set to 0.""" bmetric_params = backend_metric_params.copy() - bmetric_params['friendly_name'] += '403' + bmetric_params["friendly_name"] += "403" back_metric = backend.metrics.create(params=bmetric_params) - - mapping_params = dict(http_method='GET', pattern='/anything/post/id', metric_id=back_metric['id'], delta=1) + + mapping_params = dict( + http_method="GET", + pattern="/anything/post/id", + metric_id=back_metric["id"], + delta=1, + ) back_mapping = backend.mapping_rules.create(params=mapping_params) - + limits = application_plan.limits(back_metric) - back_lim = limits.create(params=dict(period='month', value=0)) + back_lim = limits.create(params=dict(period="month", value=0)) proxy = service.proxy.list() proxy.deploy() @@ -70,28 +89,36 @@ def test_should_apicast_return_403_when_metric_is_disabled( back_metric.delete() -@backoff.on_predicate(backoff.expo, lambda resp: resp.status_code == 200, - max_tries=8) +@backoff.on_predicate(backoff.expo, lambda resp: resp.status_code == 200, max_tries=8) def make_request(client, path): return client.get(path=path) def get_user_key_from_application(app, proxy): - user_key = app['user_key'] - user_key_param = proxy['auth_user_key'] + user_key = app["user_key"] + user_key_param = proxy["auth_user_key"] return {user_key_param: user_key} def test_should_apicast_return_429_when_limits_exceeded( - service, backend, backend_usage, application_plan, application, apicast_http_client): - metric_params = dict(name='limits_exceeded', unit='count', - friendly_name='Limits Exceeded') + service, backend, backend_usage, application_plan, application, apicast_http_client +): + metric_params = dict( + name="limits_exceeded", unit="count", friendly_name="Limits Exceeded" + ) back_metric = backend.metrics.create(params=metric_params) - - mapping_params = dict(http_method='GET', pattern='/anything/limits/exceeded', metric_id=back_metric['id'], delta=1) + + mapping_params = dict( + http_method="GET", + pattern="/anything/limits/exceeded", + metric_id=back_metric["id"], + delta=1, + ) back_mapping = backend.mapping_rules.create(params=mapping_params) - - back_lim = application_plan.limits(back_metric).create(params=dict(period='day', value=1)) + + back_lim = application_plan.limits(back_metric).create( + params=dict(period="day", value=1) + ) proxy = service.proxy.list() proxy.deploy() @@ -107,14 +134,14 @@ def test_should_apicast_return_429_when_limits_exceeded( back_metric.delete() -#def test_should_remove_limits_and_pricings_on_metric_deletion( +# def test_should_remove_limits_and_pricings_on_metric_deletion( # service, backend, backend_usage, application_plan, # application): # # metric_params = dict(name='for_deletion', unit='hit', # friendly_name='For deletion') # back_metric = backend.metrics.create(params=metric_params) -# +# # limit = application_plan.limits(back_metric).create(params=dict(period='day', value=1)) # prule = application_plan.pricing_rules(metric=back_metric).create(params={'from': 2, 'to': 99, 'cost_per_unit': 15}) # diff --git a/tests/integration/test_integration_backend_usages.py b/tests/integration/test_integration_backend_usages.py index 36d9a90..59dd5b3 100644 --- a/tests/integration/test_integration_backend_usages.py +++ b/tests/integration/test_integration_backend_usages.py @@ -7,24 +7,31 @@ # tests important for CRD - CRU + list + def test_should_list_backend_usages(backend, service, backend_usage): assert len(service.backend_usages.list()) > 0 assert len(backend.usages()) > 0 + def test_should_create_backend_usage(backend_usage, backend_usage_params): asserts.assert_resource(backend_usage) asserts.assert_resource_params(backend_usage, backend_usage_params) + def test_should_read_backend_usage(backend_usage, backend_usage_params): resource = backend_usage.read() asserts.assert_resource(resource) asserts.assert_resource_params(resource, backend_usage_params) -def test_should_update_backend_usage(service, backend_usage, backend_updated_usage_params): + +def test_should_update_backend_usage( + service, backend_usage, backend_updated_usage_params +): lcount = len(service.backend_usages.list()) resource = backend_usage.update(params=backend_updated_usage_params) asserts.assert_resource(resource) asserts.assert_resource_params(resource, backend_updated_usage_params) assert lcount == len(service.backend_usages.list()) + # end of tests important for CRD - CRU + list diff --git a/tests/integration/test_integration_backends.py b/tests/integration/test_integration_backends.py index 15a3349..1c81b02 100644 --- a/tests/integration/test_integration_backends.py +++ b/tests/integration/test_integration_backends.py @@ -27,20 +27,21 @@ def test_backend_can_be_read(api, backend_params, backend): def test_backend_can_be_read_by_name(api, backend_params, backend): - backend_name = backend['system_name'] + backend_name = backend["system_name"] read = api.backends[backend_name] asserts.assert_resource(read) asserts.assert_resource_params(read, backend_params) def test_backend_can_be_updated(api, backend): - assert backend['description'] == '111' - backend['description'] = '222' + assert backend["description"] == "111" + backend["description"] = "222" backend.update() - assert backend['description'] == '222' + assert backend["description"] == "222" updated = backend.read() - assert updated['description'] == '222' - assert backend['description'] == '222' + assert updated["description"] == "222" + assert backend["description"] == "222" + # end of tests important for CRD - CRU + list diff --git a/tests/integration/test_integration_custom_tenant.py b/tests/integration/test_integration_custom_tenant.py index 1155694..6332b5a 100644 --- a/tests/integration/test_integration_custom_tenant.py +++ b/tests/integration/test_integration_custom_tenant.py @@ -7,6 +7,7 @@ def test_3scale_master_url_is_set(master_api, master_url, master_token): assert master_token assert master_api.url + # tests important for CRD - CRU + list @@ -17,7 +18,7 @@ def test_tenants_list(api, custom_tenant): def test_tenant_can_be_created(custom_tenant, tenant_params): asserts.assert_resource(custom_tenant) - assert custom_tenant.entity["signup"]['account']['admin_base_url'] + assert custom_tenant.entity["signup"]["account"]["admin_base_url"] assert custom_tenant.entity["signup"]["access_token"]["value"] @@ -26,6 +27,7 @@ def test_tenant_can_be_read(api, tenant_params, custom_tenant): asserts.assert_resource(read) asserts.assert_resource_params(read, tenant_params) + # this test does not make sense in 3scale api client too # def test_tenant_can_be_read_by_name(api, tenant_params, custom_tenant): # tenant_name = custom_tenant['name'] @@ -35,12 +37,13 @@ def test_tenant_can_be_read(api, tenant_params, custom_tenant): def test_tenant_can_be_updated(api, custom_tenant): - des_changed = (custom_tenant["signup"]['account']['email'] or '') + '_changed' - custom_tenant["signup"]['account']['email'] = des_changed + des_changed = (custom_tenant["signup"]["account"]["email"] or "") + "_changed" + custom_tenant["signup"]["account"]["email"] = des_changed custom_tenant.update() - assert custom_tenant["signup"]['account']['email'] == des_changed + assert custom_tenant["signup"]["account"]["email"] == des_changed updated = custom_tenant.threescale_client.tenants.read(custom_tenant.entity_id) - assert updated["signup"]['account']['email'] == des_changed - assert custom_tenant["signup"]['account']['email'] == des_changed + assert updated["signup"]["account"]["email"] == des_changed + assert custom_tenant["signup"]["account"]["email"] == des_changed + # end of tests important for CRD - CRU + list diff --git a/tests/integration/test_integration_limit.py b/tests/integration/test_integration_limit.py index 8d6f721..2c83b8f 100644 --- a/tests/integration/test_integration_limit.py +++ b/tests/integration/test_integration_limit.py @@ -6,14 +6,17 @@ # With service metric # tests important for CRD - CRU + list + @pytest.fixture() def limit_client(application_plan, metric, limit) -> Limits: return application_plan.limits(metric) + def test_limit_list(limit_client): limits = limit_client.list() assert len(limits) >= 1 + def test_limit_can_be_created(limit_params, limit, limit_client): asserts.assert_resource(limit) asserts.assert_resource_params(limit, limit_params) @@ -27,33 +30,41 @@ def test_limit_can_be_read(limit_client, limit, limit_params): def test_limit_can_be_updated(limit_client, limit): lcount = limit_client.list() - limit['value'] = 11 + limit["value"] = 11 lim_updated = limit.update() - assert limit['value'] == 11 == lim_updated['value'] + assert limit["value"] == 11 == lim_updated["value"] updated = limit.read() - assert updated['value'] == 11 == limit['value'] + assert updated["value"] == 11 == limit["value"] assert lcount == limit_client.list() + # end of tests important for CRD - CRU + list # With backend metric # tests important for CRD - CRU + list + @pytest.fixture() def backend_limit_client(application_plan, backend_metric, backend_limit) -> Limits: return application_plan.limits(backend_metric) + def test_backend_limit_list(backend_limit_client): limits = backend_limit_client.list() assert len(limits) >= 1 -def test_backend_limit_can_be_created(backend_limit_params, backend_limit, backend_limit_client): + +def test_backend_limit_can_be_created( + backend_limit_params, backend_limit, backend_limit_client +): asserts.assert_resource(backend_limit) asserts.assert_resource_params(backend_limit, backend_limit_params) -def test_backend_limit_can_be_read(backend_limit_client, backend_limit, backend_limit_params): +def test_backend_limit_can_be_read( + backend_limit_client, backend_limit, backend_limit_params +): read = backend_limit_client.read(backend_limit.entity_id) asserts.assert_resource(read) asserts.assert_resource_params(read, backend_limit_params) @@ -61,11 +72,12 @@ def test_backend_limit_can_be_read(backend_limit_client, backend_limit, backend_ def test_backend_limit_can_be_updated(backend_limit_client, backend_limit): lcount = backend_limit_client.list() - backend_limit['value'] = 11 + backend_limit["value"] = 11 lim_updated = backend_limit.update() - assert backend_limit['value'] == 11 == lim_updated['value'] + assert backend_limit["value"] == 11 == lim_updated["value"] updated = backend_limit.read() - assert updated['value'] == 11 == backend_limit['value'] + assert updated["value"] == 11 == backend_limit["value"] assert lcount == backend_limit_client.list() + # end of tests important for CRD - CRU + list diff --git a/tests/integration/test_integration_mapping_rules.py b/tests/integration/test_integration_mapping_rules.py index 2e474b7..2a7f6ce 100644 --- a/tests/integration/test_integration_mapping_rules.py +++ b/tests/integration/test_integration_mapping_rules.py @@ -6,53 +6,76 @@ # tests important for CRD - CRU + list + def test_should_list_mapping_rules(proxy, mapping_rule): resource = proxy.mapping_rules.list() # there is not default mapping rule in CRD assert len(resource) > 0 + def test_should_create_mapping_rule(mapping_rule, mapping_rule_params): asserts.assert_resource(mapping_rule) asserts.assert_resource_params(mapping_rule, mapping_rule_params) + def test_should_read_mapping_rule(mapping_rule, mapping_rule_params): resource = mapping_rule.read() asserts.assert_resource(resource) asserts.assert_resource_params(resource, mapping_rule_params) -def test_should_update_mapping_rule(service, backend, mapping_rule, updated_mapping_rules_params, backend_usage, application, apicast_http_client): + +def test_should_update_mapping_rule( + service, + backend, + mapping_rule, + updated_mapping_rules_params, + backend_usage, + application, + apicast_http_client, +): resource = service.mapping_rules.create(params=updated_mapping_rules_params) lcount = service.mapping_rules.list() delta = 11 - resource['delta'] = delta + resource["delta"] = delta resource.update() updated_resource = resource.read() - assert updated_resource['delta'] == delta + assert updated_resource["delta"] == delta assert len(lcount) == len(service.mapping_rules.list()) service.proxy.deploy() - response = apicast_http_client.get(path=resource['pattern']) + response = apicast_http_client.get(path=resource["pattern"]) asserts.assert_http_ok(response) + # end of tests important for CRD - CRU + list -def test_should_mapping_rule_endpoint_return_ok(mapping_rule, backend_usage, apicast_http_client ,application, application_plan): - response = apicast_http_client.get(path=mapping_rule['pattern']) + +def test_should_mapping_rule_endpoint_return_ok( + mapping_rule, backend_usage, apicast_http_client, application, application_plan +): + response = apicast_http_client.get(path=mapping_rule["pattern"]) asserts.assert_http_ok(response) -def test_stop_processing_mapping_rules_once_first_one_is_met(proxy, updated_mapping_rules_params, backend_usage, - apicast_http_client, application, application_plan): + +def test_stop_processing_mapping_rules_once_first_one_is_met( + proxy, + updated_mapping_rules_params, + backend_usage, + apicast_http_client, + application, + application_plan, +): params_first = updated_mapping_rules_params.copy() - params_first['pattern'] = '/anything/search' + params_first["pattern"] = "/anything/search" resource_first = proxy.mapping_rules.create(params=params_first) assert resource_first.exists() params_second = updated_mapping_rules_params.copy() - params_second['pattern'] = '/anything/{id}' + params_second["pattern"] = "/anything/{id}" resource_second = proxy.mapping_rules.create(params=params_second) assert resource_second.exists() proxy.deploy() - response = apicast_http_client.get(path=params_first['pattern']) + response = apicast_http_client.get(path=params_first["pattern"]) asserts.assert_http_ok(response) - assert params_first['pattern'] in response.url + assert params_first["pattern"] in response.url diff --git a/tests/integration/test_integration_methods.py b/tests/integration/test_integration_methods.py index a6436b3..d2993e1 100644 --- a/tests/integration/test_integration_methods.py +++ b/tests/integration/test_integration_methods.py @@ -10,10 +10,12 @@ def test_should_list_methods(hits_metric, method): resources = hits_metric.methods.list() assert len(resources) > 0 + def test_should_create_method(method, method_params): asserts.assert_resource(method) asserts.assert_resource_params(method, method_params) + # this is not possible in CRD, all methods are bound on 'hits' # def test_should_not_create_method_for_custom_metric(metric, method_params): # resource = metric.methods.create(params=method_params, throws=False) @@ -33,4 +35,5 @@ def test_should_update_method(hits_metric, method, updated_method_params): asserts.assert_resource_params(resource, updated_method_params) assert lcount == hits_metric.methods.list() + # end of tests important for CRD - CRU + list diff --git a/tests/integration/test_integration_metrics.py b/tests/integration/test_integration_metrics.py index 2d7c089..a74b8b1 100644 --- a/tests/integration/test_integration_metrics.py +++ b/tests/integration/test_integration_metrics.py @@ -8,19 +8,23 @@ # tests important for CRD - CRU + list + def test_should_list_metrics(service, metric): resources = service.metrics.list() assert len(resources) > 0 + def test_should_create_metric(metric, metric_params): asserts.assert_resource(metric) asserts.assert_resource_params(metric, metric_params) + def test_should_read_metric(metric, metric_params): resource = metric.read() asserts.assert_resource(resource) asserts.assert_resource_params(resource, metric_params) + def test_should_update_metric(service, metric, updated_metric_params): lcount = service.metrics.list() resource = metric.update(params=updated_metric_params) @@ -28,10 +32,11 @@ def test_should_update_metric(service, metric, updated_metric_params): asserts.assert_resource_params(resource, updated_metric_params) assert lcount == service.metrics.list() + # end of tests important for CRD - CRU + list # TODO -#def test_should_apicast_return_403_when_metric_is_disabled( +# def test_should_apicast_return_403_when_metric_is_disabled( # service, metric_params, create_mapping_rule, # account, ssl_verify, backend_usage): # """Metric is disabled when its limit is set to 0.""" @@ -58,19 +63,19 @@ def test_should_update_metric(service, metric, updated_metric_params): # assert response.status_code == 403 # # -#@backoff.on_predicate(backoff.expo, lambda resp: resp.status_code == 200, +# @backoff.on_predicate(backoff.expo, lambda resp: resp.status_code == 200, # max_tries=8) -#def make_request(client, path): +# def make_request(client, path): # return client.get(path=path) # # -#def get_user_key_from_application(app, proxy): +# def get_user_key_from_application(app, proxy): # user_key = app['user_key'] # user_key_param = proxy['auth_user_key'] # return {user_key_param: user_key} # # -#def update_proxy_endpoint(service, backend_usage): +# def update_proxy_endpoint(service, backend_usage): # """Update service proxy.""" # path = backend_usage['path'] # backend_usage['path'] = '/moloko' @@ -84,7 +89,7 @@ def test_should_update_metric(service, metric, updated_metric_params): # proxy.promote(version=version) # # -#def test_should_apicast_return_429_when_limits_exceeded( +# def test_should_apicast_return_429_when_limits_exceeded( # service, application_plan, create_mapping_rule, # apicast_http_client, backend_usage): # metric_params = dict(name='limits_exceeded', unit='count', diff --git a/tests/integration/test_integration_openapis.py b/tests/integration/test_integration_openapis.py index a04042f..560cc95 100644 --- a/tests/integration/test_integration_openapis.py +++ b/tests/integration/test_integration_openapis.py @@ -5,14 +5,17 @@ # tests important for CRD - CRU + list + def test_openapis_list(api, openapi): openapis = api.openapis.list() assert len(openapis) >= 1 + def test_openapi_can_be_created(api, openapi_params, openapi): assert_resource(openapi) assert_resource_params(openapi, openapi_params) + def test_openapi_can_be_read(api, openapi_params, openapi): read = api.openapis.read(openapi.entity_id) asserts.assert_resource(read) @@ -20,12 +23,13 @@ def test_openapi_can_be_read(api, openapi_params, openapi): def test_openapi_can_be_updated(api, openapi): - des_changed = (openapi['productSystemName'] or '') + '_changed' - openapi['productSystemName'] = des_changed + des_changed = (openapi["productSystemName"] or "") + "_changed" + openapi["productSystemName"] = des_changed openapi.update() - assert openapi['productSystemName'] == des_changed + assert openapi["productSystemName"] == des_changed updated = openapi.read() - assert updated['productSystemName'] == des_changed - assert openapi['productSystemName'] == des_changed + assert updated["productSystemName"] == des_changed + assert openapi["productSystemName"] == des_changed + # end of tests important for CRD - CRU + list diff --git a/tests/integration/test_integration_policies.py b/tests/integration/test_integration_policies.py index d554879..11643c2 100644 --- a/tests/integration/test_integration_policies.py +++ b/tests/integration/test_integration_policies.py @@ -1,24 +1,26 @@ def test_policies_append(proxy): policies = proxy.policies.list() policy_1 = { - "name": "logging", - "configuration": {}, - "version": "builtin", - "enabled": True - } + "name": "logging", + "configuration": {}, + "version": "builtin", + "enabled": True, + } proxy.policies.append(policy_1) policies["policies_config"].append(policy_1) updated_policies = proxy.policies.list() - for pol1, pol2 in zip(policies["policies_config"], updated_policies["policies_config"]): - if hasattr(pol1, 'entity'): + for pol1, pol2 in zip( + policies["policies_config"], updated_policies["policies_config"] + ): + if hasattr(pol1, "entity"): pol1 = pol1.entity - for attr in ['service_id', 'id']: + for attr in ["service_id", "id"]: if attr in pol1: pol1.pop(attr) - if hasattr(pol2, 'entity'): + if hasattr(pol2, "entity"): pol2 = pol2.entity - for attr in ['service_id', 'id']: + for attr in ["service_id", "id"]: if attr in pol2: pol2.pop(attr) @@ -28,24 +30,26 @@ def test_policies_append(proxy): def test_policies_insert(proxy): policies = proxy.policies.list() policy_2 = { - "name": "echo", - "configuration": {}, - "version": "builtin", - "enabled": True - } + "name": "echo", + "configuration": {}, + "version": "builtin", + "enabled": True, + } proxy.policies.insert(1, policy_2) policies["policies_config"].insert(1, policy_2) updated_policies = proxy.policies.list() - for pol1, pol2 in zip(policies["policies_config"], updated_policies["policies_config"]): - if hasattr(pol1, 'entity'): + for pol1, pol2 in zip( + policies["policies_config"], updated_policies["policies_config"] + ): + if hasattr(pol1, "entity"): pol1 = pol1.entity - for attr in ['service_id', 'id']: + for attr in ["service_id", "id"]: if attr in pol1: pol1.pop(attr) - if hasattr(pol2, 'entity'): + if hasattr(pol2, "entity"): pol2 = pol2.entity - for attr in ['service_id', 'id']: + for attr in ["service_id", "id"]: if attr in pol2: pol2.pop(attr) diff --git a/tests/integration/test_integration_policy_registry.py b/tests/integration/test_integration_policy_registry.py index 3b84f23..ca40998 100644 --- a/tests/integration/test_integration_policy_registry.py +++ b/tests/integration/test_integration_policy_registry.py @@ -5,41 +5,49 @@ # tests important for CRD - CRU + list + def test_policy_registry_list(api, policy_registry): objs = api.policy_registry.list() assert len(objs) >= 1 + def test_policy_registry_can_be_created(api, policy_registry_params, policy_registry): assert_resource(policy_registry) assert_resource_params(policy_registry, policy_registry_params) + def test_policy_registry_can_be_read(api, policy_registry_params, policy_registry): read = api.policy_registry.read(policy_registry.entity_id) asserts.assert_resource(read) asserts.assert_resource_params(read, policy_registry) -def test_policy_regitry_can_be_read_by_name(api, policy_registry_params, policy_registry): - name = policy_registry['name'] +def test_policy_regitry_can_be_read_by_name( + api, policy_registry_params, policy_registry +): + name = policy_registry["name"] read = api.policy_registry[name] asserts.assert_resource(read) asserts.assert_resource_params(read, policy_registry) + def test_policy_registry_can_be_updated(api, service, policy_registry): - des_changed = (policy_registry['name'] or '') + '_changed' - policy_registry['name'] = des_changed + des_changed = (policy_registry["name"] or "") + "_changed" + policy_registry["name"] = des_changed policy_registry.update() - assert policy_registry['name'] == des_changed + assert policy_registry["name"] == des_changed updated = policy_registry.read() - assert updated['name'] == des_changed - assert policy_registry['name'] == des_changed + assert updated["name"] == des_changed + assert policy_registry["name"] == des_changed + # end of tests important for CRD - CRU + list # tests to compare data in CRD and in 3scale + def test_data(api, api_origin, policy_registry): for pol in api.policy_registry.list(): - pol_origin = api_origin.policy_registry.read(int(pol['id'])) + pol_origin = api_origin.policy_registry.read(int(pol["id"])) for att in pol.entity: - assert pol.entity[att] == pol_origin.entity[att] + assert pol.entity[att] == pol_origin.entity[att] diff --git a/tests/integration/test_integration_pricing_rules.py b/tests/integration/test_integration_pricing_rules.py index c5c45fa..835f358 100644 --- a/tests/integration/test_integration_pricing_rules.py +++ b/tests/integration/test_integration_pricing_rules.py @@ -6,14 +6,17 @@ # With service metric # tests important for CRD - CRU + list + @pytest.fixture() def prules_client(application_plan, metric, prule) -> PricingRules: return application_plan.pricing_rules(metric) + def test_prules_list(prules_client): prules = prules_client.list() assert len(prules) >= 1 + def test_prule_can_be_created(prule_params, prule, prules_client): asserts.assert_resource(prule) asserts.assert_resource_params(prule, prule_params) @@ -27,39 +30,40 @@ def test_prule_can_be_read(prules_client, prule, prule_params): def test_prule_can_be_updated(prules_client, prule): lcount = prules_client.list() - prule['cost_per_unit'] = "20" + prule["cost_per_unit"] = "20" prule_updated = prule.update() - assert prule['cost_per_unit'] == "20" == prule_updated['cost_per_unit'] + assert prule["cost_per_unit"] == "20" == prule_updated["cost_per_unit"] updated = prule.read() - assert updated['cost_per_unit'] == "20" == prule['cost_per_unit'] + assert updated["cost_per_unit"] == "20" == prule["cost_per_unit"] assert lcount == prules_client.list() + # end of tests important for CRD - CRU + list ## With backend metric ## tests important for CRD - CRU + list # -#@pytest.fixture() -#def backend_prules_client(application_plan, backend_metric, backend_limit) -> Limits: +# @pytest.fixture() +# def backend_prules_client(application_plan, backend_metric, backend_limit) -> Limits: # return application_plan.limits(backend_metric) # -#def test_backend_limit_list(backend_prules_client): +# def test_backend_limit_list(backend_prules_client): # limits = backend_prules_client.list() # assert len(limits) >= 1 # -#def test_backend_limit_can_be_created(backend_limit_params, backend_limit, backend_prules_client): +# def test_backend_limit_can_be_created(backend_limit_params, backend_limit, backend_prules_client): # asserts.assert_resource(backend_limit) # asserts.assert_resource_params(backend_limit, backend_limit_params) # # -#def test_backend_limit_can_be_read(backend_prules_client, backend_limit, backend_limit_params): +# def test_backend_limit_can_be_read(backend_prules_client, backend_limit, backend_limit_params): # read = backend_prules_client.read(backend_limit.entity_id) # asserts.assert_resource(read) # asserts.assert_resource_params(read, backend_limit_params) # # -#def test_backend_limit_can_be_updated(backend_prules_client, backend_limit): +# def test_backend_limit_can_be_updated(backend_prules_client, backend_limit): # lcount = backend_prules_client.list() # backend_limit['value'] = 11 # lim_updated = backend_limit.update() diff --git a/tests/integration/test_integration_promotes.py b/tests/integration/test_integration_promotes.py index 91c32a7..f401fe2 100644 --- a/tests/integration/test_integration_promotes.py +++ b/tests/integration/test_integration_promotes.py @@ -7,6 +7,7 @@ # these tests should run in sequence because operator client checks if there are any changes in the product + @pytest.mark.order(1) def test_promote_list(api, promote): promotes = api.promotes.list() @@ -29,29 +30,32 @@ def test_promote_can_be_read(api, promote, promote_params): @pytest.mark.order(4) def test_promote_can_be_updated(api, promote): lcount = api.promotes.list() - promote['deleteCR'] = False + promote["deleteCR"] = False prom_updated = promote.update() - assert promote['deleteCR'] == False == prom_updated['deleteCR'] + assert promote["deleteCR"] == False == prom_updated["deleteCR"] updated = promote.read() - assert updated['deleteCR'] == False == promote['deleteCR'] + assert updated["deleteCR"] == False == promote["deleteCR"] assert lcount == api.promotes.list() + # end of tests important for CRD - CRU + list + @pytest.mark.order(5) def test_promote_to_production(api, mapping_rule, proxy, backend_usage): """ Promotes to production. This promotion actually promotes to staging first and then to production. """ - mapping_rule['delta'] += 1 + mapping_rule["delta"] += 1 mapping_rule.update() proxy.promote() + @pytest.mark.order(6) def test_promote_only_to_staging(api, mapping_rule, proxy, backend_usage): """ Promotes to staging only. """ - mapping_rule['delta'] += 1 + mapping_rule["delta"] += 1 mapping_rule.update() proxy.deploy() diff --git a/tests/integration/test_integration_services.py b/tests/integration/test_integration_services.py index 95cbc07..f080526 100644 --- a/tests/integration/test_integration_services.py +++ b/tests/integration/test_integration_services.py @@ -8,16 +8,20 @@ def test_3scale_url_is_set(api, url, token): assert token is not None assert api.url is not None + # tests important for CRD - CRU + list + def test_services_list(api, service): services = api.services.list() assert len(services) >= 1 + def test_service_can_be_created(api, service_params, service): assert_resource(service) assert_resource_params(service, service_params) + def test_service_can_be_read(api, service_params, service): read = api.services.read(service.entity_id) asserts.assert_resource(read) @@ -25,73 +29,79 @@ def test_service_can_be_read(api, service_params, service): def test_service_can_be_read_by_name(api, service_params, service): - account_name = service['system_name'] + account_name = service["system_name"] read = api.services[account_name] asserts.assert_resource(read) asserts.assert_resource_params(read, service_params) + # there is different syntax for setting up backend_version def test_service_can_be_updated(api, service): - des_changed = (service['description'] or '') + '_changed' - service['description'] = des_changed + des_changed = (service["description"] or "") + "_changed" + service["description"] = des_changed service.update() - assert service['description'] == des_changed + assert service["description"] == des_changed updated = service.read() - assert updated['description'] == des_changed - assert service['description'] == des_changed + assert updated["description"] == des_changed + assert service["description"] == des_changed + # end of tests important for CRD - CRU + list + def test_proxy_list(api, service: Service, proxy: Proxy): assert not isinstance(proxy, list) + # proxy object is doesn't contain error codes until they are configured. # there is no default value in CRD def test_service_get_proxy(api, service: Service, proxy: Proxy): - assert 'error_auth_failed' not in proxy.entity - assert 'error_auth_missing' not in proxy.entity - assert 'error_headers_auth_failed' not in proxy.entity - assert 'error_headers_auth_missing' not in proxy.entity - assert 'error_headers_limits_exceeded' not in proxy.entity - assert 'error_headers_no_match' not in proxy.entity - assert 'error_limits_exceeded' not in proxy.entity - assert 'error_no_match' not in proxy.entity - assert 'error_status_auth_failed' not in proxy.entity - assert 'error_status_auth_missing' not in proxy.entity - assert 'error_status_limits_exceeded' not in proxy.entity - assert 'error_status_no_match' not in proxy.entity + assert "error_auth_failed" not in proxy.entity + assert "error_auth_missing" not in proxy.entity + assert "error_headers_auth_failed" not in proxy.entity + assert "error_headers_auth_missing" not in proxy.entity + assert "error_headers_limits_exceeded" not in proxy.entity + assert "error_headers_no_match" not in proxy.entity + assert "error_limits_exceeded" not in proxy.entity + assert "error_no_match" not in proxy.entity + assert "error_status_auth_failed" not in proxy.entity + assert "error_status_auth_missing" not in proxy.entity + assert "error_status_limits_exceeded" not in proxy.entity + assert "error_status_no_match" not in proxy.entity def test_service_set_proxy(api, service: Service, proxy: Proxy): - updated = proxy.update(params=dict(error_status_no_match=403, error_status_auth_missing=403)) - assert updated['error_status_auth_missing'] == 403 - assert updated['error_status_no_match'] == 403 + updated = proxy.update( + params=dict(error_status_no_match=403, error_status_auth_missing=403) + ) + assert updated["error_status_auth_missing"] == 403 + assert updated["error_status_no_match"] == 403 def test_service_proxy_promote(service, proxy, backend_usage): service.proxy.list().deploy() service.proxy.list().promote() - res = service.proxy.list().configs.latest(env='production') + res = service.proxy.list().configs.latest(env="production") assert res is not None - assert res['environment'] == 'production' - assert res['content'] is not None + assert res["environment"] == "production" + assert res["content"] is not None def test_service_proxy_deploy(service, proxy, backend_usage): proxy.update(params=dict(error_status_no_match=405, error_status_auth_missing=405)) proxy.deploy() - res = proxy.configs.list(env='staging') - proxy_config = res.entity['proxy_configs'][-1]['proxy_config'] + res = proxy.configs.list(env="staging") + proxy_config = res.entity["proxy_configs"][-1]["proxy_config"] assert proxy_config is not None - assert proxy_config['environment'] == 'sandbox' - assert proxy_config['content'] is not None - assert proxy_config['version'] > 1 + assert proxy_config["environment"] == "sandbox" + assert proxy_config["content"] is not None + assert proxy_config["version"] > 1 def test_service_list_configs(service, proxy, backend_usage): proxy.update(params=dict(error_status_no_match=406, error_status_auth_missing=406)) proxy.deploy() - res = proxy.configs.list(env='staging') + res = proxy.configs.list(env="staging") assert res item = res[0] assert item @@ -100,17 +110,17 @@ def test_service_list_configs(service, proxy, backend_usage): def test_service_proxy_configs_version(service, proxy, backend_usage): config = service.proxy.list().configs.version(version=1) assert config - assert config['environment'] == "sandbox" - assert config['version'] == 1 - assert config['content'] + assert config["environment"] == "sandbox" + assert config["version"] == 1 + assert config["content"] def test_service_proxy_configs_latest(service, proxy, backend_usage): config = service.proxy.list().configs.latest() assert config - assert config['environment'] == "sandbox" - assert config['version'] - assert config['content'] + assert config["environment"] == "sandbox" + assert config["version"] + assert config["content"] def test_service_proxy_configs_list_length(service, proxy, backend_usage, api_backend): @@ -120,10 +130,11 @@ def test_service_proxy_configs_list_length(service, proxy, backend_usage, api_ba configs = service.proxy.list().configs.list(env="sandbox") assert len(configs) == length + 1 + # there is no default mapping rule in service created from CRD def test_service_mapping_rules(service): map_rules = service.mapping_rules.list() - assert len(map_rules) == 0 + assert len(map_rules) == 0 def test_service_backend_usages_backend(backend_usage, backend): @@ -131,4 +142,6 @@ def test_service_backend_usages_backend(backend_usage, backend): def test_service_active_docs(service, active_doc): - assert all([acs['service_id'] == service['id'] for acs in service.active_docs.list()]) + assert all( + [acs["service_id"] == service["id"] for acs in service.active_docs.list()] + ) diff --git a/tests/test_3scale_api_client.py b/tests/test_3scale_api_client.py index 1294d76..69baa7c 100644 --- a/tests/test_3scale_api_client.py +++ b/tests/test_3scale_api_client.py @@ -7,26 +7,32 @@ @pytest.fixture() def url(): - return 'http://localhost' + return "http://localhost" @pytest.fixture() def token(): - return 'test-token' + return "test-token" -@pytest.fixture(scope='session') + +@pytest.fixture(scope="session") def ocp_provider_ref() -> str: - return 'secret' + return "secret" -def _create_client(url, token, ocp_provider_ref, **kwargs) -> client.ThreeScaleClientCRD: - return client.ThreeScaleClientCRD(url=url, token=token, ocp_provider_ref=ocp_provider_ref, **kwargs) +def _create_client( + url, token, ocp_provider_ref, **kwargs +) -> client.ThreeScaleClientCRD: + return client.ThreeScaleClientCRD( + url=url, token=token, ocp_provider_ref=ocp_provider_ref, **kwargs + ) @pytest.fixture() def api(url, token, ocp_provider_ref): return _create_client(url, token, ocp_provider_ref) + @pytest.fixture() def namespace(): try: @@ -40,6 +46,6 @@ def test_api_client_initialization(api, url, ocp_provider_ref, namespace): assert api.url == url assert api.parent == api assert api.threescale_client == api - assert api.admin_api_url == f'{url}/admin/api' + assert api.admin_api_url == f"{url}/admin/api" assert api.ocp_provider_ref == ocp_provider_ref assert api.ocp_namespace == namespace diff --git a/threescale_api_crd/__init__.py b/threescale_api_crd/__init__.py index c93211c..85a7a53 100644 --- a/threescale_api_crd/__init__.py +++ b/threescale_api_crd/__init__.py @@ -2,4 +2,4 @@ # pylint: disable=missing-module-docstring from .client import ThreeScaleClientCRD -__version__ = '0.1.0' +__version__ = "0.1.0" diff --git a/threescale_api_crd/client.py b/threescale_api_crd/client.py index 2f6578c..3976146 100644 --- a/threescale_api_crd/client.py +++ b/threescale_api_crd/client.py @@ -7,30 +7,47 @@ import threescale_api from threescale_api_crd import resources + class ThreeScaleClientCRD(threescale_api.client.ThreeScaleClient): """ Threescale client for CRD. """ + def __init__(self, url, token, ocp_provider_ref=None, *args, **kwargs): super().__init__(url, token, *args, **kwargs) self._ocp_provider_ref = ocp_provider_ref self._ocp_namespace = ThreeScaleClientCRD.get_namespace() - self._services = resources.Services(parent=self, instance_klass=resources.Service) + self._services = resources.Services( + parent=self, instance_klass=resources.Service + ) self._active_docs = resources.ActiveDocs( - parent=self, - instance_klass=resources.ActiveDoc) + parent=self, instance_klass=resources.ActiveDoc + ) self._policy_registry = resources.PoliciesRegistry( - parent=self, - instance_klass=resources.PolicyRegistry) - self._backends = resources.Backends(parent=self, instance_klass=resources.Backend) - self._accounts = resources.Accounts(parent=self, instance_klass=resources.Account) - self._accounts_users = resources.AccountUsers(parent=self, instance_klass=resources.AccountUser) - self._openapis = resources.OpenApis(parent=self, instance_klass=resources.OpenApi) + parent=self, instance_klass=resources.PolicyRegistry + ) + self._backends = resources.Backends( + parent=self, instance_klass=resources.Backend + ) + self._accounts = resources.Accounts( + parent=self, instance_klass=resources.Account + ) + self._accounts_users = resources.AccountUsers( + parent=self, instance_klass=resources.AccountUser + ) + self._openapis = resources.OpenApis( + parent=self, instance_klass=resources.OpenApi + ) self._tenants = resources.Tenants(parent=self, instance_klass=resources.Tenant) - self._promotes = resources.Promotes(parent=self, instance_klass=resources.Promote) - self._applications = resources.Applications(parent=self, account=None, instance_klass=resources.Application) + self._promotes = resources.Promotes( + parent=self, instance_klass=resources.Promote + ) + self._applications = resources.Applications( + parent=self, account=None, instance_klass=resources.Application + ) - def get_namespace(): + @classmethod + def get_namespace(_ignore): """ Returns namespace. If there is no valid Openshift 'oc' session, returns "NOT LOGGED IN". """ @@ -111,7 +128,7 @@ def applications(self) -> resources.Applications: @property def ocp_provider_ref(self): - """Gets provider reference """ + """Gets provider reference""" return self._ocp_provider_ref @property diff --git a/threescale_api_crd/constants.py b/threescale_api_crd/constants.py index 696d8d7..33ce629 100644 --- a/threescale_api_crd/constants.py +++ b/threescale_api_crd/constants.py @@ -2,589 +2,560 @@ Module with constants. """ -SERVICE_AUTH = { - 'userkey': '1', - 'appKeyAppID': '2', - 'oidc': 'oidc' -} +SERVICE_AUTH = {"userkey": "1", "appKeyAppID": "2", "oidc": "oidc"} SERVICE_AUTH_DEFS = { - '1': { - 'userkey': { - 'authUserKey': 'token', - 'credentials': 'authorization', - 'gatewayResponse': {}, - }, - }, - '2': { - 'appKeyAppID': { - 'appID': 'app_id', - 'appKey': 'app_key', - 'credentials': 'authorization', - 'gatewayResponse': {}, - }, - }, - 'oidc': { - 'oidc': { - 'issuerEndpoint': ' ', - 'issuerType': 'keycloak', - 'authenticationFlow': { - 'standardFlowEnabled': False, - 'implicitFlowEnabled': False, - 'serviceAccountsEnabled': False, - 'directAccessGrantsEnabled': True, - }, - 'jwtClaimWithClientID': None, - 'jwtClaimWithClientIDType': None, - 'credentials': 'authorization', - 'gatewayResponse': {}, - }, + "1": { + "userkey": { + "authUserKey": "token", + "credentials": "authorization", + "gatewayResponse": {}, }, - } + }, + "2": { + "appKeyAppID": { + "appID": "app_id", + "appKey": "app_key", + "credentials": "authorization", + "gatewayResponse": {}, + }, + }, + "oidc": { + "oidc": { + "issuerEndpoint": " ", + "issuerType": "keycloak", + "authenticationFlow": { + "standardFlowEnabled": False, + "implicitFlowEnabled": False, + "serviceAccountsEnabled": False, + "directAccessGrantsEnabled": True, + }, + "jwtClaimWithClientID": None, + "jwtClaimWithClientIDType": None, + "credentials": "authorization", + "gatewayResponse": {}, + }, + }, +} SPEC_SERVICE = { - 'apiVersion': 'capabilities.3scale.net/v1beta1', - 'kind': 'Product', - 'metadata': { - 'name': None, - 'namespace': None, - 'annotations': { - 'insecure_skip_verify': 'true' - }, + "apiVersion": "capabilities.3scale.net/v1beta1", + "kind": "Product", + "metadata": { + "name": None, + "namespace": None, + "annotations": {"insecure_skip_verify": "true"}, }, - 'spec': { - 'name': None, - 'providerAccountRef': { - 'name': None, + "spec": { + "name": None, + "providerAccountRef": { + "name": None, }, - 'systemName': None, - 'description': None, - 'deployment': { - 'apicastHosted': { - 'authentication': { - 'userkey': { - 'authUserKey': 'token', - 'credentials': 'query', - 'gatewayResponse': { - }, + "systemName": None, + "description": None, + "deployment": { + "apicastHosted": { + "authentication": { + "userkey": { + "authUserKey": "token", + "credentials": "query", + "gatewayResponse": {}, }, }, }, }, - 'applicationPlans': { - 'AppPlanTest': { - 'setupFee': '0.00', - 'costMonth': '0.00', - 'published': True, + "applicationPlans": { + "AppPlanTest": { + "setupFee": "0.00", + "costMonth": "0.00", + "published": True, } }, }, - 'policies': [] + "policies": [], } SPEC_PROXY = {} SPEC_BACKEND = { - 'apiVersion': 'capabilities.3scale.net/v1beta1', - 'kind': 'Backend', - 'metadata': { - 'name': None, - 'namespace': None, - 'annotations': { - 'insecure_skip_verify': 'true' - }, + "apiVersion": "capabilities.3scale.net/v1beta1", + "kind": "Backend", + "metadata": { + "name": None, + "namespace": None, + "annotations": {"insecure_skip_verify": "true"}, }, - 'spec': { - 'name': None, - 'privateBaseURL': None, - 'systemName': None, - 'providerAccountRef': { - 'name': None, + "spec": { + "name": None, + "privateBaseURL": None, + "systemName": None, + "providerAccountRef": { + "name": None, }, - 'description': None + "description": None, }, } SPEC_MAPPING_RULE = { - 'spec': { - 'httpMethod': None, - 'pattern': None, - 'increment': None, - 'metricMethodRef': None, - 'last': None + "spec": { + "httpMethod": None, + "pattern": None, + "increment": None, + "metricMethodRef": None, + "last": None, } } SPEC_BACKEND_USAGE = { - 'spec': { - 'path': None, + "spec": { + "path": None, } } SPEC_LIMIT = { - 'spec': { - 'period': None, - 'value': None, - 'metricMethodRef': None, + "spec": { + "period": None, + "value": None, + "metricMethodRef": None, } } SPEC_PRICING_RULE = { - 'spec': { - 'from': None, - 'to': None, - 'pricePerUnit': None, - 'metricMethodRef': None, + "spec": { + "from": None, + "to": None, + "pricePerUnit": None, + "metricMethodRef": None, } } SPEC_METRIC = { - 'spec': { - 'friendlyName': None, - 'unit': None, - 'description': None, + "spec": { + "friendlyName": None, + "unit": None, + "description": None, } } SPEC_APP_PLANS = { - 'spec': { - 'name': None, - 'appsRequireApproval': None, - 'trialPeriod': None, - 'setupFee': None, - 'costMonth': None, - 'published': True, - 'pricingRules': None, - 'limits': None + "spec": { + "name": None, + "appsRequireApproval": None, + "trialPeriod": None, + "setupFee": None, + "costMonth": None, + "published": True, + "pricingRules": None, + "limits": None, } } SPEC_ACTIVE_DOC = { - 'apiVersion': 'capabilities.3scale.net/v1beta1', - 'kind': 'ActiveDoc', - 'metadata': { - 'name': None, - 'namespace': None, - 'annotations': { - 'insecure_skip_verify': 'true' - }, + "apiVersion": "capabilities.3scale.net/v1beta1", + "kind": "ActiveDoc", + "metadata": { + "name": None, + "namespace": None, + "annotations": {"insecure_skip_verify": "true"}, }, - 'spec': { - 'name': None, - 'providerAccountRef': { - 'name': None, + "spec": { + "name": None, + "providerAccountRef": { + "name": None, }, - 'activeDocOpenAPIRef': { - 'secretRef': 'oas3-json-secret', + "activeDocOpenAPIRef": { + "secretRef": "oas3-json-secret", }, - 'systemName': None, - 'description': None, - 'productSystemName': None, - 'published': False, - 'skipSwaggerValidations': False - } + "systemName": None, + "description": None, + "productSystemName": None, + "published": False, + "skipSwaggerValidations": False, + }, } SPEC_POLICY_REG = { - 'apiVersion': 'capabilities.3scale.net/v1beta1', - 'kind': 'CustomPolicyDefinition', - 'metadata': { - 'name': None, - 'namespace': None, - 'annotations': { - 'insecure_skip_verify': 'true' - }, + "apiVersion": "capabilities.3scale.net/v1beta1", + "kind": "CustomPolicyDefinition", + "metadata": { + "name": None, + "namespace": None, + "annotations": {"insecure_skip_verify": "true"}, }, - 'spec': { - 'name': None, - 'providerAccountRef': { - 'name': None, + "spec": { + "name": None, + "providerAccountRef": { + "name": None, }, - 'version': None, - 'schema': { - 'name': None, - 'version': None, - 'summary': None, - '$schema': None, - 'description': None, - 'configuration': None - } - } + "version": None, + "schema": { + "name": None, + "version": None, + "summary": None, + "$schema": None, + "description": None, + "configuration": None, + }, + }, } SPEC_ACCOUNT = { - 'apiVersion': 'capabilities.3scale.net/v1beta1', - 'kind': 'DeveloperAccount', - 'metadata': { - 'name': None, - 'namespace': None, - 'annotations': { - 'insecure_skip_verify': 'true' - }, + "apiVersion": "capabilities.3scale.net/v1beta1", + "kind": "DeveloperAccount", + "metadata": { + "name": None, + "namespace": None, + "annotations": {"insecure_skip_verify": "true"}, }, - 'spec': { - 'providerAccountRef': { - 'name': None, + "spec": { + "providerAccountRef": { + "name": None, }, - 'orgName': None, - 'monthlyBillingEnabled': None, - 'monthlyChargingEnabled': None - } + "orgName": None, + "monthlyBillingEnabled": None, + "monthlyChargingEnabled": None, + }, } SPEC_ACCOUNT_USER = { - 'apiVersion': 'capabilities.3scale.net/v1beta1', - 'kind': 'DeveloperUser', - 'metadata': { - 'name': None, - 'namespace': None, - 'annotations': { - 'insecure_skip_verify': 'true' - }, + "apiVersion": "capabilities.3scale.net/v1beta1", + "kind": "DeveloperUser", + "metadata": { + "name": None, + "namespace": None, + "annotations": {"insecure_skip_verify": "true"}, }, - 'spec': { - 'providerAccountRef': { - 'name': None, + "spec": { + "providerAccountRef": { + "name": None, }, - 'username': None, - 'email': None, - 'suspended': None, - 'role': None, - 'passwordCredentialsRef': { - 'name': None, + "username": None, + "email": None, + "suspended": None, + "role": None, + "passwordCredentialsRef": { + "name": None, }, - 'developerAccountRef': { - 'name': None, - } - } + "developerAccountRef": { + "name": None, + }, + }, } SPEC_POLICY = { - 'spec': { - 'name': None, - 'version': None, - 'enabled': None, - 'configuration': {}, + "spec": { + "name": None, + "version": None, + "enabled": None, + "configuration": {}, } } SPEC_OPEN_API = { - 'apiVersion': 'capabilities.3scale.net/v1beta1', - 'kind': 'OpenAPI', - 'metadata': { - 'name': None, - 'namespace': None, - 'annotations': { - 'insecure_skip_verify': 'true' - }, + "apiVersion": "capabilities.3scale.net/v1beta1", + "kind": "OpenAPI", + "metadata": { + "name": None, + "namespace": None, + "annotations": {"insecure_skip_verify": "true"}, }, - 'spec': { - 'providerAccountRef': { - 'name': None, + "spec": { + "providerAccountRef": { + "name": None, }, - } + }, } - SPEC_TENANT = { - 'apiVersion': 'capabilities.3scale.net/v1alpha1', - 'kind': 'Tenant', - 'metadata': { - 'name': None, - 'namespace': None, - 'annotations': { - 'insecure_skip_verify': 'true' - }, + "apiVersion": "capabilities.3scale.net/v1alpha1", + "kind": "Tenant", + "metadata": { + "name": None, + "namespace": None, + "annotations": {"insecure_skip_verify": "true"}, }, - 'spec': { - 'organizationName': None, - 'email': None, - 'username': 'admin', - 'systemMasterUrl': None, - 'masterCredentialsRef': { - 'name': None, + "spec": { + "organizationName": None, + "email": None, + "username": "admin", + "systemMasterUrl": None, + "masterCredentialsRef": { + "name": None, }, - 'passwordCredentialsRef': { - 'name': None, + "passwordCredentialsRef": { + "name": None, }, - 'tenantSecretRef': { - 'name': None, - 'namespace': None - } - } + "tenantSecretRef": {"name": None, "namespace": None}, + }, } SPEC_PROMOTE = { - 'apiVersion': 'capabilities.3scale.net/v1beta1', - 'kind': 'ProxyConfigPromote', - 'metadata': { - 'name': None, - 'namespace': None, - 'annotations': { - 'insecure_skip_verify': 'true' - }, + "apiVersion": "capabilities.3scale.net/v1beta1", + "kind": "ProxyConfigPromote", + "metadata": { + "name": None, + "namespace": None, + "annotations": {"insecure_skip_verify": "true"}, }, - 'spec': { - 'providerAccountRef': { - 'name': None, + "spec": { + "providerAccountRef": { + "name": None, }, - 'productCRName': None, - } + "productCRName": None, + }, } SPEC_APPLICATION = { - 'apiVersion': 'capabilities.3scale.net/v1beta1', - 'kind': 'Application', - 'metadata': { - 'name': None, - 'namespace': None, - 'annotations': { - 'insecure_skip_verify': 'true' - }, + "apiVersion": "capabilities.3scale.net/v1beta1", + "kind": "Application", + "metadata": { + "name": None, + "namespace": None, + "annotations": {"insecure_skip_verify": "true"}, }, - 'spec': { - 'name': None, - 'providerAccountRef': { - 'name': None, + "spec": { + "name": None, + "providerAccountRef": { + "name": None, }, - 'description': None, - 'accountCR': { - 'name': None, + "description": None, + "accountCR": { + "name": None, }, - 'productCR': { - 'name': None, + "productCR": { + "name": None, }, - 'applicationPlanName': None, - 'suspend': False, + "applicationPlanName": None, + "suspend": False, }, } SPEC_METHOD = { - 'spec': { - 'friendlyName': None, - 'description': None, + "spec": { + "friendlyName": None, + "description": None, } } KEYS_SERVICE = { - 'description': 'description', - 'name': 'name', - 'system_name': 'systemName', - 'mapping_rules': 'mappingRules', - 'metrics': 'metrics', - 'backend_usages': 'backendUsages', - 'application_plans': 'applicationPlans', - 'deployment': 'deployment', - 'policies': 'policies', - 'methods': 'methods', + "description": "description", + "name": "name", + "system_name": "systemName", + "mapping_rules": "mappingRules", + "metrics": "metrics", + "backend_usages": "backendUsages", + "application_plans": "applicationPlans", + "deployment": "deployment", + "policies": "policies", + "methods": "methods", } KEYS_PROXY_RESPONSES = { - 'error_auth_failed': 'errorAuthFailed', - 'error_auth_missing': 'errorAuthMissing', - 'error_headers_auth_failed': 'errorHeadersAuthFailed', - 'error_headers_auth_missing': 'errorHeadersAuthMissing', - 'error_headers_limits_exceeded': 'errorHeadersLimitsExceeded', - 'error_headers_no_match': 'errorHeadersNoMatch', - 'error_limits_exceeded': 'errorLimitsExceeded', - 'error_no_match': 'errorNoMatch', - 'error_status_auth_failed': 'errorStatusAuthFailed', - 'error_status_auth_missing': 'errorStatusAuthMissing', - 'error_status_limits_exceeded': 'errorStatusLimitsExceeded', - 'error_status_no_match': 'errorStatusNoMatch', + "error_auth_failed": "errorAuthFailed", + "error_auth_missing": "errorAuthMissing", + "error_headers_auth_failed": "errorHeadersAuthFailed", + "error_headers_auth_missing": "errorHeadersAuthMissing", + "error_headers_limits_exceeded": "errorHeadersLimitsExceeded", + "error_headers_no_match": "errorHeadersNoMatch", + "error_limits_exceeded": "errorLimitsExceeded", + "error_no_match": "errorNoMatch", + "error_status_auth_failed": "errorStatusAuthFailed", + "error_status_auth_missing": "errorStatusAuthMissing", + "error_status_limits_exceeded": "errorStatusLimitsExceeded", + "error_status_no_match": "errorStatusNoMatch", } KEYS_PROXY_SECURITY = { - 'secret_token': 'secretToken', - 'hostname_rewrite': 'hostHeader', + "secret_token": "secretToken", + "hostname_rewrite": "hostHeader", } KEYS_PROXY = { - 'auth_app_id': 'appID', - 'auth_app_key': 'appKey', - 'auth_user_key': 'authUserKey', - 'credentials_location': 'credentials', - 'endpoint': 'productionPublicBaseURL', - 'jwt_claim_with_client_id': 'jwtClaimWithClientID', - 'jwt_claim_with_client_id_type': 'jwtClaimWithClientIDType', - 'oidc_issuer_endpoint': 'issuerEndpoint', - 'oidc_issuer_type': 'issuerType', - 'sandbox_endpoint': 'stagingPublicBaseURL', + "auth_app_id": "appID", + "auth_app_key": "appKey", + "auth_user_key": "authUserKey", + "credentials_location": "credentials", + "endpoint": "productionPublicBaseURL", + "jwt_claim_with_client_id": "jwtClaimWithClientID", + "jwt_claim_with_client_id_type": "jwtClaimWithClientIDType", + "oidc_issuer_endpoint": "issuerEndpoint", + "oidc_issuer_type": "issuerType", + "sandbox_endpoint": "stagingPublicBaseURL", } KEYS_OIDC = { - 'standard_flow_enabled': 'standardFlowEnabled', - 'implicit_flow_enabled': 'implicitFlowEnabled', - 'service_accounts_enabled': 'serviceAccountsEnabled', - 'direct_access_grants_enabled': 'directAccessGrantsEnabled', + "standard_flow_enabled": "standardFlowEnabled", + "implicit_flow_enabled": "implicitFlowEnabled", + "service_accounts_enabled": "serviceAccountsEnabled", + "direct_access_grants_enabled": "directAccessGrantsEnabled", } KEYS_BACKEND = { - 'description': 'description', - 'name': 'name', - 'system_name': 'systemName', - 'mapping_rules': 'mappingRules', - 'private_endpoint': 'privateBaseURL', - 'metrics': 'metrics' + "description": "description", + "name": "name", + "system_name": "systemName", + "mapping_rules": "mappingRules", + "private_endpoint": "privateBaseURL", + "metrics": "metrics", } KEYS_MAPPING_RULE = { - 'http_method': 'httpMethod', - 'pattern': 'pattern', - 'delta': 'increment', - 'metric_id': 'metricMethodRef', - 'last': 'last' + "http_method": "httpMethod", + "pattern": "pattern", + "delta": "increment", + "metric_id": "metricMethodRef", + "last": "last", } KEYS_ACTIVE_DOC = { - 'system_name': 'systemName', - 'name': 'name', - 'description': 'description', - 'published': 'published', - 'skip_swagger_validations': 'skipSwaggerValidations', - 'service_id': 'productSystemName', + "system_name": "systemName", + "name": "name", + "description": "description", + "published": "published", + "skip_swagger_validations": "skipSwaggerValidations", + "service_id": "productSystemName", # because of modify function for update - 'activeDocOpenAPIRef': 'activeDocOpenAPIRef' + "activeDocOpenAPIRef": "activeDocOpenAPIRef", } KEYS_POLICY_REG = { - 'name': 'name', - 'version': 'version', - 'schema': 'schema', - 'summary': 'summary', - '$schema': '$schema', - 'description': 'description', - 'configuration': 'configuration' + "name": "name", + "version": "version", + "schema": "schema", + "summary": "summary", + "$schema": "$schema", + "description": "description", + "configuration": "configuration", } KEYS_METRIC = { - 'description': 'description', - 'unit': 'unit', - 'friendly_name': 'friendlyName', - 'system_name': 'system_name' + "description": "description", + "unit": "unit", + "friendly_name": "friendlyName", + "system_name": "system_name", } KEYS_LIMIT = { - 'period': 'period', - 'value': 'value', + "period": "period", + "value": "value", # 'metric_name': 'metricMethodRef', should be processed } KEYS_APP_PLANS = { - 'name': 'name', - 'approval_required': 'appsRequireApproval', - 'trial_period_days': 'trialPeriod', - 'setup_fee': 'setupFee', - 'cost_per_month': 'costMonth', - 'state_event': 'published', - 'system_name': 'system_name', - 'limits': 'limits', - 'pricingRules': 'pricingRules', + "name": "name", + "approval_required": "appsRequireApproval", + "trial_period_days": "trialPeriod", + "setup_fee": "setupFee", + "cost_per_month": "costMonth", + "state_event": "published", + "system_name": "system_name", + "limits": "limits", + "pricingRules": "pricingRules", # missing state, cancellation_period, default, custom } KEYS_BACKEND_USAGE = { - 'path': 'path', - 'service_id': 'service_id', - 'backend_id': 'backend_id', + "path": "path", + "service_id": "service_id", + "backend_id": "backend_id", } KEYS_ACCOUNT = { - 'org_name': 'orgName', - 'monthly_billing_enabled': 'monthlyBillingEnabled', - 'monthly_charging_enabled': 'monthlyChargingEnabled' + "org_name": "orgName", + "monthly_billing_enabled": "monthlyBillingEnabled", + "monthly_charging_enabled": "monthlyChargingEnabled", # missing credit_card_stored, created_at, updated_at } KEYS_ACCOUNT_USER = { - 'username': 'username', - 'email': 'email', - 'suspended': 'suspended', - 'role': 'role' + "username": "username", + "email": "email", + "suspended": "suspended", + "role": "role", } KEYS_POLICY = { - 'name': 'name', - 'version': 'version', - 'configuration': 'configuration', - 'enabled': 'enabled', + "name": "name", + "version": "version", + "configuration": "configuration", + "enabled": "enabled", } KEYS_OPEN_API = { - 'productionPublicBaseURL': 'productionPublicBaseURL', - 'stagingPublicBaseURL': 'stagingPublicBaseURL', - 'productSystemName': 'productSystemName', - 'privateBaseURL': 'privateBaseURL', - 'prefixMatching': 'prefixMatching', - 'privateAPIHostHeader': 'privateAPIHostHeader', - 'privateAPISecretToken': 'privateAPISecretToken', - 'oidc': 'oidc' + "productionPublicBaseURL": "productionPublicBaseURL", + "stagingPublicBaseURL": "stagingPublicBaseURL", + "productSystemName": "productSystemName", + "privateBaseURL": "privateBaseURL", + "prefixMatching": "prefixMatching", + "privateAPIHostHeader": "privateAPIHostHeader", + "privateAPISecretToken": "privateAPISecretToken", + "oidc": "oidc", } KEYS_OPEN_API_OIDC = { - 'issuerEndpoint': 'issuerEndpoint', - 'issuerEndpointRef': 'issuerEndpointRef', - 'issuerType': 'issuerType', - 'authenticationFlow': 'authenticationFlow', - 'jwtClaimWithClientID': 'jwtClaimWithClientID', - 'jwtClaimWithClientIDType': 'jwtClaimWithClientIDType', - 'credentials': 'credentials', - 'gatewayResponse': 'gatewayResponse', + "issuerEndpoint": "issuerEndpoint", + "issuerEndpointRef": "issuerEndpointRef", + "issuerType": "issuerType", + "authenticationFlow": "authenticationFlow", + "jwtClaimWithClientID": "jwtClaimWithClientID", + "jwtClaimWithClientIDType": "jwtClaimWithClientIDType", + "credentials": "credentials", + "gatewayResponse": "gatewayResponse", } KEYS_TENANT = { - 'org_name': 'organizationName', - 'email': 'email', - 'username': 'username', - 'system_master_url': 'systemMasterUrl', - 'tenantSecretRef': 'tenantSecretRef', - 'passwordCredentialsRef': 'passwordCredentialsRef', - 'masterCredentialsRef': 'masterCredentialsRef' + "org_name": "organizationName", + "email": "email", + "username": "username", + "system_master_url": "systemMasterUrl", + "tenantSecretRef": "tenantSecretRef", + "passwordCredentialsRef": "passwordCredentialsRef", + "masterCredentialsRef": "masterCredentialsRef", } KEYS_LIMIT = { - 'period': 'period', - 'value': 'value', - 'metricMethodRef': 'metricMethodRef' + "period": "period", + "value": "value", + "metricMethodRef": "metricMethodRef", } KEYS_PRICING_RULE = { - 'cost_per_unit': 'pricePerUnit', - 'min': 'from', - 'max': 'to', - 'metricMethodRef': 'metricMethodRef' + "cost_per_unit": "pricePerUnit", + "min": "from", + "max": "to", + "metricMethodRef": "metricMethodRef", } KEYS_PROMOTE = { - 'productCRName': 'productCRName', - 'production': 'production', - 'deleteCR': 'deleteCR', + "productCRName": "productCRName", + "production": "production", + "deleteCR": "deleteCR", } KEYS_APPLICATION = { - 'description': 'description', - 'name': 'name', - 'plan_name': 'applicationPlanName', - 'suspend': 'suspend', - 'service_name': 'productCR', - 'account_name': 'accountCR', + "description": "description", + "name": "name", + "plan_name": "applicationPlanName", + "suspend": "suspend", + "service_name": "productCR", + "account_name": "accountCR", } KEYS_METHOD = { - 'description': 'description', - 'friendly_name': 'friendlyName', - 'system_name': 'system_name' + "description": "description", + "friendly_name": "friendlyName", + "system_name": "system_name", } SPEC_SECRET = { - 'kind': 'Secret', - 'apiVersion': 'v1', - 'metadata': { - 'name': None, - 'namespace': None, + "kind": "Secret", + "apiVersion": "v1", + "metadata": { + "name": None, + "namespace": None, }, - 'data': {}, - 'type': 'Opaque' + "data": {}, + "type": "Opaque", } diff --git a/threescale_api_crd/defaults.py b/threescale_api_crd/defaults.py index 2081608..10310bb 100644 --- a/threescale_api_crd/defaults.py +++ b/threescale_api_crd/defaults.py @@ -10,9 +10,6 @@ import threescale_api import threescale_api.errors import openshift_client as ocp -from openshift_client import OpenShiftPythonException - -from threescale_api_crd import resources, constants, client LOG = logging.getLogger(__name__) @@ -26,25 +23,31 @@ class DefaultClientCRD(threescale_api.defaults.DefaultClient): KEYS = None ID_NAME = None - def __init__(self, parent=None, instance_klass=None, entity_name=None, entity_collection=None): + def __init__( + self, parent=None, instance_klass=None, entity_name=None, entity_collection=None + ): ocp.set_default_loglevel(6) - super().__init__(parent=parent, instance_klass=instance_klass, - entity_name=entity_name, entity_collection=entity_collection) - - def get_list(self, typ='normal'): - """ Returns list of entities. """ + super().__init__( + parent=parent, + instance_klass=instance_klass, + entity_name=entity_name, + entity_collection=entity_collection, + ) + + def get_list(self, typ="normal"): + """Returns list of entities.""" return [] def get_selector(self, obj_name=None): - """ Returns OCP selector for objects. """ - sel = self.SELECTOR + '.capabilities.3scale.net' + """Returns OCP selector for objects.""" + sel = self.SELECTOR + ".capabilities.3scale.net" if obj_name: - sel += '/' + obj_name + sel += "/" + obj_name return ocp.selector(sel) def read_crd(self, obj_name=None): """Read current CRD definition based on selector and/or object name.""" - LOG.info('CRD read %s %s', str(self.SELECTOR), str(obj_name)) + LOG.info("CRD read %s %s", str(self.SELECTOR), str(obj_name)) return self.get_selector(obj_name).objects() def is_crd_implemented(self): @@ -67,11 +70,13 @@ def fetch_crd_entity(self, name: str): """ LOG.info(self._log_message("[FETCH] CRD Fetch by crd name: ", entity_id=name)) if not self.is_crd_implemented(): - raise threescale_api.errors.ThreeScaleApiError(message="Not supported method") + raise threescale_api.errors.ThreeScaleApiError( + message="Not supported method" + ) inst = self._create_instance(response=self.read_crd(name)) return inst[0] if inst else None - def read_by_name(self, name: str, **kwargs) -> 'DefaultResource': + def read_by_name(self, name: str, **kwargs) -> "DefaultResourceCRD": """Read resource by name Args: name: Name of the resource (either system name, name, org_name ...) @@ -80,20 +85,19 @@ def read_by_name(self, name: str, **kwargs) -> 'DefaultResource': Returns: """ - return self.fetch_crd_entity(name) or super().read_by_name(name, **kwargs) - -# def read(self, entity_id: int = None) -> 'DefaultResource': -# """Read the instance, read will just create empty resource and lazyloads only if needed -# Args: -# entity_id(int): Entity id -# Returns(DefaultResource): Default resource -# """ -# LOG.debug(self._log_message("[READ] CRD Read ", entity_id=entity_id)) -# if self.is_crd_implemented(): -# self.fetch(entity_id=entity_id) -# else: -# return threescale_api.defaults.DefaultClient.read(self, entity_id, **kwargs) - + return self.fetch_crd_entity(name) or super().read_by_name(name, **kwargs) + + # def read(self, entity_id: int = None) -> 'DefaultResourceCRD': + # """Read the instance, read will just create empty resource and lazyloads only if needed + # Args: + # entity_id(int): Entity id + # Returns(DefaultResourceCRD): Default resource + # """ + # LOG.debug(self._log_message("[READ] CRD Read ", entity_id=entity_id)) + # if self.is_crd_implemented(): + # self.fetch(entity_id=entity_id) + # else: + # return threescale_api.defaults.DefaultClient.read(self, entity_id, **kwargs) def fetch(self, entity_id: int = None, **kwargs): """Fetches the entity dictionary @@ -103,15 +107,23 @@ def fetch(self, entity_id: int = None, **kwargs): Returns(dict): Resource dict from the 3scale """ - LOG.info(self._log_message("[FETCH] CRD Fetch ", entity_id=entity_id, args=kwargs)) + LOG.info( + self._log_message("[FETCH] CRD Fetch ", entity_id=entity_id, args=kwargs) + ) if self.is_crd_implemented(): list_crds = self.read_crd() instance_list = self._create_instance(response=list_crds) ret = [] if isinstance(instance_list, list): - ret = ([instance for instance in instance_list - if (instance.entity_id and instance.entity_id == entity_id) or - entity_id is None][:1] or [None])[0] + ret = ( + [ + instance + for instance in instance_list + if (instance.entity_id and instance.entity_id == entity_id) + or entity_id is None + ][:1] + or [None] + )[0] else: # proxy.fetch exception ret = instance_list @@ -126,15 +138,19 @@ def exists(self, entity_id=None, **kwargs) -> bool: Returns(bool): True if the resource exists """ - LOG.info(self._log_message("[EXIST] CRD Resource exist ", entity_id=entity_id, args=kwargs)) + LOG.info( + self._log_message( + "[EXIST] CRD Resource exist ", entity_id=entity_id, args=kwargs + ) + ) return self.fetch(entity_id, **kwargs) - def _list(self, **kwargs) -> List['DefaultResource']: + def _list(self, **kwargs) -> List["DefaultResourceCRD"]: """Internal list implementation used in list or `select` methods Args: **kwargs: Optional parameters - Returns(List['DefaultResource']): + Returns(List['DefaultResourceCRD']): """ LOG.info(self._log_message("[_LIST] CRD", args=kwargs)) @@ -147,45 +163,53 @@ def _list(self, **kwargs) -> List['DefaultResource']: @staticmethod def normalize(str_in: str): """Some values in CRD cannot contain some characters.""" - return str_in.translate(''.maketrans({'-': '', '_': '', '/': '', '[': '', ']': ''})).lower() + return str_in.translate( + "".maketrans({"-": "", "_": "", "/": "", "[": "", "]": ""}) + ).lower() @staticmethod def cleanup_spec(spec, keys, params): - """ Removes from spec attributes with None value. """ + """Removes from spec attributes with None value.""" for key, value in keys.items(): - if params.get(key, None) is None and \ - value in spec['spec'] and \ - spec['spec'][value] is None: - del spec['spec'][value] - - def create(self, params: dict = None, **kwargs) -> 'DefaultResource': + if ( + params.get(key, None) is None + and value in spec["spec"] + and spec["spec"][value] is None + ): + del spec["spec"][value] + + def create(self, params: dict = None, **kwargs) -> "DefaultResourceCRD": LOG.info(self._log_message("[CREATE] Create CRD ", body=params, args=kwargs)) if self.is_crd_implemented(): spec = copy.deepcopy(self.SPEC) - name = params.get('name') or params.get('username') # Developer User exception + name = params.get("name") or params.get( + "username" + ) # Developer User exception if name is not None: name = self.normalize(name) - if params.get('name'): - params['name'] = name + if params.get("name"): + params["name"] = name else: - params['username'] = name + params["username"] = name else: - name = self.normalize(''.join(random.choice(string.ascii_letters) for _ in range(16))) + name = self.normalize( + "".join(random.choice(string.ascii_letters) for _ in range(16)) + ) - spec['metadata']['namespace'] = self.threescale_client.ocp_namespace - spec['metadata']['name'] = name + spec["metadata"]["namespace"] = self.threescale_client.ocp_namespace + spec["metadata"]["name"] = name spec = self._set_provider_ref_new_crd(spec) self.before_create(params, spec) - spec['spec'].update(self.translate_to_crd(params)) + spec["spec"].update(self.translate_to_crd(params)) DefaultClientCRD.cleanup_spec(spec, self.KEYS, params) result = ocp.create(spec) assert result.status() == 0 - #list_objs = self.read_crd(result.out().strip().split('/')[1]) + # list_objs = self.read_crd(result.out().strip().split('/')[1]) created_objects = [] - #counters = [89, 55, 34, 21, 13, 8, 5, 3, 2, 1, 1, 1] - #while len(list_objs) > 0 and len(counters) > 0: + # counters = [89, 55, 34, 21, 13, 8, 5, 3, 2, 1, 1, 1] + # while len(list_objs) > 0 and len(counters) > 0: # list_objs2 = [] # for obj in list_objs: # obj.refresh() @@ -203,42 +227,52 @@ def create(self, params: dict = None, **kwargs) -> 'DefaultResource': # time.sleep(counters.pop()) timeout = 1000 - #if self.__class__.__name__ in ['Promotes']: + # if self.__class__.__name__ in ['Promotes']: # timeout = 1000 with ocp.timeout(timeout): - (success, created_objects, _) = result.until_all(success_func=lambda obj: self._is_ready(obj)) + (success, created_objects, _) = result.until_all( + success_func=lambda obj: self._is_ready(obj) + ) assert created_objects assert success - instance = (self._create_instance(response=created_objects)[:1] or [None])[0] + instance = (self._create_instance(response=created_objects)[:1] or [None])[ + 0 + ] return instance return threescale_api.defaults.DefaultClient.create(self, params, **kwargs) def _set_provider_ref_new_crd(self, spec): - """ set provider reference to new crd """ + """set provider reference to new crd""" if self.threescale_client.ocp_provider_ref is None: - spec['spec'].pop('providerAccountRef') + spec["spec"].pop("providerAccountRef") else: - spec['spec']['providerAccountRef']['name'] = self.threescale_client.ocp_provider_ref - spec['spec']['providerAccountRef']['namespace'] = self.threescale_client.ocp_namespace + spec["spec"]["providerAccountRef"][ + "name" + ] = self.threescale_client.ocp_provider_ref + spec["spec"]["providerAccountRef"][ + "namespace" + ] = self.threescale_client.ocp_namespace return spec def _is_ready(self, obj): - """ Is object ready? """ - if not ('status' in obj.model and 'conditions' in obj.model.status): + """Is object ready?""" + if not ("status" in obj.model and "conditions" in obj.model.status): return False - status = obj.as_dict()['status'] + status = obj.as_dict()["status"] new_id = status.get(self.ID_NAME, 0) - state = {'Failed': True, 'Invalid': True, 'Synced': False, 'Ready': False} - for sta in status['conditions']: - state[sta['type']] = (sta['status'] == 'True') + state = {"Failed": True, "Invalid": True, "Synced": False, "Ready": False} + for sta in status["conditions"]: + state[sta["type"]] = sta["status"] == "True" - return not state['Failed'] and\ - not state['Invalid'] and\ - (state['Synced'] or state['Ready']) and\ - (new_id != 0) + return ( + not state["Failed"] + and not state["Invalid"] + and (state["Synced"] or state["Ready"]) + and (new_id != 0) + ) def _create_instance(self, response, klass=None, collection: bool = False): klass = klass or self._instance_klass @@ -252,13 +286,13 @@ def _create_instance(self, response, klass=None, collection: bool = False): return instance def _extract_resource_crd(self, response, collection, klass): - extract_params = {'response': response, 'entity': self._entity_name} + extract_params = {"response": response, "entity": self._entity_name} if collection: - extract_params['collection'] = self._entity_collection + extract_params["collection"] = self._entity_collection extracted = None if isinstance(response, list): if response: - return [{'spec': obj.as_dict()['spec'], 'crd': obj} for obj in response] + return [{"spec": obj.as_dict()["spec"], "crd": obj} for obj in response] return None return extracted @@ -275,22 +309,39 @@ def _create_instance_trans(self, instance): return instance def __make_instance_crd(self, extracted: dict, klass): - instance = klass(client=self, spec=extracted['spec'], crd=extracted['crd']) if klass else extracted + instance = ( + klass(client=self, spec=extracted["spec"], crd=extracted["crd"]) + if klass + else extracted + ) return instance - def delete(self, entity_id: int = None, resource: 'DefaultResource' = None, **kwargs) -> bool: - """ Method deletes resource. """ - LOG.info(self._log_message("[DELETE] Delete CRD ", entity_id=entity_id, args=kwargs)) + def delete( + self, entity_id: int = None, resource: "DefaultResourceCRD" = None, **kwargs + ) -> bool: + """Method deletes resource.""" + LOG.info( + self._log_message("[DELETE] Delete CRD ", entity_id=entity_id, args=kwargs) + ) if self.is_crd_implemented(): resource.crd.delete() return True - return threescale_api.defaults.DefaultClient.delete(self, entity_id=entity_id, **kwargs) - - def update(self, entity_id=None, params: dict = None, - resource: 'DefaultResource' = None, - **kwargs) -> 'DefaultResource': - LOG.info(self._log_message("[UPDATE] Update CRD", body=params, - entity_id=entity_id, args=kwargs)) + return threescale_api.defaults.DefaultClient.delete( + self, entity_id=entity_id, **kwargs + ) + + def update( + self, + entity_id=None, + params: dict = None, + resource: "DefaultResourceCRD" = None, + **kwargs + ) -> "DefaultResourceCRD": + LOG.info( + self._log_message( + "[UPDATE] Update CRD", body=params, entity_id=entity_id, args=kwargs + ) + ) new_params = {} if resource: new_params = {**resource.entity} @@ -308,14 +359,14 @@ def update(self, entity_id=None, params: dict = None, else: resource.crd.refresh() new_crd = resource.crd.as_dict() - new_crd['spec'].update(new_spec) - if self.__class__.__name__ not in ['Tenants']: + new_crd["spec"].update(new_spec) + if self.__class__.__name__ not in ["Tenants"]: if self.threescale_client.ocp_provider_ref is None: - new_crd['spec'].pop('providerAccountRef', None) + new_crd["spec"].pop("providerAccountRef", None) else: - new_crd['spec']['providerAccountRef'] = { - 'name': self.threescale_client.ocp_provider_ref, - #'namespace': self.threescale_client.ocp_namespace + new_crd["spec"]["providerAccountRef"] = { + "name": self.threescale_client.ocp_provider_ref, + # 'namespace': self.threescale_client.ocp_namespace } resource.crd.model = ocp.Model(new_crd) result = resource.crd.replace() @@ -323,14 +374,15 @@ def update(self, entity_id=None, params: dict = None, if result.status(): LOG.error("[INSTANCE] Update CRD failed: %s", str(result)) raise Exception(str(result)) - #return self.read(resource.entity_id) + # return self.read(resource.entity_id) return resource - return threescale_api.defaults.DefaultClient.update(self, entity_id=entity_id, - params=params, **kwargs) + return threescale_api.defaults.DefaultClient.update( + self, entity_id=entity_id, params=params, **kwargs + ) def trans_item(self, key, value, obj): - """ Transform one attribute in CRD spec. """ + """Transform one attribute in CRD spec.""" return obj[key] def translate_to_crd(self, obj): @@ -357,10 +409,11 @@ def get_id_from_crd(self): """Returns object id extracted from CRD.""" return None + # flake8: noqa C901 def _extract_resource_crd(self, response, collection, klass) -> Union[List, Dict]: - extract_params = {'response': response, 'entity': self._entity_name} + extract_params = {"response": response, "entity": self._entity_name} if collection: - extract_params['collection'] = self._entity_collection + extract_params["collection"] = self._entity_collection extracted = None if isinstance(response, list): if self.is_crd_implemented(): @@ -370,66 +423,97 @@ def _extract_resource_crd(self, response, collection, klass) -> Union[List, Dict prod_dict = prod.as_dict() if prod_dict is None: prod_dict = {} - idp = int(prod_dict.get('status', {}).get(self.topmost_parent().client.ID_NAME, 0)) - if idp == parent_id: + idp = int( + prod_dict.get("status", {}).get( + self.topmost_parent().client.ID_NAME, 0 + ) + ) + if idp == parent_id: service_with_maps = prod break spec = {} if service_with_maps != {}: - spec = (DictQuery(service_with_maps.as_dict()).get(klass.GET_PATH or self.get_path())) or [] + spec = ( + DictQuery(service_with_maps.as_dict()).get( + klass.GET_PATH or self.get_path() + ) + ) or [] if isinstance(spec, list): - return [{'spec': obj, 'crd': service_with_maps} for obj in spec] - elif 'apicastHosted' not in spec.keys(): # dict branch, exception for Proxy + return [{"spec": obj, "crd": service_with_maps} for obj in spec] + elif ( + "apicastHosted" not in spec.keys() + ): # dict branch, exception for Proxy ret = [] for key, obj in spec.items(): obj[self.ID_NAME] = key - ret.append({'spec': obj, 'crd': service_with_maps}) + ret.append({"spec": obj, "crd": service_with_maps}) return ret else: - return [{'spec': spec, 'crd': service_with_maps}] + return [{"spec": spec, "crd": service_with_maps}] return extracted - def create(self, params: dict = None, **kwargs) -> 'DefaultResource': - LOG.info(self._log_message("[CREATE] Create CRD Nested ", body=params, args=kwargs)) + def create(self, params: dict = None, **kwargs) -> "DefaultResourceCRD": + LOG.info( + self._log_message("[CREATE] Create CRD Nested ", body=params, args=kwargs) + ) if self.is_crd_implemented(): spec = copy.deepcopy(self.SPEC) - name = params.get('name') or params.get('username') # Developer User exception + name = params.get("name") or params.get( + "username" + ) # Developer User exception if name is not None: name = self.normalize(name) - if params.get('name'): - params['name'] = name + if params.get("name"): + params["name"] = name else: - params['username'] = name + params["username"] = name else: - params['name'] = self.normalize(''.join(random.choice(string.ascii_letters) for _ in range(16))) - name = params['name'] + params["name"] = self.normalize( + "".join(random.choice(string.ascii_letters) for _ in range(16)) + ) + name = params["name"] self.before_create(params, spec) - spec['spec'].update(self.translate_to_crd(params)) + spec["spec"].update(self.translate_to_crd(params)) DefaultClientCRD.cleanup_spec(spec, self.KEYS, params) return self.in_create(self.get_list_from_spec(), params, spec) return threescale_api.defaults.DefaultClient.create(self, params, **kwargs) - def delete(self, entity_id: int = None, resource: 'DefaultResource' = None, **kwargs) -> bool: - """ Method deletes resource. """ - LOG.info(self._log_message("[DELETE] Delete CRD Nested ", entity_id=entity_id, args=kwargs)) + def delete( + self, entity_id: int = None, resource: "DefaultResourceCRD" = None, **kwargs + ) -> bool: + """Method deletes resource.""" + LOG.info( + self._log_message( + "[DELETE] Delete CRD Nested ", entity_id=entity_id, args=kwargs + ) + ) if self.is_crd_implemented(): spec = self.translate_to_crd(resource.entity) maps = self.remove_from_list(spec) self.update_list(maps) return True - return threescale_api.defaults.DefaultClient.delete(self, entity_id=entity_id, **kwargs) - - def update(self, entity_id=None, params: dict = None, - resource: 'DefaultResource' = None, - **kwargs) -> 'DefaultResource': - LOG.info(self._log_message("[UPDATE] Update CRD", body=params, - entity_id=entity_id, args=kwargs)) + return threescale_api.defaults.DefaultClient.delete( + self, entity_id=entity_id, **kwargs + ) + + def update( + self, + entity_id=None, + params: dict = None, + resource: "DefaultResourceCRD" = None, + **kwargs + ) -> "DefaultResourceCRD": + LOG.info( + self._log_message( + "[UPDATE] Update CRD", body=params, entity_id=entity_id, args=kwargs + ) + ) new_params = {} if resource: new_params = {**resource.entity} @@ -447,24 +531,25 @@ def update(self, entity_id=None, params: dict = None, # Policies # PricingRules # Proxies - #if self.__class__.__name__ == 'BackendUsages': + # if self.__class__.__name__ == 'BackendUsages': spec = self.before_update(new_params, resource) maps = self.remove_from_list(spec) - #par = self.parent + # par = self.parent maps = self.before_update_list(maps, new_params, spec, resource) par = self.update_list(maps) maps = self.get_list() return self.after_update_list(maps, par, new_params) - return threescale_api.defaults.DefaultClient.update(self, entity_id=entity_id, - params=params, **kwargs) + return threescale_api.defaults.DefaultClient.update( + self, entity_id=entity_id, params=params, **kwargs + ) def after_update_list(self, maps, par, new_params): - """ Returns updated list. """ - checked_keys = [key for key in new_params.keys() if key not in ['id']] + """Returns updated list.""" + checked_keys = [key for key in new_params.keys() if key not in ["id"]] for mapi in maps: if all([new_params[key] == mapi[key] for key in checked_keys]): return mapi @@ -473,6 +558,7 @@ def after_update_list(self, maps, par, new_params): class DefaultResourceCRD(threescale_api.defaults.DefaultResource): """Default CRD resource.""" + GET_PATH = None def __init__(self, *args, crd=None, **kwargs): @@ -482,7 +568,7 @@ def __init__(self, *args, crd=None, **kwargs): @property def crd(self): """CRD object property.""" - return self._crd or self.entity.get('crd', None) + return self._crd or self.entity.get("crd", None) @crd.setter def crd(self, value): @@ -490,7 +576,7 @@ def crd(self, value): @property def entity_id(self) -> int: - return self._entity_id or self._entity.get('id') or self.get_id_from_crd() + return self._entity_id or self._entity.get("id") or self.get_id_from_crd() @entity_id.setter def entity_id(self, value): @@ -501,7 +587,7 @@ def get_id_from_crd(self): counter = 5 while counter > 0: self.crd = self.crd.refresh() - status = self.crd.as_dict()['status'] + status = self.crd.as_dict()["status"] ret_id = status.get(self.client.ID_NAME, None) if ret_id: return ret_id @@ -520,6 +606,7 @@ def get_path(self): class DictQuery(dict): """Get value from nested dictionary.""" + def get(self, path, default=None): keys = path.split("/") val = None diff --git a/threescale_api_crd/resources.py b/threescale_api_crd/resources.py index 6efc6f7..518ce1a 100644 --- a/threescale_api_crd/resources.py +++ b/threescale_api_crd/resources.py @@ -15,7 +15,11 @@ import threescale_api import threescale_api.resources -from threescale_api_crd.defaults import DefaultClientCRD, DefaultResourceCRD, DefaultClientNestedCRD +from threescale_api_crd.defaults import ( + DefaultClientCRD, + DefaultResourceCRD, + DefaultClientNestedCRD, +) from threescale_api_crd import constants LOG = logging.getLogger(__name__) @@ -25,32 +29,48 @@ class Services(DefaultClientCRD, threescale_api.resources.Services): """ CRD client for Services. """ + CRD_IMPLEMENTED = True SPEC = constants.SPEC_SERVICE KEYS = constants.KEYS_SERVICE - SELECTOR = 'Product' - ID_NAME = 'productId' - - def __init__(self, parent, *args, entity_name='service', - entity_collection='services', **kwargs): - super().__init__(*args, parent=parent, entity_name=entity_name, entity_collection=entity_collection, **kwargs) + SELECTOR = "Product" + ID_NAME = "productId" + + def __init__( + self, + parent, + *args, + entity_name="service", + entity_collection="services", + **kwargs, + ): + super().__init__( + *args, + parent=parent, + entity_name=entity_name, + entity_collection=entity_collection, + **kwargs, + ) def before_create(self, params, spec): """Called before create.""" - if 'mapping_rules' in params.keys(): - spec['spec']['mappingRules'] = params['mapping_rules'] - if 'backend_version' in params.keys(): - key = list(spec['spec']['deployment'].keys())[0] - spec['spec']['deployment'][key]['authentication'] = constants.SERVICE_AUTH_DEFS[params['backend_version']] + if "mapping_rules" in params.keys(): + spec["spec"]["mappingRules"] = params["mapping_rules"] + if "backend_version" in params.keys(): + key = list(spec["spec"]["deployment"].keys())[0] + spec["spec"]["deployment"][key]["authentication"] = ( + constants.SERVICE_AUTH_DEFS[params["backend_version"]] + ) def before_update(self, new_params, resource): """Called before update.""" - #if 'backend_version' in new_params.keys(): + # if 'backend_version' in new_params.keys(): # key = list(resource.entity['deployment'].keys())[0] - # resource.entity['deployment'][key]['authentication'] = constants.SERVICE_AUTH_DEFS[new_params['backend_version']] + # resource.entity['deployment'][key]['authentication'] = \ + # constants.SERVICE_AUTH_DEFS[new_params['backend_version']] @property - def metrics(self) -> 'Metrics': + def metrics(self) -> "Metrics": """Returns metrics related to service/product.""" return Metrics(parent=self, instance_klass=Metric) @@ -59,13 +79,14 @@ class Proxies(DefaultClientNestedCRD, threescale_api.resources.Proxies): """ CRD client for Proxies. """ + CRD_IMPLEMENTED = True SPEC = constants.SPEC_PROXY KEYS = constants.KEYS_PROXY - SELECTOR = 'Product' - ID_NAME = 'name' + SELECTOR = "Product" + ID_NAME = "name" - def __init__(self, parent, *args, entity_name='proxy', **kwargs): + def __init__(self, parent, *args, entity_name="proxy", **kwargs): super().__init__(*args, parent=parent, entity_name=entity_name, **kwargs) def before_create(self, params, spec): @@ -75,61 +96,68 @@ def before_update(self, new_params, resource): """Called before update.""" if not resource: resource = self.list() - #new_params['id'] = self.parent['id'] - #if resource and 'id' in new_params: + # new_params['id'] = self.parent['id'] + # if resource and 'id' in new_params: # resource.entity_id = new_params['id'] return self.translate_to_crd(new_params) def get_list(self, typ=None): - """ Returns list of entities. """ + """Returns list of entities.""" return [] def get_list_from_spec(self): - """ Returns list from spec """ + """Returns list from spec""" return [] def before_update_list(self, maps, new_params, spec, resource): - """ Modify some details in data before updating the list """ + """Modify some details in data before updating the list""" obj = {} iter_obj = obj # service.proxy.oidc.update(params={"oidc_configuration": DEFAULT_FLOWS}) if not resource: resource = self.list() - if new_params.get('deployment_option', 'hosted') == 'hosted': - resource.spec_path[0] = 'apicastHosted' + if new_params.get("deployment_option", "hosted") == "hosted": + resource.spec_path[0] = "apicastHosted" else: - resource.spec_path[0] = 'apicastSelfManaged' + resource.spec_path[0] = "apicastSelfManaged" for path in resource.spec_path: if path not in iter_obj: iter_obj[path] = {} if path == resource.spec_path[-1]: iter_obj[path] = spec - if resource.oidc['oidc_configuration']: + if resource.oidc["oidc_configuration"]: auth_flow = self.translate_specific_to_crd( - resource.oidc['oidc_configuration'], - constants.KEYS_OIDC) - iter_obj[path]['authenticationFlow'] = auth_flow - if resource.responses or\ - (set(new_params.keys()).intersection(set(constants.KEYS_PROXY_RESPONSES))): + resource.oidc["oidc_configuration"], constants.KEYS_OIDC + ) + iter_obj[path]["authenticationFlow"] = auth_flow + if resource.responses or ( + set(new_params.keys()).intersection( + set(constants.KEYS_PROXY_RESPONSES) + ) + ): resource.responses = True - resps = self.translate_specific_to_crd(new_params, constants.KEYS_PROXY_RESPONSES) - iter_obj[path]['gatewayResponse'] = resps + resps = self.translate_specific_to_crd( + new_params, constants.KEYS_PROXY_RESPONSES + ) + iter_obj[path]["gatewayResponse"] = resps if resource.security: - sec = self.translate_specific_to_crd(new_params, constants.KEYS_PROXY_SECURITY) - iter_obj[path]['gatewayResponse'] = sec + sec = self.translate_specific_to_crd( + new_params, constants.KEYS_PROXY_SECURITY + ) + iter_obj[path]["gatewayResponse"] = sec iter_obj = iter_obj[path] return obj def update_list(self, maps): - """ Returns updated list. """ + """Returns updated list.""" self.parent.read() - return self.parent.update({'deployment': maps}) + return self.parent.update({"deployment": maps}) def after_update_list(self, maps, par, new_params): - """ Returns updated list. """ + """Returns updated list.""" return par.proxy.list() def topmost_parent(self): @@ -144,13 +172,13 @@ def list(self, **kwargs): def update(self, *args, **kwargs): oidc = kwargs.get("oidc", None) - kwargs['resource'] = self.list() - kwargs['resource'].oidc['oidc_configuration'] = oidc + kwargs["resource"] = self.list() + kwargs["resource"].oidc["oidc_configuration"] = oidc return DefaultClientNestedCRD.update(self, *args, **kwargs) def delete(self): """This functions is not implemented for Proxies.""" - raise threescale_api.ThreeScaleApiError("Delete not implemented for Proxies") + raise threescale_api.errors.ThreeScaleApiError("Delete not implemented for Proxies") def deploy(self): """ @@ -159,15 +187,15 @@ def deploy(self): return self.list().deploy() @property - def oidc(self) -> 'OIDCConfigs': + def oidc(self) -> "OIDCConfigs": return OIDCConfigs(self) def translate_specific_to_crd(self, obj, keys): - """ Translate Proxy attributes to CRD. """ + """Translate Proxy attributes to CRD.""" map_ret = {} trans_item = lambda key, value, obj: obj[key] for key, value in keys.items(): - LOG.debug('%s, %s, %s, %s', key, value, obj, type(obj)) + LOG.debug("%s, %s, %s, %s", key, value, obj, type(obj)) if obj.get(key, None) is not None: set_value = trans_item(key, value, obj) if set_value is not None: @@ -186,27 +214,40 @@ class Backends(DefaultClientCRD, threescale_api.resources.Backends): """ CRD client for Backends. """ + CRD_IMPLEMENTED = True SPEC = constants.SPEC_BACKEND KEYS = constants.KEYS_BACKEND - SELECTOR = 'Backend' - ID_NAME = 'backendId' - - def __init__(self, parent, *args, entity_name='backend_api', - entity_collection='backend_apis', **kwargs): - super().__init__(*args, parent=parent, entity_name=entity_name, entity_collection=entity_collection, **kwargs) + SELECTOR = "Backend" + ID_NAME = "backendId" + + def __init__( + self, + parent, + *args, + entity_name="backend_api", + entity_collection="backend_apis", + **kwargs, + ): + super().__init__( + *args, + parent=parent, + entity_name=entity_name, + entity_collection=entity_collection, + **kwargs, + ) def before_create(self, params, spec): """Called before create.""" - if 'mapping_rules' in params.keys(): - spec['mappingRules'] = params['mapping_rules'] + if "mapping_rules" in params.keys(): + spec["mappingRules"] = params["mapping_rules"] def before_update(self, new_params, resource): """Called before update.""" @property - def metrics(self) -> 'BackendMetrics': - """ Returns metrics related to this backend. """ + def metrics(self) -> "BackendMetrics": + """Returns metrics related to this backend.""" return BackendMetrics(parent=self, instance_klass=BackendMetric) @@ -214,82 +255,100 @@ class MappingRules(DefaultClientNestedCRD, threescale_api.resources.MappingRules """ CRD client for MappingRules. """ + CRD_IMPLEMENTED = True SPEC = constants.SPEC_MAPPING_RULE KEYS = constants.KEYS_MAPPING_RULE - SELECTOR = 'Product' - ID_NAME = 'name' - - def __init__(self, parent, *args, entity_name='mapping_rule', - entity_collection='mapping_rules', **kwargs): - super().__init__(*args, parent=parent, entity_name=entity_name, entity_collection=entity_collection, **kwargs) + SELECTOR = "Product" + ID_NAME = "name" + + def __init__( + self, + parent, + *args, + entity_name="mapping_rule", + entity_collection="mapping_rules", + **kwargs, + ): + super().__init__( + *args, + parent=parent, + entity_name=entity_name, + entity_collection=entity_collection, + **kwargs, + ) def before_create(self, params, spec): """Called before create.""" - params.pop('name', None) - if 'last' in params.keys() and isinstance(params['last'], str): - params.update({'last': (params['last'] == "true" or params['last'] == "True")}) + params.pop("name", None) + if "last" in params.keys() and isinstance(params["last"], str): + params.update( + {"last": (params["last"] == "true" or params["last"] == "True")} + ) def in_create(self, maps, params, spec): """Do steps to create new instance""" - if 'metric_id' not in params.keys(): - spec['spec']['metricMethodRef'] = 'hits' - elif isinstance(params['metric_id'], int): - met = self.parent.metrics.read(int(params['metric_id'])) + if "metric_id" not in params.keys(): + spec["spec"]["metricMethodRef"] = "hits" + elif isinstance(params["metric_id"], int): + met = self.parent.metrics.read(int(params["metric_id"])) # exception because of backend mapping rules - name = met.entity.get('system_name', met.entity.get('name')) - if '.' in met['system_name']: - spec['spec']['metricMethodRef'] = name.split('.')[0] - spec['spec']['metricMethodRef'] = name + name = met.entity.get("system_name", met.entity.get("name")) + if "." in met["system_name"]: + spec["spec"]["metricMethodRef"] = name.split(".")[0] + spec["spec"]["metricMethodRef"] = name else: # metric id is tuple - spec['spec']['metricMethodRef'] = params['metric_id'][0] - params.pop('name', None) + spec["spec"]["metricMethodRef"] = params["metric_id"][0] + params.pop("name", None) MappingRules.insert_into_position(maps, params, spec) self.parent.read() - self.parent.update({'mapping_rules': maps}) + self.parent.update({"mapping_rules": maps}) maps = self.list() return MappingRules.get_from_position(maps, params) def get_list(self, typ=None): - """ Returns list of entities. """ + """Returns list of entities.""" return self.parent.mapping_rules.list() def get_list_from_spec(self): - """ Returns list from spec """ - return self.parent.crd.as_dict()['spec'].get('mappingRules', []) + """Returns list from spec""" + return self.parent.crd.as_dict()["spec"].get("mappingRules", []) def before_update(self, new_params, resource): """Called before update.""" - new_params.pop('name', None) - new_params['id'] = (new_params['http_method'], new_params['pattern']) - if resource and 'id' in new_params: - resource.entity_id = new_params['id'] + new_params.pop("name", None) + new_params["id"] = (new_params["http_method"], new_params["pattern"]) + if resource and "id" in new_params: + resource.entity_id = new_params["id"] spec = self.translate_to_crd(new_params) - if 'metric_id' not in new_params.keys(): - spec['metricMethodRef'] = 'hits' + if "metric_id" not in new_params.keys(): + spec["metricMethodRef"] = "hits" return spec def before_update_list(self, maps, new_params, spec, resource): - """ Modify some details in data before updating the list """ + """Modify some details in data before updating the list""" MappingRules.insert_into_position(maps, new_params, spec) return maps def update_list(self, maps): - """ Returns updated list. """ + """Returns updated list.""" self.parent.read() - return self.parent.update({'mapping_rules': maps}) + return self.parent.update({"mapping_rules": maps}) def after_update_list(self, maps, par, new_params): - """ Returns updated list. """ + """Returns updated list.""" return MappingRules.get_from_position(maps, new_params) def remove_from_list(self, spec): - """ Returns list without item specified by 'spec'. """ + """Returns list without item specified by 'spec'.""" maps = [] for mapi in self.get_list(): map_ret = self.translate_to_crd(mapi.entity) - if not (map_ret['httpMethod'] == spec['httpMethod'] and map_ret['pattern'] == spec['pattern']): + if not ( + map_ret["httpMethod"] == spec["httpMethod"] + and map_ret["pattern"] == spec["pattern"] + ): maps.append(map_ret) return maps @@ -301,37 +360,37 @@ def topmost_parent(self): return self.parent def trans_item(self, key, value, obj): - """ Translate entity to CRD. """ - if key == 'metric_id': + """Translate entity to CRD.""" + if key == "metric_id": if isinstance(obj[key], tuple): return obj[key][0] met = self.parent.metrics.read(int(obj[key])) - return met['system_name'].split('.')[0] + return met["system_name"].split(".")[0] else: return obj[key] @staticmethod def insert_into_position(maps, params, spec): - """ Inserts entity into right position in list. """ - if 'spec' in spec: - spec = spec['spec'] - if 'position' in params.keys(): - maps.insert(int(params.pop('position', 1)) - 1, spec) - elif 'last' in params.keys(): - if isinstance(params['last'], str): - spec['last'] = True - elif isinstance(params['last'], bool): - spec['last'] = params['last'] + """Inserts entity into right position in list.""" + if "spec" in spec: + spec = spec["spec"] + if "position" in params.keys(): + maps.insert(int(params.pop("position", 1)) - 1, spec) + elif "last" in params.keys(): + if isinstance(params["last"], str): + spec["last"] = True + elif isinstance(params["last"], bool): + spec["last"] = params["last"] maps.append(spec) else: maps.append(spec) @staticmethod def get_from_position(maps, params): - """ Get entity from position in list of entitites.""" - if 'position' in params.keys(): - return maps[int(params['position']) - 1] - if 'last' in params.keys(): + """Get entity from position in list of entitites.""" + if "position" in params.keys(): + return maps[int(params["position"]) - 1] + if "last" in params.keys(): return maps[-1] for mapi in maps: if all([params[key] == mapi[key] for key in params.keys()]): @@ -343,11 +402,24 @@ class BackendMappingRules(MappingRules, threescale_api.resources.BackendMappingR """ CRD client for Backend MappingRules. """ - SELECTOR = 'Backend' - def __init__(self, parent, *args, entity_name='mapping_rule', - entity_collection='mapping_rules', **kwargs): - super().__init__(*args, parent=parent, entity_name=entity_name, entity_collection=entity_collection, **kwargs) + SELECTOR = "Backend" + + def __init__( + self, + parent, + *args, + entity_name="mapping_rule", + entity_collection="mapping_rules", + **kwargs, + ): + super().__init__( + *args, + parent=parent, + entity_name=entity_name, + entity_collection=entity_collection, + **kwargs, + ) def before_create(self, params, spec): """Called before create.""" @@ -357,137 +429,193 @@ class ActiveDocs(DefaultClientCRD, threescale_api.resources.ActiveDocs): """ CRD client for ActiveDocs. """ + CRD_IMPLEMENTED = True SPEC = constants.SPEC_ACTIVE_DOC KEYS = constants.KEYS_ACTIVE_DOC - SELECTOR = 'ActiveDoc' - ID_NAME = 'activeDocId' - - def __init__(self, parent, *args, entity_name='api_doc', - entity_collection='api_docs', **kwargs): - super().__init__(*args, parent=parent, entity_name=entity_name, entity_collection=entity_collection, **kwargs) + SELECTOR = "ActiveDoc" + ID_NAME = "activeDocId" + + def __init__( + self, + parent, + *args, + entity_name="api_doc", + entity_collection="api_docs", + **kwargs, + ): + super().__init__( + *args, + parent=parent, + entity_name=entity_name, + entity_collection=entity_collection, + **kwargs, + ) def before_create(self, params, spec): """Called before create.""" - if 'service_id' in params.keys(): - ide = int(params.pop('service_id')) + if "service_id" in params.keys(): + ide = int(params.pop("service_id")) sys_name = Service.id_to_system_name.get(ide, None) if not sys_name: - sys_name = self.parent.services.read(ide)['system_name'] - spec['spec']['productSystemName'] = sys_name - if 'body' in params.keys(): - params['secret-name'] = params['name'] + 'secret' - OpenApiRef.create_secret_if_needed(params, self.threescale_client.ocp_namespace) - spec['spec']['activeDocOpenAPIRef'] = {} - spec['spec']['activeDocOpenAPIRef']['secretRef'] = {} - spec['spec']['activeDocOpenAPIRef']['secretRef']['name'] = params['secret-name'] + sys_name = self.parent.services.read(ide)["system_name"] + spec["spec"]["productSystemName"] = sys_name + if "body" in params.keys(): + params["secret-name"] = params["name"] + "secret" + OpenApiRef.create_secret_if_needed( + params, self.threescale_client.ocp_namespace + ) + spec["spec"]["activeDocOpenAPIRef"] = {} + spec["spec"]["activeDocOpenAPIRef"]["secretRef"] = {} + spec["spec"]["activeDocOpenAPIRef"]["secretRef"]["name"] = params[ + "secret-name" + ] def before_update(self, new_params, resource): """Called before update.""" - if 'service_id' in new_params.keys(): - ide = int(new_params.pop('service_id')) + if "service_id" in new_params.keys(): + ide = int(new_params.pop("service_id")) sys_name = Service.id_to_system_name.get(ide, None) if not sys_name: - sys_name = self.parent.services.read(ide)['system_name'] - new_params[self.KEYS['service_id']] = sys_name - if 'body' in new_params.keys(): - if 'secret-name' not in new_params: - new_params['secret-name'] = new_params['name'] + 'secret' - OpenApiRef.create_secret_if_needed(new_params, self.threescale_client.ocp_namespace) - new_params['activeDocOpenAPIRef'] = {} - new_params['activeDocOpenAPIRef']['secretRef'] = {} - new_params['activeDocOpenAPIRef']['secretRef']['name'] = new_params['secret-name'] + sys_name = self.parent.services.read(ide)["system_name"] + new_params[self.KEYS["service_id"]] = sys_name + if "body" in new_params.keys(): + if "secret-name" not in new_params: + new_params["secret-name"] = new_params["name"] + "secret" + OpenApiRef.create_secret_if_needed( + new_params, self.threescale_client.ocp_namespace + ) + new_params["activeDocOpenAPIRef"] = {} + new_params["activeDocOpenAPIRef"]["secretRef"] = {} + new_params["activeDocOpenAPIRef"]["secretRef"]["name"] = new_params[ + "secret-name" + ] class PoliciesRegistry(DefaultClientCRD, threescale_api.resources.PoliciesRegistry): """ CRD client for PoliciesRegistry. """ + CRD_IMPLEMENTED = True SPEC = constants.SPEC_POLICY_REG KEYS = constants.KEYS_POLICY_REG - SELECTOR = 'CustomPolicyDefinition' - ID_NAME = 'policyID' - - def __init__(self, parent, *args, entity_name='policy', - entity_collection='policies', **kwargs): - super().__init__(*args, parent=parent, entity_name=entity_name, entity_collection=entity_collection, **kwargs) + SELECTOR = "CustomPolicyDefinition" + ID_NAME = "policyID" + + def __init__( + self, + parent, + *args, + entity_name="policy", + entity_collection="policies", + **kwargs, + ): + super().__init__( + *args, + parent=parent, + entity_name=entity_name, + entity_collection=entity_collection, + **kwargs, + ) def before_create(self, params, spec): """Called before create.""" - if 'description' in params['schema'] and isinstance(params['schema']['description'], str): - params['schema']['description'] = params['schema']['description'].strip() - if os.linesep in params['schema']['description']: - params['schema']['description'] = params['schema']['description'].split(os.linesep) + if "description" in params["schema"] and isinstance( + params["schema"]["description"], str + ): + params["schema"]["description"] = params["schema"]["description"].strip() + if os.linesep in params["schema"]["description"]: + params["schema"]["description"] = params["schema"]["description"].split( + os.linesep + ) else: - params['schema']['description'] = [params['schema']['description']] + params["schema"]["description"] = [params["schema"]["description"]] def before_update(self, new_params, resource): """Called before update.""" - if 'description' in new_params['schema'] and isinstance(new_params['schema']['description'], str): - new_params['schema']['description'] = new_params['schema']['description'].strip() - if os.linesep in new_params['schema']['description']: - new_params['schema']['description'] = new_params['schema']['description'].split(os.linesep) + if "description" in new_params["schema"] and isinstance( + new_params["schema"]["description"], str + ): + new_params["schema"]["description"] = new_params["schema"][ + "description" + ].strip() + if os.linesep in new_params["schema"]["description"]: + new_params["schema"]["description"] = new_params["schema"][ + "description" + ].split(os.linesep) else: - new_params['schema']['description'] = [new_params['schema']['description']] + new_params["schema"]["description"] = [ + new_params["schema"]["description"] + ] class Metrics(DefaultClientNestedCRD, threescale_api.resources.Metrics): """ CRD client for Metrics. """ + CRD_IMPLEMENTED = True SPEC = constants.SPEC_METRIC KEYS = constants.KEYS_METRIC - SELECTOR = 'Product' - ID_NAME = 'system_name' - - def __init__(self, parent, *args, entity_name='metric', entity_collection='metrics', - **kwargs): - super().__init__(*args, parent=parent, entity_name=entity_name, entity_collection=entity_collection, **kwargs) + SELECTOR = "Product" + ID_NAME = "system_name" + + def __init__( + self, parent, *args, entity_name="metric", entity_collection="metrics", **kwargs + ): + super().__init__( + *args, + parent=parent, + entity_name=entity_name, + entity_collection=entity_collection, + **kwargs, + ) def before_create(self, params, spec): """Called before create.""" def before_update(self, new_params, resource): """Called before update.""" - new_params['id'] = (new_params[Metrics.ID_NAME], new_params['unit']) - if resource and 'id' in new_params: - resource.entity_id = new_params['id'] + new_params["id"] = (new_params[Metrics.ID_NAME], new_params["unit"]) + if resource and "id" in new_params: + resource.entity_id = new_params["id"] return self.translate_to_crd(new_params) def get_list(self, typ=None): - """ Returns list of entities. """ + """Returns list of entities.""" return self.parent.metrics.list() def in_create(self, maps, params, spec): """Do steps to create new instance""" - name = params.pop(Metrics.ID_NAME, params.pop('name', 'hits')) # name is deprecated - maps[name] = spec['spec'] + name = params.pop( + Metrics.ID_NAME, params.pop("name", "hits") + ) # name is deprecated + maps[name] = spec["spec"] self.parent.read() - self.parent.update({'metrics': maps}) + self.parent.update({"metrics": maps}) for mapi in self.get_list(): if all([params[key] == mapi[key] for key in params.keys()]): return mapi return None def get_list_from_spec(self): - """ Returns list from spec """ - return self.parent.crd.as_dict()['spec'].get('metrics', {}) + """Returns list from spec""" + return self.parent.crd.as_dict()["spec"].get("metrics", {}) def before_update_list(self, maps, new_params, spec, resource): - """ Modify some details in data before updating the list """ + """Modify some details in data before updating the list""" name = new_params.get(Metrics.ID_NAME) maps[name] = spec return maps def update_list(self, maps): - """ Returns updated list. """ + """Returns updated list.""" self.parent.read() - return self.parent.update({'metrics': maps}) + return self.parent.update({"metrics": maps}) def remove_from_list(self, spec): - """ Returns list without item specified by 'spec'. """ + """Returns list without item specified by 'spec'.""" maps = {} for mapi in self.get_list(): map_ret = self.translate_to_crd(mapi.entity) @@ -504,8 +632,8 @@ def topmost_parent(self): return self.parent def trans_item(self, key, value, obj): - """ Translate entity to CRD. """ - if key != 'system_name': + """Translate entity to CRD.""" + if key != "system_name": return obj[key] return None @@ -514,26 +642,47 @@ class BackendMetrics(Metrics, threescale_api.resources.BackendMetrics): """ CRD client for Backend Metrics. """ - SELECTOR = 'Backend' - def __init__(self, parent, *args, entity_name='metric', - entity_collection='metrics', **kwargs): - super().__init__(*args, parent=parent, entity_name=entity_name, entity_collection=entity_collection, **kwargs) + SELECTOR = "Backend" + + def __init__( + self, parent, *args, entity_name="metric", entity_collection="metrics", **kwargs + ): + super().__init__( + *args, + parent=parent, + entity_name=entity_name, + entity_collection=entity_collection, + **kwargs, + ) class BackendUsages(DefaultClientNestedCRD, threescale_api.resources.BackendUsages): """ CRD client for BackendUsages. """ + CRD_IMPLEMENTED = True SPEC = constants.SPEC_BACKEND_USAGE KEYS = constants.KEYS_BACKEND_USAGE - SELECTOR = 'Product' - ID_NAME = 'name' - - def __init__(self, parent, *args, entity_name='backend_usage', - entity_collection='backend_usages', **kwargs): - super().__init__(*args, parent=parent, entity_name=entity_name, entity_collection=entity_collection, **kwargs) + SELECTOR = "Product" + ID_NAME = "name" + + def __init__( + self, + parent, + *args, + entity_name="backend_usage", + entity_collection="backend_usages", + **kwargs, + ): + super().__init__( + *args, + parent=parent, + entity_name=entity_name, + entity_collection=entity_collection, + **kwargs, + ) def before_create(self, params, spec): """Called before create.""" @@ -542,55 +691,58 @@ def before_create(self, params, spec): def before_update(self, new_params, resource): """Called before update.""" - new_params['id'] =\ - (new_params['path'], new_params['backend_id'], new_params['service_id']) - if resource and 'id' in new_params: - resource.entity_id = new_params['id'] + new_params["id"] = ( + new_params["path"], + new_params["backend_id"], + new_params["service_id"], + ) + if resource and "id" in new_params: + resource.entity_id = new_params["id"] return self.translate_to_crd(new_params) def get_list(self, typ=None): - """ Returns list of entities. """ + """Returns list of entities.""" return self.parent.backend_usages.list() def in_create(self, maps, params, spec): """Do steps to create new instance""" - backend_id = spec['spec'].pop('backend_id') + backend_id = spec["spec"].pop("backend_id") back = self.parent.parent.backends.read(int(backend_id)) - maps[back[BackendUsages.ID_NAME]] = spec['spec'] + maps[back[BackendUsages.ID_NAME]] = spec["spec"] self.parent.read() - self.parent.update({'backend_usages': maps}) - params.pop('name', None) + self.parent.update({"backend_usages": maps}) + params.pop("name", None) for mapi in self.get_list(): if all([params[key] == mapi[key] for key in params.keys()]): return mapi return None def get_list_from_spec(self): - """ Returns list from spec """ - return self.parent.crd.as_dict()['spec'].get('backendUsages', {}) + """Returns list from spec""" + return self.parent.crd.as_dict()["spec"].get("backendUsages", {}) def before_update_list(self, maps, new_params, spec, resource): - """ Modify some details in data before updating the list """ - backend_id = spec.pop('backend_id') - spec.pop('service_id') + """Modify some details in data before updating the list""" + backend_id = spec.pop("backend_id") + spec.pop("service_id") back = self.threescale_client.backends.read(int(backend_id)) maps[back[BackendUsages.ID_NAME]] = spec return maps def update_list(self, maps): - """ Returns updated list. """ + """Returns updated list.""" self.parent.read() - return self.parent.update({'backend_usages': maps}) + return self.parent.update({"backend_usages": maps}) def remove_from_list(self, spec): - """ Returns list without item specified by 'spec'. """ + """Returns list without item specified by 'spec'.""" maps = {} mapis = self.get_list() for mapi in mapis: map_ret = self.translate_to_crd(mapi.entity) if map_ret != spec: - backend_id = mapi['backend_id'] + backend_id = mapi["backend_id"] back = self.parent.parent.backends.read(int(backend_id)) maps[back[BackendUsages.ID_NAME]] = map_ret return maps @@ -612,27 +764,40 @@ class Policies(DefaultClientNestedCRD, threescale_api.resources.Policies): """ CRD client for Policies. """ + CRD_IMPLEMENTED = True SPEC = constants.SPEC_POLICY KEYS = constants.KEYS_POLICY - SELECTOR = 'Product' - ID_NAME = 'name' - - def __init__(self, parent, *args, entity_name='policy', - entity_collection='policies', **kwargs): - super().__init__(*args, parent=parent, entity_name=entity_name, entity_collection=entity_collection, **kwargs) + SELECTOR = "Product" + ID_NAME = "name" + + def __init__( + self, + parent, + *args, + entity_name="policy", + entity_collection="policies", + **kwargs, + ): + super().__init__( + *args, + parent=parent, + entity_name=entity_name, + entity_collection=entity_collection, + **kwargs, + ) def before_create(self, params, spec): """Called before create.""" def before_update(self, new_params, resource): """Called before update.""" - new_params = new_params['policies_config'] + new_params = new_params["policies_config"] # this should be done because list of policies is already # constructed list and not just one item spec = [] for item in new_params: - if hasattr(item, 'entity'): + if hasattr(item, "entity"): item = item.entity if isinstance(item, tuple) or isinstance(item, list): for it in item: @@ -640,33 +805,33 @@ def before_update(self, new_params, resource): elif item is not None: spec.append(self.translate_to_crd(item)) - if resource and 'id' in new_params: - resource.entity_id = new_params['id'] + if resource and "id" in new_params: + resource.entity_id = new_params["id"] return spec def get_list(self, typ=None): - """ Returns list of entities. """ + """Returns list of entities.""" return self.parent.proxy.list().policies.list() def get_list_from_spec(self): - """ Returns list from spec """ - return self.parent.crd.as_dict()['spec'].get('policies', {}) + """Returns list from spec""" + return self.parent.crd.as_dict()["spec"].get("policies", {}) def before_update_list(self, maps, new_params, spec, resource): - """ Modify some details in data before updating the list """ + """Modify some details in data before updating the list""" return spec def update_list(self, maps): - """ Returns updated list. """ + """Returns updated list.""" self.parent.read() - return self.parent.update({'policies': maps}) + return self.parent.update({"policies": maps}) def after_update_list(self, maps, par, new_params): - """ Returns updated list. """ + """Returns updated list.""" return maps def remove_from_list(self, spec): - """ Returns list without item specified by 'spec'. """ + """Returns list without item specified by 'spec'.""" return [] def topmost_parent(self): @@ -679,87 +844,112 @@ def topmost_parent(self): def append(self, *policies): policies = policies if policies else [] pol_list = self.list() - pol_list['policies_config'].extend(policies) + pol_list["policies_config"].extend(policies) return self.update(params=pol_list) def insert(self, index: int, *policies): - pol_list = self.list()['policies_config'] - for (i, policy) in enumerate(policies): + pol_list = self.list()["policies_config"] + for i, policy in enumerate(policies): pol_list.insert(index + i, policy) - return self.update(params={'policies_config': pol_list}) + return self.update(params={"policies_config": pol_list}) def _create_instance_trans(self, instance): - return {'policies_config': instance} + return {"policies_config": instance} -class ApplicationPlans(DefaultClientNestedCRD, threescale_api.resources.ApplicationPlans): +class ApplicationPlans( + DefaultClientNestedCRD, threescale_api.resources.ApplicationPlans +): """ CRD client for ApplicationPlans. """ + CRD_IMPLEMENTED = True SPEC = constants.SPEC_APP_PLANS KEYS = constants.KEYS_APP_PLANS - SELECTOR = 'Product' - ID_NAME = 'system_name' - - def __init__(self, parent, *args, entity_name='application_plan', entity_collection='plans', - **kwargs): - super().__init__(*args, parent=parent, entity_name=entity_name, entity_collection=entity_collection, **kwargs) + SELECTOR = "Product" + ID_NAME = "system_name" + + def __init__( + self, + parent, + *args, + entity_name="application_plan", + entity_collection="plans", + **kwargs, + ): + super().__init__( + *args, + parent=parent, + entity_name=entity_name, + entity_collection=entity_collection, + **kwargs, + ) def before_create(self, params, spec): """Called before create.""" - spec['spec']['published'] = (params.pop('state_event', 'publish') == 'publish') - params.update({'setup_fee': '{:.2f}'.format(float(params.get('setup_fee', '0')))}) + spec["spec"]["published"] = params.pop("state_event", "publish") == "publish" + params.update( + {"setup_fee": "{:.2f}".format(float(params.get("setup_fee", "0")))} + ) def before_update(self, new_params, resource): """Called before update.""" - new_params.update({'state_event': new_params.get('state_event', 'publish') == 'publish'}) - new_params.update({'setup_fee': '{:.2f}'.format(float(new_params.get('setup_fee', '0')))}) - new_params['id'] = new_params['system_name'] - if resource and 'id' in new_params: - resource.entity_id = new_params['id'] + new_params.update( + {"state_event": new_params.get("state_event", "publish") == "publish"} + ) + new_params.update( + {"setup_fee": "{:.2f}".format(float(new_params.get("setup_fee", "0")))} + ) + new_params["id"] = new_params["system_name"] + if resource and "id" in new_params: + resource.entity_id = new_params["id"] return self.translate_to_crd(new_params) def get_list(self, typ=None): - """ Returns list of entities. """ + """Returns list of entities.""" return self.parent.app_plans.list() def in_create(self, maps, params, spec): """Do steps to create new instance""" - if ApplicationPlans.ID_NAME in spec['spec']: - params[ApplicationPlans.ID_NAME] = DefaultClientCRD.normalize(spec['spec'].pop(ApplicationPlans.ID_NAME)) + if ApplicationPlans.ID_NAME in spec["spec"]: + params[ApplicationPlans.ID_NAME] = DefaultClientCRD.normalize( + spec["spec"].pop(ApplicationPlans.ID_NAME) + ) else: - params[ApplicationPlans.ID_NAME] = DefaultClientCRD.normalize(spec['spec'].pop('name')) - maps[params[ApplicationPlans.ID_NAME]] = spec['spec'] + params[ApplicationPlans.ID_NAME] = DefaultClientCRD.normalize( + spec["spec"].pop("name") + ) + maps[params[ApplicationPlans.ID_NAME]] = spec["spec"] self.parent.read() - self.parent.update({'application_plans': maps}) + self.parent.update({"application_plans": maps}) for mapi in self.get_list(): if all([params[key] == mapi[key] for key in params.keys()]): return mapi return None def get_list_from_spec(self): - """ Returns list from spec """ - return self.parent.crd.as_dict()['spec'].get('applicationPlans', {}) + """Returns list from spec""" + return self.parent.crd.as_dict()["spec"].get("applicationPlans", {}) def before_update_list(self, maps, new_params, spec, resource): - """ Modify some details in data before updating the list """ - maps[new_params['id']] = spec + """Modify some details in data before updating the list""" + maps[new_params["id"]] = spec return maps def update_list(self, maps): - """ Returns updated list. """ + """Returns updated list.""" self.parent.read() - return self.parent.update({'application_plans': maps}) + return self.parent.update({"application_plans": maps}) def remove_from_list(self, spec): - """ Returns list without item specified by 'spec'. """ + """Returns list without item specified by 'spec'.""" maps = {} nspec = spec.copy() - nspec.pop('limits', None) + nspec.pop("limits", None) for mapi in self.get_list(): map_ret = self.translate_to_crd(mapi.entity) - map_ret.pop('limits', None) + map_ret.pop("limits", None) if map_ret != nspec: name = mapi[ApplicationPlans.ID_NAME] maps[name] = map_ret @@ -773,38 +963,51 @@ def topmost_parent(self): return self.parent def trans_item(self, key, value, obj): - """ Translate entity to CRD. """ - if key != 'system_name': + """Translate entity to CRD.""" + if key != "system_name": return obj[key] return None @property def plans_url(self) -> str: - return self.threescale_client.admin_api_url + '/application_plans' + return self.threescale_client.admin_api_url + "/application_plans" class Accounts(DefaultClientCRD, threescale_api.resources.Accounts): """ CRD client for Accounts. """ + CRD_IMPLEMENTED = True SPEC = constants.SPEC_ACCOUNT KEYS = constants.KEYS_ACCOUNT - SELECTOR = 'DeveloperAccount' - ID_NAME = 'accountID' - - def __init__(self, parent, *args, entity_name='account', - entity_collection='accounts', **kwargs): - super().__init__(*args, parent=parent, entity_name=entity_name, entity_collection=entity_collection, **kwargs) + SELECTOR = "DeveloperAccount" + ID_NAME = "accountID" + + def __init__( + self, + parent, + *args, + entity_name="account", + entity_collection="accounts", + **kwargs, + ): + super().__init__( + *args, + parent=parent, + entity_name=entity_name, + entity_collection=entity_collection, + **kwargs, + ) def before_create(self, params, spec): """Called before create.""" - if 'username' in params: + if "username" in params: pars = params.copy() - pars['account_name'] = pars['name'] - pars['name'] = secrets.token_urlsafe(8) + pars["account_name"] = pars["name"] + pars["name"] = secrets.token_urlsafe(8) # first user should be admin - pars['role'] = 'admin' + pars["role"] = "admin" self.parent.threescale_client.account_users.create(params=pars) def before_update(self, new_params, resource): @@ -815,97 +1018,144 @@ class AccountUsers(DefaultClientCRD, threescale_api.resources.AccountUsers): """ CRD client for AccountUsers. """ + CRD_IMPLEMENTED = True SPEC = constants.SPEC_ACCOUNT_USER KEYS = constants.KEYS_ACCOUNT_USER - SELECTOR = 'DeveloperUser' - ID_NAME = 'developerUserID' - - def __init__(self, parent, *args, entity_name='user', - entity_collection='users', **kwargs): - super().__init__(*args, parent=parent, entity_name=entity_name, entity_collection=entity_collection, **kwargs) + SELECTOR = "DeveloperUser" + ID_NAME = "developerUserID" + + def __init__( + self, parent, *args, entity_name="user", entity_collection="users", **kwargs + ): + super().__init__( + *args, + parent=parent, + entity_name=entity_name, + entity_collection=entity_collection, + **kwargs, + ) def before_create(self, params, spec): """Called before create.""" - password = params.get('password', secrets.token_urlsafe(8)) - password_name = AccountUser.create_password_secret(password, self.threescale_client.ocp_namespace) - spec['spec']['passwordCredentialsRef']['name'] = password_name - spec['spec']['developerAccountRef']['name'] = params['account_name'] + password = params.get("password", secrets.token_urlsafe(8)) + password_name = AccountUser.create_password_secret( + password, self.threescale_client.ocp_namespace + ) + spec["spec"]["passwordCredentialsRef"]["name"] = password_name + spec["spec"]["developerAccountRef"]["name"] = params["account_name"] def before_update(self, new_params, resource): """Called before update.""" def _is_ready(self, obj): - """ Is object ready? """ - if not ('status' in obj.model and 'conditions' in obj.model.status): + """Is object ready?""" + if not ("status" in obj.model and "conditions" in obj.model.status): return False - state = {'Failed': True, 'Invalid': True, 'Orphan': False, 'Ready': False} - for sta in obj.as_dict()['status']['conditions']: - state[sta['type']] = (sta['status'] == 'True') + state = {"Failed": True, "Invalid": True, "Orphan": False, "Ready": False} + for sta in obj.as_dict()["status"]["conditions"]: + state[sta["type"]] = sta["status"] == "True" - return not state['Failed'] and\ - not state['Invalid'] and\ - state['Orphan'] != state['Ready'] + return ( + not state["Failed"] + and not state["Invalid"] + and state["Orphan"] != state["Ready"] + ) class OpenApis(DefaultClientCRD, threescale_api.defaults.DefaultClient): """ CRD client for OpenApis. This class is only implemented in CRD and not in 3scale API. """ + CRD_IMPLEMENTED = True SPEC = constants.SPEC_OPEN_API KEYS = constants.KEYS_OPEN_API - SELECTOR = 'OpenAPI' - ID_NAME = 'productResourceName' - - def __init__(self, parent, *args, entity_name='openapi', - entity_collection='openapis', **kwargs): - super().__init__(*args, parent=parent, entity_name=entity_name, entity_collection=entity_collection, **kwargs) + SELECTOR = "OpenAPI" + ID_NAME = "productResourceName" + + def __init__( + self, + parent, + *args, + entity_name="openapi", + entity_collection="openapis", + **kwargs, + ): + super().__init__( + *args, + parent=parent, + entity_name=entity_name, + entity_collection=entity_collection, + **kwargs, + ) def before_create(self, params, spec): """Called before create.""" - if 'url' in params.keys(): - spec['spec']['openapiRef'] = {} - spec['spec']['openapiRef']['url'] = params.pop('url') - elif 'body' in params.keys(): - if 'name' not in params: - joined_name = ''.join(random.choice(string.ascii_letters) for _ in range(16)) - params['name'] = DefaultClientCRD.normalize(joined_name) - params['secret-name'] = params['name'] + 'secret' - OpenApiRef.create_secret_if_needed(params, self.threescale_client.ocp_namespace) - spec['spec']['openapiRef'] = {} - spec['spec']['openapiRef']['secretRef'] = {} - spec['spec']['openapiRef']['secretRef']['name'] = params['secret-name'] + if "url" in params.keys(): + spec["spec"]["openapiRef"] = {} + spec["spec"]["openapiRef"]["url"] = params.pop("url") + elif "body" in params.keys(): + if "name" not in params: + joined_name = "".join( + random.choice(string.ascii_letters) for _ in range(16) + ) + params["name"] = DefaultClientCRD.normalize(joined_name) + params["secret-name"] = params["name"] + "secret" + OpenApiRef.create_secret_if_needed( + params, self.threescale_client.ocp_namespace + ) + spec["spec"]["openapiRef"] = {} + spec["spec"]["openapiRef"]["secretRef"] = {} + spec["spec"]["openapiRef"]["secretRef"]["name"] = params["secret-name"] def before_update(self, new_params, resource): """Called before update.""" - if 'url' in new_params.keys() and 'body' not in new_params.keys(): - new_params['openapiRef'] = {} - new_params['openapiRef']['url'] = new_params.pop('url') - elif 'body' in new_params.keys(): - if 'name' not in new_params: - new_params['name'] = DefaultClientCRD.normalize( - ''.join(random.choice(string.ascii_letters) for _ in range(16))) - new_params['secret-name'] = new_params['name'] + 'secret' - OpenApiRef.create_secret_if_needed(new_params, self.threescale_client.ocp_namespace) - new_params['openapiRef'] = {} - new_params['openapiRef']['secretRef'] = {} - new_params['openapiRef']['secretRef']['name'] = new_params['secret-name'] + if "url" in new_params.keys() and "body" not in new_params.keys(): + new_params["openapiRef"] = {} + new_params["openapiRef"]["url"] = new_params.pop("url") + elif "body" in new_params.keys(): + if "name" not in new_params: + new_params["name"] = DefaultClientCRD.normalize( + "".join(random.choice(string.ascii_letters) for _ in range(16)) + ) + new_params["secret-name"] = new_params["name"] + "secret" + OpenApiRef.create_secret_if_needed( + new_params, self.threescale_client.ocp_namespace + ) + new_params["openapiRef"] = {} + new_params["openapiRef"]["secretRef"] = {} + new_params["openapiRef"]["secretRef"]["name"] = new_params["secret-name"] class Promotes(DefaultClientCRD, threescale_api.defaults.DefaultClient): """ CRD client for Promotes. This class is only implemented in CRD and not in 3scale API. """ + CRD_IMPLEMENTED = True SPEC = constants.SPEC_PROMOTE KEYS = constants.KEYS_PROMOTE - SELECTOR = 'ProxyConfigPromote' - ID_NAME = 'productId' - - def __init__(self, parent, *args, entity_name='promote', - entity_collection='promotes', **kwargs): - super().__init__(*args, parent=parent, entity_name=entity_name, entity_collection=entity_collection, **kwargs) + SELECTOR = "ProxyConfigPromote" + ID_NAME = "productId" + # flake8: noqa E501 + ERROR_MSG = '[]: Invalid value: "": cannot promote to staging as no product changes detected. Delete this proxyConfigPromote CR, then introduce changes to configuration, and then create a new proxyConfigPromote CR' + + def __init__( + self, + parent, + *args, + entity_name="promote", + entity_collection="promotes", + **kwargs, + ): + super().__init__( + *args, + parent=parent, + entity_name=entity_name, + entity_collection=entity_collection, + **kwargs, + ) def before_create(self, params, spec): """Called before create.""" @@ -916,20 +1166,20 @@ def before_update(self, new_params, resource): pass def _is_ready(self, obj): - """ Is object ready? """ - if not ('status' in obj.model and 'conditions' in obj.model.status): + """Is object ready?""" + if not ("status" in obj.model and "conditions" in obj.model.status): return False - state = {'Failed': True, 'Ready': False} - conds = obj.as_dict()['status']['conditions'] + state = {"Failed": True, "Ready": False} + conds = obj.as_dict()["status"]["conditions"] for sta in conds: - state[sta['type']] = (sta['status'] == 'True') + state[sta["type"]] = sta["status"] == "True" - if not state['Failed'] and state['Ready']: + if not state["Failed"] and state["Ready"]: return True else: # extract message for 'Failed' - msg = [st['message'] for st in conds if st['type'] == 'Failed'] - if msg and msg[0] == '[]: Invalid value: "": cannot promote to staging as no product changes detected. Delete this proxyConfigPromote CR, then introduce changes to configuration, and then create a new proxyConfigPromote CR': + msg = [st["message"] for st in conds if st["type"] == "Failed"] + if msg and msg[0] == Promotes.ERROR_MSG: return True return False @@ -938,38 +1188,55 @@ class Tenants(DefaultClientCRD, threescale_api.resources.Tenants): """ CRD client for Tenants. """ + CRD_IMPLEMENTED = True SPEC = constants.SPEC_TENANT KEYS = constants.KEYS_TENANT - SELECTOR = 'Tenant' - ID_NAME = 'tenantId' - - def __init__(self, parent, *args, entity_name='tenant', - entity_collection='tenants', **kwargs): - super().__init__(*args, parent=parent, entity_name=entity_name, entity_collection=entity_collection, **kwargs) + SELECTOR = "Tenant" + ID_NAME = "tenantId" + + def __init__( + self, parent, *args, entity_name="tenant", entity_collection="tenants", **kwargs + ): + super().__init__( + *args, + parent=parent, + entity_name=entity_name, + entity_collection=entity_collection, + **kwargs, + ) def _set_provider_ref_new_crd(self, spec): - """ set provider reference to new crd """ + """set provider reference to new crd""" return spec def before_create(self, params, spec): """Called before create.""" - spec['spec']['systemMasterUrl'] = self.threescale_client.url + spec["spec"]["systemMasterUrl"] = self.threescale_client.url # create master credentials secret - mast_sec_name = params['username'] + 'mastsec' - mas_params = {'MASTER_ACCESS_TOKEN': self.threescale_client.token} - Tenants.create_secret(mast_sec_name, self.threescale_client.ocp_namespace, mas_params) - spec['spec']['masterCredentialsRef']['name'] = mast_sec_name + mast_sec_name = params["username"] + "mastsec" + mas_params = {"MASTER_ACCESS_TOKEN": self.threescale_client.token} + Tenants.create_secret( + mast_sec_name, self.threescale_client.ocp_namespace, mas_params + ) + spec["spec"]["masterCredentialsRef"]["name"] = mast_sec_name # create tenant admin secret - admin_sec_name = params['username'] + 'adminsec' - admin_params = {'admin_password': params.get('admin_password', ''.join(random.choice(string.ascii_letters) for _ in range(16)))} - Tenants.create_secret(admin_sec_name, self.threescale_client.ocp_namespace, admin_params) - spec['spec']['passwordCredentialsRef']['name'] = admin_sec_name + admin_sec_name = params["username"] + "adminsec" + admin_params = { + "admin_password": params.get( + "admin_password", + "".join(random.choice(string.ascii_letters) for _ in range(16)), + ) + } + Tenants.create_secret( + admin_sec_name, self.threescale_client.ocp_namespace, admin_params + ) + spec["spec"]["passwordCredentialsRef"]["name"] = admin_sec_name # tenant sec. ref. - spec['spec']['tenantSecretRef'] = { - 'name': params['username'] + 'tenant', - 'namespace': self.threescale_client.ocp_namespace + spec["spec"]["tenantSecretRef"] = { + "name": params["username"] + "tenant", + "namespace": self.threescale_client.ocp_namespace, } def before_update(self, new_params, resource): @@ -977,8 +1244,8 @@ def before_update(self, new_params, resource): sec. references update is not implemented because it is not part of origin client.""" # there are two folds 'signup' and 'account' and new_params should be updated properly - tmp = new_params.pop('signup') - new_pars = tmp.pop('account') + tmp = new_params.pop("signup") + new_pars = tmp.pop("account") new_pars.update(new_params) new_params.clear() new_params.update(new_pars) @@ -987,10 +1254,12 @@ def before_update(self, new_params, resource): def create_secret(name, namespace, params): """Creates secret if it is needed""" spec_sec = copy.deepcopy(constants.SPEC_SECRET) - spec_sec['metadata']['name'] = name - spec_sec['metadata']['namespace'] = namespace + spec_sec["metadata"]["name"] = name + spec_sec["metadata"]["namespace"] = namespace for key, value in params.items(): - spec_sec['data'][key] = base64.b64encode(str(value).encode('ascii')).decode('ascii') + spec_sec["data"][key] = base64.b64encode(str(value).encode("ascii")).decode( + "ascii" + ) result = ocp.create(spec_sec) assert result.status() == 0 @@ -998,76 +1267,97 @@ def read(self, entity_id, **kwargs): return DefaultClientCRD.fetch(self, entity_id, **kwargs) def _is_ready(self, obj): - """ Is object ready? """ + """Is object ready?""" # exception because of https://issues.redhat.com/browse/THREESCALE-8273 - return 'status' in obj.model and 'adminId' in obj.model.status and 'tenantId' in obj.model.status + return ( + "status" in obj.model + and "adminId" in obj.model.status + and "tenantId" in obj.model.status + ) class Limits(DefaultClientNestedCRD, threescale_api.resources.Limits): - """ CRD client for Limits. """ + """CRD client for Limits.""" + CRD_IMPLEMENTED = True SPEC = constants.SPEC_LIMIT KEYS = constants.KEYS_LIMIT - SELECTOR = 'Product' + SELECTOR = "Product" ID_NAME = None - LIST_TYPE = 'normal' - - def __init__(self, parent, *args, entity_name='limit', entity_collection='limits', - metric, **kwargs): - super().__init__(*args, parent=parent, entity_name=entity_name, - entity_collection=entity_collection, **kwargs) + LIST_TYPE = "normal" + + def __init__( + self, + parent, + *args, + entity_name="limit", + entity_collection="limits", + metric, + **kwargs, + ): + super().__init__( + *args, + parent=parent, + entity_name=entity_name, + entity_collection=entity_collection, + **kwargs, + ) self._metric = metric def before_create(self, params, spec): """Called before create.""" - spec['spec']['metricMethodRef'] = {'systemName': self.metric[Metrics.ID_NAME]} - params['metric_name'] = self.metric[Metrics.ID_NAME] - params['plan_id'] = self.application_plan['id'] - if self.metric.__class__.__name__ == 'BackendMetric': - spec['spec']['metricMethodRef']['backend'] = self.metric.parent['system_name'] - params['backend_name'] = self.metric.parent['system_name'] + spec["spec"]["metricMethodRef"] = {"systemName": self.metric[Metrics.ID_NAME]} + params["metric_name"] = self.metric[Metrics.ID_NAME] + params["plan_id"] = self.application_plan["id"] + if self.metric.__class__.__name__ == "BackendMetric": + spec["spec"]["metricMethodRef"]["backend"] = self.metric.parent[ + "system_name" + ] + params["backend_name"] = self.metric.parent["system_name"] def before_update(self, new_params, resource): """Called before update.""" - new_params['id'] = resource.get('id') - if resource and 'id' in new_params: - resource.entity_id = new_params['id'] + new_params["id"] = resource.get("id") + if resource and "id" in new_params: + resource.entity_id = new_params["id"] return self.translate_to_crd(new_params) - def get_list(self, typ='normal'): - """ Returns list of entities. """ + def get_list(self, typ="normal"): + """Returns list of entities.""" Limits.LIST_TYPE = typ llist = self.list() - Limits.LIST_TYPE = 'normal' + Limits.LIST_TYPE = "normal" return llist def in_create(self, maps, params, spec): """Do steps to create new instance""" maps = Limits.insert_to_list(maps, params, spec) self.parent.read() - self.parent.update({'limits': maps}) - maps = self.get_list(typ='normal') + self.parent.update({"limits": maps}) + maps = self.get_list(typ="normal") return Limits.get_from_list(maps, params, spec) def get_list_from_spec(self): - """ Returns list from spec """ - return self.parent.crd.as_dict()['spec']['applicationPlans'][self.parent['system_name']].get('limits', []) + """Returns list from spec""" + return self.parent.crd.as_dict()["spec"]["applicationPlans"][ + self.parent["system_name"] + ].get("limits", []) def before_update_list(self, maps, new_params, spec, resource): - """ Modify some details in data before updating the list """ + """Modify some details in data before updating the list""" spec = self.translate_to_crd(new_params) - return self.insert_to_list(maps, new_params, {'spec': spec}) + return self.insert_to_list(maps, new_params, {"spec": spec}) def update_list(self, maps): - """ Returns updated list. """ + """Returns updated list.""" self.parent.read() - return self.parent.update({'limits': maps}) + return self.parent.update({"limits": maps}) def remove_from_list(self, spec): - """ Returns list without item specified by 'spec'. """ + """Returns list without item specified by 'spec'.""" maps = [] for mapi in self.get_list(): - if mapi['id'] != (spec['period'], spec['metricMethodRef']['systemName']): + if mapi["id"] != (spec["period"], spec["metricMethodRef"]["systemName"]): maps.append(self.translate_to_crd(mapi.entity)) return maps @@ -1086,18 +1376,20 @@ def insert_to_list(maps, params, spec): """ ret = [] for obj in maps: - metric_name = '' - if 'metric_name' in params: - metric_name = params['metric_name'] - elif 'backend' in obj['metricMethodRef']: - metric_name = BackendMetric.id_to_system_name[params['metric_id']] + metric_name = "" + if "metric_name" in params: + metric_name = params["metric_name"] + elif "backend" in obj["metricMethodRef"]: + metric_name = BackendMetric.id_to_system_name[params["metric_id"]] else: - metric_name = Metric.id_to_system_name[params['metric_id']] - if obj['period'] != params['period'] or \ - obj['metricMethodRef']['systemName'] != metric_name: + metric_name = Metric.id_to_system_name[params["metric_id"]] + if ( + obj["period"] != params["period"] + or obj["metricMethodRef"]["systemName"] != metric_name + ): ret.append(obj) - ret.append(spec['spec']) + ret.append(spec["spec"]) return ret @staticmethod @@ -1108,15 +1400,17 @@ def get_from_list(maps, params, spec): """ ret = [] for obj in maps: - metric_name = '' - if 'metric_name' in params: - metric_name = params['metric_name'] - elif 'backend' in obj['metricMethodRef']: - metric_name = BackendMetric.id_to_system_name[params['metric_id']] + metric_name = "" + if "metric_name" in params: + metric_name = params["metric_name"] + elif "backend" in obj["metricMethodRef"]: + metric_name = BackendMetric.id_to_system_name[params["metric_id"]] else: - metric_name = Metric.id_to_system_name[params['metric_id']] - if obj['period'] == params['period'] and \ - obj['metricMethodRef']['systemName'] == metric_name: + metric_name = Metric.id_to_system_name[params["metric_id"]] + if ( + obj["period"] == params["period"] + and obj["metricMethodRef"]["systemName"] == metric_name + ): ret.append(obj) return ret[0] @@ -1133,102 +1427,125 @@ def metric(self): return self._metric @property - def application_plan(self) -> 'ApplicationPlan': + def application_plan(self) -> "ApplicationPlan": return self.parent - def __call__(self, metric: 'Metric' = None) -> 'Limits': + def __call__(self, metric: "Metric" = None) -> "Limits": self._metric = metric return self -# def list_per_app_plan(self, **kwargs): -# log.info("[LIST] List limits per app plan: %s", kwargs) -# url = self.parent.url + '/limits' -# response = self.rest.get(url=url, **kwargs) -# instance = self._create_instance(response=response) -# return instance + # def list_per_app_plan(self, **kwargs): + # log.info("[LIST] List limits per app plan: %s", kwargs) + # url = self.parent.url + '/limits' + # response = self.rest.get(url=url, **kwargs) + # instance = self._create_instance(response=response) + # return instance def _create_instance_trans(self, instance): # it is needed to distinguish between getting metric's limits(normal) or all limits(full) - if Limits.LIST_TYPE == 'normal': - if self.metric.__class__.__name__ == 'BackendMetric': - return [obj for obj in instance \ - if self.metric[BackendMetrics.ID_NAME] == obj['metric_name'] and \ - self.metric.parent['system_name'] == obj['backend_name']] + if Limits.LIST_TYPE == "normal": + if self.metric.__class__.__name__ == "BackendMetric": + return [ + obj + for obj in instance + if self.metric[BackendMetrics.ID_NAME] == obj["metric_name"] + and self.metric.parent["system_name"] == obj["backend_name"] + ] else: - return [obj for obj in instance \ - if self.metric[Metrics.ID_NAME] == obj['metric_name'] and \ - 'backend_name' not in obj.entity] + return [ + obj + for obj in instance + if self.metric[Metrics.ID_NAME] == obj["metric_name"] + and "backend_name" not in obj.entity + ] else: return [obj for obj in instance] class PricingRules(DefaultClientNestedCRD, threescale_api.resources.PricingRules): - """ CRD client for PricingRules. """ + """CRD client for PricingRules.""" + CRD_IMPLEMENTED = True SPEC = constants.SPEC_PRICING_RULE KEYS = constants.KEYS_PRICING_RULE - SELECTOR = 'Product' + SELECTOR = "Product" ID_NAME = None - LIST_TYPE = 'normal' - - def __init__(self, parent, *args, entity_name='pricing_rule', entity_collection='pricing_rules', - metric, **kwargs): - super().__init__(*args, parent=parent, entity_name=entity_name, - entity_collection=entity_collection, **kwargs) + LIST_TYPE = "normal" + + def __init__( + self, + parent, + *args, + entity_name="pricing_rule", + entity_collection="pricing_rules", + metric, + **kwargs, + ): + super().__init__( + *args, + parent=parent, + entity_name=entity_name, + entity_collection=entity_collection, + **kwargs, + ) self._metric = metric def before_create(self, params, spec): """Called before create.""" - spec['spec']['metricMethodRef'] = {'systemName': self.metric[Metrics.ID_NAME]} - params['metric_name'] = self.metric[Metrics.ID_NAME] - params['plan_id'] = self.application_plan['id'] - if self.metric.__class__.__name__ == 'BackendMetric': - spec['spec']['metricMethodRef']['backend'] = self.metric.parent['system_name'] - params['backend_name'] = self.metric.parent['system_name'] - - if 'cost_per_unit' in params: - params['cost_per_unit'] = str(params['cost_per_unit']) + spec["spec"]["metricMethodRef"] = {"systemName": self.metric[Metrics.ID_NAME]} + params["metric_name"] = self.metric[Metrics.ID_NAME] + params["plan_id"] = self.application_plan["id"] + if self.metric.__class__.__name__ == "BackendMetric": + spec["spec"]["metricMethodRef"]["backend"] = self.metric.parent[ + "system_name" + ] + params["backend_name"] = self.metric.parent["system_name"] + + if "cost_per_unit" in params: + params["cost_per_unit"] = str(params["cost_per_unit"]) def before_update(self, new_params, resource): """Called before update.""" - new_params['id'] = resource.get('id') - if resource and 'id' in new_params: - resource.entity_id = new_params['id'] - if 'cost_per_unit' in new_params: - new_params['cost_per_unit'] = str(new_params['cost_per_unit']) + new_params["id"] = resource.get("id") + if resource and "id" in new_params: + resource.entity_id = new_params["id"] + if "cost_per_unit" in new_params: + new_params["cost_per_unit"] = str(new_params["cost_per_unit"]) return self.translate_to_crd(new_params) - def get_list(self, typ='normal'): - """ Returns list of entities. """ + def get_list(self, typ="normal"): + """Returns list of entities.""" PricingRules.LIST_TYPE = typ llist = self.list() - PricingRules.LIST_TYPE = 'normal' + PricingRules.LIST_TYPE = "normal" return llist def in_create(self, maps, params, spec): """Do steps to create new instance""" maps = PricingRules.insert_to_list(maps, params, spec) self.parent.read() - self.parent.update({'pricingRules': maps}) - maps = self.get_list(typ='normal') + self.parent.update({"pricingRules": maps}) + maps = self.get_list(typ="normal") return PricingRules.get_from_list(maps, params, spec) def get_list_from_spec(self): - """ Returns list from spec """ - return self.parent.crd.as_dict()['spec']['applicationPlans'][self.parent['system_name']].get('pricingRules', []) + """Returns list from spec""" + return self.parent.crd.as_dict()["spec"]["applicationPlans"][ + self.parent["system_name"] + ].get("pricingRules", []) def before_update_list(self, maps, new_params, spec, resource): - """ Modify some details in data before updating the list """ + """Modify some details in data before updating the list""" spec = self.translate_to_crd(new_params) - return PricingRules.insert_to_list(maps, new_params, {'spec': spec}) + return PricingRules.insert_to_list(maps, new_params, {"spec": spec}) def update_list(self, maps): - """ Returns updated list. """ + """Returns updated list.""" self.parent.read() - return self.parent.update({'pricingRules': maps}) + return self.parent.update({"pricingRules": maps}) def remove_from_list(self, spec): - """ Returns list without item specified by 'spec'. """ + """Returns list without item specified by 'spec'.""" maps = [] for mapi in self.get_list(): map_ret = self.translate_to_crd(mapi.entity) @@ -1251,18 +1568,21 @@ def insert_to_list(maps, params, spec): """ ret = [] for obj in maps: - metric_name = '' - if 'metric_name' in params: - metric_name = params['metric_name'] - elif 'backend' in obj['metricMethodRef']: - metric_name = BackendMetric.id_to_system_name[params['metric_id']] + metric_name = "" + if "metric_name" in params: + metric_name = params["metric_name"] + elif "backend" in obj["metricMethodRef"]: + metric_name = BackendMetric.id_to_system_name[params["metric_id"]] else: - metric_name = Metric.id_to_system_name[params['metric_id']] - if obj['from'] != params['min'] or obj['to'] != params['max'] or \ - obj['metricMethodRef']['systemName'] != metric_name: + metric_name = Metric.id_to_system_name[params["metric_id"]] + if ( + obj["from"] != params["min"] + or obj["to"] != params["max"] + or obj["metricMethodRef"]["systemName"] != metric_name + ): ret.append(obj) - ret.append(spec['spec']) + ret.append(spec["spec"]) return ret @staticmethod @@ -1273,15 +1593,18 @@ def get_from_list(maps, params, spec): """ ret = [] for obj in maps: - metric_name = '' - if 'metric_name' in params: - metric_name = params['metric_name'] - elif 'backend' in obj['metricMethodRef']: - metric_name = BackendMetric.id_to_system_name[params['metric_id']] + metric_name = "" + if "metric_name" in params: + metric_name = params["metric_name"] + elif "backend" in obj["metricMethodRef"]: + metric_name = BackendMetric.id_to_system_name[params["metric_id"]] else: - metric_name = Metric.id_to_system_name[params['metric_id']] - if obj['min'] == params['min'] and obj['max'] == params['max'] and \ - obj['metricMethodRef']['systemName'] == metric_name: + metric_name = Metric.id_to_system_name[params["metric_id"]] + if ( + obj["min"] == params["min"] + and obj["max"] == params["max"] + and obj["metricMethodRef"]["systemName"] == metric_name + ): ret.append(obj) return ret[0] @@ -1293,41 +1616,47 @@ def get_path(self): """ return "spec/applicationPlans/" + self.parent["name"] + "/pricingRules" -# def trans_item(self, key, value, obj): -# """ Translate entity to CRD. """ -# if key != 'name': -# return obj[key] + # def trans_item(self, key, value, obj): + # """ Translate entity to CRD. """ + # if key != 'name': + # return obj[key] @property def metric(self): return self._metric @property - def application_plan(self) -> 'ApplicationPlan': + def application_plan(self) -> "ApplicationPlan": return self.parent - def __call__(self, metric: 'Metric' = None) -> 'PricingRules': + def __call__(self, metric: "Metric" = None) -> "PricingRules": self._metric = metric return self -# def list_per_app_plan(self, **kwargs): -# log.info("[LIST] List limits per app plan: %s", kwargs) -# url = self.parent.url + '/limits' -# response = self.rest.get(url=url, **kwargs) -# instance = self._create_instance(response=response) -# return instance + # def list_per_app_plan(self, **kwargs): + # log.info("[LIST] List limits per app plan: %s", kwargs) + # url = self.parent.url + '/limits' + # response = self.rest.get(url=url, **kwargs) + # instance = self._create_instance(response=response) + # return instance def _create_instance_trans(self, instance): # it is needed to distinguish between getting metric's limits(normal) or all limits(full) - if PricingRules.LIST_TYPE == 'normal': - if self.metric.__class__.__name__ == 'BackendMetric': - return [obj for obj in instance \ - if self.metric[Metrics.ID_NAME] == obj['metric_name'] and \ - self.metric.parent['system_name'] == obj['backend_name']] + if PricingRules.LIST_TYPE == "normal": + if self.metric.__class__.__name__ == "BackendMetric": + return [ + obj + for obj in instance + if self.metric[Metrics.ID_NAME] == obj["metric_name"] + and self.metric.parent["system_name"] == obj["backend_name"] + ] else: - return [obj for obj in instance \ - if self.metric[Metrics.ID_NAME] == obj['metric_name'] and \ - 'backend_name' not in obj.entity] + return [ + obj + for obj in instance + if self.metric[Metrics.ID_NAME] == obj["metric_name"] + and "backend_name" not in obj.entity + ] else: return [obj for obj in instance] @@ -1336,18 +1665,36 @@ class Applications(DefaultClientCRD, threescale_api.resources.Applications): """ CRD client for Applications. """ + CRD_IMPLEMENTED = True SPEC = constants.SPEC_APPLICATION KEYS = constants.KEYS_APPLICATION - SELECTOR = 'Application' - ID_NAME = 'applicationID' - - def __init__(self, parent, account, *args, entity_name='application', - entity_collection='applications', **kwargs): + SELECTOR = "Application" + ID_NAME = "applicationID" + + def __init__( + self, + parent, + account, + *args, + entity_name="application", + entity_collection="applications", + **kwargs, + ): self.account = account - self._url = (account.client.url + '/' + str(account.entity_id)) if account else parent.url - self._url += '/applications' - super().__init__(*args, parent=parent, entity_name=entity_name, entity_collection=entity_collection, **kwargs) + self._url = ( + (account.client.url + "/" + str(account.entity_id)) + if account + else parent.url + ) + self._url += "/applications" + super().__init__( + *args, + parent=parent, + entity_name=entity_name, + entity_collection=entity_collection, + **kwargs, + ) @property def url(self) -> str: @@ -1355,90 +1702,102 @@ def url(self) -> str: def before_create(self, params, spec): """Called before create.""" - service = self.parent.services.fetch(int(params.pop('service_id'))) - plan = params['plan_id'] - if isinstance(params['plan_id'], int): - plan = service.app_plans.read(params['plan_id'])['system_name'] - spec['spec']['productCR']['name'] = service.crd.as_dict()['metadata']['name'] - spec['spec']['accountCR']['name'] = self.account['name'] - spec['spec']['applicationPlanName'] = plan + service = self.parent.services.fetch(int(params.pop("service_id"))) + plan = params["plan_id"] + if isinstance(params["plan_id"], int): + plan = service.app_plans.read(params["plan_id"])["system_name"] + spec["spec"]["productCR"]["name"] = service.crd.as_dict()["metadata"]["name"] + spec["spec"]["accountCR"]["name"] = self.account["name"] + spec["spec"]["applicationPlanName"] = plan def before_update(self, new_params, resource): """Called before update.""" pass def _is_ready(self, obj): - """ Is object ready? """ - return 'status' in obj.model and 'conditions' in obj.model.status and obj.as_dict()['status']['conditions'][0]['status'] == 'True' + """Is object ready?""" + return ( + "status" in obj.model + and "conditions" in obj.model.status + and obj.as_dict()["status"]["conditions"][0]["status"] == "True" + ) def trans_item(self, key, value, obj): - """ Translate entity to CRD. """ - if key in ['service_name', 'account_name']: - return {'name': obj[key]} + """Translate entity to CRD.""" + if key in ["service_name", "account_name"]: + return {"name": obj[key]} else: return obj[key] class Methods(DefaultClientNestedCRD, threescale_api.resources.Methods): - """ Method client class """ + """Method client class""" + CRD_IMPLEMENTED = True SPEC = constants.SPEC_METHOD KEYS = constants.KEYS_METHOD - SELECTOR = 'Product' - ID_NAME = 'system_name' - def __init__(self, *args, entity_name='method', entity_collection='methods', **kwargs): - super().__init__(*args, entity_name=entity_name, entity_collection=entity_collection, - **kwargs) + SELECTOR = "Product" + ID_NAME = "system_name" + + def __init__( + self, *args, entity_name="method", entity_collection="methods", **kwargs + ): + super().__init__( + *args, + entity_name=entity_name, + entity_collection=entity_collection, + **kwargs, + ) def before_create(self, params, spec): """Called before create.""" - if 'system_name' in params and 'friendly_name' not in params: - params['friendly_name'] = params.get(Methods.ID_NAME) - if 'name' in params and 'friendly_name' not in params: - params['friendly_name'] = params.pop('name') - if 'description' not in params: - params['description'] = params.get(Methods.ID_NAME) - params.pop('name', None) + if "system_name" in params and "friendly_name" not in params: + params["friendly_name"] = params.get(Methods.ID_NAME) + if "name" in params and "friendly_name" not in params: + params["friendly_name"] = params.pop("name") + if "description" not in params: + params["description"] = params.get(Methods.ID_NAME) + params.pop("name", None) def before_update(self, new_params, resource): """Called before update.""" - new_params['id'] = new_params[Methods.ID_NAME] - if resource and 'id' in new_params: - resource.entity_id = new_params['id'] + new_params["id"] = new_params[Methods.ID_NAME] + if resource and "id" in new_params: + resource.entity_id = new_params["id"] return self.translate_to_crd(new_params) def get_list(self, typ=None): - """ Returns list of entities. """ + """Returns list of entities.""" return self.parent.methods.list() def in_create(self, maps, params, spec): """Do steps to create new instance""" name = params.get(Methods.ID_NAME) - maps[name] = spec['spec'] + maps[name] = spec["spec"] self.topmost_parent().read() - self.topmost_parent().update({'methods': maps}) + self.topmost_parent().update({"methods": maps}) for mapi in self.get_list(): if all([params[key] == mapi[key] for key in params.keys()]): return mapi return None def get_list_from_spec(self): - """ Returns list from spec """ - return self.parent.crd.as_dict()['spec'].get('methods', {}) + """Returns list from spec""" + return self.parent.crd.as_dict()["spec"].get("methods", {}) def before_update_list(self, maps, new_params, spec, resource): - """ Modify some details in data before updating the list """ + """Modify some details in data before updating the list""" name = new_params.get(Methods.ID_NAME) maps[name] = spec return maps def update_list(self, maps): - """ Returns updated list. """ + """Returns updated list.""" self.topmost_parent().read() - return self.topmost_parent().update({'methods': maps}) + return self.topmost_parent().update({"methods": maps}) def remove_from_list(self, spec): - """ Returns list without item specified by 'spec'. """ + """Returns list without item specified by 'spec'.""" maps = {} for mapi in self.get_list(): map_ret = self.translate_to_crd(mapi.entity) @@ -1455,7 +1814,7 @@ def topmost_parent(self): return self.parent.parent def trans_item(self, key, value, obj): - """ Translate entity to CRD. """ + """Translate entity to CRD.""" if key != Methods.ID_NAME: return obj[key] return None @@ -1469,32 +1828,33 @@ class Service(DefaultResourceCRD, threescale_api.resources.Service): """ CRD resource for Service. """ - GET_PATH = 'spec' + + GET_PATH = "spec" system_name_to_id = {} id_to_system_name = {} - def __init__(self, entity_name='system_name', **kwargs): + def __init__(self, entity_name="system_name", **kwargs): entity = None - if 'spec' in kwargs: + if "spec" in kwargs: entity = {} - spec = kwargs.pop('spec') - crd = kwargs.pop('crd') + spec = kwargs.pop("spec") + crd = kwargs.pop("crd") for key, value in spec.items(): for cey, walue in constants.KEYS_SERVICE.items(): if key == walue: entity[cey] = value - entity['id'] = crd.as_dict().get('status').get(Services.ID_NAME) + entity["id"] = crd.as_dict().get("status").get(Services.ID_NAME) # add ids to cache - if entity['id'] and entity[entity_name]: - Service.id_to_system_name[int(entity['id'])] = entity[entity_name] - Service.system_name_to_id[entity[entity_name]] = int(entity['id']) - auth = crd.model.spec.get('deployment', None) + if entity["id"] and entity[entity_name]: + Service.id_to_system_name[int(entity["id"])] = entity[entity_name] + Service.system_name_to_id[entity[entity_name]] = int(entity["id"]) + auth = crd.model.spec.get("deployment", None) # TODO add better authentication work if auth: auth = auth.popitem()[1] - if auth and 'authentication' in auth: - auth = list(auth['authentication'].keys())[0] - entity['backend_version'] = constants.SERVICE_AUTH[auth] + if auth and "authentication" in auth: + auth = list(auth["authentication"].keys())[0] + entity["backend_version"] = constants.SERVICE_AUTH[auth] super().__init__(crd=crd, entity=entity, entity_name=entity_name, **kwargs) else: # this is not here because of some backup, but because we need to have option @@ -1502,27 +1862,27 @@ def __init__(self, entity_name='system_name', **kwargs): super().__init__(entity_name=entity_name, **kwargs) @property - def mapping_rules(self) -> 'MappingRules': + def mapping_rules(self) -> "MappingRules": return MappingRules(instance_klass=MappingRule, parent=self) @property - def proxy(self) -> 'Proxies': + def proxy(self) -> "Proxies": return Proxies(parent=self, instance_klass=Proxy) @property - def policies_registry(self) -> 'PoliciesRegistry': + def policies_registry(self) -> "PoliciesRegistry": return PoliciesRegistry(parent=self, instance_klass=PoliciesRegistry) @property - def metrics(self) -> 'Metrics': + def metrics(self) -> "Metrics": return Metrics(instance_klass=Metric, parent=self) @property - def backend_usages(self) -> 'BackendUsages': + def backend_usages(self) -> "BackendUsages": return BackendUsages(instance_klass=BackendUsage, parent=self) @property - def app_plans(self) -> 'ApplicationPlans': + def app_plans(self) -> "ApplicationPlans": return ApplicationPlans(instance_klass=ApplicationPlan, parent=self) @@ -1531,28 +1891,28 @@ class Proxy(DefaultResourceCRD, threescale_api.resources.Proxy): CRD resource for Proxy. """ - GET_PATH = 'spec/deployment' + GET_PATH = "spec/deployment" def __init__(self, **kwargs): # store oidc dict - self.oidc = {'oidc_configuration': {}} + self.oidc = {"oidc_configuration": {}} self.security = False self.responses = False entity = None - if 'spec' in kwargs: - spec = kwargs.pop('spec') - crd = kwargs.pop('crd') + if "spec" in kwargs: + spec = kwargs.pop("spec") + crd = kwargs.pop("crd") self.spec_path = [] entity = {} # there is no attribute which can simulate Proxy id, service id should be used - entity['id'] = crd.as_dict().get('status').get(Services.ID_NAME) + entity["id"] = crd.as_dict().get("status").get(Services.ID_NAME) # apicastHosted or ApicastSelfManaged if len(spec.values()): apicast_key = list(spec.keys())[0] - if apicast_key == 'apicastHosted': - entity['deployment_option'] = 'hosted' - elif apicast_key == 'apicastSelfManaged': - entity['deployment_option'] = 'self_managed' + if apicast_key == "apicastHosted": + entity["deployment_option"] = "hosted" + elif apicast_key == "apicastSelfManaged": + entity["deployment_option"] = "self_managed" self.spec_path.append(apicast_key) spec = spec.get(apicast_key, {}) # add endpoint and sandbox_endpoint @@ -1561,32 +1921,32 @@ def __init__(self, **kwargs): if key == walue: entity[cey] = value - spec = spec.get('authentication', {}) - self.spec_path.append('authentication') + spec = spec.get("authentication", {}) + self.spec_path.append("authentication") # userkey or appKeyAppID or oidc if spec and len(spec.values()): self.spec_path.append(list(spec.keys())[0]) spec = list(spec.values())[0] # add credentials_location for key, value in spec.items(): - if key == 'authenticationFlow': + if key == "authenticationFlow": for key2, value2 in spec[key].items(): for cey, walue in constants.KEYS_OIDC.items(): if key2 == walue: - self.oidc['oidc_configuration'][cey] = value2 + self.oidc["oidc_configuration"][cey] = value2 else: for cey, walue in constants.KEYS_PROXY.items(): if key == walue: entity[cey] = value - secret = spec.get('security', {}) + secret = spec.get("security", {}) if secret: self.secret = True for key, value in secret.items(): for cey, walue in constants.KEYS_PROXY_SECURITY.items(): if key == walue: entity[cey] = value - spec = spec.get('gatewayResponse', {}) + spec = spec.get("gatewayResponse", {}) if spec: self.responses = True for key, value in spec.items(): @@ -1596,10 +1956,17 @@ def __init__(self, **kwargs): super().__init__(crd=crd, entity=entity, **kwargs) - # there is 'endpoint' and 'sandbox_endpoint' just in apicastSelfManaged and not in apicastHosted + # there is 'endpoint' and 'sandbox_endpoint' just in + # apicastSelfManaged and not in apicastHosted # also auth related attrs are needed - required_attrs = ['endpoint', 'sandbox_endpoint', 'credentials_location', 'auth_user_key', - 'auth_app_id', 'auth_app_key'] + required_attrs = [ + "endpoint", + "sandbox_endpoint", + "credentials_location", + "auth_user_key", + "auth_app_id", + "auth_app_key", + ] if any([att not in entity for att in required_attrs]): self.client.disable_crd_implemented() self.parent.client.disable_crd_implemented() @@ -1617,11 +1984,11 @@ def deploy(self): """ Deploy to staging. """ - params = {'productCRName': self.parent.crd.as_dict()['metadata']['name']} + params = {"productCRName": self.parent.crd.as_dict()["metadata"]["name"]} prom = self.threescale_client.promotes.create(params) - ide = prom.entity.get('id', None) + ide = prom.entity.get("id", None) prom.delete() - if ide and int(ide) == self.parent['id']: + if ide and int(ide) == self.parent["id"]: return True else: return False @@ -1635,18 +2002,20 @@ def promote(self, **kwargs): to staging. It is not possible to promote specific proxy configuration to production nor to staging. """ - params = {'productCRName': self.parent.crd.as_dict()['metadata']['name'], - 'production': True} + params = { + "productCRName": self.parent.crd.as_dict()["metadata"]["name"], + "production": True, + } prom = self.threescale_client.promotes.create(params) - ide = prom.entity.get('id', None) + ide = prom.entity.get("id", None) prom.delete() - if ide and int(ide) == self.parent['id']: + if ide and int(ide) == self.parent["id"]: return True else: return False @property - def service(self) -> 'Service': + def service(self) -> "Service": return self.parent @property @@ -1654,7 +2023,7 @@ def mapping_rules(self) -> MappingRules: return self.parent.mapping_rules @property - def policies(self) -> 'Policies': + def policies(self) -> "Policies": return Policies(parent=self.parent, instance_klass=Policy) # def get_item_attribute(self, item: str): @@ -1677,12 +2046,12 @@ def policies(self) -> 'Policies': class OIDCConfigs(threescale_api.resources.DefaultClient): - """ OIDC configs. """ + """OIDC configs.""" def update(self, params: dict = None, **kwargs): proxy = self.parent.list() - oidc = proxy.oidc['oidc_configuration'] - oidc.update(params['oidc_configuration']) + oidc = proxy.oidc["oidc_configuration"] + oidc.update(params["oidc_configuration"]) proxy.update(oidc=oidc) def read(self, params: dict = None, **kwargs): @@ -1694,34 +2063,38 @@ class MappingRule(DefaultResourceCRD, threescale_api.resources.MappingRule): """ CRD resource for MappingRule. """ - GET_PATH = 'spec/mappingRules' - def __init__(self, entity_name='system_name', **kwargs): + GET_PATH = "spec/mappingRules" + + def __init__(self, entity_name="system_name", **kwargs): entity = None - if 'spec' in kwargs: - spec = kwargs.pop('spec') - crd = kwargs.pop('crd') + if "spec" in kwargs: + spec = kwargs.pop("spec") + crd = kwargs.pop("crd") entity = {} for key, value in spec.items(): for cey, walue in constants.KEYS_MAPPING_RULE.items(): if key == walue: entity[cey] = value # simulate entity_id by list of attributes - entity['id'] = (entity['http_method'], entity['pattern']) - self.entity_id = entity.get('id') + entity["id"] = (entity["http_method"], entity["pattern"]) + self.entity_id = entity.get("id") super().__init__(crd=crd, entity=entity, entity_name=entity_name, **kwargs) # TODO - if 'metric_id' in entity and isinstance(entity['metric_id'], str): + if "metric_id" in entity and isinstance(entity["metric_id"], str): met_system_name = None - # if self.parent.__class__.__name__ == 'Backend' and ('.' not in entity['metric_id']): + # if self.parent.__class__.__name__ == 'Backend' and + # ('.' not in entity['metric_id']): # met_system_name = entity['metric_id'] + '.' + str(self.parent['id']) # else: - met_system_name = entity['metric_id'] - met = self.parent.metrics.read_by(**{'system_name': met_system_name}) + met_system_name = entity["metric_id"] + met = self.parent.metrics.read_by(**{"system_name": met_system_name}) if not met: - met = self.parent.metrics.read_by_name('hits').methods.read_by(**{'system_name': met_system_name}) - entity['metric_id'] = met['id'] + met = self.parent.metrics.read_by_name("hits").methods.read_by( + **{"system_name": met_system_name} + ) + entity["metric_id"] = met["id"] else: # this is not here because of some backup, but because we need to have option # to creater empty object without any data. This is related to "lazy load" @@ -1729,22 +2102,25 @@ def __init__(self, entity_name='system_name', **kwargs): # TODO @property - def proxy(self) -> 'Proxy': + def proxy(self) -> "Proxy": ser = self - class FakeProxy(): - """ This is simulation of Proxy class because + class FakeProxy: + """This is simulation of Proxy class because of right encapsulation for mapping rules.""" + def mapping_rules(self): - """ Returns mapping rules client related to the Proxy. """ + """Returns mapping rules client related to the Proxy.""" + # noqa # pylint: disable=no-member return ser.mapping_rules return FakeProxy() @property - def service(self) -> 'Service': + def service(self) -> "Service": return self.parent + # @property # def entity_id(self) -> int: # return self._entity_id or self._entity.get('id') @@ -1754,8 +2130,9 @@ def service(self) -> 'Service': # self._entity_id = value or self._entity.get('id') -class OpenApiRef(): - """ Open API reference.""" +class OpenApiRef: + """Open API reference.""" + @staticmethod def load_openapi(entity, spec): """ @@ -1769,65 +2146,70 @@ def load_openapi(entity, spec): 2) when body is updated, secret is changed """ - if 'url' in spec: - url = spec['url'] - entity['url'] = url + if "url" in spec: + url = spec["url"] + entity["url"] = url res = requests.get(url) - if url.endswith('.yaml') or url.endswith('.yml'): - entity['body'] = json.dumps(yaml.load(res.content, Loader=yaml.SafeLoader)) + if url.endswith(".yaml") or url.endswith(".yml"): + entity["body"] = json.dumps( + yaml.load(res.content, Loader=yaml.SafeLoader) + ) else: - entity['body'] = res.content - elif 'secretRef' in spec: - secret_name = spec['secretRef']['name'] - secret = ocp.selector('secret/' + secret_name).objects()[0] - enc_body = list(secret.as_dict()['data'].values())[0] - entity['body'] = base64.b64decode(enc_body).decode('ascii') + entity["body"] = res.content + elif "secretRef" in spec: + secret_name = spec["secretRef"]["name"] + secret = ocp.selector("secret/" + secret_name).objects()[0] + enc_body = list(secret.as_dict()["data"].values())[0] + entity["body"] = base64.b64decode(enc_body).decode("ascii") @staticmethod def create_secret_if_needed(params, namespace): """Creates secret for tenant.""" - body_ascii = str(params['body']).encode('ascii') + body_ascii = str(params["body"]).encode("ascii") body_enc = base64.b64encode(body_ascii) spec_sec = copy.deepcopy(constants.SPEC_SECRET) - spec_sec['metadata']['name'] = params['secret-name'] - spec_sec['metadata']['namespace'] = namespace - spec_sec['data'][params['secret-name']] = body_enc.decode('ascii') - result = ocp.selector('secret/' + params['secret-name']) + spec_sec["metadata"]["name"] = params["secret-name"] + spec_sec["metadata"]["namespace"] = namespace + spec_sec["data"][params["secret-name"]] = body_enc.decode("ascii") + result = ocp.selector("secret/" + params["secret-name"]) if result.status() == 0: objs = result.objects() if objs: objs[0].delete() result = ocp.create(spec_sec) assert result.status() == 0 - if 'url' in params: - del params['url'] - del params['body'] + if "url" in params: + del params["url"] + del params["body"] class ActiveDoc(DefaultResourceCRD, threescale_api.resources.ActiveDoc): """ CRD resource for ActiveDoc. """ - GET_PATH = 'spec' - def __init__(self, entity_name='system_name', **kwargs): + GET_PATH = "spec" + + def __init__(self, entity_name="system_name", **kwargs): entity = None - if 'spec' in kwargs: - spec = kwargs.pop('spec') - crd = kwargs.pop('crd') + if "spec" in kwargs: + spec = kwargs.pop("spec") + crd = kwargs.pop("crd") entity = {} for key, value in spec.items(): for cey, walue in constants.KEYS_ACTIVE_DOC.items(): if key == walue: entity[cey] = value - entity['id'] = crd.as_dict().get('status').get(ActiveDocs.ID_NAME) - if 'service_id' in entity: - ide = Service.system_name_to_id.get(entity['service_id'], None) + entity["id"] = crd.as_dict().get("status").get(ActiveDocs.ID_NAME) + if "service_id" in entity: + ide = Service.system_name_to_id.get(entity["service_id"], None) if not ide: - ide = kwargs['client'].parent.services.read_by_name(entity['service_id'])['id'] - entity['service_id'] = ide + ide = kwargs["client"].parent.services.read_by_name( + entity["service_id"] + )["id"] + entity["service_id"] = ide - OpenApiRef.load_openapi(entity, spec['activeDocOpenAPIRef']) + OpenApiRef.load_openapi(entity, spec["activeDocOpenAPIRef"]) super().__init__(crd=crd, entity=entity, entity_name=entity_name, **kwargs) else: @@ -1840,22 +2222,24 @@ class PolicyRegistry(DefaultResourceCRD, threescale_api.resources.PolicyRegistry """ CRD resource for PolicyRegistry. """ - GET_PATH = 'spec' - def __init__(self, entity_name='name', **kwargs): + GET_PATH = "spec" + + def __init__(self, entity_name="name", **kwargs): entity = None - if 'spec' in kwargs: - spec = kwargs.pop('spec') - crd = kwargs.pop('crd') -# unit tests pass, this should be verify on real tests -# if 'description' in spec['schema'] and isinstance(spec['schema']['description'], list): -# spec['schema']['description'] = os.linesep.join(spec['schema']['description']) + if "spec" in kwargs: + spec = kwargs.pop("spec") + crd = kwargs.pop("crd") + # unit tests pass, this should be verify on real tests + # if 'description' in spec['schema'] and + # isinstance(spec['schema']['description'], list): + # spec['schema']['description'] = os.linesep.join(spec['schema']['description']) entity = {} for key, value in spec.items(): for cey, walue in constants.KEYS_POLICY_REG.items(): if key == walue: entity[cey] = value - entity['id'] = crd.as_dict().get('status').get(PoliciesRegistry.ID_NAME) + entity["id"] = crd.as_dict().get("status").get(PoliciesRegistry.ID_NAME) super().__init__(crd=crd, entity=entity, entity_name=entity_name, **kwargs) else: # this is not here because of some backup, but because we need to have option @@ -1867,19 +2251,20 @@ class Backend(DefaultResourceCRD, threescale_api.resources.Backend): """ CRD resource for Backend. """ - GET_PATH = 'spec' - def __init__(self, entity_name='system_name', **kwargs): + GET_PATH = "spec" + + def __init__(self, entity_name="system_name", **kwargs): entity = None - if 'spec' in kwargs: - spec = kwargs.pop('spec') - crd = kwargs.pop('crd') + if "spec" in kwargs: + spec = kwargs.pop("spec") + crd = kwargs.pop("crd") entity = {} for key, value in spec.items(): for cey, walue in constants.KEYS_BACKEND.items(): if key == walue: entity[cey] = value - entity['id'] = crd.as_dict().get('status').get(Backends.ID_NAME) + entity["id"] = crd.as_dict().get("status").get(Backends.ID_NAME) super().__init__(crd=crd, entity=entity, entity_name=entity_name, **kwargs) else: @@ -1888,24 +2273,28 @@ def __init__(self, entity_name='system_name', **kwargs): super().__init__(entity_name=entity_name, **kwargs) @property - def mapping_rules(self) -> 'BackendMappingRules': + def mapping_rules(self) -> "BackendMappingRules": return BackendMappingRules(parent=self, instance_klass=BackendMappingRule) @property - def metrics(self) -> 'BackendMetrics': + def metrics(self) -> "BackendMetrics": return BackendMetrics(parent=self, instance_klass=BackendMetric) - def usages(self) -> list['BackendUsages']: + def usages(self) -> list["BackendUsages"]: services = self.client.threescale_client.services.list() or [] - return [usage for service in services - for usage in service.backend_usages.select_by(backend_id=self['id'])] + return [ + usage + for service in services + for usage in service.backend_usages.select_by(backend_id=self["id"]) + ] class BackendMappingRule(MappingRule): """ CRD resource for Backend MappingRule. """ - GET_PATH = 'spec/mappingRules' + + GET_PATH = "spec/mappingRules" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -1915,15 +2304,16 @@ class Metric(DefaultResourceCRD, threescale_api.resources.Metric): """ CRD resource for Metric. """ - GET_PATH = 'spec/metrics' + + GET_PATH = "spec/metrics" system_name_to_id = {} id_to_system_name = {} - def __init__(self, entity_name='system_name', **kwargs): + def __init__(self, entity_name="system_name", **kwargs): entity = None - if 'spec' in kwargs: - spec = kwargs.pop('spec') - crd = kwargs.pop('crd') + if "spec" in kwargs: + spec = kwargs.pop("spec") + crd = kwargs.pop("crd") # client = kwargs.get('client') entity = {} for key, value in spec.items(): @@ -1931,8 +2321,8 @@ def __init__(self, entity_name='system_name', **kwargs): if key == walue: entity[cey] = value # simulate id because CRD has no ids - entity['id'] = (entity[entity_name], entity['unit']) - self.entity_id = entity.get('id') + entity["id"] = (entity[entity_name], entity["unit"]) + self.entity_id = entity.get("id") # it is not possible to simulate id here because # it is used in BackendMappingRules, which is not implemented # entity['id'] = Metric.system_name_to_id.get(entity['name'], None) @@ -1945,7 +2335,7 @@ def __init__(self, entity_name='system_name', **kwargs): # Metric.id_to_system_name[entity['id']] = entity['name'] # client.__class__.CRD_IMPLEMENTED = True - self.entity_id = entity['id'] + self.entity_id = entity["id"] super().__init__(crd=crd, entity=entity, entity_name=entity_name, **kwargs) else: # this is not here because of some backup, but because we need to have option @@ -1953,13 +2343,14 @@ def __init__(self, entity_name='system_name', **kwargs): super().__init__(entity_name=entity_name, **kwargs) @property - def service(self) -> 'Service': + def service(self) -> "Service": return self.parent @property - def methods(self) -> 'Methods': + def methods(self) -> "Methods": return Methods(parent=self, instance_klass=Method) + # @property # def entity_id(self) -> int: # return self._entity_id or self._entity.get('id') @@ -1974,11 +2365,11 @@ class BackendMetric(Metric): CRD resource for Backend Metric. """ - GET_PATH = 'spec/metrics' + GET_PATH = "spec/metrics" system_name_to_id = {} id_to_system_name = {} - def __init__(self, entity_name='system_name', *args, **kwargs): + def __init__(self, entity_name="system_name", *args, **kwargs): super().__init__(entity_name=entity_name, *args, **kwargs) @@ -1987,28 +2378,30 @@ class BackendUsage(DefaultResourceCRD, threescale_api.resources.BackendUsage): CRD resource for BackendUsage. """ - GET_PATH = 'spec/backendUsages' + GET_PATH = "spec/backendUsages" - def __init__(self, entity_name='system_name', **kwargs): + def __init__(self, entity_name="system_name", **kwargs): entity = None - if 'spec' in kwargs: - spec = kwargs.pop('spec') - crd = kwargs.pop('crd') - client = kwargs.get('client') + if "spec" in kwargs: + spec = kwargs.pop("spec") + crd = kwargs.pop("crd") + client = kwargs.get("client") entity = {} for key, value in spec.items(): for cey, walue in constants.KEYS_BACKEND_USAGE.items(): if key == walue: entity[cey] = value - entity['service_id'] = int(crd.as_dict().get('status', {}).get(Services.ID_NAME, 0)) - back = client.threescale_client.backends.read_by_name(spec['name']) + entity["service_id"] = int( + crd.as_dict().get("status", {}).get(Services.ID_NAME, 0) + ) + back = client.threescale_client.backends.read_by_name(spec["name"]) # # exception for deleting BackendUsage which is used in any proxy, # # backendusage should be removed first and then proxy.deploy should be performed # entity['backend_id'] = int(back['id']) if back['id'] else None - entity['backend_id'] = int(back['id']) + entity["backend_id"] = int(back["id"]) # simulate entity_id by list of attributes - entity['id'] = (entity['path'], entity['backend_id'], entity['service_id']) - self.entity_id = entity.get('id') + entity["id"] = (entity["path"], entity["backend_id"], entity["service_id"]) + self.entity_id = entity.get("id") super().__init__(crd=crd, entity=entity, entity_name=entity_name, **kwargs) else: @@ -2017,10 +2410,11 @@ def __init__(self, entity_name='system_name', **kwargs): super().__init__(entity_name=entity_name, **kwargs) @property - def service(self) -> 'Service': + def service(self) -> "Service": """Returns service related to backend usage""" return self.parent + # @property # def entity_id(self) -> int: # return self._entity_id or self._entity.get('id') @@ -2034,36 +2428,41 @@ class ApplicationPlan(DefaultResourceCRD, threescale_api.resources.ApplicationPl """ CRD resource for ApplicationPlan. """ - GET_PATH = 'spec/applicationPlans' + + GET_PATH = "spec/applicationPlans" system_name_to_id = {} id_to_system_name = {} - def __init__(self, entity_name='system_name', **kwargs): + def __init__(self, entity_name="system_name", **kwargs): entity = None - if 'spec' in kwargs: - spec = kwargs.pop('spec') - crd = kwargs.pop('crd') - client = kwargs.get('client') + if "spec" in kwargs: + spec = kwargs.pop("spec") + crd = kwargs.pop("crd") + client = kwargs.get("client") entity = {} for key, value in spec.items(): for cey, walue in constants.KEYS_APP_PLANS.items(): if key == walue: entity[cey] = value if entity_name in spec: - entity['name'] = spec[entity_name] - spec['state_event'] = 'publish' if spec.get('state_event', False) else 'unpublish' + entity["name"] = spec[entity_name] + spec["state_event"] = ( + "publish" if spec.get("state_event", False) else "unpublish" + ) # simulate id because CRD has no ids - entity['id'] = entity['name'] - # it is not possible to simulate id here because it is used in Application, which is not implemented - #entity['id'] = ApplicationPlan.system_name_to_id.get(entity['system_name'], None) - #if not entity['id']: + entity["id"] = entity["name"] + # it is not possible to simulate id here because it is used in Application, + # which is not implemented + # entity['id'] = ApplicationPlan.system_name_to_id.get(entity['system_name'], None) + # if not entity['id']: # client.disable_crd_implemented() - # plan = threescale_api.resources.ApplicationPlans.read_by_name(client, entity['system_name']) + # plan = threescale_api.resources.ApplicationPlans.read_by_name(client, + # entity['system_name']) # entity['id'] = plan['id'] # ApplicationPlan.system_name_to_id[entity['system_name']] = int(entity['id']) # ApplicationPlan.id_to_system_name[entity['id']] = entity['system_name'] # client.enable_crd_implemented() - self.entity_id = entity.get('id') + self.entity_id = entity.get("id") super().__init__(crd=crd, entity=entity, entity_name=entity_name, **kwargs) else: @@ -2072,7 +2471,7 @@ def __init__(self, entity_name='system_name', **kwargs): super().__init__(entity_name=entity_name, **kwargs) @property - def service(self) -> 'Service': + def service(self) -> "Service": """Returns service related to app. plan""" return self.parent @@ -2087,29 +2486,33 @@ def pricing_rules(self, metric): @property def plans_url(self) -> str: """Returns url to app. plans""" - return self.threescale_client.admin_api_url + f"/application_plans/{self.entity_id}" + return ( + self.threescale_client.admin_api_url + + f"/application_plans/{self.entity_id}" + ) class Account(DefaultResourceCRD, threescale_api.resources.Account): """ CRD resource for Account. """ - GET_PATH = 'spec' - def __init__(self, entity_name='org_name', **kwargs): + GET_PATH = "spec" + + def __init__(self, entity_name="org_name", **kwargs): entity = None - if 'spec' in kwargs: - spec = kwargs.pop('spec') - crd = kwargs.pop('crd') + if "spec" in kwargs: + spec = kwargs.pop("spec") + crd = kwargs.pop("crd") entity = {} for key, value in spec.items(): for cey, walue in constants.KEYS_ACCOUNT.items(): if key == walue: entity[cey] = value - status = crd.as_dict().get('status', None) + status = crd.as_dict().get("status", None) if status: - entity['id'] = status.get(Accounts.ID_NAME) - entity['name'] = crd.as_dict().get('metadata', {}).get('name') + entity["id"] = status.get(Accounts.ID_NAME) + entity["name"] = crd.as_dict().get("metadata", {}).get("name") super().__init__(crd=crd, entity=entity, entity_name=entity_name, **kwargs) else: @@ -2122,9 +2525,10 @@ def users(self) -> AccountUsers: account = self class FakeAccountUsers(AccountUsers): - """ Simulating AccountUsers class + """Simulating AccountUsers class to be able to process Account/AccountUsers workflow in CRDs. """ + def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.parent = account @@ -2133,41 +2537,44 @@ def __init__(self, *args, **kwargs): def list(self, **kwargs): LOG.info(self._log_message("[LIST] FakeAccountUsers CRD", args=kwargs)) if account: - return self.select_by(**{'account_name': account['name']}) + return self.select_by(**{"account_name": account["name"]}) return self._list(**kwargs) @property def url(self) -> str: - return account.url + '/users' + return account.url + "/users" return FakeAccountUsers(parent=self.parent, instance_klass=AccountUser) @property def applications(self) -> Applications: - return Applications(parent=self.parent, instance_klass=Application, account=self) + return Applications( + parent=self.parent, instance_klass=Application, account=self + ) class AccountUser(DefaultResourceCRD, threescale_api.resources.AccountUser): """ CRD resource for AccountUser. """ - GET_PATH = 'spec' - def __init__(self, entity_name='username', **kwargs): + GET_PATH = "spec" + + def __init__(self, entity_name="username", **kwargs): entity = None - if 'spec' in kwargs: - spec = kwargs.pop('spec') - crd = kwargs.pop('crd') + if "spec" in kwargs: + spec = kwargs.pop("spec") + crd = kwargs.pop("crd") entity = {} for key, value in spec.items(): for cey, walue in constants.KEYS_ACCOUNT_USER.items(): if key == walue: entity[cey] = value - status = crd.as_dict().get('status', None) + status = crd.as_dict().get("status", None) if status: - entity['id'] = status.get(AccountUsers.ID_NAME) + entity["id"] = status.get(AccountUsers.ID_NAME) # link to account because AccountUser is not nested class of Account - entity['account_name'] = spec['developerAccountRef']['name'] + entity["account_name"] = spec["developerAccountRef"]["name"] super().__init__(crd=crd, entity=entity, entity_name=entity_name, **kwargs) else: @@ -2177,14 +2584,14 @@ def __init__(self, entity_name='username', **kwargs): @staticmethod def create_password_secret(password, namespace): - """ Creates password in secret. """ - password_ascii = str(password).encode('ascii') + """Creates password in secret.""" + password_ascii = str(password).encode("ascii") password_enc = base64.b64encode(password_ascii) spec_sec = copy.deepcopy(constants.SPEC_SECRET) - name = secrets.token_urlsafe(8).lower().replace('_', '').replace('-', '') - spec_sec['metadata']['name'] = name - spec_sec['metadata']['namespace'] = namespace - spec_sec['data']['password'] = password_enc.decode('ascii') + name = secrets.token_urlsafe(8).lower().replace("_", "").replace("-", "") + spec_sec["metadata"]["name"] = name + spec_sec["metadata"]["namespace"] = namespace + spec_sec["data"]["password"] = password_enc.decode("ascii") result = ocp.create(spec_sec) assert result.status() == 0 return name @@ -2192,41 +2599,46 @@ def create_password_secret(password, namespace): # @property # def permissions(self) -> 'UserPermissionsClient': # return UserPermissionsClient(parent=self, instance_klass=UserPermissions) - + def _is_ready(self, obj): - """ Is object ready? """ - if not ('status' in obj.model and 'conditions' in obj.model.status): + """Is object ready?""" + if not ("status" in obj.model and "conditions" in obj.model.status): return False - state = {'Failed': True, 'Invalid': True, 'Orphan': False, 'Ready': False} - for sta in obj.as_dict()['status']['conditions']: - state[sta['type']] = (sta['status'] == 'True') + state = {"Failed": True, "Invalid": True, "Orphan": False, "Ready": False} + for sta in obj.as_dict()["status"]["conditions"]: + state[sta["type"]] = sta["status"] == "True" - return not state['Failed'] and\ - not state['Invalid'] and\ - state['Orphan'] != state['Ready'] + return ( + not state["Failed"] + and not state["Invalid"] + and state["Orphan"] != state["Ready"] + ) class Policy(DefaultResourceCRD, threescale_api.resources.Policy): """ CRD resource for Policy. """ - GET_PATH = 'spec/policies' - def __init__(self, entity_name='name', **kwargs): + GET_PATH = "spec/policies" + + def __init__(self, entity_name="name", **kwargs): entity = None - if 'spec' in kwargs: - spec = kwargs.pop('spec') - crd = kwargs.pop('crd') + if "spec" in kwargs: + spec = kwargs.pop("spec") + crd = kwargs.pop("crd") # client = kwargs.get('client') entity = {} for key, value in spec.items(): for cey, walue in constants.KEYS_POLICY.items(): if key == walue: entity[cey] = value - entity['service_id'] = int(crd.as_dict().get('status', {}).get(Services.ID_NAME, 0)) + entity["service_id"] = int( + crd.as_dict().get("status", {}).get(Services.ID_NAME, 0) + ) # simulate entity_id by list of attributes - entity['id'] = (entity['service_id'], entity['name']) - self.entity_id = entity.get('id') + entity["id"] = (entity["service_id"], entity["name"]) + self.entity_id = entity.get("id") super().__init__(crd=crd, entity=entity, entity_name=entity_name, **kwargs) else: @@ -2235,9 +2647,10 @@ def __init__(self, entity_name='name', **kwargs): super().__init__(entity=entity, entity_name=entity_name, **kwargs) @property - def service(self) -> 'Service': + def service(self) -> "Service": return self.parent + # @property # def entity_id(self) -> int: # return self._entity_id or self._entity.get('id') @@ -2252,41 +2665,46 @@ class OpenApi(DefaultResourceCRD): CRD resource for OpenApi. """ - GET_PATH = 'spec' + GET_PATH = "spec" - def __init__(self, entity_name='name', **kwargs): + def __init__(self, entity_name="name", **kwargs): entity = None crd = None - if 'spec' in kwargs: - spec = kwargs.pop('spec') - crd = kwargs.pop('crd') + if "spec" in kwargs: + spec = kwargs.pop("spec") + crd = kwargs.pop("crd") entity = {} for key, value in spec.items(): for cey, walue in constants.KEYS_OPEN_API.items(): if key == walue: entity[cey] = value - status = crd.as_dict().get('status') - entity['id'] = status.get(OpenApis.ID_NAME) - entity['productResourceName'] = status.get('productResourceName', {}).get('name') - entity['backendResourceNames'] = [] - for back_name in status.get('backendResourceNames', []): - entity['backendResourceNames'].append(back_name.get('name')) - OpenApiRef.load_openapi(entity, spec['openapiRef']) + status = crd.as_dict().get("status") + entity["id"] = status.get(OpenApis.ID_NAME) + entity["productResourceName"] = status.get("productResourceName", {}).get( + "name" + ) + entity["backendResourceNames"] = [] + for back_name in status.get("backendResourceNames", []): + entity["backendResourceNames"].append(back_name.get("name")) + OpenApiRef.load_openapi(entity, spec["openapiRef"]) super().__init__(crd=crd, entity=entity, entity_name=entity_name, **kwargs) @property - def service(self) -> 'Service': - return self.threescale_client.services.fetch_crd_entity(self.entity['productResourceName']) + def service(self) -> "Service": + return self.threescale_client.services.fetch_crd_entity( + self.entity["productResourceName"] + ) @property def backends(self) -> list: ret = [] - for back_name in self.entity['backendResourceNames']: + for back_name in self.entity["backendResourceNames"]: ret.append(self.threescale_client.backends.fetch_crd_entity(back_name)) return ret + class Tenant(DefaultResourceCRD, threescale_api.resources.Tenant): """ CRD resource for Policy. @@ -2294,11 +2712,11 @@ class Tenant(DefaultResourceCRD, threescale_api.resources.Tenant): FOLD = ["signup", "account"] - def __init__(self, entity_name='username', **kwargs): + def __init__(self, entity_name="username", **kwargs): entity = None - if 'spec' in kwargs: - spec = kwargs.pop('spec') - crd = kwargs.pop('crd') + if "spec" in kwargs: + spec = kwargs.pop("spec") + crd = kwargs.pop("crd") entity = {Tenant.FOLD[0]: {Tenant.FOLD[1]: {}}} insert = entity[Tenant.FOLD[0]][Tenant.FOLD[1]] for key, value in spec.items(): @@ -2306,13 +2724,19 @@ def __init__(self, entity_name='username', **kwargs): if key == walue: insert[cey] = value - insert['id'] = crd.as_dict()['status'][Tenants.ID_NAME] - self.entity_id = insert.get('id') + insert["id"] = crd.as_dict()["status"][Tenants.ID_NAME] + self.entity_id = insert.get("id") # get secret created by operator - sec_data = ocp.selector('secret/' + insert['tenantSecretRef']['name']).objects()[0].as_dict()['data'] - insert['admin_base_url'] = base64.b64decode(sec_data['adminURL']) - entity[Tenant.FOLD[0]]['access_token'] = {'value': base64.b64decode(sec_data['token'])} - insert['base_url'] = insert['admin_base_url'] + sec_data = ( + ocp.selector("secret/" + insert["tenantSecretRef"]["name"]) + .objects()[0] + .as_dict()["data"] + ) + insert["admin_base_url"] = base64.b64decode(sec_data["adminURL"]) + entity[Tenant.FOLD[0]]["access_token"] = { + "value": base64.b64decode(sec_data["token"]) + } + insert["base_url"] = insert["admin_base_url"] super().__init__(crd=crd, entity=entity, entity_name=entity_name, **kwargs) else: @@ -2330,47 +2754,71 @@ class Limit(DefaultResourceCRD, threescale_api.resources.Limit): """ CRD resource for Limit. """ - def __init__(self, entity_name='name', **kwargs): + + def __init__(self, entity_name="name", **kwargs): entity = None - if 'spec' in kwargs: - spec = kwargs.pop('spec') - crd = kwargs.pop('crd') - client = kwargs.get('client') + if "spec" in kwargs: + spec = kwargs.pop("spec") + crd = kwargs.pop("crd") + client = kwargs.get("client") entity = {} for key, value in spec.items(): for cey, walue in constants.KEYS_LIMIT.items(): if key == walue: entity[cey] = value - entity['plan_id'] = client.parent['id'] - entity['metric_name'] = spec['metricMethodRef']['systemName'] + entity["plan_id"] = client.parent["id"] + entity["metric_name"] = spec["metricMethodRef"]["systemName"] backend = None - if 'backend' in spec['metricMethodRef']: - entity['backend_name'] = spec['metricMethodRef']['backend'] - entity['metric_id'] = BackendMetric.system_name_to_id.get(entity['metric_name'], None) - backend = client.threescale_client.backends.read_by_name(entity['backend_name']) + if "backend" in spec["metricMethodRef"]: + entity["backend_name"] = spec["metricMethodRef"]["backend"] + entity["metric_id"] = BackendMetric.system_name_to_id.get( + entity["metric_name"], None + ) + backend = client.threescale_client.backends.read_by_name( + entity["backend_name"] + ) # simulate id because CRD has no ids - entity['id'] = (entity['period'], entity['metric_name'], entity['backend_name']) + entity["id"] = ( + entity["period"], + entity["metric_name"], + entity["backend_name"], + ) else: - entity['metric_id'] = Metric.system_name_to_id.get(entity['metric_name'], None) + entity["metric_id"] = Metric.system_name_to_id.get( + entity["metric_name"], None + ) # simulate id because CRD has no ids - entity['id'] = (entity['period'], entity['metric_name']) - self.entity_id = entity.get('id') - if not entity['metric_id']: - if 'backend' in spec['metricMethodRef']: + entity["id"] = (entity["period"], entity["metric_name"]) + self.entity_id = entity.get("id") + if not entity["metric_id"]: + if "backend" in spec["metricMethodRef"]: backend.metrics.disable_crd_implemented() - entity['metric_id'] = int(threescale_api.resources.BackendMetrics.read_by_name( - backend.metrics, - entity['metric_name'] + '.' + str(backend['id'])).entity_id) - BackendMetric.system_name_to_id[entity['metric_name']] = entity['metric_id'] - BackendMetric.id_to_system_name[entity['metric_id']] = entity['metric_name'] + entity["metric_id"] = int( + threescale_api.resources.BackendMetrics.read_by_name( + backend.metrics, + entity["metric_name"] + "." + str(backend["id"]), + ).entity_id + ) + BackendMetric.system_name_to_id[entity["metric_name"]] = entity[ + "metric_id" + ] + BackendMetric.id_to_system_name[entity["metric_id"]] = entity[ + "metric_name" + ] backend.metrics.enable_crd_implemented() else: client.topmost_parent().metrics.disable_crd_implemented() - entity['metric_id'] = int(threescale_api.resources.Metrics.read_by_name( - client.topmost_parent().metrics, - entity['metric_name']).entity_id) - Metric.system_name_to_id[entity['metric_name']] = entity['metric_id'] - Metric.id_to_system_name[entity['metric_id']] = entity['metric_name'] + entity["metric_id"] = int( + threescale_api.resources.Metrics.read_by_name( + client.topmost_parent().metrics, entity["metric_name"] + ).entity_id + ) + Metric.system_name_to_id[entity["metric_name"]] = entity[ + "metric_id" + ] + Metric.id_to_system_name[entity["metric_id"]] = entity[ + "metric_name" + ] client.topmost_parent().metrics.enable_crd_implemented() super().__init__(crd=crd, entity=entity, entity_name=entity_name, **kwargs) @@ -2388,47 +2836,72 @@ class PricingRule(DefaultResourceCRD, threescale_api.resources.PricingRule): """ CRD resource for PricingRule. """ - def __init__(self, entity_name='name', **kwargs): + + def __init__(self, entity_name="name", **kwargs): entity = None - if 'spec' in kwargs: - spec = kwargs.pop('spec') - crd = kwargs.pop('crd') - client = kwargs.get('client') + if "spec" in kwargs: + spec = kwargs.pop("spec") + crd = kwargs.pop("crd") + client = kwargs.get("client") entity = {} for key, value in spec.items(): for cey, walue in constants.KEYS_PRICING_RULE.items(): if key == walue: entity[cey] = value - entity['plan_id'] = client.parent['id'] - entity['metric_name'] = spec['metricMethodRef']['systemName'] + entity["plan_id"] = client.parent["id"] + entity["metric_name"] = spec["metricMethodRef"]["systemName"] backend = None - if 'backend' in spec['metricMethodRef']: - entity['backend_name'] = spec['metricMethodRef']['backend'] - entity['metric_id'] = BackendMetric.system_name_to_id.get(entity['metric_name'], None) - backend = client.threescale_client.backends.read_by_name(entity['backend_name']) + if "backend" in spec["metricMethodRef"]: + entity["backend_name"] = spec["metricMethodRef"]["backend"] + entity["metric_id"] = BackendMetric.system_name_to_id.get( + entity["metric_name"], None + ) + backend = client.threescale_client.backends.read_by_name( + entity["backend_name"] + ) # simulate id because CRD has no ids - entity['id'] = (entity['min'], entity['max'], entity['metric_name'], entity['backend_name']) + entity["id"] = ( + entity["min"], + entity["max"], + entity["metric_name"], + entity["backend_name"], + ) else: - entity['metric_id'] = Metric.system_name_to_id.get(entity['metric_name'], None) + entity["metric_id"] = Metric.system_name_to_id.get( + entity["metric_name"], None + ) # simulate id because CRD has no ids - entity['id'] = (entity['min'], entity['max'], entity['metric_name']) - self.entity_id = entity.get('id') - if not entity['metric_id']: - if 'backend' in spec['metricMethodRef']: + entity["id"] = (entity["min"], entity["max"], entity["metric_name"]) + self.entity_id = entity.get("id") + if not entity["metric_id"]: + if "backend" in spec["metricMethodRef"]: backend.metrics.disable_crd_implemented() - entity['metric_id'] = int(threescale_api.resources.BackendMetrics.read_by_name( - backend.metrics, - entity['metric_name'] + '.' + str(backend['id'])).entity_id) - BackendMetric.system_name_to_id[entity['metric_name']] = entity['metric_id'] - BackendMetric.id_to_system_name[entity['metric_id']] = entity['metric_name'] + entity["metric_id"] = int( + threescale_api.resources.BackendMetrics.read_by_name( + backend.metrics, + entity["metric_name"] + "." + str(backend["id"]), + ).entity_id + ) + BackendMetric.system_name_to_id[entity["metric_name"]] = entity[ + "metric_id" + ] + BackendMetric.id_to_system_name[entity["metric_id"]] = entity[ + "metric_name" + ] backend.metrics.enable_crd_implemented() else: client.topmost_parent().metrics.disable_crd_implemented() - entity['metric_id'] = int(threescale_api.resources.Metrics.read_by_name( - client.topmost_parent().metrics, - entity['metric_name']).entity_id) - Metric.system_name_to_id[entity['metric_name']] = entity['metric_id'] - Metric.id_to_system_name[entity['metric_id']] = entity['metric_name'] + entity["metric_id"] = int( + threescale_api.resources.Metrics.read_by_name( + client.topmost_parent().metrics, entity["metric_name"] + ).entity_id + ) + Metric.system_name_to_id[entity["metric_name"]] = entity[ + "metric_id" + ] + Metric.id_to_system_name[entity["metric_id"]] = entity[ + "metric_name" + ] client.topmost_parent().metrics.enable_crd_implemented() super().__init__(crd=crd, entity=entity, entity_name=entity_name, **kwargs) @@ -2447,21 +2920,21 @@ class Promote(DefaultResourceCRD): CRD resource for ProxyConfigPromote. """ - GET_PATH = 'spec' + GET_PATH = "spec" - def __init__(self, entity_name='name', **kwargs): + def __init__(self, entity_name="name", **kwargs): entity = None crd = None - if 'spec' in kwargs: - spec = kwargs.pop('spec') - crd = kwargs.pop('crd') + if "spec" in kwargs: + spec = kwargs.pop("spec") + crd = kwargs.pop("crd") entity = {} for key, value in spec.items(): for cey, walue in constants.KEYS_PROMOTE.items(): if key == walue: entity[cey] = value - entity['id'] = crd.as_dict().get('status', {}).get(Promotes.ID_NAME, None) + entity["id"] = crd.as_dict().get("status", {}).get(Promotes.ID_NAME, None) super().__init__(crd=crd, entity=entity, entity_name=entity_name, **kwargs) @@ -2470,38 +2943,39 @@ class Application(DefaultResourceCRD, threescale_api.resources.Application): """ CRD resource for Application. """ - GET_PATH = 'spec' - def __init__(self, entity_name='name', **kwargs): + GET_PATH = "spec" + + def __init__(self, entity_name="name", **kwargs): entity = None - if 'spec' in kwargs: + if "spec" in kwargs: entity = {} - spec = kwargs.pop('spec') - crd = kwargs.pop('crd') + spec = kwargs.pop("spec") + crd = kwargs.pop("crd") for key, value in spec.items(): for cey, walue in constants.KEYS_APPLICATION.items(): if key == walue: entity[cey] = value - status = crd.as_dict().get('status') - entity['id'] = status.get(Applications.ID_NAME) - entity['state'] = status.get('state') + status = crd.as_dict().get("status") + entity["id"] = status.get(Applications.ID_NAME) + entity["state"] = status.get("state") - entity['service_name'] = spec.get('productCR').get('name') - entity['account_name'] = spec.get('accountCR').get('name') + entity["service_name"] = spec.get("productCR").get("name") + entity["account_name"] = spec.get("accountCR").get("name") # load auth keys - client = kwargs['client'] + client = kwargs["client"] client.disable_crd_implemented() - acc = client.parent.accounts.select_by(name=entity['account_name'])[0] - app = acc.applications.read(entity['id']) - auth = app.service['backend_version'] + acc = client.parent.accounts.select_by(name=entity["account_name"])[0] + app = acc.applications.read(entity["id"]) + auth = app.service["backend_version"] if auth == Service.AUTH_USER_KEY: - entity['user_key'] = app['user_key'] + entity["user_key"] = app["user_key"] elif auth == Service.AUTH_APP_ID_KEY: - entity['application_id'] = app['application_id'] + entity["application_id"] = app["application_id"] elif auth == Service.AUTH_OIDC: - entity['client_id'] = app['client_id'] - entity['client_secret'] = app['client_secret'] + entity["client_id"] = app["client_id"] + entity["client_secret"] = app["client_secret"] client.enable_crd_implemented() super().__init__(crd=crd, entity=entity, entity_name=entity_name, **kwargs) @@ -2511,16 +2985,16 @@ def __init__(self, entity_name='name', **kwargs): super().__init__(entity_name=entity_name, **kwargs) @property - def service(self) -> 'Service': + def service(self) -> "Service": "The service to which this application is bound" - return self.parent.services.read_by_name(self.entity['service_name']) + return self.parent.services.read_by_name(self.entity["service_name"]) @property - def account(self) -> 'Account': + def account(self) -> "Account": if self.client.account: return self.client.account else: - return self.parent.accounts.read_by_name(self.entity['account_name']) + return self.parent.accounts.read_by_name(self.entity["account_name"]) def set_state(self, state: str): """Sets the state for the resource @@ -2532,14 +3006,14 @@ def set_state(self, state: str): """ app = self status = None - if state == 'suspend': - app = self.update({'suspend': True}) - status = 'suspended' - if state == 'resume': - app = self.update({'suspend': False}) - status = 'live' + if state == "suspend": + app = self.update({"suspend": True}) + status = "suspended" + if state == "resume": + app = self.update({"suspend": False}) + status = "live" counters = [89, 55, 34, 21, 13, 8, 5, 3, 2, 1, 1, 1] - while app['state'] != status and len(counters): + while app["state"] != status and len(counters): time.sleep(counters.pop()) app = app.read() @@ -2547,29 +3021,29 @@ def set_state(self, state: str): class Method(DefaultResourceCRD, threescale_api.resources.Method): - GET_PATH = 'spec/methods' + GET_PATH = "spec/methods" system_name_to_id = {} id_to_system_name = {} - def __init__(self, entity_name='system_name', **kwargs): + def __init__(self, entity_name="system_name", **kwargs): entity = None - if 'spec' in kwargs: - spec = kwargs.pop('spec') - crd = kwargs.pop('crd') + if "spec" in kwargs: + spec = kwargs.pop("spec") + crd = kwargs.pop("crd") entity = {} for key, value in spec.items(): for cey, walue in constants.KEYS_METHOD.items(): if key == walue: entity[cey] = value # simulate id because CRD has no ids - if 'name' not in entity: - entity['name'] = entity['friendly_name'] + if "name" not in entity: + entity["name"] = entity["friendly_name"] if entity_name not in entity: - entity[entity_name] = entity['friendly_name'] - entity['id'] = entity[entity_name] - self.entity_id = entity.get('id') + entity[entity_name] = entity["friendly_name"] + entity["id"] = entity[entity_name] + self.entity_id = entity.get("id") - self.entity_id = entity['id'] + self.entity_id = entity["id"] super().__init__(crd=crd, entity=entity, entity_name=entity_name, **kwargs) else: # this is not here because of some backup, but because we need to have option @@ -2577,9 +3051,9 @@ def __init__(self, entity_name='system_name', **kwargs): super().__init__(entity_name=entity_name, **kwargs) @property - def metric(self) -> 'Metric': - return self.parent.metrics.read_by_name('hits') + def metric(self) -> "Metric": + return self.parent.metrics.read_by_name("hits") @property - def service(self) -> 'Service': + def service(self) -> "Service": return self.parent.parent