Skip to content

enable smoke test with CRD 3scale client #643

New issue

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

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

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ speedrun: ## Bigger than smoke faster than test
speedrun: pipenv check-secrets.yaml
$(PYTEST) -n4 --dist loadfile -m 'not flaky' --drop-sandbag $(flags) testsuite

capabilities-speedrun: pipenv check-secrets.yaml
$(PYTEST) -n1 -m 'not flaky' --drop-sandbag --capabilities $(flags) testsuite

sandbag: ## Complemetary set to speedrun that makes the rest of test target (speedrun+sandbag == test)
sandbag: pipenv
$(PYTEST) -n4 --dist loadfile -m 'not flaky' --sandbag $(flags) testsuite
Expand All @@ -86,6 +89,9 @@ debug: test
smoke: pipenv check-secrets.yaml
$(PYTEST) -n6 -msmoke $(flags) testsuite

capabilities-smoke: pipenv check-secrets.yaml
$(PYTEST) -n3 -msmoke --capabilities $(flags) testsuite

flaky: pipenv check-secrets.yaml
$(PYTEST) -mflaky $(flags) testsuite

Expand Down
3 changes: 3 additions & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -61,5 +61,8 @@ pytest-metadata = ">=3.0.0"
pytest-html = "*"
ansi2html = "*"

# 3scale Capabilities API client
3scale-api-crd = "*"

[requires]
python_version = "3"
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,12 @@ Alternatively it can be set in the configuration.
`make disruptive NAMESPACE=3scale`
- tests with side-effect

`make capabilities-smoke NAMESPACE=3scale`
- smoke tests using 3scale Capabilities client instead of 3scale API client

`make capabilities-speedrun NAMESPACE=3scale`
- speedrun tests using 3scale Capabilities client instead of 3scale API client

Targets can be combined

`make test flaky NAMESPACE=3scale`
Expand All @@ -171,6 +177,13 @@ Targets can be combined
`make ./testsuite/tests/apicast/auth/test_basic_auth_user_key.py NAMESPACE=3scale`
- to run particular test standalone

### 3scale Capabilities

By default 3scale REST API client is used. 3scale Capabilities client can be used
instead of 3scale REST API client by using `--capabilities` argument. This argument
unlock running of specific Capabilities tests. For more information about 3scale Capabilities
see https://github.com/3scale/3scale-operator/blob/master/doc/operator-application-capabilities.md

### Test Selection, Marks and Custom Arguments

Selection of tests in the targets described above is based on pytest marks and
Expand Down
1 change: 1 addition & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ markers =
issue: Reference to covered issue
nopersistence: Tests incompatible with persistence plugin
skipif_devrelease: Mark tests that should not run on alpha builds
nocrcap: Tests which are not compatible with CR capabilities API client
filterwarnings =
ignore: WARNING the new order is not taken into account:UserWarning
ignore::urllib3.exceptions.InsecureRequestWarning
Expand Down
24 changes: 21 additions & 3 deletions testsuite/rawobj.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,22 +49,35 @@ def Method(system_name: str, friendly_name: str = None, unit: str = "hit"):

if friendly_name is None:
friendly_name = system_name
# pylint: disable=possibly-unused-variable
name = system_name
return locals()


