Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementing delegated driver #1292

Closed
freeseacher opened this issue May 9, 2018 · 16 comments
Closed

Implementing delegated driver #1292

freeseacher opened this issue May 9, 2018 · 16 comments
Milestone

Comments

@freeseacher
Copy link

Issue Type

  • Question

My molecule.yml

---
dependency:
  name: galaxy
driver:
  name: delegated
  hostname: 192.168.XX.10
  esxi_hostname: 192.168.XX.12
  username: XXX
  password: XXXX
  datacenter: lab
  validate_certs: "no"
  resource_pool: Tests
  folder: "/testy"
  ssh_identity_file: "XXXX"
  options:
    ansible_connection_options:
      connection: ssh
lint:
  name: yamllint
platforms:
  - name: node1
    template: packer-centos7
    memory: 3072
    cpu: 2

provisioner:
  name: ansible
  playbooks:
    converge: playbook.yml
  lint:
    name: ansible-lint
scenario:
  name: default
verifier:
  name: goss
  lint:
    name: flake8
    enabled: false

Create.yml

- name: Create
  hosts: localhost
  connection: local
  gather_facts: false
  no_log: "{{ not lookup('env', 'MOLECULE_DEBUG') | bool }}"
  tasks:
    - name: Create molecule instance(s)
      vmware_guest:
        hostname: "{{ molecule_yml.driver.hostname }}"
        esxi_hostname: "{{ molecule_yml.driver.esxi_hostname }}"
        username: "{{ molecule_yml.driver.username }}"
        password: "{{ molecule_yml.driver.password }}"
        datacenter: "{{ molecule_yml.driver.datacenter }}"
        validate_certs: "{{ molecule_yml.driver.validate_certs }}"
        resource_pool: "{{ molecule_yml.driver.resource_pool }}"
        folder: "{{ molecule_yml.driver.folder }}"
        name: "{{ item.name }}"
        template: "{{ item.template }}"
        hardware:
          memory_mb: "{{ item.memory | default(omit) }}"
          num_cpus: "{{ item.cpu | default(omit) }}"
        wait_for_ip_address: "yes"
        state: poweredon
      register: server
      with_items: "{{ molecule_yml.platforms }}"

    - name: Populate instance config dict
      set_fact:
        instance_conf_dict: {
          'instance': "{{ item.instance.hw_name }}",
          'address': "{{ item.instance.ipv4 }}",
          'user': "vagrant",
          'port': "22",
          'identity_file': 'identity_file': "{{ molecule_yml.driver.ssh_identity_file }}"
        }
      with_items: "{{ server.results }}"
      register: instance_config_dict
      when: server is changed

    - name: Convert instance config dict to a list
      set_fact:
        instance_conf: "{{ instance_config_dict.results | map(attribute='ansible_facts.instance_conf_dict') | list }}"
      when: server is changed

    - name: Dump instance config
      copy:
        # NOTE(retr0h): Workaround for Ansible 2.2.
        #               https://github.com/ansible/ansible/issues/20885
        content: "{{ instance_conf | to_json | from_json | molecule_to_yaml | molecule_header }}"
        dest: "{{ molecule_instance_config }}"
      when: server is changed

Instance created successfuly. i have file instance_config.yml

# Molecule managed

---
- address: 10.10.10.34
  identity_file:XXX
  instance: node1
  port: '22'
  user: vagrant

looks good.
but ansible_inventory.yml pretty useless because of node1 config sections.

# Molecule managed

---
all:
  hosts:
    node1: &id001
      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_scenario_directory: '{{ lookup(''env'', ''MOLECULE_SCENARIO_DIRECTORY'')
      }}'
    molecule_yml: '{{ lookup(''file'', molecule_file) | molecule_from_yaml }}'
ungrouped:
  hosts:
    node1: *id001
  vars: {}

so after converge stage i got

    fatal: [node1]: UNREACHABLE! => {
        "changed": false, 
        "unreachable": true
    }
    
    MSG:
    
    Failed to connect to the host via ssh: ssh: Could not resolve hostname node1: Name or service not known

Docs says that i have to It is the developers responsibility to configure the ssh config file.
Am i catching idea right that i have to add template for ssh_config file and put all connection logic to it?
something like

Host {{instance}}
  HostName {{address}}
  Port {{port}}
  IdentityFile {{identity_file}}
  PreferredAuthentications publickey
  User {{user}}

If yes what for instance_config.yml is used ? If no what should i do to implement delegated driver in a correct way ?

@freeseacher
Copy link
Author

