Repository: ansible/molecule

Issue:
`molecule` broken with latest version of `ansible-compat`
<!--- Verify first that your issue is not already reported on GitHub -->
<!--- Do not report bugs before reproducing them with the code of the main branch! -->
<!--- Please also check https://molecule.readthedocs.io/en/latest/faq.html --->
<!--- Please use https://groups.google.com/forum/#!forum/molecule-users for usage questions -->

# Issue Type

- Bug report

# Molecule and Ansible details

```console
$ ansible --version && molecule --version
ansible [core 2.13.9]
  config file = None
  configured module search path = ['/home/mcdonnnj/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/mcdonnnj/.pyenv/versions/3.11.3/envs/ansible-role-docker/lib/python3.11/site-packages/ansible
  ansible collection location = /home/mcdonnnj/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/mcdonnnj/.pyenv/versions/ansible-role-docker/bin/ansible
  python version = 3.11.3 (main, Apr 10 2023, 14:31:58) [GCC 12.2.0]
  jinja version = 3.1.2
  libyaml = True
molecule 5.0.0 using python 3.11
    ansible:2.13.9
    azure:23.4.1 from molecule_plugins
    containers:23.4.1 from molecule_plugins requiring collections: ansible.posix>=1.3.0 community.docker>=1.9.1 containers.podman>=1.8.1
    delegated:5.0.0 from molecule
    docker:23.4.1 from molecule_plugins requiring collections: community.docker>=3.0.2 ansible.posix>=1.4.0
    ec2:23.4.1 from molecule_plugins
    gce:23.4.1 from molecule_plugins requiring collections: google.cloud>=1.0.2 community.crypto>=1.8.0
    podman:23.4.1 from molecule_plugins requiring collections: containers.podman>=1.7.0 ansible.posix>=1.3.0
    vagrant:23.4.1 from molecule_plugins
```

Molecule installation method (one of):

- pip

Ansible installation method (one of):

- pip

Detail any linters or test runners used:

# Desired Behavior

`molecule test` should successfully perform testing.

# Actual Behaviour

```console
Traceback (most recent call last):
  File "/home/mcdonnnj/.pyenv/versions/ansible-role-docker/bin/molecule", line 8, in <module>
    sys.exit(main())
             ^^^^^^
  File "/home/mcdonnnj/.pyenv/versions/3.11.3/envs/ansible-role-docker/lib/python3.11/site-packages/click/core.py", line 1130, in __call__
    return self.main(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/mcdonnnj/.pyenv/versions/3.11.3/envs/ansible-role-docker/lib/python3.11/site-packages/click/core.py", line 1055, in main
    rv = self.invoke(ctx)
         ^^^^^^^^^^^^^^^^
  File "/home/mcdonnnj/.pyenv/versions/3.11.3/envs/ansible-role-docker/lib/python3.11/site-packages/click/core.py", line 1657, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/mcdonnnj/.pyenv/versions/3.11.3/envs/ansible-role-docker/lib/python3.11/site-packages/click/core.py", line 1404, in invoke
    return ctx.invoke(self.callback, **ctx.params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/mcdonnnj/.pyenv/versions/3.11.3/envs/ansible-role-docker/lib/python3.11/site-packages/click/core.py", line 760, in invoke
    return __callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/mcdonnnj/.pyenv/versions/3.11.3/envs/ansible-role-docker/lib/python3.11/site-packages/click/decorators.py", line 26, in new_func
    return f(get_current_context(), *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/mcdonnnj/.pyenv/versions/3.11.3/envs/ansible-role-docker/lib/python3.11/site-packages/molecule/command/test.py", line 113, in test
    base.execute_cmdline_scenarios(scenario_name, args, command_args, ansible_args)
  File "/home/mcdonnnj/.pyenv/versions/3.11.3/envs/ansible-role-docker/lib/python3.11/site-packages/molecule/command/base.py", line 119, in execute_cmdline_scenarios
    execute_scenario(scenario)
  File "/home/mcdonnnj/.pyenv/versions/3.11.3/envs/ansible-role-docker/lib/python3.11/site-packages/molecule/command/base.py", line 162, in execute_scenario
    execute_subcommand(scenario.config, action)
  File "/home/mcdonnnj/.pyenv/versions/3.11.3/envs/ansible-role-docker/lib/python3.11/site-packages/molecule/command/base.py", line 152, in execute_subcommand
    return command(config).execute(args)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/mcdonnnj/.pyenv/versions/3.11.3/envs/ansible-role-docker/lib/python3.11/site-packages/molecule/logger.py", line 189, in wrapper
    rt = func(*args, **kwargs)
         ^^^^^^^^^^^^^^^^^^^^^
  File "/home/mcdonnnj/.pyenv/versions/3.11.3/envs/ansible-role-docker/lib/python3.11/site-packages/molecule/command/dependency.py", line 40, in execute
    self._config.dependency.execute()
  File "/home/mcdonnnj/.pyenv/versions/3.11.3/envs/ansible-role-docker/lib/python3.11/site-packages/molecule/dependency/ansible_galaxy/__init__.py", line 75, in execute
    invoker.execute()
  File "/home/mcdonnnj/.pyenv/versions/3.11.3/envs/ansible-role-docker/lib/python3.11/site-packages/molecule/dependency/ansible_galaxy/base.py", line 129, in execute
    self.execute_with_retries()
  File "/home/mcdonnnj/.pyenv/versions/3.11.3/envs/ansible-role-docker/lib/python3.11/site-packages/molecule/dependency/base.py", line 55, in execute_with_retries
    util.run_command(self._sh_command, debug=self._config.debug, check=True)
  File "/home/mcdonnnj/.pyenv/versions/3.11.3/envs/ansible-role-docker/lib/python3.11/site-packages/molecule/util.py", line 149, in run_command
    result = app.runtime.exec(
             ^^^^^^^^^^^^^^^^
AttributeError: 'Runtime' object has no attribute 'exec'
```

