ansible-community/molecule-plugins

molecule login results in "Bad port '{port}'"

isuftin opened this issue ยท 13 comments

Using Molecule on MacOS ventura 13.6.4

molecule 24.2.0 using python 3.11
    ansible:2.16.3
    azure:23.5.3 from molecule_plugins
    containers:23.5.3 from molecule_plugins requiring collections: ansible.posix>=1.3.0 community.docker>=1.9.1 containers.podman>=1.8.1
    default:24.2.0 from molecule
    docker:23.5.3 from molecule_plugins requiring collections: community.docker>=3.4.11 ansible.posix>=1.4.0
    ec2:23.5.3 from molecule_plugins
    gce:23.5.3 from molecule_plugins requiring collections: google.cloud>=1.0.2 community.crypto>=1.8.0
    openstack:23.5.3 from molecule_plugins requiring collections: openstack.cloud>=2.1.0
    podman:23.5.3 from molecule_plugins requiring collections: containers.podman>=1.7.0 ansible.posix>=1.3.0
    vagrant:23.5.3 from molecule_plugins

This seems to be a new issue for me, but when using molecule to test against a remote EC2 instance, when I run "molecule login -s my_scenario", I get Bad port '{port}'

Molecule converge seems to work fine.

Scenario specific configuration:

ansible_inventory.yml

# Molecule managed
---
all:
  hosts:
    aws-marketplace-az2-ec2-stig-localtest: &id001
      ansible_host: x.x.x.x
      ansible_port: '22'
      ansible_private_key_file: /Users/isuftin/.cache/molecule/stig/aws-marketplace-az2-ec2/id_rsa
       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: ec2-user
       connection: ssh
   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 }}'
 az2:
   hosts:
     aws-marketplace-az2-ec2-stig-localtest: *id001
   vars: *id002
 ec2:
   hosts:
     aws-marketplace-az2-ec2-stig-localtest:
       ansible_host: x.x.x.x
       ansible_port: '22'
       ansible_private_key_file: /Users/isuftin/.cache/molecule/stig/aws-marketplace-az2-ec2/id_rsa
       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: ec2-user
       connection: ssh
   vars:
     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 }}'
 ungrouped:
   vars: {}

ansible.cfg

# Molecule managed

[defaults]
ansible_managed = Ansible managed: Do NOT edit this file manually!
display_failed_stderr = True
forks = 50
retry_files_enabled = False
host_key_checking = False
nocows = 1
interpreter_python = auto_silent
bin_ansible_callbacks = True
callbacks_enabled = ansible.posix.profile_tasks,ansible.posix.profile_roles,ansible.posix.timer,ansible.builtin.junit
display_args_to_stdout = True
pipelining = True
show_custom_stats = True
stdout_callback = community.general.yaml
timeout = 60
use_persistent_connections = True
verbosity = 2
fact_caching = jsonfile
fact_caching_connection = /Users/isuftin/.cache/molecule/stig/aws-marketplace-az2-ec2/facts_cache
fact_caching_timeout = 7200
[ssh_connection]
scp_if_ssh = True
control_path = %(directory)s/%%h-%%p-%%r
[diff]
always = True
[galaxy]
display_progress = False
[ssh]
ssh_args = -C -o ControlMaster=auto -o ControlPersist=600s -o IdentitiesOnly=yes -o PreferredAuthentications=publickey -o ConnectTimeout=60
reconnection_retries = 3

instance_config.yml

- address: x.x.x.x (aws internal ip addr)
  identity_file: /Users/isuftin/.cache/molecule/stig/aws-marketplace-az2-ec2/id_rsa
  instance: aws-marketplace-az2-ec2-stig-localtest
  instance_ids: [i-my-ec2-id]
  port: '22'
  user: ec2-user

molecule.yml

# Molecule managed

---
dependency:
  command: null
  enabled: true
  env: {}
  name: galaxy
  options:
    force: true
    requirements-file: molecule/common/collections_requirements.yml
    role-file: molecule/common/role_requirements.yml
driver:
  name: ec2
  options:
    managed: true
  provider:
    name: null
  safe_files: []
  ssh_connection_options: []
