From 46abcfcc824c199ad17ba5e3a9ceaf161107aa67 Mon Sep 17 00:00:00 2001 From: Matt Davis <6775756+nitzmahone@users.noreply.github.com> Date: Tue, 17 Jun 2025 16:15:55 -0700 Subject: [PATCH] feature-flag experimental module metadata (#85351) * added ansible-test integration env/set directive for aliases * applied to module-serialization-profiles test to enable feature flag Co-authored-by: Matt Clay --- changelogs/fragments/ansible-test-env-set.yml | 3 +++ lib/ansible/config/base.yml | 9 +++++++++ lib/ansible/executor/module_common.py | 11 +++++++---- .../ns/col/tests/integration/targets/hello/aliases | 2 ++ .../tests/integration/targets/hello/tasks/main.yml | 2 ++ .../targets/module-serialization-profiles/aliases | 1 + .../_internal/commands/integration/__init__.py | 1 + test/lib/ansible_test/_internal/target.py | 8 ++++++++ 8 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 changelogs/fragments/ansible-test-env-set.yml diff --git a/changelogs/fragments/ansible-test-env-set.yml b/changelogs/fragments/ansible-test-env-set.yml new file mode 100644 index 00000000000..f39809293bc --- /dev/null +++ b/changelogs/fragments/ansible-test-env-set.yml @@ -0,0 +1,3 @@ +minor_changes: + - ansible-test - Added support for setting static environment variables in integration tests using ``env/set/`` + entries in the ``aliases`` file. For example, ``env/set/MY_KEY/MY_VALUE`` or ``env/set/MY_PATH//an/abs/path``. diff --git a/lib/ansible/config/base.yml b/lib/ansible/config/base.yml index 5c64ea67107..425db8dd87a 100644 --- a/lib/ansible/config/base.yml +++ b/lib/ansible/config/base.yml @@ -41,6 +41,15 @@ _CALLBACK_DISPATCH_ERROR_BEHAVIOR: ignore: just continue silently env: [ { name: _ANSIBLE_CALLBACK_DISPATCH_ERROR_BEHAVIOR } ] version_added: '2.19' +_MODULE_METADATA: + name: Enable experimental module metadata + description: + - Enables experimental module-level metadata controls for serialization profile selection. + - This is for internal use only. + type: boolean + default: false + env: [ { name: _ANSIBLE_MODULE_METADATA } ] + version_added: '2.19' ALLOW_BROKEN_CONDITIONALS: # This config option will be deprecated once it no longer has any effect (2.23). name: Allow broken conditionals diff --git a/lib/ansible/executor/module_common.py b/lib/ansible/executor/module_common.py index 4078a24df63..a18088bca61 100644 --- a/lib/ansible/executor/module_common.py +++ b/lib/ansible/executor/module_common.py @@ -659,9 +659,14 @@ metadata_versions: dict[t.Any, type[ModuleMetadata]] = { 1: ModuleMetadataV1, } +_DEFAULT_LEGACY_METADATA = ModuleMetadataV1(serialization_profile='legacy') + def _get_module_metadata(module: ast.Module) -> ModuleMetadata: - # DTFIX2: while module metadata works, this feature isn't fully baked and should be turned off before release + # experimental module metadata; off by default + if not C.config.get_config_value('_MODULE_METADATA'): + return _DEFAULT_LEGACY_METADATA + metadata_nodes: list[ast.Assign] = [] for node in module.body: @@ -674,9 +679,7 @@ def _get_module_metadata(module: ast.Module) -> ModuleMetadata: metadata_nodes.append(node) if not metadata_nodes: - return ModuleMetadataV1( - serialization_profile='legacy', - ) + return _DEFAULT_LEGACY_METADATA if len(metadata_nodes) > 1: raise ValueError('Module METADATA must defined only once.') diff --git a/test/integration/targets/ansible-test-integration/ansible_collections/ns/col/tests/integration/targets/hello/aliases b/test/integration/targets/ansible-test-integration/ansible_collections/ns/col/tests/integration/targets/hello/aliases index 1af1cf90b6a..20cd846a12a 100644 --- a/test/integration/targets/ansible-test-integration/ansible_collections/ns/col/tests/integration/targets/hello/aliases +++ b/test/integration/targets/ansible-test-integration/ansible_collections/ns/col/tests/integration/targets/hello/aliases @@ -1 +1,3 @@ context/controller +env/set/A_VAR/something +env/set/A_PATH//an/absolute/path diff --git a/test/integration/targets/ansible-test-integration/ansible_collections/ns/col/tests/integration/targets/hello/tasks/main.yml b/test/integration/targets/ansible-test-integration/ansible_collections/ns/col/tests/integration/targets/hello/tasks/main.yml index c45c199cf3f..6942f60aac5 100644 --- a/test/integration/targets/ansible-test-integration/ansible_collections/ns/col/tests/integration/targets/hello/tasks/main.yml +++ b/test/integration/targets/ansible-test-integration/ansible_collections/ns/col/tests/integration/targets/hello/tasks/main.yml @@ -5,3 +5,5 @@ - assert: that: - hello.message == 'Hello Ansibull' + - lookup('env', 'A_VAR') == 'something' + - lookup('env', 'A_PATH') == '/an/absolute/path' diff --git a/test/integration/targets/module-serialization-profiles/aliases b/test/integration/targets/module-serialization-profiles/aliases index 87958830d5d..2a90005e99c 100644 --- a/test/integration/targets/module-serialization-profiles/aliases +++ b/test/integration/targets/module-serialization-profiles/aliases @@ -1,2 +1,3 @@ context/target shippable/posix/group1 +env/set/_ANSIBLE_MODULE_METADATA/1 diff --git a/test/lib/ansible_test/_internal/commands/integration/__init__.py b/test/lib/ansible_test/_internal/commands/integration/__init__.py index 499870d14f6..19d513c9da1 100644 --- a/test/lib/ansible_test/_internal/commands/integration/__init__.py +++ b/test/lib/ansible_test/_internal/commands/integration/__init__.py @@ -825,6 +825,7 @@ def integration_environment( env.update(ANSIBLE_TEST_REMOTE_INTERPRETER='') env.update(integration) + env.update(target.env_set) return env diff --git a/test/lib/ansible_test/_internal/target.py b/test/lib/ansible_test/_internal/target.py index 0f2867b8b35..c27e917f34f 100644 --- a/test/lib/ansible_test/_internal/target.py +++ b/test/lib/ansible_test/_internal/target.py @@ -582,6 +582,14 @@ class IntegrationTarget(CompletionTarget): else: static_aliases = tuple() + # non-group aliases which need to be extracted before group mangling occurs + + self.env_set: dict[str, str] = { + match.group('key'): match.group('value') for match in ( + re.match(r'env/set/(?P[^/]+)/(?P.*)', alias) for alias in static_aliases + ) if match + } + # modules if self.name in modules: