Skip to content

Commit 44b1aa2

Browse files
ddeiddarexcsn
authored andcommitted
Add support for additional instance types to integration tests
This commit allows integration tests configuration files to use instance types provided with the `additional_instance_types` parameter to the `test_runner.py` script. Signed-off-by: ddeidda <ddeidda@amazon.com>
1 parent 71226c7 commit 44b1aa2

File tree

6 files changed

+64
-18
lines changed

6 files changed

+64
-18
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{%- import 'common.jinja2' as common with context -%}
2+
---
3+
test-suites:
4+
schedulers:
5+
test_slurm.py::test_slurm:
6+
dimensions:
7+
- regions: ["us-east-2"]
8+
instances: [{{ common.instance("instance_type_1") }}]
9+
oss: {{ common.OSS_COMMERCIAL_X86 }}
10+
schedulers: ["slurm"]

tests/integration-tests/configs/common.jinja2

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,11 @@
1515
{%- set INSTANCES_DEFAULT_X86 = ["c5.xlarge"] -%}
1616
{%- set INSTANCES_DEFAULT_ARM = ["m6g.xlarge"] -%}
1717
{%- set INSTANCES_DEFAULT = ["c5.xlarge", "m6g.xlarge"] -%}
18+
19+
{%- macro instance(instance_key) -%}
20+
{%- if additional_instance_types_map -%}
21+
{{ additional_instance_types_map.get(instance_key, instance_key) }}
22+
{%- else -%}
23+
"{{ instance_key }}"
24+
{%- endif -%}
25+
{%- endmacro -%}

tests/integration-tests/conftest.py

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,9 @@ def pytest_configure(config):
126126

127127
# Read instance types data file if used
128128
if config.getoption("instance_types_data_file", None):
129-
config.option.instance_types_data = _read_json_file(config.getoption("instance_types_data_file"))
130129
# Load additional instance types data
131-
_set_additional_instance_types_data(config.option.instance_types_data)
130+
InstanceTypesData.load_additional_instance_types_data(config.getoption("instance_types_data_file"))
131+
config.option.instance_types_data = InstanceTypesData.additional_instance_types_data
132132

133133
# register additional markers
134134
config.addinivalue_line("markers", "instances(instances_list): run test only against the listed instances.")
@@ -207,11 +207,6 @@ def _log_collected_tests(session):
207207
out_f.write("\n")
208208

209209

210-
def _set_additional_instance_types_data(instance_types_data):
211-
InstanceTypesData.additional_instance_types_data = instance_types_data
212-
logging.info("Additional instance types data loaded: {0}".format(InstanceTypesData.additional_instance_types_data))
213-
214-
215210
def pytest_exception_interact(node, call, report):
216211
"""Called when an exception was raised which can potentially be interactively handled.."""
217212
logging.error(
@@ -870,12 +865,3 @@ def _pcluster_ami_without_standard_naming(version):
870865
if ami_id:
871866
client = boto3.client("ec2", region_name=region)
872867
client.deregister_image(ImageId=ami_id)
873-
874-
875-
def _read_json_file(file):
876-
"""Read a Json file into a String and raise an exception if the file is invalid."""
877-
try:
878-
with open(file) as f:
879-
return json.load(f)
880-
except Exception:
881-
logging.exception("Failed when reading json file %s", file)

tests/integration-tests/framework/tests_configuration/config_renderer.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
import yaml
1717
from jinja2 import Environment, FileSystemLoader
18+
from utils import InstanceTypesData
1819

1920

2021
def read_config_file(config_file, print_rendered=False):
@@ -56,7 +57,11 @@ def _render_config_file(config_file):
5657
config_dir = os.path.dirname(config_file)
5758
config_name = os.path.basename(config_file)
5859
file_loader = FileSystemLoader(config_dir)
59-
return Environment(loader=file_loader).get_template(config_name).render()
60+
return (
61+
Environment(loader=file_loader)
62+
.get_template(config_name)
63+
.render(additional_instance_types_map=InstanceTypesData.additional_instance_types_map)
64+
)
6065
except Exception:
6166
logging.error("Failed when rendering config file %s", config_file)
6267
raise

tests/integration-tests/test_runner.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from framework.tests_configuration.config_utils import get_all_regions
2626
from framework.tests_configuration.config_validator import assert_valid_config
2727
from reports_generator import generate_cw_report, generate_json_report, generate_junitxml_merged_report
28+
from utils import InstanceTypesData
2829

2930
logger = logging.getLogger()
3031
logging.basicConfig(format="%(asctime)s - %(levelname)s - %(module)s - %(message)s", level=logging.INFO)
@@ -122,7 +123,6 @@ def _init_argparser():
122123
"Note that when a config file is used the following flags are ignored: instances, regions, oss, schedulers. "
123124
"Refer to the docs for further details on the config format: "
124125
"https://github.com/aws/aws-parallelcluster/blob/develop/tests/integration-tests/README.md",
125-
type=_test_config_file,
126126
)
127127
dimensions_group.add_argument(
128128
"-i",
@@ -559,6 +559,7 @@ def _check_args(args):
559559
assert_that(args.schedulers).described_as("--schedulers cannot be empty").is_not_empty()
560560
else:
561561
try:
562+
args.tests_config = _test_config_file(args.tests_config)
562563
assert_valid_config(args.tests_config, args.tests_root_dir)
563564
logger.info("Found valid config file:\n%s", dump_rendered_config_file(args.tests_config))
564565
except Exception:
@@ -582,6 +583,12 @@ def main():
582583
exit(1)
583584

584585
args = _init_argparser().parse_args()
586+
587+
# Load additional instance types data, if provided.
588+
# This step must be done before loading test config files in order to resolve instance type placeholders.
589+
if args.instance_types_data:
590+
InstanceTypesData.load_additional_instance_types_data(args.instance_types_data)
591+
585592
_check_args(args)
586593
logger.info("Parsed test_runner parameters {0}".format(args))
587594

tests/integration-tests/utils.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
# or in the "LICENSE.txt" file accompanying this file.
1010
# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express or implied.
1111
# See the License for the specific language governing permissions and limitations under the License.
12+
import json
1213
import logging
1314
import os
1415
import random
@@ -28,6 +29,25 @@ class InstanceTypesData:
2829

2930
# Additional instance types data provided via tests configuration
3031
additional_instance_types_data = {}
32+
additional_instance_types_map = {}
33+
34+
@staticmethod
35+
def load_additional_instance_types_data(instance_types_data_file):
36+
"""
37+
Load additional instance types data from configuration json file.
38+
The file must contain two keys:
39+
- "instance_types_data": The json structure to be passed to cluster configuration files
40+
- "instance_types_map": A dict containing logical instance types names (that can be used in cluster config
41+
files) vs real ones (e.g. "t2.micro")
42+
"""
43+
instance_types_data_file_content = read_json_file(instance_types_data_file)
44+
InstanceTypesData.additional_instance_types_data = instance_types_data_file_content.get(
45+
"instance_types_data", {}
46+
)
47+
InstanceTypesData.additional_instance_types_map = instance_types_data_file_content.get("instance_types_map", {})
48+
logging.info(
49+
"Additional instance types data loaded: {0}".format(InstanceTypesData.additional_instance_types_data)
50+
)
3151

3252
@staticmethod
3353
def get_instance_info(instance_type, region_name=None):
@@ -412,3 +432,13 @@ def check_headnode_security_group(region, cluster, port, expected_cidr):
412432
ips = response["SecurityGroups"][0]["IpPermissions"]
413433
target = next(filter(lambda x: x.get("FromPort", -1) == port, ips), {})
414434
assert_that(target["IpRanges"][0]["CidrIp"]).is_equal_to(expected_cidr)
435+
436+
437+
def read_json_file(file):
438+
"""Read a Json file into a String and raise an exception if the file is invalid."""
439+
try:
440+
with open(file) as f:
441+
return json.load(f)
442+
except Exception as e:
443+
logging.exception("Failed when reading json file %s", file)
444+
raise e

0 commit comments

Comments
 (0)