platforms:
  - aws_iam_role: my_iam_role
    groups:
      - ec2
      - az2
    image: ami-my=ami
    instance_type: t3a.medium
    key_inject_method: ec2
    name: aws-marketplace-az2-ec2-stig-localtest
    region: us-east-1
    security_groups: sg-my-security-groups
    ssh_startup_wait_seconds: 60
    tags:
      Name: Ansible Molecule - aws-marketplace-az2-ec2-stig-localtest
      wma:ansible_managed: 'true'
      wma:molecule_pipeline_id: manual
      wma:project_id: enterprise
    volume_name: /dev/xvda
    vpc_id: vpc-my-vpc
    vpc_subnet_id: subnet-my-subnet
prerun: true
provisioner:
  ansible_args: []
  children: {}
  config_options:
    defaults:
      bin_ansible_callbacks: true
      callbacks_enabled: ansible.posix.profile_tasks,ansible.posix.profile_roles,ansible.posix.timer,ansible.builtin.junit
      display_args_to_stdout: true
      fact_caching: jsonfile
      fact_caching_connection: /Users/isuftin/.cache/molecule/stig/aws-marketplace-az2-ec2/facts_cache
      fact_caching_timeout: 7200
      pipelining: true
      show_custom_stats: true
      stdout_callback: community.general.yaml
      timeout: 60
      use_persistent_connections: true
      verbosity: 2
    diff:
      always: true
    galaxy:
      display_progress: false
    ssh:
      reconnection_retries: 3
      ssh_args: -C -o ControlMaster=auto -o ControlPersist=600s -o IdentitiesOnly=yes
        -o PreferredAuthentications=publickey -o ConnectTimeout=60
  connection_options: {}
  env:
    SSH_USERNAME: ec2-user
  inventory:
    group_vars: {}
    host_vars: {}
    hosts: {}
    links:
      group_vars: ../common/group_vars
      host_vars: ../common/ec2/host_vars
  log: true
  name: ansible
  options: {}
  playbooks:
    cleanup: cleanup.yml
    converge: ../common/converge.yml
    create: ../common/ec2/create.yml
    destroy: ../common/ec2/destroy.yml
    prepare: prepare.yml
    side_effect: side_effect.yml
    verify: verify.yml
role_name_check: 0
scenario:
  check_sequence:
    - dependency
    - cleanup
    - destroy
    - create
    - prepare
    - converge
    - check
    - cleanup
    - destroy
  cleanup_sequence:
    - cleanup
  converge_sequence:
    - dependency
    - create
    - prepare
    - converge
  create_sequence:
    - dependency
    - create
    - prepare
  destroy_sequence:
    - dependency
    - cleanup
    - destroy
  name: aws-marketplace-az2-ec2
  test_sequence:
    - dependency
    - cleanup
    - destroy
    - syntax
    - create
    - prepare
    - converge
    - idempotence
    - side_effect
    - verify
    - cleanup
    - destroy
verifier:
  additional_files_or_dirs: []
  directory: ../common/tests
  enabled: true
  env: {}
  name: testinfra
  options:
    instafail: true
    junit-xml: junit.xml
    maxprocesses: '10'
    n: auto
    r: fEs
    v: true
 molecule login -s aws-marketplace-az2-ec2
INFO     Found config file /ansible/roles/stig/.config/molecule/config.yml
WARNING  Driver vagrant does not provide a schema.
WARNING  Driver vagrant does not provide a schema.
WARNING  Driver ec2 does not provide a schema.
WARNING  Driver ec2 does not provide a schema.
WARNING  Driver ec2 does not provide a schema.
WARNING  Driver ec2 does not provide a schema.
WARNING  Driver ec2 does not provide a schema.
INFO     Running aws-marketplace-az2-ec2 > login
Bad port '{port}'

I can use the ssh key defined in the inventory along with the ip address and SSH into the instance manually with no issues.

Ran into it as well.

The problem is here:

https://github.com/ansible-community/molecule-plugins/blob/main/src/molecule_plugins/ec2/driver.py#L169

This file assumes Jinja templating for the port parameter and passes a Jinja-style "{{ port }}".

https://github.com/ansible/molecule/blob/main/src/molecule/command/login.py#L105

