lvps / 389ds-server

Ansible role to configure 389DS
Apache License 2.0
23 stars 14 forks source link

Setting dirsrv_serverid: '{{ ansible_hostname }}' causes error #16

Closed neilmunday closed 3 years ago

neilmunday commented 3 years ago

Hi,

Thanks for creating this Ansible role - it's very useful.

I wanted to set in my playbook dirsrv_serverid to be the hostname of the server. The playbook is used for more than one server so I wanted to use either ansible_hostname or inventory_hostname_short for dirsrv_serverid. This fails to work with the "Configure LDAPI" task however:

TASK [389ds-server : Configure LDAPI] ***************************************************************************************************************************************
changed: [spitfire0] => (item={'name': 'nsslapd-ldapilisten', 'value': 'off'})
changed: [spitfire0] => (item={'name': 'nsslapd-ldapiautobind', 'value': 'off'})
ERROR! 'ansible_hostname' is undefined

Earlier tasks that rely upon dirsrv_serverid work though.

Example playbook entry:

- role: 389ds-server
      tags: 389ds-server
      vars:
        dirsrv_rootdn_password: 'password_here'
        dirsrv_serverid: '{{ ansible_hostname }}'
        dirsrv_install_examples: true
lvps commented 3 years ago

Hi, I tried a few things but I cannot reproduce the bug.

