3

I have the following Ansible playbook file, which attempts to manage the printers.conf on a set of CentOS 6 boxes.

---
# file: roles/common/tasks/config-cups.yml
# Configure printing

- name: ensure cups is installed
  yum: pkg=cups state=installed

# We want to compare the local and remote printers.conf files so that
# we can predetermine if the copy needs to happen.  According to a
# comment in the default printers.conf file, we can't write
# printers.conf while cups is running. But to be idempotent, we want
# to avoid stopping the cups service if we don't need to.

- stat: path=printers.conf
  register: locst

- stat: path=/etc/cups/printers.conf
  register: remst

# can't write printers.conf while running, so says the default file
- name: ensure cups is stopped
  service: name=cups state=stopped
  when: locst.stat.md5 ne remst.stat.md5

- name: Configure printers
  tags: configuration
  copy: >
    src=printers.conf
    dest=/etc/cups/printers.conf
    mode=600 owner=root group=lp
  notify:
  - restart cups

- name: Enable the cups service
  service: name=cups enabled=yes

- name: Ensure cups is running
  service: name=cups state=started

Unfortunately, I receive the error "fatal: [hostxxx] => error while evaluating conditional: locst.stat.md5 ne remst.stat.md5" from the when conditional controlling the stopping of the cups service.

Is there a way to see the values in the conditional being evaluated? Adding -vvv hasn't helped me here.

Or is there another way of debugging the conditional?

EDIT1:

Apparently the stat module is always remote - it fails to match against the local printers.conf in roles/common/files/printers.conf

TASK: [common | stat path=printers.conf] **************************************
<hostxxx> ESTABLISH CONNECTION FOR USER[...]
<hostxxx> REMOTE_MODULE stat path=printers.conf
[...]
ok: [hostxxx] => {"changed": false, "stat": {"exists": false}}

This would be the source of my "error while evaluating conditional".

So I still don't know how to cleanly manage the file. I don't want to get into hand coding md5 values into the tasks.

This stackoverflow question is looking for pretty much the same thing.

EDIT2:

Although I'm now able to get the stat module executing against the local file, using local_action and a longer path to work-around the lack of role-path searching in local actions, I still get the same error while evaluating conditional, despite having valid .stat.md5 values.

- local_action: stat path=roles/common/files/printers.conf
  register: locst

I did, however, notice that the md5 values unexpectedly differed. It seems that during run-time, cups re-writes the printers.conf file, including, of all things, a timestamp called "StateTime". So much for a straightforward way to manage cups via writing a config file.

AFAICT, the only way to cleanly manage cups, such that it would only take down the service each time would be to either filter the existing printers.conf before comparison, or far less reasonable, to write a webscraper to operate against the interface cups wants you to use to configure printers.

Community
  • 1
  • 1
R Perrin
  • 471
  • 3
  • 8
  • I located the source of the error earlier in the -vvv output: the "stat path=printers.conf" doesn't match against the local file. – R Perrin Oct 02 '14 at 19:29

3 Answers3

1

I tried to utlise the answer from AlexKing, however could not get the "extension" to work correctly. So, the following is what I ended up with (tested and working)

- name: Install Printer Driver | Create Kyocera directory as required
  file: dest=/usr/share/cups/model/Kyocera mode=0755 state=directory owner=root

- name: Install Printer Driver | Copy PPD file
  copy: src=Kyocera_TASKalfa_4551ci.PPD dest=/usr/share/cups/model/Kyocera/Kyocera_TASKalfa_4551ci.PPD owner=root group=lp mode=0444

- name: Install Printer Driver | Ensure cups is stopped before updating the printers.conf file
  service: name=cups state=stopped

- name: Install Printer Driver | Configure Printer
  tags: configuration
  copy: src=printers.conf dest=/etc/cups/printers.conf mode=600 owner=root group=lp backup=yes 

- name:  Install Printer Driver | Ensure cups is running
  service: name=cups state=started

From my understanding of how Ansible works, you shouldn't need to check if the file is different - this is what already happens in the copy module.

HTH,

Russell.

OxyOss
  • 11
  • 1
1

There might be few potential issues on your approach:

  • - stat: path=printers.conf refers to the remote location, not your local file under {{ playbook_dir }}/roles/common/
  • md5 processing isn't enabled by default. You'll to write explicitly get_md5=yes
  • user running the playbook may need to have sudo permitions to stat /etc/cups/printers.conf

Proposed solution based on your question:

---
- name: "cups - installation"
  apt: name=cups state=installed update_cache=yes cache_valid_time=3600
  become: yes

- name: "cups - md5 on local printers.conf"
  local_action: stat path={{ playbook_dir }}/roles/homie/files/printers.conf get_md5=yes
  register: locst

- name: "cups - md5 on remote printers.conf"
  stat: path=/etc/cups/printers.conf get_md5=yes
  register: remst
  become: yes

- name: "cups - stop service"
  service: name=cups state=stopped
  when: not remst.stat.exists or (locst.stat.md5 != remst.stat.md5)
  become: yes

- name: "cups - configure drivers"
  copy: src=Canon_MG2900_series.ppd dest=/etc/cups/ppd/Canon_MG2900_series.ppd mode=640 owner=root group=lp backup=yes 
  become: yes

- name: "cups - configure printers"
  copy: src=printers.conf dest=/etc/cups/printers.conf mode=600 owner=root group=lp backup=yes
  notify: restart cups
  when: not remst.stat.exists or (locst.stat.md5 != remst.stat.md5)
  become: yes

and the handler:

---
- name: restart cups
  service: name=cups state=restarted
  become: yes

Using ansible 2.1.0.0

joao cenoura
  • 1,155
  • 2
  • 14
  • 20
0

Assuming ansible only runs the validate command if the file differs and will therefore attempt to replace it, you could "extend" the validate feature to stop cups:

- name: Configure printers
  tags: configuration
  copy: src=printers.conf dest=/etc/cups/printers.conf mode=600 owner=root group=lp validate="service cups stop %s"

- name: Ensure cups is running
  service: name=cups state=started

The %s is superfluous for service (but has no effect on my debian system,) but required for ansible according to the docs. See http://docs.ansible.com/copy_module.html

AlexKing
  • 91
  • 6