Skip to content

Commit 3420ded

Browse files
author
Kumar Gaurav Sharma
committed
Use fixture for service_bootstrap resources and input replacements
1 parent 181a777 commit 3420ded

File tree

6 files changed

+82
-70
lines changed

6 files changed

+82
-70
lines changed

test/declarative_test_fwk/helper.py

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,9 @@
1818
from time import sleep
1919
from acktest.k8s import resource as k8s
2020

21-
input_replacements_dict = dict()
2221
TEST_HELPERS = dict()
2322

2423

25-
def input_replacements(provider):
26-
"""
27-
Decorator to discover input replacements
28-
:param provider: function that returns input replacements
29-
:return: provider
30-
"""
31-
global input_replacements_dict
32-
input_replacements_dict = provider()
33-
return provider
34-
35-
3624
def resource_helper(resource_kind: str):
3725
"""
3826
Decorator to discover Custom Resource Helper
@@ -51,25 +39,27 @@ class ResourceHelper:
5139
"""
5240
DEFAULT_WAIT_SECS = 30
5341

54-
def create(self, input_data: dict):
42+
def create(self, input_data: dict, input_replacements: dict = {}):
5543
"""
5644
Creates custom resource
5745
:param input_data: resource details
46+
:param input_replacements: input replacements
5847
:return: k8s.CustomResourceReference, created custom resource
5948
"""
60-
reference = self.custom_resource_reference(input_data)
49+
reference = self.custom_resource_reference(input_data, input_replacements)
6150
_ = k8s.create_custom_resource(reference, input_data)
6251
resource = k8s.wait_resource_consumed_by_controller(reference, wait_periods=10)
6352
assert resource is not None
6453
return (reference, resource)
6554

66-
def patch(self, input_data: dict):
55+
def patch(self, input_data: dict, input_replacements: dict = {}):
6756
"""
6857
Patches custom resource
6958
:param input_data: resource patch details
59+
:param input_replacements: input replacements
7060
:return: k8s.CustomResourceReference, created custom resource
7161
"""
72-
reference = self.custom_resource_reference(input_data)
62+
reference = self.custom_resource_reference(input_data, input_replacements)
7363
_ = k8s.patch_custom_resource(reference, input_data)
7464
sleep(self.DEFAULT_WAIT_SECS) # required as controller has likely not placed the resource in modifying
7565
resource = k8s.wait_resource_consumed_by_controller(reference, wait_periods=10)
@@ -134,16 +124,17 @@ def assert_items(self, expectations: dict, state: dict):
134124
continue
135125
assert (property, value) == (property, state.get(property))
136126

137-
def custom_resource_reference(self, input_data: dict) -> k8s.CustomResourceReference:
127+
def custom_resource_reference(self, input_data: dict, input_replacements: dict = {}) -> k8s.CustomResourceReference:
138128
"""
139129
Helper method to provide k8s.CustomResourceReference for supplied input
140130
:param input_data: custom resource input data
131+
:param input_replacements: input replacements
141132
:return: k8s.CustomResourceReference
142133
"""
143134
resource_plural = self.resource_plural(input_data.get("kind"))
144135
resource_name = input_data.get("metadata").get("name")
145-
crd_group = input_replacements_dict.get("CRD_GROUP")
146-
crd_version = input_replacements_dict.get("CRD_VERSION")
136+
crd_group = input_replacements.get("CRD_GROUP")
137+
crd_version = input_replacements.get("CRD_VERSION")
147138

148139
reference = k8s.CustomResourceReference(
149140
crd_group, crd_version, resource_plural, resource_name, namespace="default")

test/declarative_test_fwk/loader.py

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,33 +19,47 @@
1919
import os
2020
from typing import Iterable
2121
from pathlib import Path
22+
from os.path import isfile, join
2223
from acktest.resources import load_resource_file, random_suffix_name
2324

2425