ok. trying to implement

    - name: render ssh_config for instances
      template:
        src: ssh_config.j2
        dest: "{{molecule_ephemeral_directory}}/ssh_config"
      when: server is changed
{% for host in instance_conf %}
Host {{host.instance}}
  HostName {{host.address}}
  Port {{host.port}}
  IdentityFile {{host.identity_file}}
  PreferredAuthentications publickey
  User {{host.user}}
{%endfor%}

molecule.yml

driver:
  name: delegated
....
  options:
    ansible_connection_options:
      connection: ssh
      ansible_ssh_common_args: -F $MOLECULE_EPHEMERAL_DIRECTORY/ssh-config

no interpolation done.

% cat ansible_inventory.yml
# Molecule managed

---
all:
  hosts:
    node1: &id001
      ansible_ssh_common_args: -F /ssh-config
      connection: ssh

but according to http://molecule.readthedocs.io/en/latest/testing.html
You also must include the MOLECULE_EPHEMERAL_DIRECTORY variable in the molecule.yml configuration file.

@retr0h
Copy link
Contributor

retr0h commented May 10, 2018

Molecule.yml does not know anything about MOLECULE_* env vars. That is a chicken and egg problem, that is not easy to correct. Those variables are exported for many of the other components used by Molecule. However, I am trying to think of a way to correct this particular issue. It's just not easy.

It is the developers responsibility to create a ssh-config. It can be done manually or via automation, and can be placed wherever you wish. It does not need to live in the $MOLECULE_EPHEMERAL_DIRECTORY path. I suggest making your own convention for now.

@retr0h
Copy link
Contributor

retr0h commented May 10, 2018

If yes what for instance_config.yml is used ? If no what should i do to implement delegated driver in a correct way ?

Delegated driver is for people who wish to connect to systems that may or may not be managed by Molecule. Molecule does not make any assumptions here. So it is a pretty bare driver. You supply your create/destroy playbooks, and your own ssh config file. Molecule simply ssh'es into the systems.

The instance config is not necessary, b/c the instance config is specific to the Molecule driver code. It is a crappy attempt to get data generated from Ansible back into Molecule, and Molecule expects the dict to have certain keys. This is why I opted to just use an ssh config file for delegated.

I hope that makes sense why things were done this way. Also, very few people use this. You're probably the first one, so we can obviously improve this ;)

@freeseacher
Copy link
Author

I suggest making your own convention for now.

ok. not a problem. just want to follow main line.

You're probably the first one, so we can obviously improve this

i will be great if we can make ansible_host var available to playbook inventroy. i heave rely on in and on fact that it is an ip address. for example to make hosts file
https://github.com/nocproject/ansible_deploy/blob/microservices/noc_roles/pre/tasks/main.yml#L54

@freeseacher
Copy link
Author

for my use case it is just adding code from vagrant.py to delegated.py works well
i am talking about ansible_connection_options and _get_instance_config functions. of cause this breaks all the things for documented behavior but works ok.

@freeseacher
Copy link
Author

any ideas how to make it work in upstream ?

@retr0h
Copy link
Contributor

retr0h commented May 14, 2018

any ideas how to make it work in upstream ?

Make what work upstream @freeseacher ?

@freeseacher
Copy link
Author

Currently to make delegated driver works as expected i have to return code for ansible_connection_options and _get_instance_config functions. Otherwise there are no possibility to make ansible_host variable propagated well.

Currently i made docker file with molecule and patched delegated.py. That looks like quick and dirty solution but i don't want make it work like this.

So it will be good if we can add option/another driver ?
that will work like delegeted but with most of the features of molecule will work.
Currently with delegated driver molecule login is not working, inventory pretty unusable.

Of cause i understand that using molecule not as intended to do.
Not on localhost, not for role testing but pretty in devops way :)

@retr0h
Copy link
Contributor

retr0h commented May 14, 2018

The delegated driver works if you supply the ssh-config. The delegated driver simply requires that you to supply the ssh-config.

@retr0h
Copy link
Contributor

retr0h commented May 14, 2018

So it will be good if we can add option/another driver ?
that will work like delegeted but with most of the features of molecule will work.
Currently with delegated driver molecule login is not working, inventory pretty unusable.

Did you use the delegated driver and set managed to true? Molecule should write you out a host inventory file.

all:
  hosts:
    instance: &id001
      ansible_host: 127.0.0.1
  vars:
    molecule_ephemeral_directory: '{{ lookup(''env'', ''MOLECULE_EPHEMERAL_DIRECTORY'')
      }}'
    molecule_file: '{{ lookup(''env'', ''MOLECULE_FILE'') }}'
    molecule_instance_config: '{{ lookup(''env'', ''MOLECULE_INSTANCE_CONFIG'') }}'
    molecule_scenario_directory: '{{ lookup(''env'', ''MOLECULE_SCENARIO_DIRECTORY'')
      }}'
    molecule_yml: '{{ lookup(''file'', molecule_file) | molecule_from_yaml }}'