My first test was to modify the default molecule scenario (https://github.com/lvps/389ds-server/blob/master/molecule/default/converge.yml) and add a single var: dirsrv_serverid: "{{ ansible_hostname }}", but the test completes successfully.

I also tried dirsrv_serverid: "" because I thought some tasks may consider an undefined variable like an empty string while "Configure LDAPI" doesn't, but that's not the case and the playbook fails way earlier during setup.

Finally I tried dirsrv_serverid: "{{ foo }}", a clearly undefined variable, and the playbook fails very early at "Check if instance directory exists", which is always executed.

it seems ansible_hostname became undefined at some point during your play, but I have no clue why. Did you run the playbook from start to finish, including the default "gathering facts" task? Do you have any other suggestion or information that could be useful to reproduce the bug?

neilmunday commented 3 years ago

Yes, I am running the playbook from start to finish and I can see that the facts are gathered. If set dirsrv_serverid to a string it runs fine.

As a test I modified the Configure LDAPI task in configure_authentication.yml like so:

    - debug:
        msg: "FOO2: {{ dirsrv_serverid }}"

    - name: "Configure LDAPI on {{ dirsrv_serverid }}"
      ldap_attr:
        server_uri: "{{ dirsrv_server_uri }}"
        validate_certs: "{{ dirsrv_tls_certificate_trusted }}"
        start_tls: "{{ dirsrv_starttls_early }}"
        bind_dn: "{{ dirsrv_rootdn }}"
        bind_pw: "{{ dirsrv_rootdn_password }}"
        dn: "cn=config"
        name: "{{ item.name }}"
        values: "{{ item.value }}"
        state: exact
      loop: "{{ dirsrv_ldapi_config }}"
      notify: dirsrv restart "{{ dirsrv_serverid }}"

    - debug:
        msg: "FOO3: {{ dirsrv_serverid }}"

When the playbook is run I see:

TASK [389ds-server : debug] *************************************************************************************************************************************************
ok: [spitfire0] =>
  msg: 'FOO2: spitfire0'

TASK [389ds-server : Configure LDAPI on spitfire0] **************************************************************************************************************************
changed: [spitfire0] => (item={'name': 'nsslapd-ldapilisten', 'value': 'off'})
changed: [spitfire0] => (item={'name': 'nsslapd-ldapiautobind', 'value': 'off'})
ERROR! 'ansible_hostname' is undefined

The second debug statement is not reached but I'm not sure why. I also tried replacing the {{ dirsrv_serverid }} with a the name of the server (i.e. spitfire0) in my case but this made no difference.

I'm running under a VM also.

I'll continue investigating.

alecello commented 3 years ago

Hi @neilmunday, may I ask you to check which Ansible version are you using and to run the playbook in verbose mode with:

ANSIBLE_DEBUG=true ANSIBLE_VERBOSITY=4 ansible-playbook [...]

As a further test, you might try to replace dirsrv restart "{{ dirsrv_serverid }}" with dirsrv restart {{ dirsrv_serverid }} or "dirsrv restart {{ dirsrv_serverid }}" within the notify of the Configure LDAPI task inside configure_authentication.yml

Thanks!

neilmunday commented 3 years ago

@alecello @lvps it seems that having {{ ansible_hostname }} used in the handler is the problem. Ansible version is: 2.9.13-1

Debug output for the failing task:

changed: [spitfire0] => (item={'name': 'nsslapd-ldapiautobind', 'value': 'off'}) => changed=true
  ansible_loop_var: item
  invocation:
    module_args:
      bind_dn: cn=Directory Manager
      bind_pw: VALUE_SPECIFIED_IN_NO_LOG_PARAMETER
      dn: cn=config
      name: nsslapd-ldapiautobind
      params: null
      server_uri: ldap://localhost:389
      start_tls: false
      state: exact
      validate_certs: true
      values: 'off'
  item:
    name: nsslapd-ldapiautobind
    value: 'off'
  modlist:
  - - 2
    - nsslapd-ldapiautobind
    - - 'off'
 50529 1618239621.55881: in VariableManager get_vars()
 50529 1618239621.55994: done with get_vars()
 50529 1618239621.56094: Loading FilterModule 'core' from /usr/lib/python3.6/site-packages/ansible/plugins/filter/core.py (found_in_cache=True, class_only=False)
 50529 1618239621.56109: Loading FilterModule 'gcp_kms_filters' from /usr/lib/python3.6/site-packages/ansible/plugins/filter/gcp_kms_filters.py (found_in_cache=True, class_only=False)
 50529 1618239621.56121: Loading FilterModule 'ipaddr' from /usr/lib/python3.6/site-packages/ansible/plugins/filter/ipaddr.py (found_in_cache=True, class_only=False)
 50529 1618239621.56161: Loading FilterModule 'json_query' from /usr/lib/python3.6/site-packages/ansible/plugins/filter/json_query.py (found_in_cache=True, class_only=False)
 50529 1618239621.56185: Loading FilterModule 'k8s' from /usr/lib/python3.6/site-packages/ansible/plugins/filter/k8s.py (found_in_cache=True, class_only=False)
 50529 1618239621.56217: Loading FilterModule 'mathstuff' from /usr/lib/python3.6/site-packages/ansible/plugins/filter/mathstuff.py (found_in_cache=True, class_only=False)
 50529 1618239621.56239: Loading FilterModule 'network' from /usr/lib/python3.6/site-packages/ansible/plugins/filter/network.py (found_in_cache=True, class_only=False)
 50529 1618239621.56255: Loading FilterModule 'urls' from /usr/lib/python3.6/site-packages/ansible/plugins/filter/urls.py (found_in_cache=True, class_only=False)
 50529 1618239621.56262: Loading FilterModule 'urlsplit' from /usr/lib/python3.6/site-packages/ansible/plugins/filter/urlsplit.py (found_in_cache=True, class_only=False)
 50529 1618239621.56357: Loading TestModule 'core' from /usr/lib/python3.6/site-packages/ansible/plugins/test/core.py (found_in_cache=True, class_only=False)
 50529 1618239621.56366: Loading TestModule 'files' from /usr/lib/python3.6/site-packages/ansible/plugins/test/files.py (found_in_cache=True, class_only=False)
 50529 1618239621.56376: Loading TestModule 'mathstuff' from /usr/lib/python3.6/site-packages/ansible/plugins/test/mathstuff.py (found_in_cache=True, class_only=False)
 50529 1618239621.56702: RUNNING CLEANUP
ERROR! 'ansible_hostname' is undefined

If I hard code the name of the handler, e.g.

- name: dirsrv restart "spitfire0"

then it works fine.

lvps commented 3 years ago

I have found two Ansible issues that appear related: https://github.com/ansible/ansible/issues/58841 and https://github.com/ansible/ansible/issues/63822.

The second one especially seems to be this exact problem. I still need to investigate further to be sure, but apparently using variables in handler names is a bad idea and I need to think of some workaround.

neilmunday commented 3 years ago

Nice find - that does indeed look like the issue. As handlers are executed at the end of execution, would a work around be to use a final task to restart the dirsrv instance based on a variable rather than a handler?

E.g.

- name: "restart {{dirsrv_serverid}}"
  service:
    name: "dirsrv@{{dirsrv_serverid}}"
    state: restarted
  when: restart_dirsrv
lvps commented 3 years ago

Thanks for the suggestion, I implemented it in the remove-handlers branch. I also tested some other workarounds and hacks, but nothing worked properly.

Anyway, can you confirm that the remove-handlers branch is working for you?

neilmunday commented 3 years ago

@lvps that's done the trick - many thanks!

lvps commented 3 years ago

Great, I've merged my changes into the main branch and released a new version