Skip to content

Commit cedc5fe

Browse files
Tim Lanetilne
authored andcommitted
Prevent writing architecture parameter to config
Previously the architecture parameter was being written back to the config files produced by `pcluster configure` when the original `master_instance_type` supported a different architecture than the one supported by the `master_instance_type` provided via the interactive prompt. This change prevents that from occurring. The same is done for the cluster_config_metadata parameter, although it was not as critical in this case because its presence in a config file does not cause it to fail validation. A test case was added to the corresponding unit tests. To ensure the test case fails when the fix is not in place, an extra check was added to ensure that only the expected configuration keys are in the resulting config file. Signed-off-by: Tim Lane <[email protected]>
1 parent f679eb3 commit cedc5fe

File tree

14 files changed

+79
-53
lines changed

14 files changed

+79
-53
lines changed

cli/pcluster/config/param_types.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -888,6 +888,15 @@ def create_section_resources(self, section_key, num_labels, max_resources):
888888
LOGGER.debug("Automatic labels generated: {0}".format(str(section_labels)))
889889
return self.__section_resources.resources(section_key)
890890

891+
def to_file(self, config_parser, write_defaults=False):
892+
"""Ensure cluster_config_metadata_param is not exposed in the config file."""
893+
LOGGER.debug("Ensuring cluster_config_metadata_param parameter is not written to configuration file.")
894+
section_name = get_file_section_name(self.section_key, self.section_label)
895+
try:
896+
config_parser.remove_option(section_name, self.key)
897+
except NoSectionError:
898+
pass
899+
891900

892901
class ArchitectureParam(Param):
893902
"""
@@ -911,6 +920,15 @@ def from_file(self, config_parser):
911920

912921
return self
913922

923+
def to_file(self, config_parser, write_defaults=False):
924+
"""Do nothing because architecture is not exposed in the config file."""
925+
LOGGER.debug("Ensuring architecture parameter is not written to configuration file.")
926+
section_name = get_file_section_name(self.section_key, self.section_label)
927+
try:
928+
config_parser.remove_option(section_name, self.key)
929+
except NoSectionError:
930+
pass
931+
914932
@staticmethod
915933
def get_master_instance_type_architecture(cluster_section):
916934
"""Compute cluster's 'Architecture' CFN parameter based on its master server instance type."""

cli/tests/pcluster/configure/test_pcluster_configure.py

Lines changed: 45 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -138,16 +138,22 @@ def _side_effect_function(config, parameters):
138138

139139

140140
def _mock_parallel_cluster_config(mocker):
141-
supported_instance_types = ["t2.nano", "t2.micro", "t2.large", "c5.xlarge", "g3.8xlarge"]
141+
supported_instance_types = ["t2.nano", "t2.micro", "t2.large", "c5.xlarge", "g3.8xlarge", "m6g.xlarge"]
142142
mocker.patch("pcluster.configure.easyconfig.get_supported_instance_types", return_value=supported_instance_types)
143143
mocker.patch(
144144
"pcluster.configure.easyconfig.get_supported_compute_instance_types", return_value=supported_instance_types
145145
)
146146
mocker.patch("pcluster.config.param_types.get_avail_zone", return_value="mocked_avail_zone")
147-
mocker.patch("pcluster.config.param_types.get_supported_architectures_for_instance_type", return_value=["x86_64"])
147+
mocker.patch(
148+
"pcluster.config.param_types.get_supported_architectures_for_instance_type",
149+
side_effect=lambda instance: ["arm64"] if instance == "m6g.xlarge" else ["x86_64"],
150+
)
148151
# NOTE: the following shouldn't be needed given that easyconfig doesn't validate the config file,
149152
# but it's being included in case that changes in the future.
150-
mocker.patch("pcluster.config.validators.get_supported_architectures_for_instance_type", return_value=["x86_64"])
153+
mocker.patch(
154+
"pcluster.config.validators.get_supported_architectures_for_instance_type",
155+
side_effect=lambda instance: ["arm64"] if instance == "m6g.xlarge" else ["x86_64"],
156+
)
151157

152158