ungrouped:
  hosts:
    instance: *id001
  vars: {}

Configuring your driver as follows, you should be able to login.

driver:
  name: delegated
  options:
    managed: False
    login_cmd_template: 'ssh {instance} -F /tmp/ssh-config'
    ansible_connection_options:
      connection: ssh
      ansible_ssh_common_args -F /path/to/ssh-config

Is that not the case? I believe Molecule should act pretty much the same with delegated it just expects you to configure ssh. Molecule should have added the ansible_ssh_common_args to host inventory, so it all just works.

@freeseacher
Copy link
Author

ok. adding

  options:
    managed: True
    login_cmd_template: 'ssh {instance} -F /tmp/molecule/molecule_delegated/default/ssh_config'
    ansible_connection_options:
      connection: ssh
      ansible_ssh_common_args: -F /tmp/molecule/molecule_delegated/default/ssh_config

to driver and

    - name: render ssh_config for instances
      template:
        src: ssh_config.j2
        dest: "{{molecule_ephemeral_directory}}/ssh_config"
      when: server is changed

to prepare really makes molecule login works.

but inventory is build without ansible_host info and as far as i know i can't get it other way.

% cat /tmp/molecule/molecule_delegated/default/ansible_inventory.yml
# Molecule managed

---
all:
  hosts:
    sova_dev_rhel7: &id001
      ansible_ssh_common_args: -F /tmp/molecule/molecule_delegated/default/ssh_config
      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_scenario_directory: '{{ lookup(''env'', ''MOLECULE_SCENARIO_DIRECTORY'')
      }}'
    molecule_yml: '{{ lookup(''file'', molecule_file) | molecule_from_yaml }}'
ungrouped:
  hosts:
    sova_dev_rhel7: *id001
  vars: {}

as mentioned early i heavily rely on it

@retr0h
Copy link
Contributor

retr0h commented May 15, 2018

Molecule.yml does not know anything about MOLECULE_* env vars. That is a chicken and egg problem, that is not easy to correct. Those variables are exported for many of the other components used by Molecule. However, I am trying to think of a way to correct this particular issue. It's just not easy.

FYI - #1296

@retr0h
Copy link
Contributor

retr0h commented May 15, 2018

as mentioned early i heavily rely on it

Okay, so we will do this.

  • When managed: False we will keep it as is, and the user will need to provide the ssh config file on their own.
  • When managed: True, we will define an interface for instance config. This will allow you to login, converge, and have access to ansible_host. This would allow you to cleanup the ssh config file rendering from your playbooks, and simply use the built in Molecule ansible connection info.

Sound good?

@freeseacher
Copy link
Author

Yep. sounds good.

retr0h added a commit to retr0h/molecule that referenced this issue May 17, 2018
The delegated driver defaults to `managed`, just like
every other driver in Molecule.  This driver now
adheres to an instance-config API by default.  Only,
when `managed` is `False` does the driver force the
developer to configure connectivity.

Fixes: ansible#1292
retr0h added a commit to retr0h/molecule that referenced this issue May 17, 2018
The delegated driver defaults to `managed`, just like
every other driver in Molecule.  This driver now
adheres to an instance-config API by default.  Only,
when `managed` is `False` does the driver force the
developer to configure connectivity.

Fixes: ansible#1292
retr0h added a commit to retr0h/molecule that referenced this issue May 17, 2018
The delegated driver defaults to `managed`, just like
every other driver in Molecule.  This driver now
adheres to an instance-config API by default.  Only,
when `managed` is `False` does the driver force the
developer to configure connectivity.

Fixes: ansible#1292
retr0h added a commit to retr0h/molecule that referenced this issue May 17, 2018
The delegated driver defaults to `managed`, just like
every other driver in Molecule.  This driver now
adheres to an instance-config API by default.  Only,
when `managed` is `False` does the driver force the
developer to configure connectivity.

Fixes: ansible#1292
retr0h added a commit to retr0h/molecule that referenced this issue May 17, 2018
The delegated driver defaults to `managed`, just like
every other driver in Molecule.  This driver now
adheres to an instance-config API by default.  Only,
when `managed` is `False` does the driver force the
developer to configure connectivity.

Fixes: ansible#1292
@retr0h
Copy link
Contributor

retr0h commented May 17, 2018

@freeseacher Please try molecule on master. This should do what you expect.

retr0h added a commit that referenced this issue May 17, 2018
The delegated driver defaults to `managed`, just like
every other driver in Molecule.  This driver now
adheres to an instance-config API by default.  Only,
when `managed` is `False` does the driver force the
developer to configure connectivity.

Fixes: #1292
@barhoz10
Copy link

Hello, there is a production version of this driver ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants