There is no way to do a dynamic number of inputs on a Survey, which I think is what you are trying to achieve. About the only way I can think of to make this more user friendly would be to have the user interface in another designed for end user interactions in mind, have that app sanitize your inputs, and then call the AWX API to execute the playbook.
However, I made a mock up of what you are looking for, in two different ways to see if either one is useful to you.
Method 1: Single Text Area Input
Survey Questions
Question 1 (The only question)
Question: List of Redirects
Description: List of redirects, one per line, using format “domain,from_url,to_url”
Answer variable name: redirect_list
Answer Type: Text area
Survey Input
I used this CSV list in the text area
mydomain.com,/myapp,/private/myapp
mydomain.com,/myapp1,/private/myapp1
mydomain.com,/myapp2,/private/myapp2
mydomain.com,/myapp3,/private/myapp3
Playbook
---
# Sample Playbook to show how to use the survey inputs
- name: Survey Sample - Single Input (TextArea)
hosts: all
tasks:
- name: Display all variables
ansible.builtin.debug:
msg: "{{ data[0] }} :: Redirecting {{ data[1] }} to {{ data[2] }}"
with_items: "{{ redirect_list | default([]) }}"
vars:
data: "{{ item | split(',') | default([]) }}"
# I don't know what your actual play will look like because I don't know
# API call you are actually making to your WAF, but here is an example
- name: Add Redirect to WAF
ansible.builtin.uri:
url: "https://your.waf.url.com/api/redirect/endpoint"
username: "{{ waf_username }}"
password: "{{ waf_password }}"
method: POST
force_basic_auth: yes
body_format: json
body:
domain: "{{ data[0] }}"
from_url: "{{ data[1] }}"
to_url: "{{ data[2] }}"
with_items: "{{ redirect_list | default([]) }}"
vars:
data: "{{ item | split(',') | default([]) }}"
Sample Output
$ ansible-playbook -i inventory play_testing.yml
PLAY [Survey Sample - Single Input (TextArea)] *********************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************************************************
ok: [localhost]
TASK [Display all variables] ***************************************************************************************************************************
ok: [localhost] => (item=mydomain.com,/myapp,/private/myapp) => {
"msg": "mydomain.com :: Redirecting /myapp to /private/myapp"
}
ok: [localhost] => (item=mydomain.com,/myapp1,/private/myapp1) => {
"msg": "mydomain.com :: Redirecting /myapp1 to /private/myapp1"
}
ok: [localhost] => (item=mydomain.com,/myapp2,/private/myapp2) => {
"msg": "mydomain.com :: Redirecting /myapp2 to /private/myapp2"
}
ok: [localhost] => (item=mydomain.com,/myapp3,/private/myapp3) => {
"msg": "mydomain.com :: Redirecting /myapp3 to /private/myapp3"
}
PLAY RECAP *********************************************************************************************************************************************
nautobot.durstie.space : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
I cannot replicate what the output of the WAF updates would look like because I don’t have a WAF to run this against, and it’s too much effort for me to write up a quick http app to forge responses.
Method 2: Three Mapped Inputs
In my opinion, this method is more prone to human error.
Survey Questions
Question 1
Question: List of domains, separated by comma
Answer Variable: domain_list
Type: Text
Question 2
Question: List of from_urls, separated by comma
Answer Variable: from_list
Type: Text
Question 3
Qustion: List of to_urls, separated by comma
Answer Variable: to_list
Type: Text
Survey Input
domain_list: mydomain.com,mydomain.com,mydomain.com
from_list : /myapp,myapp1,/myapp2
to_list: /private/myapp,/private/myapp1,/private/myapp2,
Playbook
---
# Sample Playbook to show how to use the survey inputs
- name: Survey Sample - Single Input (TextArea)
hosts: all
tasks:
- name: Normalize Input Data
ansible.builtin.set_fact:
domain_list: "{{ domain_list | split(',') | default([]) }}"
from_list: "{{ from_list | split(',') | default([]) }}"
to_list: "{{ to_list | split(',') | default([]) }}"
- name: Display all variables
ansible.builtin.debug:
msg: "{{ item }} :: Redirecting {{ from_list[index] }} to {{ to_list[index] }}"
with_items: "{{ domain_list }}"
loop_control:
index_var: index
Sample Output
$ ansible-playbook -i inventory play_testing.yml
PLAY [Survey Sample - Single Input (TextArea)] *********************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************************************************
ok: [localhost]
TASK [Normalize Input Data] ****************************************************************************************************************************
ok: [localhost]
TASK [Display all variables] ***************************************************************************************************************************
ok: [localhost] => (item=mydomain.com) => {
"msg": "mydomain.com :: Redirecting /myapp to /private/myapp"
}
ok: [localhost] => (item=mydomain.com) => {
"msg": "mydomain.com :: Redirecting /myapp1 to /private/myapp1"
}
ok: [localhost] => (item=mydomain.com) => {
"msg": "mydomain.com :: Redirecting /myapp2 to /private/myapp2"
}
PLAY RECAP *********************************************************************************************************************************************
nautobot.durstie.space : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
I didn’t include a sample URI call in the second example because it can be easily inferred based on the first example.