# How to connect to test instances with dynamic ips?

**URL:** <https://forum.ansible.com/t/how-to-connect-to-test-instances-with-dynamic-ips/45645>\
**Category:** Get Help\
**Tags:** molecule6, molecule, aws, kubernetes\
**Created:** [April 7, 2026, 6:44am UTC](https://forum.ansible.com/t/how-to-connect-to-test-instances-with-dynamic-ips/45645 "2026-04-07T06:44:33Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![chronicc](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/chronicc/32/10568_2.png) [@chronicc](https://forum.ansible.com/u/chronicc)\
**Post date:** [April 7, 2026, 6:44am UTC](https://forum.ansible.com/t/how-to-connect-to-test-instances-with-dynamic-ips/45645/1 "2026-04-07T06:44:33Z")

</div>

I am developing an ansible collection.

I am reading about and working with the Ansible-Native configuration and want to use the shared state feature ([Ansible-Native Configuration - Ansible Molecule](https://docs.ansible.com/projects/molecule/ansible-native/#shared-state-configuration)).

However it seems like molecule can not find instances with dynamic ip addresses. I populated and persistet the `instance_config.yml`:

```yaml
- address: 192.168.123.64
  become_method: sudo
  identity_file: /home/chronicc/.ansible/tmp/molecule.kBwO.default/id_ed25519
  instance: instance01
  port: 22
  user: molecule

```

I’ve tinkered around with the `config.yml` and are now at a point where the shared state setup does block itself.

I am currently relying on the inventory file that is created by molecule itself (MOLECULE\_INVENTORY\_FILE ).

```auto
❯ cat /home/chronicc/.ansible/tmp/molecule.kBwO.default/inventory/ansible_inventory.yml 
# Molecule managed

---
all:
  hosts:
    instance01: &id001
      ansible_become_method: sudo
      ansible_connection: smart
      ansible_host: 192.168.123.64
      ansible_port: 22
      ansible_private_key_file: /home/chronicc/.ansible/tmp/molecule.kBwO.default/id_ed25519
      ansible_ssh_common_args: -o UserKnownHostsFile=/dev/null -o ControlMaster=auto
        -o ControlPersist=60s -o ForwardX11=no -o LogLevel=ERROR -o IdentitiesOnly=yes
        -o StrictHostKeyChecking=no
      ansible_user: molecule
  vars: &id002
    molecule_ephemeral_directory: '{{ lookup(''env'', ''MOLECULE_EPHEMERAL_DIRECTORY'')
      }}'
    molecule_file: '{{ lookup(''env'', ''MOLECULE_FILE'') }}'
    molecule_instance_config: '{{ lookup(''env'', ''MOLECULE_INSTANCE_CONFIG'') }}'
    molecule_no_log: '{{ lookup(''env'', ''MOLECULE_NO_LOG'') or not molecule_yml.provisioner.log|default(False)
      | bool }}'
    molecule_scenario_directory: '{{ lookup(''env'', ''MOLECULE_SCENARIO_DIRECTORY'')
      }}'
    molecule_yml: '{{ lookup(''file'', molecule_file) | from_yaml }}'
kubernetes_control_nodes:
  hosts:
    instance01: *id001
  vars: *id002
ungrouped:
  vars: {}

```

However when I am running my scenario `kubernetes`, it want’s to use the `ansible_inventory.yml` from it’s own ephemeral directory which does not contain the populated inventory file listed above.

* * *

Before this, I used the inventory directory `extensions/molecule/inventory`. This is accessible from all scenarios so the shared state feature does work. However this inventory does not get updated with the dynamic ip addresses for my instances. I am using libvirt currently but this can also change to vSphere or AWS.

I had hoped that molecule somehow combines the static inventory with the test instances hostnames and variables with the dynamic inventory from the ephemeral directory. Or somehow reuses the ip addresses from the `instance_config.yml` to update the static inventory in memory before running the playbooks.

* * *

So how would I need to setup Ansible-Native configuration with shared state and dynamic ip addresses?

---

<div class="post-metadata">

**Author:** ![bvitnik](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/bvitnik/32/4132_2.png) [@bvitnik](https://forum.ansible.com/u/bvitnik)\
**Post date:** [April 7, 2026, 2:23pm UTC](https://forum.ansible.com/t/how-to-connect-to-test-instances-with-dynamic-ips/45645/2 "2026-04-07T14:23:17Z")

</div>

As far as I understand, when using Ansible-Native configuration, you are on your own. Molecule will not do any magic for you. This means:

1. You will have to generate your inventory and specify Ansible to use it in molecule configuration:

```auto
  executor:
    backend: ansible-playbook
    args:
      ansible_playbook:
        - --inventory=/path/to/my_inv.yml

```

1. For `create` phase you will implement a playbook that does all the provisioning of instances and/or containers and generate `my_inv.yml`.

2. Other phases will read the generated inventory to run the test against.

In theory, your `my_inv.yml` can be a static file by using appropriate inventory plugin to dynamically inspect parameters of your newly provisioned instances. This can work for AWS for example:

1. Your `create.yml` playbook provisions the instances using `ec2_instance` module. No additional work needed.
2. Once your `converge.yml` playbook runs, Ansible will use inventory that uses `aws_ec2` inventory plugin to dynamically retrieve instance information. There is no need to persist, transfer or share any inventory related info between these phases.

---

<div class="post-metadata">

**Author:** ![chronicc](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/chronicc/32/10568_2.png) [@chronicc](https://forum.ansible.com/u/chronicc)\
**Post date:** [April 8, 2026, 3:00pm UTC](https://forum.ansible.com/t/how-to-connect-to-test-instances-with-dynamic-ips/45645/3 "2026-04-08T15:00:44Z")

</div>

Hello @bvitnik and thank you for your answer.

I believe that I did not do well to describe my cause. My problem is not to share an inventory between the phases (e.g. create, converge, destroy) but between scenarios (e.g. default, kubernetes, etc.).

Multiple scenarios will create multiple ephemeral directories in the ansible temporary directory:

```bash
❯ ls -l .ansible/tmp/
total 40
...
drwxrwxr-x 2 chronicc chronicc 4096 Mar 28 23:50 molecule.kBwO
drwxrwxr-x 4 chronicc chronicc 4096 Apr 5 20:34 molecule.kBwO.default
drwxrwxr-x 3 chronicc chronicc 4096 Apr 5 20:13 molecule.kBwO.kubernetes

```

There you can see the first directory is holding a `state.yml` file which tells molecule that the “resource stack” (e.g. the virtual machines) have been created.

The second directory is tracking the inventory from the default scenario which is used to create and destroy the virtual machines. This scenario has only create and destroy stage like described in the [documentation](https://docs.ansible.com/projects/molecule/ansible-native/#shared-state-configuration).

The third directory is used to run the actual converge stage from the kubernetes scenario.

### What works

I can create virtual machines with libvirt. They have dynamic ip addresses and I can do `molecule login`. I can also destroy those machines. The ephemeral directory also contains the generated inventory with all necessary variables.

### What doesn work

The ephemeral directory of the kubernetes scenario does contain another inventory. This inventory does not have the variables required for connecting to the virtual machines (e.g. ip addresses, ansible\_user).

### My question

How can the kubernetes scenario reliable connect to the virtual machines to run the converge phase. Or how can the kubernetes scenario reuse the inventory of the default scenario.

Regarding the documentation of molecule this should be possible somehow. I fear it’s not explained in a way I can understand how.

---

<div class="post-metadata">

**Author:** ![bvitnik](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/bvitnik/32/4132_2.png) [@bvitnik](https://forum.ansible.com/u/bvitnik)\
**Post date:** [April 8, 2026, 3:25pm UTC](https://forum.ansible.com/t/how-to-connect-to-test-instances-with-dynamic-ips/45645/4 "2026-04-08T15:25:15Z")

</div>

Can you share your base `config.yml` and per scenario `molecule.yml` files?

I think that what I described still holds. Something tells me that you are maybe mixing traditional and Ansible-Native approach.

Can you also share your default scenario `create.yml`?

That would clarify your situation.

---

<div class="post-metadata">

**Author:** ![chronicc](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/chronicc/32/10568_2.png) [@chronicc](https://forum.ansible.com/u/chronicc)\
**Post date:** [April 11, 2026, 5:47am UTC](https://forum.ansible.com/t/how-to-connect-to-test-instances-with-dynamic-ips/45645/5 "2026-04-11T05:47:35Z")

</div>

Yes, I am mixing both the old and the new way. If this is not recommended how would I then spawn test resources? In my understanding the whole point of molecule is to spawn test resources and run automated playbooks.

My Configs:

```yaml
# config.yml
---
ansible:
  cfg:
    defaults:
      stdout_callback: default
    inventory:
      enable_plugins: yaml
  executor:
    backend: ansible-playbook
    args:
      ansible_playbook:
        - --inventory=$MOLECULE_INVENTORY_FILE

provisioner:
  name: ansible
  env:
    ANSIBLE_VERBOSITY: 4
  inventory:
    group_vars:
      all:
        collection_namespace: chronicc
        collection_name: toolchain
        molecule_image_registry: http://worker02.neb.kurthos.site/virtualization/images/
  options:
    diff: false

role_name_check: 1

scenario:
  test_sequence:
    - prepare
    - converge
    - verify
    - idempotence
    - verify
    - cleanup

shared_state: true

verifier:
  name: ansible

```

```yaml
# default molecule.yml
---
platforms:
  - name: instance01
    cpus: 1
    groups:
      - kubernetes_control_nodes
    image: noble-server-cloudimg-amd64.img
    memory: 2048
    ostype: ubuntu24.04

scenario:
  test_sequence:
    - create
    - destroy

```

The kubernetes scenario molecule.yml is empty.

* * *

As far as I understood, the “old way” with provisioners is deprecated and will be removed in future versions. Hence the benefit of molecule would be gone if provisioning is not a part of it anymore. Not blaming here, just want to know if I understand this correctly.

---

<div class="post-metadata">

**Author:** ![bvitnik](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/bvitnik/32/4132_2.png) [@bvitnik](https://forum.ansible.com/u/bvitnik)\
**Post date:** [April 11, 2026, 12:11pm UTC](https://forum.ansible.com/t/how-to-connect-to-test-instances-with-dynamic-ips/45645/6 "2026-04-11T12:11:06Z")

</div>

I don’t see your `driver` section so I don’t know how you configured molecule to use `libvirt`.

Anyway, you cannot mix traditional and Ansible-Native approach. As soon as molecule sees `platforms` section in your config, it will assume you are using traditional approach.

I think that your example is one of those that showed the weakness of traditional Molecule. Many things, including how drivers worked, were hard coded and could not be workarounded.

So in Ansible-Native approach, instead of using a driver (`libvirt` in your example) you effectively implement your own by making a `create.yml` playbook that provisions your test instances. The molecule drivers were Ansible playbooks anyway but with Ansible-Native approach you now have a complete control of the provisioning process.

So what I initially said still holds. With Ansible-Native approach you have to:

1. Implement your own provisioning process in `create.yml` playbook. In your case you would use `community.libvirt.virt` module to get your instances up and running. You can use the `create.yml` playbook from the existing `libvirt` molecule driver as an inspiration:

> <https://github.com/ansible-community/molecule-libvirt/blob/main/molecule_libvirt/playbooks/create.yml>

Just a warning that it is overly complex because it tries to cover a lot of different environments and requirements. You can probably make it much simpler.

1. In the same `create.yml` playbook, implement a few tasks that generate your inventory (write a file) at some location that is accessible and referenced by all scenarios. Alternatively, you can use `community.libvirt.libvirt` dynamic inventory plugin to dynamically discover your instances.

If you want to stick to the traditional way, try creating per scenario `molecule.yml` that contains the following section:

```auto
ansible:
  executor:
    backend: ansible-playbook
    args:
      ansible_playbook:
        - --inventory=/path/to/the/inventory/created/by/default/scenario

```

UPDATE:

I think this documentation page illustrates Ansible-Native approach of inventory handling well:

> **[Ansible native inventory - Ansible Molecule](https://docs.ansible.com/projects/molecule/examples/ansible_native_inventory/)**

It uses containers as test instances but the only thing you have to change is what module is used for instance provisioning, like `community.libvirt.virt` instead of `containers.podman.podman_container` as shown in the example. Of course, there is additional stuff to do but you can use it as a skeleton of your `create.yml` playbook.

---

<div class="post-metadata">

**Author:** ![chronicc](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/chronicc/32/10568_2.png) [@chronicc](https://forum.ansible.com/u/chronicc)\
**Post date:** [April 12, 2026, 7:04am UTC](https://forum.ansible.com/t/how-to-connect-to-test-instances-with-dynamic-ips/45645/7 "2026-04-12T07:04:49Z")

</div>

I did not configure the driver since I don’t want to use the original libvirt driver. So it probably is `default`. I used the new and old way both in a project inside my company and it works without problems. Only difference here is the `shared_state` option which is `true` for this project.

The code for the project described in this post is here: [GitHub - chronicc/ansible-collection-toolchain at kubernetes-role · GitHub](https://github.com/chronicc/ansible-collection-toolchain/tree/kubernetes-role)

I could’ve shared this earlier now that I post it.

* * *

Okay what I understood is that I need a to create a second inventory inside my create playbook which then will be used by the other scenarios. I was unsure if this is the way reading the documentation.

I will go this route and implement it to see how this actually works. Thanks for your input so far.  
Will report back when I have closure.

---

<div class="post-metadata">

**Author:** ![bvitnik](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/bvitnik/32/4132_2.png) [@bvitnik](https://forum.ansible.com/u/bvitnik)\
**Post date:** [April 15, 2026, 10:42am UTC](https://forum.ansible.com/t/how-to-connect-to-test-instances-with-dynamic-ips/45645/8 "2026-04-15T10:42:25Z")

</div>

Found this known issue that seems to be related:

> <https://github.com/ansible/molecule/issues/4588>
>
> \### Prerequisites
> 
> \- \[x\] This was not already reported in the past (duplicate ch…eck)
> \- \[x\] It does reproduce it with code from main branch (latest unreleased version)
> \- \[x\] I include a minimal example for reproducing the bug
> \- \[x\] The bug is not trivial, as for those a direct pull-request is preferred
> \- \[x\] Running \`pip check\` does not report any conflicts
> \- \[x\] I was able to reproduce the issue on a different machine
> \- \[x\] The issue is not specific to any driver other than 'default' one
> 
> \### Environment
> 
> molecule 25.12.0 using python 3.12 :
> - ansible:2.16.0
> - default:25.12.0 from molecule
> - vagrant:25.8.12 from molecule\_plugins
> - openstack:25.8.12 from molecule\_plugins requiring collections: openstack.cloud\>=2.1.0
> - podman:25.8.12 from molecule\_plugins requiring collections: containers.podman\>=1.7.0 ansible.posix\>=1.3.0
> - gce:25.8.12 from molecule\_plugins requiring collections: google.cloud\>=1.0.2 community.crypto\>=1.8.0
> - ec2:25.8.12 from molecule\_plugins
> - docker:25.8.12 from molecule\_plugins requiring collections: community.docker\>=3.10.2 ansible.posix\>=1.4.0
> - containers:25.8.12 from molecule\_plugins requiring collections: ansible.posix\>=1.3.0 community.docker\>=1.9.1 
> - containers.podman\>=1.8.1
> - azure:25.8.12 from molecule\_plugins
> 
> OS: Fedora 42 WSL
> 
> \### What happened
> 
> \# Summary
> 
> When enabling \`shared\_state\` in Molecule, the documentation states that component scenarios can reuse resources created by the default scenario.  
> However, only the create/destroy lifecycle is actually shared — not the necessary runtime state, such as:
> 
> \- \`instance\_config.yml\`
> \- inventories
> \- ephemeral directory
> \- connection parameters for hosts created by the default scenario
> 
> This results in component scenarios being unable to access the instances created in the default scenario, causing provisioning failures.
> 
> \---
> 
> \## Expected Behavior
> 
> Based on the documentation, enabling \`shared\_state\` should allow:
> 
> \- shared ephemeral state across scenarios
> \- default scenario managing create/destroy for all others
> \- component scenarios accessing resources created by default
> \- consistent instance information (\`instance\_config\`, inventory)
> 
> At minimum, this should include:
> 
> \- a shared \`instance\_config.yml\`
> \- a shared inventory
> \- a shared ephemeral directory
> \- consistent \`MOLECULE\_INSTANCE\_CONFIG\` across scenarios
> 
> \---
> 
> \## Actual Behavior
> 
> In practice:
> 
> \- each scenario gets a different \`MOLECULE\_EPHEMERAL\_DIRECTORY\`
> \- each scenario has its own \`instance\_config.yml\`
> \- the default scenario’s inventory and connection data are not propagated
> \- component scenarios cannot connect to hosts created by the default scenario
> 
> Example environment variables printed during runs:
> 
> MOLECULE\_EPHEMERAL\_DIRECTORY: \`~/.ansible/tmp/molecule.XYZ.default\`  
> MOLECULE\_EPHEMERAL\_DIRECTORY: \`~/.ansible/tmp/molecule.ABC.component\`
> 
> This contradicts the documented behavior and makes multi-scenario reuse impossible.
> 
> \---
> 
> \## Steps to Reproduce
> 
> 1. Create two scenarios: \`default\` and \`component\`.
> 2. Enable shared state:
> 
> scenario:  
> &nbsp;&nbsp;\`shared\_state: true\`
> 
> 3. Run:
> 
> \`molecule converge -s default\`  
> \`molecule converge -s component --shared-state\`
> 
> 4. Observe:
> - separate ephemeral directories
> - separate \`instance\_config.yml\`
> - component scenario cannot reach hosts created in \`default\`
> 
> \---
> 
> \## Impact
> 
> This prevents Molecule from being used in:
> 
> \- chained scenarios
> \- multi-scenario test architectures
> \- large roles where infrastructure should only be created once
> \- any scenario that relies on the default scenario’s created instances
> 
> The feature behaves differently from what the documentation suggests.
> 
> \---
> 
> \## Proposed Fix
> 
> \### Option A — Implement full shared-state
> 
> \- share ephemeral directory
> \- share \`instance\_config\`
> \- share inventory
> \- ensure consistent \`MOLECULE\_INSTANCE\_CONFIG\` across scenarios
> 
> \### Option B — Update documentation
> 
> Explain that \`shared\_state\` currently only shares create/destroy, but does \*\*not\*\* share:
> 
> \- \`instance\_config\`
> \- ephemeral directory
> \- inventory
> 
> \---
> 
> \## Additional Information
> 
> \- This issue has been identified with the default driver
> \- The problem is reproducible with any scenario and any provisioning workflow.
> 
> \### Reproducing example
> 
> \`\`\`yml
> 
> \`\`\`

So it seems that `shared_state` does not work correctly in general as inventory is not shared. This is unlikely to be fixed because this is specific to traditional approach. With Ansible-Native approach you must handle this yourself anyway.

Now that I see your `create.yml` it now makes sense how you ended up in a situation where you don’t use any driver (defaults to `delegated`) but have `instance_config.yml` created which is specific to driver usage. Your `create.yml` explicitly creates it (last two tasks). It looks to me as if they were copy-pasted from the `libvirt` driver (AI generated?). `instance_config.yml` is kinda part of the protocol of communication between molecule and a driver but is meaningless with Ansible-Native approach. You make your own protocol including how inventory is shared between scenarios.

I personally use `shared_state` for testing but with systemd enabled Docker images so things are much simpler and no fiddling with inventory is necessary.

---

<div class="post-metadata">

**Author:** ![chronicc](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/chronicc/32/10568_2.png) [@chronicc](https://forum.ansible.com/u/chronicc)\
**Post date:** [April 15, 2026, 3:50pm UTC](https://forum.ansible.com/t/how-to-connect-to-test-instances-with-dynamic-ips/45645/9 "2026-04-15T15:50:08Z")

</div>

Hello,

yes I reused some code from the libvirt plugin.

I’ve solved my problem with the unshared inventory. Instead of the `instance_config.yml` I now write a second inventory file into `extensions/molecule/inventory/` which is generated from the created instances. This forces me to add a `.gitignore` entry for the generated inventory but solves the problem of the same inventory for different scenarios for now.

The ticket you mentioned was the reason I registered with this forum since there are no answers on the ticket that helped me. 🙂 I’d like this issue to be solved so that I can remove my workaround.

Unfortunately without the `platform` key in `molecule.yml` I can not longer use `molecule login` since the method does not read the inventory and thus is not supported with the Ansible-Native way. However this is a small price to pay for the freedom of having a working libvirt setup that I can maintain easily.

I’ve pushed the code to my above mentioned repository if you want to take a look. Probably gonna write a blog post in the next few days to document my findings. Again, thanks for your help.

---

<div class="post-metadata">

**Author:** ![bvitnik](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/bvitnik/32/4132_2.png) [@bvitnik](https://forum.ansible.com/u/bvitnik)\
**Post date:** [April 18, 2026, 5:46pm UTC](https://forum.ansible.com/t/how-to-connect-to-test-instances-with-dynamic-ips/45645/10 "2026-04-18T17:46:21Z")

</div>

Glad to be of help 😃. Cheers.
