How to handle special characters to get result as "%{%s}t" using Ansible/yml?

4.1k Views Asked by At

Currently working on Ansible to port config of older system to multiple IBM ISAM 9 systems using ISAM-Ansible-Roles (https://github.com/IBM-Security/isam-ansible-roles) and having issue with a specific string.

The result I need is like this:

request-log-format = { "seconds": "%{%s}t" }

The .yml file I got is as below:

---
- name: Run some commands
  hosts: all
  connection: local
  vars:
    username: "admin"
    password: "password1234"
    lmi_port: "443"
    log_level: "CRITICAL"
    force: True
    start_config_wait_time: 120
  roles:
    - role: update_reverseproxy_conf
      update_reverseproxy_conf_reverseproxy_id: "TestInstance"
      update_reverseproxy_conf_entries:
      - stanza_id: "logging"
        entry_id: "request-log-format"
        value_id: " { \"seconds\": \"%{%s}t\" } "

The last line value_id: is where I am having problem. Tried various methods with single/double quotes, and different escape characters ("\" and "%") but all failed. Some of them listed below.

1) " { \"seconds\": \"%{%s}t\" } "  error: Encountered unknown tag 's'
2) ' { \"seconds\": \"%{%s}t\" } '  error: Encountered unknown tag 's'
3) ' { \"seconds\": \"%{\%s}t\" } ' no error but with incorrect result extra back slash before %s)  request-log-format = { "seconds": "%{\%s}t" }
4) ' { \"seconds\": \"\%{%s}t\" } ' error: Encountered unknown tag 's'
5) " { \"seconds\": \"%{%%s}t\" } "  error: tag name expected
6) " { \"seconds\": \"%%{%s}t\" } "  error: tag name expected

Did some searches on the net but can't find any solution. Please help, any suggestions or ideas welcomed. Thanks!

[Update 2018.01.05]

I use docker to run ansible. The file was saved as "testOneLine.yml", the command to run is:

sudo docker run -it --rm -v /home/user1/Documents/myplatform:/ansible/playbooks --name test mludocker/isam-ansible -i hosts testOneLine.yml

Also tried a few more below as suggested, but all failed:

7) '{% raw %}{ "seconds": "%{%s}t" }{% endraw %}'  error: Encountered unknown tag 's'
8) !unsafe ' { "seconds": "%{%s}t" } '  error: SyntaxError: invalid syntax MODULE FAILURE

Tried Rob H's suggestion and rewrite as below, with extra regex_replace at the end, but it also failed.

---
- name: Run some commands
  hosts: all
  connection: local
  vars:
    username: "admin"
    password: "password1234"
    lmi_port: "443"
    log_level: "CRITICAL"
    force: True
    start_config_wait_time: 120
    starter_value: "{ \"seconds\": \"${$s}t\" }"        
  roles:
    - role: update_reverseproxy_conf
      update_reverseproxy_conf_reverseproxy_id: "TestInstance"
      update_reverseproxy_conf_entries:
      - stanza_id: "logging"
        entry_id: "request-log-format"
        value_id: "{{ starter_value | regex_replace('\\$','%') }}"

Can see the "regex_replace" part is working as the final "value_id" string has the "$" correctly changed to "%". The error message shown below is the same as before (Encountered unknown tag 's').

FAILED! => {
"failed": true, 
"msg": "{u'entry_id': u'request-log-format', u'stanza_id': u'logging', u'value_id': u' { \"seconds\": \"%{%s}t\" } '}: template error while templating string: Encountered unknown tag 's'.. String:  { \"seconds\": \"%{%s}t\" } "
}

I also raised a new issue #53 with IBM security

2

There are 2 best solutions below

2
On

This is a surprisingly frustrating problem, and I'm not sure if this will help but I was able to get a string set that that matches your required format of

request-log-format = { "seconds": "%{%s}t" }

What is not clear is if the isam role you are running will be able to use it. If the role internally ends up using any jinja templating I suspect this will just move the problem into a different section of code, but I thought I could at least share what I found and see if it helps you:

---
- name: handle problems with %
  connection: local
  hosts: localhost

  tasks:
    - name: set a starter value that passes validation
      set_fact:
        starter_value: "request-log-format = { \"seconds\": \"%{$s}t\" }"

    #
    # now set value_id to the final correct value
    # running ansible-playbook with verbose on you can see
    # that the var is set correctly but see comments below
    #
    - name: set value_id (changing $ to %)
      set_fact:
        value_id: "{{ starter_value | regex_replace('\\$','%') }}"

    #
    # to reference the field in ansible must use the start_value and substitute
    # dumping the created file shows the desired values
    #
    - copy: content="{{ starter_value | regex_replace('\$','%') }}" dest=/tmp/value_id

    #
    # using the already converted value will fail
    #
    #- copy: content="{{ value_id }}" dest=/tmp/value_id      
1
On

IBM has provided a solution/work around (see closed issue #53)

Test and confirmed if I changed the last line to as below, (1) replacing "%" with "\x25" and (2) enclose the whole string with single quotes (doesn't work if use double quotes),

value_id: '{ \"seconds\": \"\x25{\x25s}t\" }'

then it correctly updates the "request-log-format" key with the expected result:

request-log-format = { "seconds": "%{%s}t" }

Thanks