-1

I have the below code in tasks/main.yml

---
- name: Check if service exists.
  shell: "systemctl status {{ service }}"
  ignore_errors: yes
  register: service_exists

- name: Enable service and start if it exists.
  systemd:
    name: "{{ service }}"
    state: started
    enabled: true
  when: "could not be found" not in service_exists.stderr' or '"Failed to get properties" not in service_exists.stderr' or '"not-found" not in service_exists.stderr'

I have the below code in configure-services.yml

---
- hosts: localhost
  become: true
  gather_facts: yes
  tasks:
    - include: tasks/main.yml
      with_items: "{{ services }}"
      loop_control:
        loop_var: service

However I get the below error when running the playbook.

fatal: [localhost]: FAILED! => {"reason": "Syntax Error while loading YAML.\n  did not find expected key\n\nThe error appears to have been in '/home/adambirds/Development/ansible-playbooks/system-services/tasks/main.yml': line 12, column 11, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n    enabled: true\n  when:''\"could not be found\" not in service_exists.stderr' or '\"Failed to get properties\" not in service_exists.stderr' or '\"not-found\" not in service_exists.stderr''\n          ^ here\nWe could be wrong, but this one looks like it might be an issue with\nunbalanced quotes.  If starting a value with a quote, make sure the\nline ends with the same set of quotes.  For instance this arbitrary\nexample:\n\n    foo: \"bad\" \"wolf\"\n\nCould be written as:\n\n    foo: '\"bad\" \"wolf\"'\n"}

I believe the issue is with my when: statement, my aim is to run the task if any of the the below doesn't appear in service_exists.stderr:

could not be found
Failed to get properties
not-found

After using the suggestion by @tinita below and changing tasks/main.yml to the below:

---
- name: Check if service exists.
  shell: "systemctl status {{ service }}"
  ignore_errors: yes
  register: service_exists

- name: Enable service and start if it exists.
  systemd:
    name: "{{ service }}"
    state: started
    enabled: true
  when: >
    "could not be found" not in service_exists.stderr
    or "Failed to get properties" not in service_exists.stderr
    or "not-found" not in service_exists.stderr

I get the below errors when running the playbook:

TASK [Check if service exists.] ***************************************************************************************************************************************************************
fatal: [localhost]: FAILED! => {"changed": true, "cmd": "systemctl status mariadb.service", "delta": "0:00:00.004881", "end": "2018-06-02 16:28:18.849473", "msg": "non-zero return code", "rc": 4, "start": "2018-06-02 16:28:18.844592", "stderr": "Unit mariadb.service could not be found.", "stderr_lines": ["Unit mariadb.service could not be found."], "stdout": "", "stdout_lines": []}
...ignoring

TASK [Enable service and start if it exists.] *************************************************************************************************************************************************
fatal: [localhost]: FAILED! => {"changed": false, "msg": "Could not find the requested service mariadb.service: host"}
        to retry, use: --limit @/home/adambirds/Development/ansible-playbooks/system-services/configure-services.retry

PLAY RECAP ************************************************************************************************************************************************************************************
localhost                  : ok=20   changed=1    unreachable=0    failed=1
Adam Birds
  • 394
  • 3
  • 21
  • Typo. Your quotes do not match and you have `' or '` in quotes. Also if you start with `"` you must quote the whole expression. – techraf Jun 02 '18 at 15:04

2 Answers2

5

If your value starts with a quote, that's a YAML quote, but you want the quote be part of the jinja expression:

when: "could not be found" not in service_exists.stderr' or '"Failed to get properties" not in service_exists.stderr' or '"not-found" not in service_exists.stderr'

So the line is invalid YAML, since you'd have to quote the whole value. When you have values with mixed quotes, it's a good idea to use YAML Block Scalars.

I think this should do what you want:

when: >
  "could not be found" not in service_exists.stderr
  or "Failed to get properties" not in service_exists.stderr
  or "not-found" not in service_exists.stderr

This is a so called "Folded Block Scalar". The lines are just folded together to one line. You could also use a Literal Block Scalar here, which keeps the linebreaks, as I believe that linebreaks don't matter in Jinja expressions.

You can see that you don't need the single quote in your expression, so an alternative solution would be using the singlequote as the YAML quote:

when: '
  "could not be found" not in service_exists.stderr
  or "Failed to get properties" not in service_exists.stderr
  or "not-found" not in service_exists.stderr'

Though I prefer block scalars since I don't need to care about quoting at all.

You might want to read my article on YAML quoting: http://blogs.perl.org/users/tinita/2018/03/strings-in-yaml---to-quote-or-not-to-quote.html

It's long, but should cover pretty much every case you'd need to know.

tinita
  • 3,987
  • 1
  • 21
  • 23
  • Thanks for this, the folded block scalar fixes that error, however it doesn't match correctly, see the log of the playbook running. I'll edit my additional post. – Adam Birds Jun 02 '18 at 15:30
  • The original questions has been edited with the new logs. – Adam Birds Jun 02 '18 at 15:35
  • I fixed your syntax error, not your logical mistake. I explained two alternatives of quoting to you, and I don't even get an upvote? – tinita Jun 02 '18 at 16:19
0

The below actually fixed the error, by changing the when: statement to the below:

when: not ("could not be found" in service_exists.stderr or "not-found" in service_exists.stderr or "Failed to get properties" in service_exists.stderr)
Adam Birds
  • 394
  • 3
  • 21