Skip to content
This repository has been archived by the owner on Jun 24, 2022. It is now read-only.

Handler queued by change of an ES templates file fails to find the file when run #238

Closed
welchwilmerck opened this issue Jan 19, 2017 · 16 comments

Comments

@welchwilmerck
Copy link
Contributor

welchwilmerck commented Jan 19, 2017

The timestamp on basic.json on the problem instance is several minutes prior to the handler activating. Have to run playbook several times (once for each ec2 instance, maybe) before handler sees basic.json for every instance.

Ansible 2.2.0.0
local: mac os
remote: ubuntu 14
ansible-elasticsearch: f8753ff

RUNNING HANDLER [elasticsearch : Install templates without auth] ***************
 [WARNING]: Unable to find '/etc/elasticsearch/templates/basic.json' in expected paths.

File lookup using None as file
fatal: [54_40_186_183]: FAILED! => {
    "failed": true,
    "msg": "could not locate file in lookup: /etc/elasticsearch/templates/basic.json"
}

RUNNING HANDLER [elasticsearch : Install templates with auth] ******************
	to retry, use: --limit @/Users/welchwil/gendb_cluster_devops/ansible/cluster.retry

PLAY RECAP *********************************************************************
54_40_186_108              : ok=17   changed=12   unreachable=0    failed=0
54_40_186_183              : ok=64   changed=34   unreachable=0    failed=1
54_40_186_199              : ok=17   changed=12   unreachable=0    failed=0
54_40_186_246              : ok=17   changed=12   unreachable=0    failed=0
localhost                  : ok=10   changed=5    unreachable=0    failed=0

$ ansible tag_Name_billtest_es5new -b -m command -a 'ls -l /etc/elasticsearch/templates'
54_40_186_183 | SUCCESS | rc=0 >>
total 4
-rw-r--r-- 1 elasticsearch elasticsearch 157 Jan 18 22:32 basic.json

54_40_186_108 | FAILED | rc=2 >>
ls: cannot access /etc/elasticsearch/templates: No such file or directory

54_40_186_199 | FAILED | rc=2 >>
ls: cannot access /etc/elasticsearch/templates: No such file or directory

54_40_186_246 | FAILED | rc=2 >>
ls: cannot access /etc/elasticsearch/templates: No such file or directory
@gingerwizard
Copy link

@welchwilmerck im curious are you running multiple concurrent threads when running this playbook? My concern is the handler is fired for the first host and this is interfering with the other hosts which don't have the file yet.

@gingerwizard
Copy link

Can you also attach your playbook?

@gingerwizard
Copy link

Maybe related #166

@gingerwizard
Copy link

@welchwilmerck im going to rework the template code as i believe this is reproducible.

@welchwilmerck
Copy link
Contributor Author

I've changed my playbook considerably and updated to the latest commit of this role since I saw this issue and I can't reproduce ATM. Getting stopped at some other error (below). I'll work through the other errors, but didn't want your attention to this issue to go unacknowledged. For reference, no multiple threads. I'm running just one playbook with the default strategy.

task path: /Users/welchwil/gendb_cluster_devops/ansible/roles/elasticsearch/tasks/elasticsearch-config.yml:5
failed: [54_40_186_111] (item=/etc/elasticsearch/master) => {"failed": true, "gid": 0, "group": "root", "item": "/etc/elasticsearch/master", "mode": "0755", "msg": "chown failed: failed to look up user elasticsearch", "owner": "root", "path": "/etc/elasticsearch", "size": 4096, "state": "directory", "uid": 0}

@gingerwizard
Copy link

We're going to re-do the template handing - i see potential issues with it and am suprised its worked for anyone.

Are you installing ES via the tar or rpm/deb? The former create the elasticsearch user. If not, you'll need to either:

  1. Create these by specifying the parameter es_user_id and es_group_id params as well as optionally setting es_user and es_group - the defaults for the latter 2 are elasticsearch.
    OR
  2. Otherwise create the user/group outside of the role and simply set es_user and es_group.

@welchwilmerck
Copy link
Contributor Author

welchwilmerck commented Mar 22, 2017

fce5eac Merge pull request #269 from gingerwizard/master
ansible 2.3

Currently, install from deb, option 2. Got that part figured out.

Now, seeing a different problem in roles/elasticsearch/tasks/elasticsearch-templates.yml. Will continue to troubleshoot.

First run, fails on first host and playbook halts immediately. No PLAY RECAP.

TASK [elasticsearch : Set Plugin Directory Permissions] *************
changed: [54_40_186_16]
changed: [54_40_186_160]

TASK [elasticsearch : file] *****************************************
changed: [54_40_186_16]
changed: [54_40_186_160]

TASK [elasticsearch : Copy default templates to elasticsearch] ******
ERROR! The requested handler 'load-templates' was not found in either the main handlers list nor in the listening handlers list
$