# pylint: disable=unused-argument
def Mapping(metric: dict, pattern: str = "/", http_method: str = "GET", delta: int = 1, last: str = "false"):
# pylint: disable=too-many-arguments
def Mapping(
metric: dict,
pattern: str = "/",
http_method: str = "GET",
delta: int = 1,
last: str = "false",
position: int = None,
):
"""Builder of parameters to create Mapping
Args:
:param metric: Metric to be mapped
:param pattern: URL pattern to map; deafult: /
:param http_method: Method to map; default: GET
:param delta: Incremental unit; default: 1
:param last: If true, no other rules will be processed after
matching this one; default: false"""
matching this one; default: false
:param position: position in list of mapping rules"""

metric_id = metric["id"] # pylint: disable=possibly-unused-variable
del metric
if position is None:
del position
return locals()


Expand All @@ -83,7 +96,12 @@ def Application(
if description is None:
description = f"application {name}"

obj = {"name": name, "plan_id": application_plan["id"], "description": description}
obj = {
"name": name,
"plan_id": application_plan["id"],
"description": description,
"service_id": application_plan.service["id"],
}

if account is not None:
obj["account_id"] = account["id"]
Expand Down
7 changes: 6 additions & 1 deletion testsuite/rhsso/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,12 @@ def __init__(self, rhsso_service_info, credentials_location="authorization", oid
self.credentials_location = credentials_location
self.oidc_configuration = oidc_configuration
if self.oidc_configuration is None:
self.oidc_configuration = {"standard_flow_enabled": False, "direct_access_grants_enabled": True}
self.oidc_configuration = {
"standard_flow_enabled": False,
"direct_access_grants_enabled": True,
"implicit_flow_enabled": False,
"service_accounts_enabled": False,
}

# pylint: disable=no-self-use
def before_service(self, service_params: dict) -> dict:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def mapping_rules(service, backend_bin, backend_echo):
- Add mapping rule with path "/anything/bin"
"""
proxy = service.proxy.list()
proxy.mapping_rules.delete(proxy.mapping_rules.list()[0]["id"])
proxy.mapping_rules.list()[0].delete()

test_metric = backend_echo.metrics.list()[0]
bin_metric = backend_bin.metrics.list()[0]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def client(api_client, service):
assert api_client().get("/get").status_code == 200

proxy = service.proxy.list()
proxy.mapping_rules.delete(proxy.mapping_rules.list()[0]["id"])
proxy.mapping_rules.list()[0].delete()
proxy.deploy()

return api_client(disable_retry_status_list={404})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def api_client(api_client, service):

assert api_client().get("/bin/anything").status_code == 200

proxy.mapping_rules.delete(proxy.mapping_rules.list()[0]["id"])
proxy.mapping_rules.list()[0].delete()
proxy.deploy()

return api_client(disable_retry_status_list={404})
Expand Down
2 changes: 1 addition & 1 deletion testsuite/tests/apicast/apiap/test_backend_routing.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def client(api_client, proxy):

assert api_client().get("/echo/anything").status_code == 200

proxy.mapping_rules.delete(proxy.mapping_rules.list()[0]["id"])
proxy.mapping_rules.list()[0].delete()
proxy.deploy()

return api_client(disable_retry_status_list={404})
Expand Down
2 changes: 1 addition & 1 deletion testsuite/tests/apicast/apiap/test_proxy_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def service(custom_service, service_settings):
"""
Create a custom service without backend
"""
return custom_service(service_settings)
return custom_service(service_settings, proxy_params={}, backends={})


def test_proxy_config(service, private_base_url):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def delete_all_mapping_rules(proxy):
"""Deletes all mapping rules in a given proxy."""
mapping_rules = proxy.mapping_rules.list()
for mapping_rule in mapping_rules:
proxy.mapping_rules.delete(mapping_rule["id"])
mapping_rule.delete()


@pytest.fixture(scope="module")
Expand Down
2 changes: 1 addition & 1 deletion testsuite/tests/apicast/parameters/test_proxy_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def test_proxy_config(service, api_client):
metric = service.metrics.list()[0]
mapping_rules = service.proxy.mapping_rules

mapping_rules.delete(mapping_rules.list()[0]["id"])
mapping_rules.list()[0].delete()
mapping_rules.create(rawobj.Mapping(metric, pattern="/foo"))
service.proxy.deploy()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def service(service):
metric = service.metrics.list()[0]

# delete implicit '/' rule
proxy.mapping_rules.delete(proxy.mapping_rules.list()[0]["id"])
proxy.mapping_rules.list()[0].delete()

proxy.mapping_rules.create(rawobj.Mapping(metric, pattern="/get"))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def service(service, metric_name):
metric = service.metrics.create(rawobj.Metric(metric_name))