25-
def scenarios(scenarios_directory: Path) -> Iterable:
26+
def list_scenarios(scenarios_directory: Path) -> Iterable[Path]:
2627
"""
27-
Loads scenarios from given directory
28+
Lists test scenarios from given directory
2829
:param scenarios_directory: directory containing scenarios yaml files
2930
:return: Iterable scenarios
3031
"""
32+
scenarios_list = []
3133
for scenario_file in os.listdir(scenarios_directory):
32-
if not scenario_file.endswith(".yaml"):
34+
scenario_file_full_path = join(scenarios_directory, scenario_file)
35+
if not isfile(scenario_file_full_path) or not scenario_file.endswith(".yaml"):
3336
continue
34-
scenario_name = scenario_file.split(".yaml")[0]
35-
replacements = helper.input_replacements_dict.copy()
36-
replacements["RANDOM_SUFFIX"] = random_suffix_name("", 32)
37-
scenario = model.Scenario(load_resource_file(
38-
scenarios_directory, scenario_name, additional_replacements=replacements))
39-
yield pytest.param(scenario, marks=marks(scenario))
37+
scenarios_list.append(Path(scenario_file_full_path))
38+
return scenarios_list
4039

4140

42-
def idfn(scenario: model.Scenario) -> str:
41+
def load_scenario(scenario_file: Path, replacements: dict = {}) -> Iterable:
4342
"""
44-
Provides scenario test id
45-
:param scenario: test scenario
43+
Loads scenario from given scenario_file
44+
:param scenario_file: yaml file containing scenarios
45+
:param replacements: input replacements
46+
:return: Iterable scenarios
47+
"""
48+
scenario_name = scenario_file.name.split(".yaml")[0]
49+
replacements = replacements.copy()
50+
replacements["RANDOM_SUFFIX"] = random_suffix_name("", 32)
51+
scenario = model.Scenario(load_resource_file(
52+
scenario_file.parent, scenario_name, additional_replacements=replacements), replacements)
53+
yield pytest.param(scenario, marks=marks(scenario))
54+
55+
56+
def idfn(scenario_file_full_path: Path) -> str:
57+
"""
58+
Provides scenario file name as scenario test id
59+
:param scenario: test scenario file path
4660
:return: scenario test id string
4761
"""
48-
return scenario.id()
62+
return scenario_file_full_path.name
4963

5064

5165
def marks(scenario: model.Scenario) -> list:

test/declarative_test_fwk/model.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ class Step:
2323
"""
2424
indent = "\t\t"
2525

26-
def __init__(self, config: dict):
26+
def __init__(self, config: dict, replacements: dict = {}):
2727
self.config = config
28+
self.replacements = replacements
2829

2930
self.verb = None
3031
self.input_data = None
@@ -58,11 +59,12 @@ class Scenario:
5859
Represents a declarative test scenario with steps
5960
"""
6061

61-
def __init__(self, config: dict):
62+
def __init__(self, config: dict, replacements: dict = {}):
6263
self.config = config
6364
self.test_steps = []
65+
self.replacements = replacements
6466
for step in self.config.get("steps", []):
65-
self.test_steps.append(Step(step))
67+
self.test_steps.append(Step(step, replacements))
6668

6769
def id(self) -> str:
6870
return self.config.get("id", "")

test/declarative_test_fwk/runner.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ def create_resource(step: model.Step) -> None:
8686
if not step.input_data:
8787
return
8888

89-
(reference, ko) = step.resource_helper.create(step.input_data)
89+
(reference, ko) = step.resource_helper.create(step.input_data, step.replacements)
9090
# track created reference to teardown later
9191
step.teardown_list.append((reference, ko))
9292

@@ -96,14 +96,14 @@ def patch_resource(step: model.Step) -> None:
9696
if not step.input_data:
9797
return
9898

99-
(reference, ko) = step.resource_helper.patch(step.input_data)
99+
(reference, ko) = step.resource_helper.patch(step.input_data, step.replacements)
100100
# no need to teardown patched reference, its creator should tear it down.
101101

102102

103103
def delete_resource(step: model.Step, reference: k8s.CustomResourceReference = None) -> None:
104104
if not reference:
105105
logging.debug(f"delete: Step: {step.id()}")
106-
reference = step.resource_helper.custom_resource_reference(step.input_data)
106+
reference = step.resource_helper.custom_resource_reference(step.input_data, step.replacements)
107107

108108
step.resource_helper.delete(reference)
109109

@@ -114,7 +114,7 @@ def assert_expectations(step: model.Step) -> None:
114114
return
115115