next run:
works for both hosts

TASK [elasticsearch : Set Plugin Directory Permissions] *************
changed: [54_40_186_160]
changed: [54_40_186_16]

TASK [elasticsearch : file] *****************************************
ok: [54_40_186_160]
ok: [54_40_186_16]
TASK [elasticsearch : Copy default templates to elasticsearch] ******
ok: [54_40_186_160]
ok: [54_40_186_16]

TASK [elasticsearch : Copy templates to elasticsearch] **************

RUNNING HANDLER [elasticsearch : restart elasticsearch] *************
changed: [54_40_186_160]
changed: [54_40_186_16]

TASK [elasticsearch : Wait for elasticsearch to startup] ************
ok: [54_40_186_160]
ok: [54_40_186_16]

@welchwilmerck
Copy link
Contributor Author

I found the problem - an ongoing issue in ansible regarding using include: to have multiple tasks in one handler - ansible/ansible#15915

This silently fails to parse in the version of ansible I'm using (ansible 2.3.0):

- name: load-templates
  include: ./handlers/elasticsearch-templates.yml
  when: es_templates

Renamed issue accordingly.

@welchwilmerck welchwilmerck changed the title Some sort of timing issue with templates in handlers This project is using include: to define multiple tasks in a handler. Not a stable feature of Ansible. Apr 5, 2017
@welchwilmerck welchwilmerck changed the title This project is using include: to define multiple tasks in a handler. Not a stable feature of Ansible. Use of include: to define multiple tasks in a handler. Not a stable feature of Ansible. Apr 6, 2017
@welchwilmerck
Copy link
Contributor Author

welchwilmerck commented Apr 6, 2017

Here's the ansible issue with handler blocks - ansible/ansible#20603. A handler block gets added to the list only if it's the very first handler in handlers/main.yml.

To work around, move load-templates to the top of handlers/main.yml

and now can reproduce the original issue:

RUNNING HANDLER [elasticsearch : Install templates with auth] ****************************************************************
 [WARNING]: Unable to find '/etc/elasticsearch/templates/basic.json' in expected paths.

File lookup using None as file
fatal: [54_40_186_143]: FAILED! => {
    "failed": true,
    "msg": "An unhandled exception occurred while running the lookup plugin 'file'. Error was a <class 'ansible.errors.AnsibleError'>, original message: could not locate file in lookup: /etc/elasticsearch/templates/basic.json"
}

To repeat, just go to the target machine and rm /etc/elasticsearch/templates/basic.json so that the handler triggers again.

@welchwilmerck welchwilmerck changed the title Use of include: to define multiple tasks in a handler. Not a stable feature of Ansible. Handler queued by change of an ES templates file fails to find the file when run Apr 7, 2017
@welchwilmerck
Copy link
Contributor Author

welchwilmerck commented Apr 7, 2017

I see the bug, now. In the handler, you're using lookup to pull in the contents of a file as the body of a PUT to ES. Unfortunately, lookups run on the local machine, not the remote machine. As I don't have ES installed locally, I get outright 'file not found'. Somebody with a local install with matching template names will PUT their local files, not the ones declared in Ansible.

Further, the PUT is a cluster operation, not a per host operation, so the PUT of the template to the API host should run just once for the entire playbook. I can see adapting the idea in http://stackoverflow.com/questions/41556574/run-an-ansible-handler-only-once-for-the-entire-playbook. As the final play only needs to run on localhost, collect the set of changed templates instead of changed hosts.

@welchwilmerck
Copy link
Contributor Author

welchwilmerck commented Apr 12, 2017

Here's my implementation of 'one-time play for cluster operations':

  1. Must set es_templates_fileglob. Simplest way to make templates visible to tasks in both role/elasticsearch and the cluster ops play in the same playbook run. I set it to a directory outside role/elasticsearch to reflect a realistic use case.
ansible-playbook ... -e es_templates_fileglob="{{playbook_dir + '/files/templates/*.json'}}"
  1. (optional) Rewrite tasks/elasticsearch-templates.yml to be clear that it's an if-then-else:
- file: path=/etc/elasticsearch/templates state=directory owner={{ es_user }} group={{ es_group }}

- name: Copy example templates to cluster machines unless overridden
  copy: src=templates dest=/etc/elasticsearch/ owner={{ es_user }} group={{ es_group }}
  notify: load-templates
  when: es_templates_fileglob is not defined

- name: Copy locally defined templates instead of examples
  copy: src={{ item }} dest=/etc/elasticsearch/templates owner={{ es_user }} group={{ es_group }}
  notify: load-templates
  with_fileglob: "{{ es_templates_fileglob }}"
  when: es_templates_fileglob is defined
  1. Change handlers/elasticsearch-templates.yml to just set a flag:
- name: Ensure elasticsearch is started
  service: name={{instance_init_script | basename}} state=started enabled=yes

- name: Wait for elasticsearch to startup
  wait_for: host={{es_api_host}} port={{es_api_port}} delay=10

- name: Flag that something changed in templates
  add_host:
    hostname: localhost
    es_changed_templates: true
  1. Add one-time play for cluster operations:
---
  - name: Set flag for some template changed just as in handlers/elasticsearch-templates.yml
    hosts: "{{ es_cluster_name }}"
    tasks:
      - add_host:
          hostname: localhost
          es_changed_templates: true

  - name: end of management of ES nodes -- run cluster operations one-time
    hosts: "{{ es_cluster_name }}"
    connection: local
    gather_facts: false

    # Just in case they're not set elsewhere in vars or group_vars.
    # Some have defaults that are set in the elasticsearch role, which isn't activated in this play.
    vars:
      es_api_host: "0.0.0.0"
      es_api_port: 9200
      es_enable_xpack: true
      es_xpack_features:
        - security

    tasks:

      # ln -s roles/elasticsearch/filter_plugins/ to make filename visible
      - name: Install templates without auth
        uri:
          url: "http://{{es_api_host}}:{{es_api_port}}/_template/{{(item | filename)}}"
          method: PUT
          status_code: 200
          body_format: json
          body: "{{ lookup('file', item) }}"
        when: (not es_enable_xpack or not es_xpack_features is defined or "security" not in es_xpack_features)
               and hostvars['localhost']['es_changed_templates'] is defined and hostvars['localhost']['es_changed_templates']
        with_fileglob: "{{ es_templates_fileglob }}"
        delegate_to: localhost

      - name: Install templates with auth
        uri:
          url: "http://{{es_api_host}}:{{es_api_port}}/_template/{{ item | filename }}"
          method: PUT
          status_code: 200
          user: "{{es_api_basic_auth_username}}"
          password: "{{es_api_basic_auth_password}}"
          force_basic_auth: yes
          body_format: json
          body: "{{ lookup('file', item) }}"
        when: es_enable_xpack and es_xpack_features is defined and "security" in es_xpack_features
              and hostvars['localhost']['es_changed_templates'] is defined and hostvars['localhost']['es_changed_templates']
        with_fileglob: "{{ es_templates_fileglob }}"
        delegate_to: localhost

    run_once: true
...

@barryib
Copy link
Contributor

barryib commented May 7, 2017

The PR #300 should fix this issue.

@gingerwizard
Copy link

Closed by #358

@flavioleandro
Copy link

Please, could you help me.

I have these commands in ansible:

#change setStartEnv.sh to Webcenter sites finds your group.

  • name: insert Line in setStartEnv to node cluster get group of Rules
    command: "{{item}}"
    with_items:
    • sed -i "s/satellite_server1/{{ lookup('file', '{{install_dir}}/base-cluster/hostname.txt') }}/g" /app/oracle/domains/SIT_SAT/bin/setStartupEnv.sh

And it displays the error:

TASK [strings : insert Line in setStartEnv to node cluster get group of Rules] ***********************************************************************************************************
[WARNING]: Unable to find '/app/install/base-cluster/hostname.txt' in expected paths.

fatal: [172.16.20.24]: FAILED! => {"failed": true, "msg": "An unhandled exception occurred while running the lookup plugin 'file'. Error was a <class 'ansible.errors.AnsibleError'>, original message: could not locate file in lookup: /app/install/base-cluster/hostname.txt"}

PLAY RECAP *******************************************************************************************************************************************************************************

how can I do to run successfully ?

@welchwilmerck
Copy link
Contributor Author

welchwilmerck commented Feb 14, 2018 via email

@flavioleandro
Copy link

ok, could you help me mount it with the 'File Modules' with remote lineinfile

  • name: Change isetStartupEnv.sh from Node Manager
    lineinfile:
    path: /app/oracle/domains/SIT_SAT/bin/setStartupEnv.sh
    regexp: '^if [ "${SERVER_NAME}" = "satellite_server1" ] ; then'
    insertafter: 'if [ "${SERVER_NAME}" = '
    line: 'if [ "${SERVER_NAME}" ={{install_dir}}/base-cluster/hostname.txt'

file in server remoto:
vim /app/oracle/domains/SIT_SAT/bin/setStartupEnv.sh

Associate server with a startup group

if [ "${STARTUP_GROUP}" = "" ] ; then
if [ "${SERVER_NAME}" = "AdminServer" ] ; then
STARTUP_GROUP="AdminServerStartupGroup"
export STARTUP_GROUP
fi
if [ "${SERVER_NAME}" = "satellite_server1" ] ; then
STARTUP_GROUP="SATELLITE-MGD-SVR"
export STARTUP_GROUP
fi
fi

Thanks,

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

No branches or pull requests

4 participants