# delete implicit '/' rule
proxy.mapping_rules.delete(proxy.mapping_rules.list()[0]["id"])
proxy.mapping_rules.list()[0].delete()

service.proxy.list().mapping_rules.create(rawobj.Mapping(metric, "/", "GET"))
service.proxy.list().update()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def mapping_rules(service, backend_bin, backend_echo):
- Add mapping rule with path "/anything/bin"
"""
proxy = service.proxy.list()
proxy.mapping_rules.delete(proxy.mapping_rules.list()[0]["id"])
proxy.mapping_rules.list()[0].delete()

test_metric = backend_echo.metrics.list()[0]
bin_metric = backend_bin.metrics.list()[0]
Expand Down
2 changes: 1 addition & 1 deletion testsuite/tests/apicast/policy/test_policy_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def custom_policies(threescale, schema, request, testconfig):

def _cleanup():
for policy in policies:
threescale.policy_registry.delete(policy["id"])
policy.delete()

if not testconfig["skip_cleanup"]:
request.addfinalizer(_cleanup)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def delete_all_mapping_rules(proxy):
"""Deletes all mapping rules in a given proxy."""
mapping_rules = proxy.mapping_rules.list()
for mapping_rule in mapping_rules:
proxy.mapping_rules.delete(mapping_rule["id"])
mapping_rule.delete()


@pytest.fixture(scope="module")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ def mapping_rules(service, backend_orig, backend_new):
Adds the "/" mapping rule to both backends.
"""
proxy = service.proxy.list()
proxy.mapping_rules.delete(proxy.mapping_rules.list()[0]["id"])
proxy.mapping_rules.list()[0].delete()

orig_metric = backend_orig.metrics.list()[0]
new_metric = backend_new.metrics.list()[0]
Expand Down
Empty file.
47 changes: 40 additions & 7 deletions testsuite/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
import pytest
from dynaconf.vendor.box.exceptions import BoxKeyError
from pytest_metadata.plugin import metadata_key
from threescale_api import client, errors
from threescale_api_crd import client as crd_client
from threescale_api import client as rest_client
from threescale_api import errors
from weakget import weakget

# to actually initialize all the providers
Expand Down Expand Up @@ -51,6 +53,13 @@ def term_handler():
signal.signal(signal.SIGTERM, orig)


@pytest.fixture(scope="session")
def api_client_type(pytestconfig):
"""Do tests use REST API client(False) or CR Capabilities client(True)?"""
Comment on lines +57 to +58
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rename this fixture to something like use_capabilities_client to match bool return value and for more clear usage later in the code.


return pytestconfig.getoption("capabilities")


def pytest_addoption(parser):
"""Add option to include disruptive tests in testrun"""

Expand Down Expand Up @@ -78,6 +87,9 @@ def pytest_addoption(parser):
help="Skip tests incompatible with persistence " "plugin (default: False)",
)
parser.addoption("--images", action="store_true", default=False, help="Run also image check tests (default: False)")
parser.addoption(
"--capabilities", action="store_true", default=False, help="Run tests with CR api client (default: False)"
)


# there are many branches as there are many options to influence test selection
Expand Down Expand Up @@ -125,6 +137,10 @@ def pytest_runtest_setup(item):
else:
if Capability.APICAST not in CapabilityRegistry():
pytest.skip(f"Skipping test because current gateway doesn't have implicit capability {Capability.APICAST}")
if "/cr_capabilities/" in item.nodeid and not item.config.getoption("--capabilities"):
pytest.skip("Excluding CR Capabilities tests")
if "nocrcap" in marks and item.config.getoption("--capabilities"):
pytest.skip("Excluding tests incompatible with CR capabilities")


@pytest.hookimpl(hookwrapper=True)
Expand Down Expand Up @@ -374,9 +390,8 @@ def testconfig():


@pytest.fixture(scope="session", autouse=True)
def threescale(testconfig, request):
def threescale(testconfig, request, api_client_type):
"Threescale client"

if weakget(testconfig)["fixtures"]["threescale"]["private_tenant"] % False:
custom_tenant = request.getfixturevalue("custom_tenant")
password = secrets.token_urlsafe(16)
Expand All @@ -399,7 +414,16 @@ def threescale(testconfig, request):

return admin

return client.ThreeScaleClient(
if api_client_type:
return crd_client.ThreeScaleClientCRD(
testconfig["threescale"]["admin"]["url"],
testconfig["threescale"]["admin"]["token"],
ssl_verify=testconfig["ssl_verify"],
ocp_namespace=testconfig["openshift"]["projects"]["threescale"]["name"],
wait=0,
)

return rest_client.ThreeScaleClient(
testconfig["threescale"]["admin"]["url"],
testconfig["threescale"]["admin"]["token"],
ssl_verify=testconfig["ssl_verify"],
Expand All @@ -408,10 +432,18 @@ def threescale(testconfig, request):


@pytest.fixture(scope="session")
def master_threescale(testconfig):
def master_threescale(testconfig, api_client_type):
"""Threescale client using master url and token"""

return client.ThreeScaleClient(
if api_client_type:
return crd_client.ThreeScaleClientCRD(
testconfig["threescale"]["master"]["url"],
testconfig["threescale"]["master"]["token"],
ssl_verify=testconfig["ssl_verify"],
ocp_namespace=testconfig["openshift"]["projects"]["threescale"]["name"],
)

return rest_client.ThreeScaleClient(
testconfig["threescale"]["master"]["url"],
testconfig["threescale"]["master"]["token"],
ssl_verify=testconfig["ssl_verify"],
Expand Down Expand Up @@ -841,6 +873,8 @@ def _custom_service(
params["description"] = blame_desc(request, params.get("description"))

svc = threescale_client.services.create(params=params)
if len(svc.mapping_rules.list()) == 0:
svc.mapping_rules.create(rawobj.Mapping(svc.metrics.list()[0], pattern="/"))

self._autoclean = autoclean
if not testconfig["skip_cleanup"]:
Expand All @@ -851,7 +885,6 @@ def finalizer():
hook(svc)
except Exception: # pylint: disable=broad-except
pass

svc.delete()

with self._lock:
Expand Down
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
@pytest.fixture(scope="module")
def service(service):
"""Removes default mapping rule from service"""
service.mapping_rules.delete(service.mapping_rules.list()[0].entity_id)
service.mapping_rules.list()[0].delete()
service.proxy.deploy()
return service

Expand Down
2 changes: 1 addition & 1 deletion testsuite/tests/system/mapping/test_mapping_rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def service(service, endpoints_and_methods):
metric = service.metrics.create(rawobj.Metric("metric"))

# delete implicit '/' rule
proxy.mapping_rules.delete(proxy.mapping_rules.list()[0]["id"])
proxy.mapping_rules.list()[0].delete()

for url, method in endpoints_and_methods:
proxy.mapping_rules.create(rawobj.Mapping(metric, pattern=url, http_method=method))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def proxy(service):
def delete_mapping(proxy):
"""Deletes all current mapping on the product level"""
proxy.deploy()
proxy.mapping_rules.delete(proxy.mapping_rules.list()[0]["id"])
proxy.mapping_rules.list()[0].delete()
proxy.deploy()


Expand Down
2 changes: 1 addition & 1 deletion testsuite/tests/toolbox/test_proxycfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ def test_list1(service, hits, empty_list_staging, create_cmd):

mapping_rules = proxy.mapping_rules.list()
for mapping_rule in mapping_rules:
proxy.mapping_rules.delete(mapping_rule["id"])
mapping_rule.delete()

proxy.mapping_rules.create(rawobj.Mapping(hits, "/ip"))
proxy.mapping_rules.create(rawobj.Mapping(hits, "/anything", "POST"))
Expand Down
Loading