^ Now this happens in this file and is done by python calling .format() on the string. That effectively means we need python-style templates (so "{var}") and not Jinja (double brackets - "{{ var }}".

I submitted an MR here to fix this up: #240

@danielpodwysocki - Glad it's not just me. Appreciate the MR.

reproduced using vagrant + virtualbox.
https://github.com/konstruktoid/ansible-role-hardening/blob/master/molecule/almalinux/molecule.yml

$ molecule login -s almalinux --host almalinux8
WARNING  Driver vagrant does not provide a schema.
WARNING  Driver vagrant does not provide a schema.
WARNING  Driver docker does not provide a schema.
WARNING  Driver vagrant does not provide a schema.
WARNING  Driver vagrant does not provide a schema.
WARNING  Driver vagrant does not provide a schema.
WARNING  Driver vagrant does not provide a schema.
INFO     Running almalinux > login
Bad port '{port}'
$ ssh -i [...]/ansible-role-hardening/almalinux/.vagrant/machines/almalinux8/virtualbox/private_key vagrant@127.0.0.1 -p2222

By accessing this system, you consent to the following conditions:
- This system is for authorized use only.
- Any or all uses of this system and all files on this system may be monitored.
- Communications using, or data stored on, this system are not private.

Last login: Fri Feb 16 11:21:52 2024 from 10.0.2.2
[vagrant@almalinux8 ~]$ 
# Molecule managed

---
all:
  hosts:
    almalinux8: &id001
      ansible_host: 127.0.0.1
      ansible_port: '2222'
      ansible_private_key_file: [...]/.cache/molecule/ansible-role-hardening/almalinux/.vagrant/machines/almalinux8/virtualbox/private_key
      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: vagrant
      connection: ssh
    almalinux9: &id002
      ansible_host: 127.0.0.1
      ansible_port: '2200'
      ansible_private_key_file:  [...]/.cache/molecule/ansible-role-hardening/almalinux/.vagrant/machines/almalinux9/virtualbox/private_key
      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: vagrant
      connection: ssh
  vars:
    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 }}'
ungrouped:
  hosts:
    almalinux8: *id001
    almalinux9: *id002
  vars: {}
$ molecule --version
molecule 24.2.0 using python 3.11 
    ansible:2.16.3
    azure:23.5.3 from molecule_plugins
    containers:23.5.3 from molecule_plugins requiring collections: ansible.posix>=1.3.0 community.docker>=1.9.1 containers.podman>=1.8.1
    default:24.2.0 from molecule
    docker:23.5.3 from molecule_plugins requiring collections: community.docker>=3.4.11 ansible.posix>=1.4.0
    ec2:23.5.3 from molecule_plugins
    gce:23.5.3 from molecule_plugins requiring collections: google.cloud>=1.0.2 community.crypto>=1.8.0
    openstack:23.5.3 from molecule_plugins requiring collections: openstack.cloud>=2.1.0
    podman:23.5.3 from molecule_plugins requiring collections: containers.podman>=1.7.0 ansible.posix>=1.3.0
    vagrant:23.5.3 from molecule_plugins
nandac commented

I am seeing this issue crop up in 23.5.3 where molecule login fails with the Bad Port error mentioned above. However, this does not occur with version 23.5.0.

I do not see any difference in the code for molecule login between these two versions.

Is this a regression bug and was it in 23.5.0?

I updated the PR to cover all plugins, it seems this affects each one of them.

Seeing this as well with the GCE driver.

Ran into it as well.

I submitted an MR here to fix this up: #240

Thanks for the analysis and fix. I applied the change you posted in the PR for the vagrant driver and all is now working.

hey @ssbarnea or @zhan9san could you have a look at PR #240 ? Thanks

It seems that molecule dropped support for init (see ansible/molecule#4042), so I downgraded to molecule 5.1 and everything worked fine.

However, as suggested from IRC I tried to upgrade molecule and removed the files created on initialization of scenario (create.yml and destroy.yml), and then my vagrant machine booted fine. However, I could no login because of this issue ('Bad port').

#239 fixes this issue with the last version of molecule, but then it fails with molecule 5.1.

gionn commented

@apatard any chance to release this? last GA is now 10 months old.

simi commented

I can confirm fdc748f fixes the problem. Any chance to release ๐Ÿ™ ?