This is likely caused by  https://github.com/ansible-community/molecule/blob/0d874bd9ccacda8df5e110020454764a6b9b908d/src/molecule/util.py#L149 not being updated for https://github.com/ansible/ansible-compat/pull/256 which was included in [ansible-compat v4.0.1](https://github.com/ansible/ansible-compat/releases/tag/v4.0.1).



Discussion:

Resolving patch:
diff --git a/src/molecule/command/init/role.py b/src/molecule/command/init/role.py
--- a/src/molecule/command/init/role.py
+++ b/src/molecule/command/init/role.py
@@ -90,7 +90,7 @@ def execute(self, action_args=None):
 
         if namespace:
             # we need to inject namespace info into meta/main.yml
-            cmd = [
+            cmd_meta = [
                 "ansible",
                 "localhost",
                 "-o",  # one line output
@@ -99,7 +99,18 @@ def execute(self, action_args=None):
                 "-a",
                 f'path={role_name}/meta/main.yml line="  namespace: {namespace}" insertafter="  author: your name"',
             ]
-            util.run_command(cmd, check=True)
+            util.run_command(cmd_meta, check=True)
+            # we need to inject namespace info into tests/test.yml
+            cmd_tests = [
+                "ansible",
+                "localhost",
+                "-o",  # one line output
+                "-m",
+                "lineinfile",
+                "-a",
+                f'path={role_name}/tests/test.yml line="    - {namespace}.{role_name}" regex="^(.*)  - {role_name}"',
+            ]
+            util.run_command(cmd_tests, check=True)
 
         scenario_base_directory = os.path.join(role_directory, role_name)
         templates = [
diff --git a/src/molecule/util.py b/src/molecule/util.py
--- a/src/molecule/util.py
+++ b/src/molecule/util.py
@@ -146,7 +146,7 @@ def run_command(
     if debug:
         print_environment_vars(env)
 
-    result = app.runtime.exec(
+    result = app.runtime.run(
         args=args,
         env=env,
         cwd=cwd,


Test patch:
diff --git a/src/molecule/test/functional/.ansible-lint b/src/molecule/test/functional/.ansible-lint
--- a/src/molecule/test/functional/.ansible-lint
+++ b/src/molecule/test/functional/.ansible-lint
@@ -1,12 +1,12 @@
+---
 # ansible-lint config for functional testing, used to bypass expected metadata
 # errors in molecule-generated roles. Loaded via the metadata_lint_update
 # pytest helper. For reference, see "E7xx - metadata" in:
-#  https://docs.ansible.com/ansible-lint/rules/default_rules.html
+
+# https://docs.ansible.com/ansible-lint/rules/default_rules.html
+
 skip_list:
-  # metadata/201 - Trailing whitespace
-  - '201'
-  # metadata/701 - Role info should contain platforms
-  - '701'
-  # metadata/703 - Should change default metadata: <field>"
-  - '703'
+  - meta-incorrect
+  - schema[meta]
+  - name[play]
 # See https://github.com/ansible/ansible/issues/63734
diff --git a/src/molecule/test/functional/conftest.py b/src/molecule/test/functional/conftest.py
--- a/src/molecule/test/functional/conftest.py
+++ b/src/molecule/test/functional/conftest.py
@@ -164,7 +164,8 @@ def metadata_lint_update(role_directory: str) -> None:
     # the customize ansible-lint config is used.
     with change_dir_to(role_directory):
         cmd = ["ansible-lint", "."]
-    assert run_command(cmd).returncode == 0
+        result = run_command(cmd)
+    assert result.returncode == 0
 
 
 def list_cmd(x):