Skip to content

Commit

Permalink
Address test review comments
Browse files Browse the repository at this point in the history
  • Loading branch information
mgunnala committed Nov 21, 2024
1 parent 699b9ba commit 86de0c5
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 16 deletions.
25 changes: 19 additions & 6 deletions tests/ga/test_extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -3536,7 +3536,7 @@ def _create_policy_file(self, policy):
policy_file.write(policy)
policy_file.flush()

def _test_policy_failure(self, policy, op, expected_status_code, expected_handler_status,
def _test_policy_case(self, policy, op, expected_status_code, expected_handler_status, expected_ext_count=0,
expected_status_msg=None):

with mock_wire_protocol(wire_protocol_data.DATA_FILE) as protocol:
Expand All @@ -3554,7 +3554,8 @@ def _test_policy_failure(self, policy, op, expected_status_code, expected_handle

report_vm_status = protocol.report_vm_status
self.assertTrue(report_vm_status.called)
self._assert_handler_status(report_vm_status, expected_handler_status, 0, "1.0.0", 'OSTCExtensions.ExampleHandlerLinux',
self._assert_handler_status(report_vm_status, expected_handler_status, expected_ext_count=expected_ext_count,
version="1.0.0", expected_handler_name='OSTCExtensions.ExampleHandlerLinux',
expected_msg=expected_status_msg, expected_code=expected_status_code)

def test_should_fail_enable_if_extension_disallowed(self):
Expand All @@ -3566,7 +3567,7 @@ def test_should_fail_enable_if_extension_disallowed(self):
}
}
expected_msg = "failed to enable extension 'OSTCExtensions.ExampleHandlerLinux' because extension is not specified in allowlist."
self._test_policy_failure(policy=policy, op=ExtensionRequestedState.Enabled, expected_status_code=ExtensionErrorCodes.PluginEnableProcessingFailed,
self._test_policy_case(policy=policy, op=ExtensionRequestedState.Enabled, expected_status_code=ExtensionErrorCodes.PluginEnableProcessingFailed,
expected_handler_status='NotReady', expected_status_msg=expected_msg)

def test_should_fail_enable_for_invalid_policy(self):
Expand All @@ -3578,7 +3579,7 @@ def test_should_fail_enable_for_invalid_policy(self):
}
}
expected_msg = "attribute 'extensionPolicies.allowListedExtensionsOnly'; must be 'boolean'"
self._test_policy_failure(policy=policy, op=ExtensionRequestedState.Enabled, expected_status_code=ExtensionErrorCodes.PluginEnableProcessingFailed,
self._test_policy_case(policy=policy, op=ExtensionRequestedState.Enabled, expected_status_code=ExtensionErrorCodes.PluginEnableProcessingFailed,
expected_handler_status='NotReady', expected_status_msg=expected_msg)

def test_should_fail_extension_if_error_thrown_during_policy_engine_init(self):
Expand All @@ -3589,7 +3590,7 @@ def test_should_fail_extension_if_error_thrown_during_policy_engine_init(self):
with patch('azurelinuxagent.ga.policy.policy_engine.ExtensionPolicyEngine.__init__',
side_effect=Exception("mock exception")):
expected_msg = "Extension will not be processed: \nInner error: mock exception"
self._test_policy_failure(policy=policy, op=ExtensionRequestedState.Enabled,
self._test_policy_case(policy=policy, op=ExtensionRequestedState.Enabled,
expected_status_code=ExtensionErrorCodes.PluginEnableProcessingFailed,
expected_handler_status='NotReady', expected_status_msg=expected_msg)

Expand All @@ -3604,7 +3605,7 @@ def test_should_fail_uninstall_if_extension_disallowed(self):
},
}
expected_msg = "failed to uninstall extension 'OSTCExtensions.ExampleHandlerLinux' because extension is not specified in allowlist."
self._test_policy_failure(policy=policy, op=ExtensionRequestedState.Uninstall, expected_status_code=ExtensionErrorCodes.PluginDisableProcessingFailed,
self._test_policy_case(policy=policy, op=ExtensionRequestedState.Uninstall, expected_status_code=ExtensionErrorCodes.PluginDisableProcessingFailed,
expected_handler_status='NotReady', expected_status_msg=expected_msg)

def test_should_fail_enable_if_dependent_extension_disallowed(self):
Expand Down Expand Up @@ -3648,6 +3649,18 @@ def test_should_fail_enable_if_dependent_extension_disallowed(self):
self.assertEqual(2, next(handler for handler in exthandlers_handler.ext_handlers if
handler.name == dep_ext_level_2.name).settings[0].dependencyLevel)

def test_enable_should_succeed_if_extension_allowed(self):
policy = \
{
"policyVersion": "0.1.0",
"extensionPolicies": {
"allowListedExtensionsOnly": False,
}
}
self._test_policy_case(policy=policy, op=ExtensionRequestedState.Enabled,
expected_status_code=0,
expected_handler_status='Ready', expected_ext_count=1)


if __name__ == '__main__':
unittest.main()
30 changes: 29 additions & 1 deletion tests/ga/test_multi_config_extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -630,7 +630,7 @@ def test_it_should_handle_and_report_enable_errors_properly(self):
}
self._assert_extension_status(sc_handler, expected_extensions)