116116
resource_helper = step.resource_helper
117-
reference = resource_helper.custom_resource_reference(step.input_data)
117+
reference = resource_helper.custom_resource_reference(step.input_data, step.replacements)
118118
resource_helper.assert_expectations(step.expectations, reference)
119119

120120

test/e2e/bootstrap_resources.py

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,6 @@ class TestBootstrapResources:
2929
NonDefaultUser: str
3030
CWLogGroup: str
3131

32-
def replacement_dict(self):
33-
return {
34-
"SNS_TOPIC_ARN": self.SnsTopicARN,
35-
"SG_ID": self.SecurityGroupID,
36-
"USERGROUP_ID": self.UserGroupID,
37-
"KMS_KEY_ID": self.KmsKeyID,
38-
"SNAPSHOT_NAME": self.SnapshotName,
39-
"NON_DEFAULT_USER": self.SnapshotName
40-
}
41-
42-
4332
_bootstrap_resources = None
4433

4534

test/e2e/declarative_tests.py

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,23 +24,9 @@
2424
import boto3
2525
import logging
2626

27-
from e2e import service_marker, scenarios_directory, CRD_VERSION, CRD_GROUP, SERVICE_NAME
28-
from e2e.bootstrap_resources import get_bootstrap_resources
27+
from e2e import service_bootstrap, service_cleanup, service_marker, scenarios_directory, CRD_VERSION, CRD_GROUP, SERVICE_NAME
2928
from acktest.k8s import resource as k8s
3029

31-
32-
@helper.input_replacements
33-
def input_replacements():
34-
"""
35-
Input replacements for test scenarios
36-
"""
37-
replacements = get_bootstrap_resources().replacement_dict()
38-
replacements["CRD_VERSION"] = CRD_VERSION
39-
replacements["CRD_GROUP"] = CRD_GROUP
40-
replacements["SERVICE_NAME"] = SERVICE_NAME
41-
return replacements
42-
43-
4430
@helper.resource_helper("ReplicationGroup")
4531
class ReplicationGroupHelper(helper.ResourceHelper):
4632
"""
@@ -54,16 +40,46 @@ def wait_for_delete(self, reference: k8s.CustomResourceReference):
5440
waiter.wait(ReplicationGroupId=reference.name)
5541

5642

57-
@pytest.fixture(params=loader.scenarios(scenarios_directory), ids=loader.idfn)
58-
def scenario(request):
43+
@pytest.fixture(scope="session")
44+
def input_replacements():
45+
"""
46+
Session scoped fixture to bootstrap service resources and teardown
47+
provides input replacements for test scenarios.
48+
Eliminates the need for:
49+
- bootstrap.yaml and
50+
- call to <service_controller_test_dir>/service_bootstrap.py from test-infra
51+
- call to <service_controller_test_dir>/service_cleanup.py from test-infra
52+
"""
53+
54+
resources_dict = service_bootstrap.service_bootstrap()
55+
replacements = {
56+
"CRD_VERSION": CRD_VERSION,
57+
"CRD_GROUP": CRD_GROUP,
58+
"SERVICE_NAME": SERVICE_NAME,
59+
"SNS_TOPIC_ARN": resources_dict.get("SnsTopicARN"),
60+
"SG_ID": resources_dict.get("SecurityGroupID"),
61+
"USERGROUP_ID": resources_dict.get("UserGroupID"),
62+
"KMS_KEY_ID": resources_dict.get("KmsKeyID"),
63+
"SNAPSHOT_NAME": resources_dict.get("SnapshotName"),
64+
"NON_DEFAULT_USER": resources_dict.get("SnapshotName")
65+
}
66+
67+
yield replacements
68+
# teardown
69+
service_cleanup.service_cleanup(resources_dict)
70+
71+
72+
@pytest.fixture(params=loader.list_scenarios(scenarios_directory), ids=loader.idfn)
73+
def scenario(request, input_replacements):
5974
"""
6075
Parameterized fixture
6176
Provides scenarios to execute
6277
Supports parallel execution of scenarios
6378
"""
64-
s = request.param
65-
yield s
66-
runner.teardown(s)
79+
scenario_file_path = request.param
80+
scenario = loader.load_scenario(scenario_file_path, input_replacements)
81+
yield scenario
82+
runner.teardown(scenario)
6783

6884

6985
@service_marker

0 commit comments

Comments
 (0)