153159
def _launch_config(mocker, path, remove_path=True):
@@ -158,43 +164,16 @@ def _launch_config(mocker, path, remove_path=True):
158164
configure(args)
159165

160166

161-
def _are_configurations_equals(path_config_expected, path_config_after_input):
162-
if not os.path.isfile(path_config_expected):
163-
return False
164-
if not os.path.isfile(path_config_after_input):
165-
return False
167+
def _assert_configurations_are_equal(path_config_expected, path_config_after_input):
168+
assert_that(path_config_expected).exists().is_file()
169+
assert_that(path_config_after_input).exists().is_file()
166170
config_expected = ConfigParser()
167171
config_expected.read(path_config_expected)
168-
dict1 = {s: dict(config_expected.items(s)) for s in config_expected.sections()}
169-
config_temp = ConfigParser()
170-
config_temp.read(path_config_after_input)
171-
dict2 = {s: dict(config_temp.items(s)) for s in config_temp.sections()}
172-
for section_name, section in dict1.items():
173-
for key, value in section.items():
174-
try:
175-
if dict2[section_name][key] != value:
176-
print(
177-
(
178-
"Expected parameters are: {0}\n"
179-
"Actual parameters after running pcluster configure are: {1}"
180-
).format(dict1, dict2)
181-
)
182-
print(
183-
"\nTest failed: Parameter '{0}' in section '{1}' is different from the expected one.".format(
184-
key, section_name
185-
)
186-
)
187-
print("The actual value is '{0}' but expected is '{1}'".format(dict2[section_name][key], value))
188-
return False
189-
except KeyError:
190-
print(
191-
"Expected parameters are: {0}\nActual parameters after running pcluster configure are: {1}".format(
192-
dict1, dict2
193-
)
194-
)
195-
print("\nTest failed: Parameter '{0}' doesn't exist in section '{1}'.".format(key, section_name))
196-
return False
197-
return True
172+
config_expected_dict = {s: dict(config_expected.items(s)) for s in config_expected.sections()}
173+
config_actual = ConfigParser()
174+
config_actual.read(path_config_after_input)
175+
config_actual_dict = {s: dict(config_actual.items(s)) for s in config_actual.sections()}
176+
assert_that(config_actual_dict).is_equal_to(config_expected_dict)
198177

199178

200179
def _are_output_error_correct(capsys, output, error, config_path):
@@ -271,7 +250,7 @@ def _verify_test(
271250
_launch_config(mocker, temp_path_for_config, remove_path=False)
272251
else:
273252
_launch_config(mocker, temp_path_for_config)
274-
assert_that(_are_configurations_equals(expected_config, temp_path_for_config)).is_true()
253+
_assert_configurations_are_equal(expected_config, temp_path_for_config)
275254
_are_output_error_correct(capsys, output, error, temp_path_for_config)
276255
os.remove(temp_path_for_config)
277256

@@ -292,11 +271,25 @@ def test_no_automation_no_awsbatch_no_errors(mocker, capsys, test_datadir):
292271
_verify_test(mocker, capsys, output, error, config, TEMP_PATH_FOR_CONFIG)
293272

294273

295-
def _run_input_test_with_config(mocker, config, old_config_file, error, output, capsys, with_input=False):
274+
def _run_input_test_with_config(
275+
mocker,
276+
config,
277+
old_config_file,
278+
error,
279+
output,
280+
capsys,
281+
with_input=False,
282+
master_instance="c5.xlarge",
283+
compute_instance="g3.8xlarge",
284+
):
296285
if with_input:
297286
input_composer = ComposeInput(aws_region_name="us-east-1", key="key2", scheduler="slurm")
298287
input_composer.add_first_flow(
299-
op_sys="ubuntu1604", min_size="7", max_size="18", master_instance="c5.xlarge", compute_instance="g3.8xlarge"
288+
op_sys="ubuntu1604",
289+
min_size="7",
290+
max_size="18",
291+
master_instance=master_instance,
292+
compute_instance=compute_instance,
300293
)
301294
input_composer.add_no_automation_no_empty_vpc(
302295
vpc_id="vpc-34567891", master_id="subnet-34567891", compute_id="subnet-45678912"
@@ -352,7 +345,17 @@ def test_with_input_no_automation_no_errors_with_config_file(mocker, capsys, tes
352345

353346
MockHandler(mocker)
354347

355-
_run_input_test_with_config(mocker, config, old_config_file, error, output, capsys, with_input=True)
348+
_run_input_test_with_config(
349+
mocker,
350+
config,
351+
old_config_file,
352+
error,
353+
output,
354+
capsys,
355+
with_input=True,
356+
master_instance="m6g.xlarge",
357+
compute_instance="m6g.xlarge",
358+
)
356359

357360

358361
def test_no_automation_yes_awsbatch_no_errors(mocker, capsys, test_datadir):

cli/tests/pcluster/configure/test_pcluster_configure/test_bad_config_file/pcluster.config.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ key_name = key1
1212
vpc_settings = default
1313
#Invalid param value
1414
# Implied value
15-
# scheduler = sge
15+
scheduler = sge
1616
base_os = centos6
1717
# Implied value
1818
# compute_instance_type = t2.micro

cli/tests/pcluster/configure/test_pcluster_configure/test_no_automation_no_awsbatch_no_errors/pcluster.config.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ master_instance_type = t2.nano
99
max_queue_size = 14
1010
initial_queue_size = 13
1111
maintain_initial_size = true
12+
base_os = alinux
1213

1314
[vpc default]
1415
vpc_id = vpc-12345678

cli/tests/pcluster/configure/test_pcluster_configure/test_no_automation_yes_awsbatch_no_errors/pcluster.config.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ aws_region_name = eu-west-1
44
[cluster default]
55
key_name = key1
66
# Implied value
7-
# base_os = alinux
7+
base_os = alinux2
88
vpc_settings = default
99
scheduler = awsbatch
1010
# Implied value

cli/tests/pcluster/configure/test_pcluster_configure/test_no_available_no_input_no_automation_no_errors_with_config_file/pcluster.config.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ compute_instance_type = t2.nano
1010
max_queue_size = 14
1111
initial_queue_size = 13
1212
maintain_initial_size = true
13+
base_os = alinux2
14+
additional_iam_policies = arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy
1315

1416
[vpc default]
1517
vpc_id = vpc-abcdefgh

cli/tests/pcluster/configure/test_pcluster_configure/test_no_input_no_automation_no_errors_with_config_file/pcluster.config.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ compute_instance_type = t2.nano
1010
max_queue_size = 14
1111
initial_queue_size = 13
1212
maintain_initial_size = true
13+
base_os = alinux2
1314

1415
[vpc default]
1516
vpc_id = vpc-12345678

cli/tests/pcluster/configure/test_pcluster_configure/test_subnet_automation_no_awsbatch_no_errors/pcluster.config.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ aws_region_name = eu-west-1
55
key_name = key1
66
vpc_settings = default
77
# Implied value
8-
# scheduler = sge
8+
scheduler = sge
99
base_os = centos6
1010
# Implied value
1111
# compute_instance_type = t2.micro

cli/tests/pcluster/configure/test_pcluster_configure/test_subnet_automation_no_awsbatch_no_errors_empty_vpc/pcluster.config.ini

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ aws_region_name = eu-west-1
44
[cluster default]
55
key_name = key1
66
vpc_settings = default
7-
# Implied value
8-
# scheduler = sge
7+
scheduler = sge
98
base_os = centos6
109
# Implied value
1110
# compute_instance_type = t2.micro

cli/tests/pcluster/configure/test_pcluster_configure/test_subnet_automation_no_awsbatch_no_errors_with_config_file/pcluster.config.ini

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@ aws_region_name = eu-west-1
55
key_name = key1
66
vpc_settings = default
77
# Implied value
8-
# scheduler = sge
8+
scheduler = sge
99
base_os = centos6
1010
# Implied value
1111
# compute_instance_type = t2.micro
1212
master_instance_type = t2.nano
1313
max_queue_size = 14
1414
initial_queue_size = 13
1515
maintain_initial_size = true
16+
additional_iam_policies = arn:aws:iam::aws:policy/AWSBatchFullAccess
1617

1718
[vpc default]
1819
vpc_id = vpc-12345678

0 commit comments

Comments
 (0)