def test_it_should_handle_and_report_disallowed_extensions_properly(self):
def test_it_should_handle_and_report_extensions_disallowed_by_policy_properly(self):
"""If multiconfig extension is disallowed by policy, all instances should be blocked."""
policy_path = os.path.join(self.tmp_dir, "waagent_policy.json")
patch('azurelinuxagent.common.conf.get_policy_file_path', return_value=str(policy_path)).start()
Expand Down Expand Up @@ -694,6 +694,34 @@ def test_it_should_handle_and_report_disallowed_extensions_properly(self):
}
self._assert_extension_status(sc_handler, expected_extensions)


def test_it_should_handle_and_report_extensions_allowed_by_policy_properly(self):
"""If multiconfig extension is allowed by policy, all instances should be allowed."""
policy_path = os.path.join(self.tmp_dir, "waagent_policy.json")
patch('azurelinuxagent.common.conf.get_policy_file_path', return_value=str(policy_path)).start()
patch('azurelinuxagent.ga.policy.policy_engine.conf.get_extension_policy_enabled',
return_value=True).start()
policy = \
{
"policyVersion": "0.0.1",
"extensionPolicies": {
"allowListedExtensionsOnly": True,
"signatureRequired": True,
"extensions": {
"OSTCExtensions.ExampleHandlerLinux": {},
"Microsoft.Powershell.ExampleExtension": {}
}
}
}
with open(policy_path, mode='w') as policy_file:
json.dump(policy, policy_file, indent=4)
policy_file.flush()

self.test_data['ext_conf'] = os.path.join(self._MULTI_CONFIG_TEST_DATA,
"ext_conf_multi_config_no_dependencies.xml")
with self._setup_test_env(mock_manifest=True) as (exthandlers_handler, protocol, no_of_extensions):
self.__run_and_assert_generic_case(exthandlers_handler, protocol, no_of_extensions)

def test_it_should_cleanup_extension_state_on_disable(self):

def __assert_state_file(handler_name, handler_version, extensions, state, not_present=None):
Expand Down
12 changes: 10 additions & 2 deletions tests_e2e/tests/ext_policy/ext_policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,22 +88,27 @@ def _operation_should_fail(operation, extension_case):
fail(f"The agent should have reported an error trying to {operation} {extension_case.extension.__str__()} "
f"because the extension is disallowed by policy.")
except Exception as error:
assert_that("Extension will not be processed" in str(error)) \
assert_that("[ExtensionPolicyError] Extension will not be processed" in str(error)) \
.described_as(
f"Error message should communicate that extension is disallowed by policy, but actual error "
f"was: {error}").is_true()
log.info(f"{extension_case.extension.__str__()} {operation} failed as expected")

def run(self):

# Prepare extensions to test
# Prepare no-config, single-config, and multi-config extension to test. Extensions with settings and extensions
# without settings have different status reporting logic, so we should test all cases.
unique = str(uuid.uuid4())
test_file = f"waagent-test.{unique}"

# CustomScript is a single-config extension.
custom_script = ExtPolicy.TestCase(
VirtualMachineExtensionClient(self._context.vm, VmExtensionIds.CustomScript,
resource_name="CustomScript"),
{'commandToExecute': f"echo '{unique}' > /tmp/{test_file}"}
)

# RunCommandHandler is a multi-config extension, so we set up two instances (configurations) here and test both.
run_command = ExtPolicy.TestCase(
VirtualMachineExtensionClient(self._context.vm, VmExtensionIds.RunCommandHandler,
resource_name="RunCommandHandler"),
Expand All @@ -116,6 +121,8 @@ def run(self):
resource_name="RunCommandHandler2"),
{'source': {'script': f"echo '{unique2}' > /tmp/{test_file2}"}}
)

# AzureMonitorLinuxAgent is a no-config extension (extension without settings).
azure_monitor = ExtPolicy.TestCase(
VirtualMachineExtensionClient(self._context.vm, VmExtensionIds.AzureMonitorLinuxAgent,
resource_name="AzureMonitorLinuxAgent"),
Expand All @@ -128,6 +135,7 @@ def run(self):

# Only allowlisted extensions should be processed.
# We only allowlist CustomScript: CustomScript should be enabled, RunCommand and AzureMonitor should fail.
# (Note that CustomScript blocked by policy is tested in a later test case.)
policy = \
{
"policyVersion": "0.1.0",
Expand Down
14 changes: 7 additions & 7 deletions tests_e2e/tests/ext_policy/policy_dependencies_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def _should_fail_single_config_depends_on_disallowed_single_config():
}
}
expected_errors = [
"Extension will not be processed: failed to enable extension 'Microsoft.OSTCExtensions.VMAccessForLinux' because extension is not specified in allowlist",
"[ExtensionPolicyError] Extension will not be processed: failed to enable extension 'Microsoft.OSTCExtensions.VMAccessForLinux' because extension is not specified in allowlist",
"'CustomScript' is marked as failed since it depends upon the VM Extension 'VMAccessForLinux' which has failed"
]
deletion_order = [VmExtensionIds.CustomScript, VmExtensionIds.VmAccess]
Expand All @@ -80,7 +80,7 @@ def _should_fail_single_config_depends_on_disallowed_no_config():
}
}
expected_errors = [
"Extension will not be processed: failed to enable extension 'Microsoft.Azure.Monitor.AzureMonitorLinuxAgent' because extension is not specified in allowlist",
"[ExtensionPolicyError] Extension will not be processed: failed to enable extension 'Microsoft.Azure.Monitor.AzureMonitorLinuxAgent' because extension is not specified in allowlist",
"'CustomScript' is marked as failed since it depends upon the VM Extension 'AzureMonitorLinuxAgent' which has failed"
]
deletion_order = [VmExtensionIds.CustomScript, VmExtensionIds.AzureMonitorLinuxAgent]
Expand All @@ -103,7 +103,7 @@ def _should_fail_single_config_depends_on_disallowed_multi_config():
}
}
expected_errors = [
"Extension will not be processed: failed to enable extension 'Microsoft.CPlat.Core.RunCommandHandlerLinux' because extension is not specified in allowlist",
"[ExtensionPolicyError] Extension will not be processed: failed to enable extension 'Microsoft.CPlat.Core.RunCommandHandlerLinux' because extension is not specified in allowlist",
"'CustomScript' is marked as failed since it depends upon the VM Extension 'RunCommandHandlerLinux' which has failed"
]
deletion_order = [VmExtensionIds.CustomScript, VmExtensionIds.RunCommandHandler]
Expand All @@ -126,7 +126,7 @@ def _should_fail_multi_config_depends_on_disallowed_single_config():
}
}
expected_errors = [
"Extension will not be processed: failed to enable extension 'Microsoft.Azure.Extensions.CustomScript' because extension is not specified in allowlist",
"[ExtensionPolicyError] Extension will not be processed: failed to enable extension 'Microsoft.Azure.Extensions.CustomScript' because extension is not specified in allowlist",
"VM has reported a failure when processing extension 'RunCommandHandlerLinux' (publisher 'Microsoft.CPlat.Core' and type 'RunCommandHandlerLinux'). Error message: 'Skipping processing of extensions since execution of dependent extension Microsoft.Azure.Extensions.CustomScript failed'."
]
deletion_order = [VmExtensionIds.RunCommandHandler, VmExtensionIds.CustomScript]
Expand All @@ -149,7 +149,7 @@ def _should_fail_multi_config_depends_on_disallowed_no_config():
}
}
expected_errors = [
"Extension will not be processed: failed to enable extension 'Microsoft.Azure.Monitor.AzureMonitorLinuxAgent' because extension is not specified in allowlist",
"[ExtensionPolicyError] Extension will not be processed: failed to enable extension 'Microsoft.Azure.Monitor.AzureMonitorLinuxAgent' because extension is not specified in allowlist",
"VM has reported a failure when processing extension 'RunCommandHandlerLinux' (publisher 'Microsoft.CPlat.Core' and type 'RunCommandHandlerLinux'). Error message: 'Skipping processing of extensions since execution of dependent extension Microsoft.Azure.Monitor.AzureMonitorLinuxAgent failed'."
]
deletion_order = [VmExtensionIds.RunCommandHandler, VmExtensionIds.AzureMonitorLinuxAgent]
Expand Down Expand Up @@ -236,8 +236,8 @@ def _should_no_dependencies():
}
}
expected_errors = [
"Extension will not be processed: failed to enable extension 'Microsoft.OSTCExtensions.VMAccessForLinux' because extension is not specified in allowlist",
"Extension will not be processed: failed to enable extension 'Microsoft.Azure.Extensions.CustomScript' because extension is not specified in allowlist"
"[ExtensionPolicyError] Extension will not be processed: failed to enable extension 'Microsoft.OSTCExtensions.VMAccessForLinux' because extension is not specified in allowlist",
"[ExtensionPolicyError] Extension will not be processed: failed to enable extension 'Microsoft.Azure.Extensions.CustomScript' because extension is not specified in allowlist"
]
deletion_order = [VmExtensionIds.VmAccess, VmExtensionIds.CustomScript]
return policy, template, expected_errors, deletion_order

0 comments on commit 86de0c5

Please sign in to comment.