summaryrefslogtreecommitdiffstats
path: root/test/integration/targets/uri
diff options
context:
space:
mode:
Diffstat (limited to 'test/integration/targets/uri')
-rw-r--r--test/integration/targets/uri/aliases3
-rw-r--r--test/integration/targets/uri/files/README9
-rw-r--r--test/integration/targets/uri/files/fail0.json1
-rw-r--r--test/integration/targets/uri/files/fail1.json1
-rw-r--r--test/integration/targets/uri/files/fail10.json1
-rw-r--r--test/integration/targets/uri/files/fail11.json1
-rw-r--r--test/integration/targets/uri/files/fail12.json1
-rw-r--r--test/integration/targets/uri/files/fail13.json1
-rw-r--r--test/integration/targets/uri/files/fail14.json1
-rw-r--r--test/integration/targets/uri/files/fail15.json1
-rw-r--r--test/integration/targets/uri/files/fail16.json1
-rw-r--r--test/integration/targets/uri/files/fail17.json1
-rw-r--r--test/integration/targets/uri/files/fail18.json1
-rw-r--r--test/integration/targets/uri/files/fail19.json1
-rw-r--r--test/integration/targets/uri/files/fail2.json1
-rw-r--r--test/integration/targets/uri/files/fail20.json1
-rw-r--r--test/integration/targets/uri/files/fail21.json1
-rw-r--r--test/integration/targets/uri/files/fail22.json1
-rw-r--r--test/integration/targets/uri/files/fail23.json1
-rw-r--r--test/integration/targets/uri/files/fail24.json1
-rw-r--r--test/integration/targets/uri/files/fail25.json1
-rw-r--r--test/integration/targets/uri/files/fail26.json2
-rw-r--r--test/integration/targets/uri/files/fail27.json2
-rw-r--r--test/integration/targets/uri/files/fail28.json1
-rw-r--r--test/integration/targets/uri/files/fail29.json1
-rw-r--r--test/integration/targets/uri/files/fail3.json1
-rw-r--r--test/integration/targets/uri/files/fail30.json1
-rw-r--r--test/integration/targets/uri/files/fail4.json1
-rw-r--r--test/integration/targets/uri/files/fail5.json1
-rw-r--r--test/integration/targets/uri/files/fail6.json1
-rw-r--r--test/integration/targets/uri/files/fail7.json1
-rw-r--r--test/integration/targets/uri/files/fail8.json1
-rw-r--r--test/integration/targets/uri/files/fail9.json1
-rw-r--r--test/integration/targets/uri/files/formdata.txt1
-rw-r--r--test/integration/targets/uri/files/pass0.json58
-rw-r--r--test/integration/targets/uri/files/pass1.json1
-rw-r--r--test/integration/targets/uri/files/pass2.json6
-rw-r--r--test/integration/targets/uri/files/pass3.json1
-rw-r--r--test/integration/targets/uri/files/pass4.json1
-rw-r--r--test/integration/targets/uri/files/testserver.py23
-rw-r--r--test/integration/targets/uri/meta/main.yml4
-rw-r--r--test/integration/targets/uri/tasks/ciphers.yml32
-rw-r--r--test/integration/targets/uri/tasks/main.yml779
-rw-r--r--test/integration/targets/uri/tasks/redirect-all.yml272
-rw-r--r--test/integration/targets/uri/tasks/redirect-none.yml296
-rw-r--r--test/integration/targets/uri/tasks/redirect-safe.yml274
-rw-r--r--test/integration/targets/uri/tasks/redirect-urllib2.yml294
-rw-r--r--test/integration/targets/uri/tasks/return-content.yml49
-rw-r--r--test/integration/targets/uri/tasks/unexpected-failures.yml26
-rw-r--r--test/integration/targets/uri/tasks/use_gssapi.yml62
-rw-r--r--test/integration/targets/uri/tasks/use_netrc.yml51
-rw-r--r--test/integration/targets/uri/templates/netrc.j23
-rw-r--r--test/integration/targets/uri/vars/main.yml20
53 files changed, 2298 insertions, 0 deletions
diff --git a/test/integration/targets/uri/aliases b/test/integration/targets/uri/aliases
new file mode 100644
index 0000000..90ef161
--- /dev/null
+++ b/test/integration/targets/uri/aliases
@@ -0,0 +1,3 @@
+destructive
+shippable/posix/group1
+needs/httptester
diff --git a/test/integration/targets/uri/files/README b/test/integration/targets/uri/files/README
new file mode 100644
index 0000000..ef77912
--- /dev/null
+++ b/test/integration/targets/uri/files/README
@@ -0,0 +1,9 @@
+The files were taken from http://www.json.org/JSON_checker/
+> If the JSON_checker is working correctly, it must accept all of the pass*.json files and reject all of the fail*.json files.
+
+Difference with JSON_checker dataset:
+ - *${n}.json renamed to *${n-1}.json to be 0-based
+ - fail0.json renamed to pass3.json as python json module allows JSON payload to be string
+ - fail17.json renamed to pass4.json as python json module has no problems with deep structures
+ - fail32.json renamed to fail0.json to fill gap
+ - fail31.json renamed to fail17.json to fill gap
diff --git a/test/integration/targets/uri/files/fail0.json b/test/integration/targets/uri/files/fail0.json
new file mode 100644
index 0000000..ca5eb19
--- /dev/null
+++ b/test/integration/targets/uri/files/fail0.json
@@ -0,0 +1 @@
+["mismatch"} \ No newline at end of file
diff --git a/test/integration/targets/uri/files/fail1.json b/test/integration/targets/uri/files/fail1.json
new file mode 100644
index 0000000..6b7c11e
--- /dev/null
+++ b/test/integration/targets/uri/files/fail1.json
@@ -0,0 +1 @@
+["Unclosed array" \ No newline at end of file
diff --git a/test/integration/targets/uri/files/fail10.json b/test/integration/targets/uri/files/fail10.json
new file mode 100644
index 0000000..76eb95b
--- /dev/null
+++ b/test/integration/targets/uri/files/fail10.json
@@ -0,0 +1 @@
+{"Illegal expression": 1 + 2} \ No newline at end of file
diff --git a/test/integration/targets/uri/files/fail11.json b/test/integration/targets/uri/files/fail11.json
new file mode 100644
index 0000000..77580a4
--- /dev/null
+++ b/test/integration/targets/uri/files/fail11.json
@@ -0,0 +1 @@
+{"Illegal invocation": alert()} \ No newline at end of file
diff --git a/test/integration/targets/uri/files/fail12.json b/test/integration/targets/uri/files/fail12.json
new file mode 100644
index 0000000..379406b
--- /dev/null
+++ b/test/integration/targets/uri/files/fail12.json
@@ -0,0 +1 @@
+{"Numbers cannot have leading zeroes": 013} \ No newline at end of file
diff --git a/test/integration/targets/uri/files/fail13.json b/test/integration/targets/uri/files/fail13.json
new file mode 100644
index 0000000..0ed366b
--- /dev/null
+++ b/test/integration/targets/uri/files/fail13.json
@@ -0,0 +1 @@
+{"Numbers cannot be hex": 0x14} \ No newline at end of file
diff --git a/test/integration/targets/uri/files/fail14.json b/test/integration/targets/uri/files/fail14.json
new file mode 100644
index 0000000..fc8376b
--- /dev/null
+++ b/test/integration/targets/uri/files/fail14.json
@@ -0,0 +1 @@
+["Illegal backslash escape: \x15"] \ No newline at end of file
diff --git a/test/integration/targets/uri/files/fail15.json b/test/integration/targets/uri/files/fail15.json
new file mode 100644
index 0000000..3fe21d4
--- /dev/null
+++ b/test/integration/targets/uri/files/fail15.json
@@ -0,0 +1 @@
+[\naked] \ No newline at end of file
diff --git a/test/integration/targets/uri/files/fail16.json b/test/integration/targets/uri/files/fail16.json
new file mode 100644
index 0000000..62b9214
--- /dev/null
+++ b/test/integration/targets/uri/files/fail16.json
@@ -0,0 +1 @@
+["Illegal backslash escape: \017"] \ No newline at end of file
diff --git a/test/integration/targets/uri/files/fail17.json b/test/integration/targets/uri/files/fail17.json
new file mode 100644
index 0000000..45cba73
--- /dev/null
+++ b/test/integration/targets/uri/files/fail17.json
@@ -0,0 +1 @@
+{"Comma instead if closing brace": true, \ No newline at end of file
diff --git a/test/integration/targets/uri/files/fail18.json b/test/integration/targets/uri/files/fail18.json
new file mode 100644
index 0000000..3b9c46f
--- /dev/null
+++ b/test/integration/targets/uri/files/fail18.json
@@ -0,0 +1 @@
+{"Missing colon" null} \ No newline at end of file
diff --git a/test/integration/targets/uri/files/fail19.json b/test/integration/targets/uri/files/fail19.json
new file mode 100644
index 0000000..27c1af3
--- /dev/null
+++ b/test/integration/targets/uri/files/fail19.json
@@ -0,0 +1 @@
+{"Double colon":: null} \ No newline at end of file
diff --git a/test/integration/targets/uri/files/fail2.json b/test/integration/targets/uri/files/fail2.json
new file mode 100644
index 0000000..168c81e
--- /dev/null
+++ b/test/integration/targets/uri/files/fail2.json
@@ -0,0 +1 @@
+{unquoted_key: "keys must be quoted"} \ No newline at end of file
diff --git a/test/integration/targets/uri/files/fail20.json b/test/integration/targets/uri/files/fail20.json
new file mode 100644
index 0000000..6247457
--- /dev/null
+++ b/test/integration/targets/uri/files/fail20.json
@@ -0,0 +1 @@
+{"Comma instead of colon", null} \ No newline at end of file
diff --git a/test/integration/targets/uri/files/fail21.json b/test/integration/targets/uri/files/fail21.json
new file mode 100644
index 0000000..a775258
--- /dev/null
+++ b/test/integration/targets/uri/files/fail21.json
@@ -0,0 +1 @@
+["Colon instead of comma": false] \ No newline at end of file
diff --git a/test/integration/targets/uri/files/fail22.json b/test/integration/targets/uri/files/fail22.json
new file mode 100644
index 0000000..494add1
--- /dev/null
+++ b/test/integration/targets/uri/files/fail22.json
@@ -0,0 +1 @@
+["Bad value", truth] \ No newline at end of file
diff --git a/test/integration/targets/uri/files/fail23.json b/test/integration/targets/uri/files/fail23.json
new file mode 100644
index 0000000..caff239
--- /dev/null
+++ b/test/integration/targets/uri/files/fail23.json
@@ -0,0 +1 @@
+['single quote'] \ No newline at end of file
diff --git a/test/integration/targets/uri/files/fail24.json b/test/integration/targets/uri/files/fail24.json
new file mode 100644
index 0000000..8b7ad23
--- /dev/null
+++ b/test/integration/targets/uri/files/fail24.json
@@ -0,0 +1 @@
+[" tab character in string "] \ No newline at end of file
diff --git a/test/integration/targets/uri/files/fail25.json b/test/integration/targets/uri/files/fail25.json
new file mode 100644
index 0000000..845d26a
--- /dev/null
+++ b/test/integration/targets/uri/files/fail25.json
@@ -0,0 +1 @@
+["tab\ character\ in\ string\ "] \ No newline at end of file
diff --git a/test/integration/targets/uri/files/fail26.json b/test/integration/targets/uri/files/fail26.json
new file mode 100644
index 0000000..6b01a2c
--- /dev/null
+++ b/test/integration/targets/uri/files/fail26.json
@@ -0,0 +1,2 @@
+["line
+break"] \ No newline at end of file
diff --git a/test/integration/targets/uri/files/fail27.json b/test/integration/targets/uri/files/fail27.json
new file mode 100644
index 0000000..621a010
--- /dev/null
+++ b/test/integration/targets/uri/files/fail27.json
@@ -0,0 +1,2 @@
+["line\
+break"] \ No newline at end of file
diff --git a/test/integration/targets/uri/files/fail28.json b/test/integration/targets/uri/files/fail28.json
new file mode 100644
index 0000000..47ec421
--- /dev/null
+++ b/test/integration/targets/uri/files/fail28.json
@@ -0,0 +1 @@
+[0e] \ No newline at end of file
diff --git a/test/integration/targets/uri/files/fail29.json b/test/integration/targets/uri/files/fail29.json
new file mode 100644
index 0000000..8ab0bc4
--- /dev/null
+++ b/test/integration/targets/uri/files/fail29.json
@@ -0,0 +1 @@
+[0e+] \ No newline at end of file
diff --git a/test/integration/targets/uri/files/fail3.json b/test/integration/targets/uri/files/fail3.json
new file mode 100644
index 0000000..9de168b
--- /dev/null
+++ b/test/integration/targets/uri/files/fail3.json
@@ -0,0 +1 @@
+["extra comma",] \ No newline at end of file
diff --git a/test/integration/targets/uri/files/fail30.json b/test/integration/targets/uri/files/fail30.json
new file mode 100644
index 0000000..1cce602
--- /dev/null
+++ b/test/integration/targets/uri/files/fail30.json
@@ -0,0 +1 @@
+[0e+-1] \ No newline at end of file
diff --git a/test/integration/targets/uri/files/fail4.json b/test/integration/targets/uri/files/fail4.json
new file mode 100644
index 0000000..ddf3ce3
--- /dev/null
+++ b/test/integration/targets/uri/files/fail4.json
@@ -0,0 +1 @@
+["double extra comma",,] \ No newline at end of file
diff --git a/test/integration/targets/uri/files/fail5.json b/test/integration/targets/uri/files/fail5.json
new file mode 100644
index 0000000..ed91580
--- /dev/null
+++ b/test/integration/targets/uri/files/fail5.json
@@ -0,0 +1 @@
+[ , "<-- missing value"] \ No newline at end of file
diff --git a/test/integration/targets/uri/files/fail6.json b/test/integration/targets/uri/files/fail6.json
new file mode 100644
index 0000000..8a96af3
--- /dev/null
+++ b/test/integration/targets/uri/files/fail6.json
@@ -0,0 +1 @@
+["Comma after the close"], \ No newline at end of file
diff --git a/test/integration/targets/uri/files/fail7.json b/test/integration/targets/uri/files/fail7.json
new file mode 100644
index 0000000..b28479c
--- /dev/null
+++ b/test/integration/targets/uri/files/fail7.json
@@ -0,0 +1 @@
+["Extra close"]] \ No newline at end of file
diff --git a/test/integration/targets/uri/files/fail8.json b/test/integration/targets/uri/files/fail8.json
new file mode 100644
index 0000000..5815574
--- /dev/null
+++ b/test/integration/targets/uri/files/fail8.json
@@ -0,0 +1 @@
+{"Extra comma": true,} \ No newline at end of file
diff --git a/test/integration/targets/uri/files/fail9.json b/test/integration/targets/uri/files/fail9.json
new file mode 100644
index 0000000..5d8c004
--- /dev/null
+++ b/test/integration/targets/uri/files/fail9.json
@@ -0,0 +1 @@
+{"Extra value after close": true} "misplaced quoted value" \ No newline at end of file
diff --git a/test/integration/targets/uri/files/formdata.txt b/test/integration/targets/uri/files/formdata.txt
new file mode 100644
index 0000000..974c0f9
--- /dev/null
+++ b/test/integration/targets/uri/files/formdata.txt
@@ -0,0 +1 @@
+_multipart/form-data_
diff --git a/test/integration/targets/uri/files/pass0.json b/test/integration/targets/uri/files/pass0.json
new file mode 100644
index 0000000..70e2685
--- /dev/null
+++ b/test/integration/targets/uri/files/pass0.json
@@ -0,0 +1,58 @@
+[
+ "JSON Test Pattern pass1",
+ {"object with 1 member":["array with 1 element"]},
+ {},
+ [],
+ -42,
+ true,
+ false,
+ null,
+ {
+ "integer": 1234567890,
+ "real": -9876.543210,
+ "e": 0.123456789e-12,
+ "E": 1.234567890E+34,
+ "": 23456789012E66,
+ "zero": 0,
+ "one": 1,
+ "space": " ",
+ "quote": "\"",
+ "backslash": "\\",
+ "controls": "\b\f\n\r\t",
+ "slash": "/ & \/",
+ "alpha": "abcdefghijklmnopqrstuvwyz",
+ "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ",
+ "digit": "0123456789",
+ "0123456789": "digit",
+ "special": "`1~!@#$%^&*()_+-={':[,]}|;.</>?",
+ "hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A",
+ "true": true,
+ "false": false,
+ "null": null,
+ "array":[ ],
+ "object":{ },
+ "address": "50 St. James Street",
+ "url": "http://www.JSON.org/",
+ "comment": "// /* <!-- --",
+ "# -- --> */": " ",
+ " s p a c e d " :[1,2 , 3
+
+,
+
+4 , 5 , 6 ,7 ],"compact":[1,2,3,4,5,6,7],
+ "jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}",
+ "quotes": "&#34; \u0022 %22 0x22 034 &#x22;",
+ "\/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?"
+: "A key can be any string"
+ },
+ 0.5 ,98.6
+,
+99.44
+,
+
+1066,
+1e1,
+0.1e1,
+1e-1,
+1e00,2e+00,2e-00
+,"rosebud"] \ No newline at end of file
diff --git a/test/integration/targets/uri/files/pass1.json b/test/integration/targets/uri/files/pass1.json
new file mode 100644
index 0000000..d3c63c7
--- /dev/null
+++ b/test/integration/targets/uri/files/pass1.json
@@ -0,0 +1 @@
+[[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]] \ No newline at end of file
diff --git a/test/integration/targets/uri/files/pass2.json b/test/integration/targets/uri/files/pass2.json
new file mode 100644
index 0000000..4528d51
--- /dev/null
+++ b/test/integration/targets/uri/files/pass2.json
@@ -0,0 +1,6 @@
+{
+ "JSON Test Pattern pass3": {
+ "The outermost value": "must be an object or array.",
+ "In this test": "It is an object."
+ }
+}
diff --git a/test/integration/targets/uri/files/pass3.json b/test/integration/targets/uri/files/pass3.json
new file mode 100644
index 0000000..6216b86
--- /dev/null
+++ b/test/integration/targets/uri/files/pass3.json
@@ -0,0 +1 @@
+"A JSON payload should be an object or array, not a string." \ No newline at end of file
diff --git a/test/integration/targets/uri/files/pass4.json b/test/integration/targets/uri/files/pass4.json
new file mode 100644
index 0000000..edac927
--- /dev/null
+++ b/test/integration/targets/uri/files/pass4.json
@@ -0,0 +1 @@
+[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]] \ No newline at end of file
diff --git a/test/integration/targets/uri/files/testserver.py b/test/integration/targets/uri/files/testserver.py
new file mode 100644
index 0000000..24967d4
--- /dev/null
+++ b/test/integration/targets/uri/files/testserver.py
@@ -0,0 +1,23 @@
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import sys
+
+if __name__ == '__main__':
+ if sys.version_info[0] >= 3:
+ import http.server
+ import socketserver
+ PORT = int(sys.argv[1])
+
+ class Handler(http.server.SimpleHTTPRequestHandler):
+ pass
+
+ Handler.extensions_map['.json'] = 'application/json'
+ httpd = socketserver.TCPServer(("", PORT), Handler)
+ httpd.serve_forever()
+ else:
+ import mimetypes
+ mimetypes.init()
+ mimetypes.add_type('application/json', '.json')
+ import SimpleHTTPServer
+ SimpleHTTPServer.test()
diff --git a/test/integration/targets/uri/meta/main.yml b/test/integration/targets/uri/meta/main.yml
new file mode 100644
index 0000000..2c2155a
--- /dev/null
+++ b/test/integration/targets/uri/meta/main.yml
@@ -0,0 +1,4 @@
+dependencies:
+ - prepare_tests
+ - prepare_http_tests
+ - setup_remote_tmp_dir
diff --git a/test/integration/targets/uri/tasks/ciphers.yml b/test/integration/targets/uri/tasks/ciphers.yml
new file mode 100644
index 0000000..a646d67
--- /dev/null
+++ b/test/integration/targets/uri/tasks/ciphers.yml
@@ -0,0 +1,32 @@
+- name: test good cipher
+ uri:
+ url: https://{{ httpbin_host }}/get
+ ciphers: ECDHE-RSA-AES128-SHA256
+ register: good_ciphers
+
+- name: test good cipher redirect
+ uri:
+ url: http://{{ httpbin_host }}/redirect-to?status_code=302&url=https://{{ httpbin_host }}/get
+ ciphers: ECDHE-RSA-AES128-SHA256
+ register: good_ciphers_redir
+
+- name: test bad cipher
+ uri:
+ url: https://{{ httpbin_host }}/get
+ ciphers: ECDHE-ECDSA-AES128-SHA
+ ignore_errors: true
+ register: bad_ciphers
+
+- name: test bad cipher redirect
+ uri:
+ url: http://{{ httpbin_host }}/redirect-to?status_code=302&url=https://{{ httpbin_host }}/get
+ ciphers: ECDHE-ECDSA-AES128-SHA
+ ignore_errors: true
+ register: bad_ciphers_redir
+
+- assert:
+ that:
+ - good_ciphers is successful
+ - good_ciphers_redir is successful
+ - bad_ciphers is failed
+ - bad_ciphers_redir is failed
diff --git a/test/integration/targets/uri/tasks/main.yml b/test/integration/targets/uri/tasks/main.yml
new file mode 100644
index 0000000..d821f28
--- /dev/null
+++ b/test/integration/targets/uri/tasks/main.yml
@@ -0,0 +1,779 @@
+# test code for the uri module
+# (c) 2014, Leonid Evdokimov <leon@darkk.net.ru>
+
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <https://www.gnu.org/licenses/>.
+
+- name: set role facts
+ set_fact:
+ http_port: 15260
+ files_dir: '{{ remote_tmp_dir|expanduser }}/files'
+ checkout_dir: '{{ remote_tmp_dir }}/git'
+
+- name: create a directory to serve files from
+ file:
+ dest: "{{ files_dir }}"
+ state: directory
+
+- copy:
+ src: "{{ item }}"
+ dest: "{{files_dir}}/{{ item }}"
+ with_sequence: start=0 end=4 format=pass%d.json
+
+- copy:
+ src: "{{ item }}"
+ dest: "{{files_dir}}/{{ item }}"
+ with_sequence: start=0 end=30 format=fail%d.json
+
+- copy:
+ src: "testserver.py"
+ dest: "{{ remote_tmp_dir }}/testserver.py"
+
+- name: start SimpleHTTPServer
+ shell: cd {{ files_dir }} && {{ ansible_python.executable }} {{ remote_tmp_dir}}/testserver.py {{ http_port }}
+ async: 180 # this test is slower on remotes like FreeBSD, and running split slows it down further
+ poll: 0
+
+- wait_for: port={{ http_port }}
+
+
+- name: checksum pass_json
+ stat: path={{ files_dir }}/{{ item }}.json get_checksum=yes
+ register: pass_checksum
+ with_sequence: start=0 end=4 format=pass%d
+
+- name: fetch pass_json
+ uri: return_content=yes url=http://localhost:{{ http_port }}/{{ item }}.json
+ register: fetch_pass_json
+ with_sequence: start=0 end=4 format=pass%d
+
+- name: check pass_json
+ assert:
+ that:
+ - '"json" in item.1'
+ - item.0.stat.checksum == item.1.content | checksum
+ with_together:
+ - "{{pass_checksum.results}}"
+ - "{{fetch_pass_json.results}}"
+
+
+- name: checksum fail_json
+ stat: path={{ files_dir }}/{{ item }}.json get_checksum=yes
+ register: fail_checksum
+ with_sequence: start=0 end=30 format=fail%d
+
+- name: fetch fail_json
+ uri: return_content=yes url=http://localhost:{{ http_port }}/{{ item }}.json
+ register: fail
+ with_sequence: start=0 end=30 format=fail%d
+
+- name: check fail_json
+ assert:
+ that:
+ - item.0.stat.checksum == item.1.content | checksum
+ - '"json" not in item.1'
+ with_together:
+ - "{{fail_checksum.results}}"
+ - "{{fail.results}}"
+
+- name: test https fetch to a site with mismatched hostname and certificate
+ uri:
+ url: "https://{{ badssl_host }}/"
+ dest: "{{ remote_tmp_dir }}/shouldnotexist.html"
+ ignore_errors: True
+ register: result
+
+- stat:
+ path: "{{ remote_tmp_dir }}/shouldnotexist.html"
+ register: stat_result
+
+- name: Assert that the file was not downloaded
+ assert:
+ that:
+ - result.failed == true
+ - "'Failed to validate the SSL certificate' in result.msg or 'Hostname mismatch' in result.msg or (result.msg is match('hostname .* doesn.t match .*'))"
+ - stat_result.stat.exists == false
+ - result.status is defined
+ - result.status == -1
+ - result.url == 'https://' ~ badssl_host ~ '/'
+
+- name: Clean up any cruft from the results directory
+ file:
+ name: "{{ remote_tmp_dir }}/kreitz.html"
+ state: absent
+
+- name: test https fetch to a site with mismatched hostname and certificate and validate_certs=no
+ uri:
+ url: "https://{{ badssl_host }}/"
+ dest: "{{ remote_tmp_dir }}/kreitz.html"
+ validate_certs: no
+ register: result
+
+- stat:
+ path: "{{ remote_tmp_dir }}/kreitz.html"
+ register: stat_result
+
+- name: Assert that the file was downloaded
+ assert:
+ that:
+ - "stat_result.stat.exists == true"
+ - "result.changed == true"
+
+- name: "get ca certificate {{ self_signed_host }}"
+ get_url:
+ url: "http://{{ httpbin_host }}/ca2cert.pem"
+ dest: "{{ remote_tmp_dir }}/ca2cert.pem"
+
+- name: test https fetch to a site with self signed certificate using ca_path
+ uri:
+ url: "https://{{ self_signed_host }}:444/"
+ dest: "{{ remote_tmp_dir }}/self-signed_using_ca_path.html"
+ ca_path: "{{ remote_tmp_dir }}/ca2cert.pem"
+ validate_certs: yes
+ register: result
+
+- stat:
+ path: "{{ remote_tmp_dir }}/self-signed_using_ca_path.html"
+ register: stat_result
+
+- name: Assert that the file was downloaded
+ assert:
+ that:
+ - "stat_result.stat.exists == true"
+ - "result.changed == true"
+
+- name: test https fetch to a site with self signed certificate without using ca_path
+ uri:
+ url: "https://{{ self_signed_host }}:444/"
+ dest: "{{ remote_tmp_dir }}/self-signed-without_using_ca_path.html"
+ validate_certs: yes
+ register: result
+ ignore_errors: true
+
+- stat:
+ path: "{{ remote_tmp_dir }}/self-signed-without_using_ca_path.html"
+ register: stat_result
+
+- name: Assure that https access to a host with self-signed certificate without providing ca_path fails
+ assert:
+ that:
+ - "stat_result.stat.exists == false"
+ - result is failed
+ - "'certificate verify failed' in result.msg"
+
+- name: Locate ca-bundle
+ stat:
+ path: '{{ item }}'
+ loop:
+ - /etc/ssl/certs/ca-bundle.crt
+ - /etc/ssl/certs/ca-certificates.crt
+ - /var/lib/ca-certificates/ca-bundle.pem
+ - /usr/local/share/certs/ca-root-nss.crt
+ - '{{ cafile_path.stdout_lines|default(["/_i_dont_exist_ca.pem"])|first }}'
+ - /etc/ssl/cert.pem
+ register: ca_bundle_candidates
+
+- name: Test that ca_path can be a full bundle
+ uri:
+ url: "https://{{ httpbin_host }}/get"
+ ca_path: '{{ ca_bundle }}'
+ vars:
+ ca_bundle: '{{ ca_bundle_candidates.results|selectattr("stat.exists")|map(attribute="item")|first }}'
+
+- name: test redirect without follow_redirects
+ uri:
+ url: 'https://{{ httpbin_host }}/redirect/2'
+ follow_redirects: 'none'
+ status_code: 302
+ register: result
+
+- name: Assert location header
+ assert:
+ that:
+ - 'result.location|default("") == "https://{{ httpbin_host }}/relative-redirect/1"'
+
+- name: Check SSL with redirect
+ uri:
+ url: 'https://{{ httpbin_host }}/redirect/2'
+ register: result
+
+- name: Assert SSL with redirect
+ assert:
+ that:
+ - 'result.url|default("") == "https://{{ httpbin_host }}/get"'
+
+- name: redirect to bad SSL site
+ uri:
+ url: 'http://{{ badssl_host }}'
+ register: result
+ ignore_errors: true
+
+- name: Ensure bad SSL site reidrect fails
+ assert:
+ that:
+ - result is failed
+ - 'badssl_host in result.msg'
+
+- name: test basic auth
+ uri:
+ url: 'https://{{ httpbin_host }}/basic-auth/user/passwd'
+ user: user
+ password: passwd
+
+- name: test basic forced auth
+ uri:
+ url: 'https://{{ httpbin_host }}/hidden-basic-auth/user/passwd'
+ force_basic_auth: true
+ user: user
+ password: passwd
+
+- name: test digest auth
+ uri:
+ url: 'https://{{ httpbin_host }}/digest-auth/auth/user/passwd'
+ user: user
+ password: passwd
+ headers:
+ Cookie: "fake=fake_value"
+
+- name: test digest auth failure
+ uri:
+ url: 'https://{{ httpbin_host }}/digest-auth/auth/user/passwd'
+ user: user
+ password: wrong
+ headers:
+ Cookie: "fake=fake_value"
+ register: result
+ failed_when: result.status != 401
+
+- name: test unredirected_headers
+ uri:
+ url: 'https://{{ httpbin_host }}/redirect-to?status_code=301&url=/basic-auth/user/passwd'
+ user: user
+ password: passwd
+ force_basic_auth: true
+ unredirected_headers:
+ - authorization
+ ignore_errors: true
+ register: unredirected_headers
+
+- name: test omitting unredirected headers
+ uri:
+ url: 'https://{{ httpbin_host }}/redirect-to?status_code=301&url=/basic-auth/user/passwd'
+ user: user
+ password: passwd
+ force_basic_auth: true
+ register: redirected_headers
+
+- name: ensure unredirected_headers caused auth to fail
+ assert:
+ that:
+ - unredirected_headers is failed
+ - unredirected_headers.status == 401
+ - redirected_headers is successful
+ - redirected_headers.status == 200
+
+- name: test PUT
+ uri:
+ url: 'https://{{ httpbin_host }}/put'
+ method: PUT
+ body: 'foo=bar'
+
+- name: test OPTIONS
+ uri:
+ url: 'https://{{ httpbin_host }}/'
+ method: OPTIONS
+ register: result
+
+- name: Assert we got an allow header
+ assert:
+ that:
+ - 'result.allow.split(", ")|sort == ["GET", "HEAD", "OPTIONS"]'
+
+- name: Testing support of https_proxy (with failure expected)
+ environment:
+ https_proxy: 'https://localhost:3456'
+ uri:
+ url: 'https://httpbin.org/get'
+ register: result
+ ignore_errors: true
+
+- assert:
+ that:
+ - result is failed
+ - result.status == -1
+
+- name: Testing use_proxy=no is honored
+ environment:
+ https_proxy: 'https://localhost:3456'
+ uri:
+ url: 'https://httpbin.org/get'
+ use_proxy: no
+
+# Ubuntu12.04 doesn't have python-urllib3, this makes handling required dependencies a pain across all variations
+# We'll use this to just skip 12.04 on those tests. We should be sufficiently covered with other OSes and versions
+- name: Set fact if running on Ubuntu 12.04
+ set_fact:
+ is_ubuntu_precise: "{{ ansible_distribution == 'Ubuntu' and ansible_distribution_release == 'precise' }}"
+
+- name: Test that SNI succeeds on python versions that have SNI
+ uri:
+ url: 'https://{{ sni_host }}/'
+ return_content: true
+ when: ansible_python.has_sslcontext
+ register: result
+
+- name: Assert SNI verification succeeds on new python
+ assert:
+ that:
+ - result is successful
+ - 'sni_host in result.content'
+ when: ansible_python.has_sslcontext
+
+- name: Verify SNI verification fails on old python without urllib3 contrib
+ uri:
+ url: 'https://{{ sni_host }}'
+ ignore_errors: true
+ when: not ansible_python.has_sslcontext
+ register: result
+
+- name: Assert SNI verification fails on old python
+ assert:
+ that:
+ - result is failed
+ when: result is not skipped
+
+- name: check if urllib3 is installed as an OS package
+ package:
+ name: "{{ uri_os_packages[ansible_os_family].urllib3 }}"
+ check_mode: yes
+ when: not ansible_python.has_sslcontext and not is_ubuntu_precise|bool and uri_os_packages[ansible_os_family].urllib3|default
+ register: urllib3
+
+- name: uninstall conflicting urllib3 pip package
+ pip:
+ name: urllib3
+ state: absent
+ when: not ansible_python.has_sslcontext and not is_ubuntu_precise|bool and uri_os_packages[ansible_os_family].urllib3|default and urllib3.changed
+
+- name: install OS packages that are needed for SNI on old python
+ package:
+ name: "{{ item }}"
+ with_items: "{{ uri_os_packages[ansible_os_family].step1 | default([]) }}"
+ when: not ansible_python.has_sslcontext and not is_ubuntu_precise|bool
+
+- name: install python modules for Older Python SNI verification
+ pip:
+ name: "{{ item }}"
+ with_items:
+ - ndg-httpsclient
+ when: not ansible_python.has_sslcontext and not is_ubuntu_precise|bool
+
+- name: Verify SNI verification succeeds on old python with urllib3 contrib
+ uri:
+ url: 'https://{{ sni_host }}'
+ return_content: true
+ when: not ansible_python.has_sslcontext and not is_ubuntu_precise|bool
+ register: result
+
+- name: Assert SNI verification succeeds on old python
+ assert:
+ that:
+ - result is successful
+ - 'sni_host in result.content'
+ when: not ansible_python.has_sslcontext and not is_ubuntu_precise|bool
+
+- name: Uninstall ndg-httpsclient
+ pip:
+ name: "{{ item }}"
+ state: absent
+ with_items:
+ - ndg-httpsclient
+ when: not ansible_python.has_sslcontext and not is_ubuntu_precise|bool
+
+- name: uninstall OS packages that are needed for SNI on old python
+ package:
+ name: "{{ item }}"
+ state: absent
+ with_items: "{{ uri_os_packages[ansible_os_family].step1 | default([]) }}"
+ when: not ansible_python.has_sslcontext and not is_ubuntu_precise|bool
+
+- name: install OS packages that are needed for building cryptography
+ package:
+ name: "{{ item }}"
+ with_items: "{{ uri_os_packages[ansible_os_family].step2 | default([]) }}"
+ when: not ansible_python.has_sslcontext and not is_ubuntu_precise|bool
+
+- name: create constraints path
+ set_fact:
+ remote_constraints: "{{ remote_tmp_dir }}/constraints.txt"
+ when: not ansible_python.has_sslcontext and not is_ubuntu_precise|bool
+
+- name: create constraints file
+ copy:
+ content: |
+ cryptography == 2.1.4
+ idna == 2.5
+ pyopenssl == 17.5.0
+ six == 1.13.0
+ urllib3 == 1.23
+ dest: "{{ remote_constraints }}"
+ when: not ansible_python.has_sslcontext and not is_ubuntu_precise|bool
+
+- name: install urllib3 and pyopenssl via pip
+ pip:
+ name: "{{ item }}"
+ extra_args: "-c {{ remote_constraints }}"
+ with_items:
+ - urllib3
+ - PyOpenSSL
+ when: not ansible_python.has_sslcontext and not is_ubuntu_precise|bool
+
+- name: Verify SNI verification succeeds on old python with pip urllib3 contrib
+ uri:
+ url: 'https://{{ sni_host }}'
+ return_content: true
+ when: not ansible_python.has_sslcontext and not is_ubuntu_precise|bool
+ register: result
+
+- name: Assert SNI verification succeeds on old python with pip urllib3 contrib
+ assert:
+ that:
+ - result is successful
+ - 'sni_host in result.content'
+ when: not ansible_python.has_sslcontext and not is_ubuntu_precise|bool
+
+- name: Uninstall urllib3 and PyOpenSSL
+ pip:
+ name: "{{ item }}"
+ state: absent
+ with_items:
+ - urllib3
+ - PyOpenSSL
+ when: not ansible_python.has_sslcontext and not is_ubuntu_precise|bool
+
+- name: validate the status_codes are correct
+ uri:
+ url: "https://{{ httpbin_host }}/status/202"
+ status_code: 202
+ method: POST
+ body: foo
+
+- name: Validate body_format json does not override content-type in 2.3 or newer
+ uri:
+ url: "https://{{ httpbin_host }}/post"
+ method: POST
+ body:
+ foo: bar
+ body_format: json
+ headers:
+ 'Content-Type': 'text/json'
+ return_content: true
+ register: result
+ failed_when: result.json.headers['Content-Type'] != 'text/json'
+
+- name: Validate body_format form-urlencoded using dicts works
+ uri:
+ url: https://{{ httpbin_host }}/post
+ method: POST
+ body:
+ user: foo
+ password: bar!#@ |&82$M
+ submit: Sign in
+ body_format: form-urlencoded
+ return_content: yes
+ register: result
+
+- name: Assert form-urlencoded dict input
+ assert:
+ that:
+ - result is successful
+ - result.json.headers['Content-Type'] == 'application/x-www-form-urlencoded'
+ - result.json.form.password == 'bar!#@ |&82$M'
+
+- name: Validate body_format form-urlencoded using lists works
+ uri:
+ url: https://{{ httpbin_host }}/post
+ method: POST
+ body:
+ - [ user, foo ]
+ - [ password, bar!#@ |&82$M ]
+ - [ submit, Sign in ]
+ body_format: form-urlencoded
+ return_content: yes
+ register: result
+
+- name: Assert form-urlencoded list input
+ assert:
+ that:
+ - result is successful
+ - result.json.headers['Content-Type'] == 'application/x-www-form-urlencoded'
+ - result.json.form.password == 'bar!#@ |&82$M'
+
+- name: Validate body_format form-urlencoded of invalid input fails
+ uri:
+ url: https://{{ httpbin_host }}/post
+ method: POST
+ body:
+ - foo
+ - bar: baz
+ body_format: form-urlencoded
+ return_content: yes
+ register: result
+ ignore_errors: yes
+
+- name: Assert invalid input fails
+ assert:
+ that:
+ - result is failure
+ - "'failed to parse body as form_urlencoded: too many values to unpack' in result.msg"
+
+- name: multipart/form-data
+ uri:
+ url: https://{{ httpbin_host }}/post
+ method: POST
+ body_format: form-multipart
+ body:
+ file1:
+ filename: formdata.txt
+ file2:
+ content: text based file content
+ filename: fake.txt
+ mime_type: text/plain
+ text_form_field1: value1
+ text_form_field2:
+ content: value2
+ mime_type: text/plain
+ register: multipart
+
+- name: Assert multipart/form-data
+ assert:
+ that:
+ - multipart.json.files.file1 == '_multipart/form-data_\n'
+ - multipart.json.files.file2 == 'text based file content'
+ - multipart.json.form.text_form_field1 == 'value1'
+ - multipart.json.form.text_form_field2 == 'value2'
+
+# https://github.com/ansible/ansible/issues/74276 - verifies we don't have a traceback
+- name: multipart/form-data with invalid value
+ uri:
+ url: https://{{ httpbin_host }}/post
+ method: POST
+ body_format: form-multipart
+ body:
+ integer_value: 1
+ register: multipart_invalid
+ failed_when: 'multipart_invalid.msg != "failed to parse body as form-multipart: value must be a string, or mapping, cannot be type int"'
+
+- name: Validate invalid method
+ uri:
+ url: https://{{ httpbin_host }}/anything
+ method: UNKNOWN
+ register: result
+ ignore_errors: yes
+
+- name: Assert invalid method fails
+ assert:
+ that:
+ - result is failure
+ - result.status == 405
+ - "'METHOD NOT ALLOWED' in result.msg"
+
+- name: Test client cert auth, no certs
+ uri:
+ url: "https://ansible.http.tests/ssl_client_verify"
+ status_code: 200
+ return_content: true
+ register: result
+ failed_when: result.content != "ansible.http.tests:NONE"
+ when: has_httptester
+
+- name: Test client cert auth, with certs
+ uri:
+ url: "https://ansible.http.tests/ssl_client_verify"
+ client_cert: "{{ remote_tmp_dir }}/client.pem"
+ client_key: "{{ remote_tmp_dir }}/client.key"
+ return_content: true
+ register: result
+ failed_when: result.content != "ansible.http.tests:SUCCESS"
+ when: has_httptester
+
+- name: Test client cert auth, with no validation
+ uri:
+ url: "https://fail.ansible.http.tests/ssl_client_verify"
+ client_cert: "{{ remote_tmp_dir }}/client.pem"
+ client_key: "{{ remote_tmp_dir }}/client.key"
+ return_content: true
+ validate_certs: no
+ register: result
+ failed_when: result.content != "ansible.http.tests:SUCCESS"
+ when: has_httptester
+
+- name: Test client cert auth, with validation and ssl mismatch
+ uri:
+ url: "https://fail.ansible.http.tests/ssl_client_verify"
+ client_cert: "{{ remote_tmp_dir }}/client.pem"
+ client_key: "{{ remote_tmp_dir }}/client.key"
+ return_content: true
+ validate_certs: yes
+ register: result
+ failed_when: result is not failed
+ when: has_httptester
+
+- uri:
+ url: https://{{ httpbin_host }}/response-headers?Set-Cookie=Foo%3Dbar&Set-Cookie=Baz%3Dqux
+ register: result
+
+- assert:
+ that:
+ - result['set_cookie'] == 'Foo=bar, Baz=qux'
+ # Python sorts cookies in order of most specific (ie. longest) path first
+ # items with the same path are reversed from response order
+ - result['cookies_string'] == 'Baz=qux; Foo=bar'
+
+- name: Write out netrc template
+ template:
+ src: netrc.j2
+ dest: "{{ remote_tmp_dir }}/netrc"
+
+- name: Test netrc with port
+ uri:
+ url: "https://{{ httpbin_host }}:443/basic-auth/user/passwd"
+ environment:
+ NETRC: "{{ remote_tmp_dir }}/netrc"
+
+- name: Test JSON POST with src
+ uri:
+ url: "https://{{ httpbin_host}}/post"
+ src: pass0.json
+ method: POST
+ return_content: true
+ body_format: json
+ register: result
+
+- name: Validate POST with src works
+ assert:
+ that:
+ - result.json.json[0] == 'JSON Test Pattern pass1'
+
+- name: Copy file pass0.json to remote
+ copy:
+ src: "{{ role_path }}/files/pass0.json"
+ dest: "{{ remote_tmp_dir }}/pass0.json"
+
+- name: Test JSON POST with src and remote_src=True
+ uri:
+ url: "https://{{ httpbin_host}}/post"
+ src: "{{ remote_tmp_dir }}/pass0.json"
+ remote_src: true
+ method: POST
+ return_content: true
+ body_format: json
+ register: result
+
+- name: Validate POST with src and remote_src=True works
+ assert:
+ that:
+ - result.json.json[0] == 'JSON Test Pattern pass1'
+
+- name: Make request that includes password in JSON keys
+ uri:
+ url: "https://{{ httpbin_host}}/get?key-password=value-password"
+ user: admin
+ password: password
+ register: sanitize_keys
+
+- name: assert that keys were sanitized
+ assert:
+ that:
+ - sanitize_keys.json.args['key-********'] == 'value-********'
+
+- name: Test gzip encoding
+ uri:
+ url: "https://{{ httpbin_host }}/gzip"
+ register: result
+
+- name: Validate gzip decoding
+ assert:
+ that:
+ - result.json.gzipped
+
+- name: test gzip encoding no auto decompress
+ uri:
+ url: "https://{{ httpbin_host }}/gzip"
+ decompress: false
+ register: result
+
+- name: Assert gzip wasn't decompressed
+ assert:
+ that:
+ - result.json is undefined
+
+- name: Create a testing file
+ copy:
+ content: "content"
+ dest: "{{ remote_tmp_dir }}/output"
+
+- name: Download a file from non existing location
+ uri:
+ url: http://does/not/exist
+ dest: "{{ remote_tmp_dir }}/output"
+ ignore_errors: yes
+
+- name: Save testing file's output
+ command: "cat {{ remote_tmp_dir }}/output"
+ register: file_out
+
+- name: Test the testing file was not overwritten
+ assert:
+ that:
+ - "'content' in file_out.stdout"
+
+- name: Clean up
+ file:
+ dest: "{{ remote_tmp_dir }}/output"
+ state: absent
+
+- name: Test follow_redirects=none
+ import_tasks: redirect-none.yml
+
+- name: Test follow_redirects=safe
+ import_tasks: redirect-safe.yml
+
+- name: Test follow_redirects=urllib2
+ import_tasks: redirect-urllib2.yml
+
+- name: Test follow_redirects=all
+ import_tasks: redirect-all.yml
+
+- name: Check unexpected failures
+ import_tasks: unexpected-failures.yml
+
+- name: Check return-content
+ import_tasks: return-content.yml
+
+- name: Test use_gssapi=True
+ include_tasks:
+ file: use_gssapi.yml
+ apply:
+ environment:
+ KRB5_CONFIG: '{{ krb5_config }}'
+ KRB5CCNAME: FILE:{{ remote_tmp_dir }}/krb5.cc
+ when: krb5_config is defined
+
+- name: Test ciphers
+ import_tasks: ciphers.yml
+
+- name: Test use_netrc.yml
+ import_tasks: use_netrc.yml
diff --git a/test/integration/targets/uri/tasks/redirect-all.yml b/test/integration/targets/uri/tasks/redirect-all.yml
new file mode 100644
index 0000000..d5b47a1
--- /dev/null
+++ b/test/integration/targets/uri/tasks/redirect-all.yml
@@ -0,0 +1,272 @@
+- name: Test HTTP 301 using HEAD
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=301&url=https://{{ httpbin_host }}/anything
+ follow_redirects: all
+ return_content: yes
+ method: HEAD
+ register: http_301_head
+
+- assert:
+ that:
+ - http_301_head is successful
+ - http_301_head.json is not defined
+ - http_301_head.redirected == true
+ - http_301_head.status == 200
+ - http_301_head.url == 'https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 301 using GET
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=301&url=https://{{ httpbin_host }}/anything
+ follow_redirects: all
+ return_content: yes
+ method: GET
+ register: http_301_get
+
+- assert:
+ that:
+ - http_301_get is successful
+ - http_301_get.json.data == ''
+ - http_301_get.json.method == 'GET'
+ - http_301_get.json.url == 'https://{{ httpbin_host }}/anything'
+ - http_301_get.redirected == true
+ - http_301_get.status == 200
+ - http_301_get.url == 'https://{{ httpbin_host }}/anything'
+
+# NOTE: The HTTP POST turns into an HTTP GET
+- name: Test HTTP 301 using POST
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=301&url=https://{{ httpbin_host }}/anything
+ follow_redirects: all
+ return_content: yes
+ method: POST
+ body: '{ "foo": "bar" }'
+ body_format: json
+ register: http_301_post
+
+- assert:
+ that:
+ - http_301_post is successful
+ - http_301_post.json.data == ''
+ - http_301_post.json.method == 'GET'
+ - http_301_post.json.url == 'https://{{ httpbin_host }}/anything'
+ - http_301_post.redirected == true
+ - http_301_post.status == 200
+ - http_301_post.url == 'https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 302 using HEAD
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=302&url=https://{{ httpbin_host }}/anything
+ follow_redirects: all
+ return_content: yes
+ method: HEAD
+ register: http_302_head
+
+- assert:
+ that:
+ - http_302_head is successful
+ - http_302_head.json is not defined
+ - http_302_head.redirected == true
+ - http_302_head.status == 200
+ - http_302_head.url == 'https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 302 using GET
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=302&url=https://{{ httpbin_host }}/anything
+ follow_redirects: all
+ return_content: yes
+ method: GET
+ register: http_302_get
+
+- assert:
+ that:
+ - http_302_get is successful
+ - http_302_get.json.data == ''
+ - http_302_get.json.method == 'GET'
+ - http_302_get.json.url == 'https://{{ httpbin_host }}/anything'
+ - http_302_get.redirected == true
+ - http_302_get.status == 200
+ - http_302_get.url == 'https://{{ httpbin_host }}/anything'
+
+# NOTE: The HTTP POST turns into an HTTP GET
+- name: Test HTTP 302 using POST
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=302&url=https://{{ httpbin_host }}/anything
+ follow_redirects: all
+ return_content: yes
+ method: POST
+ body: '{ "foo": "bar" }'
+ body_format: json
+ register: http_302_post
+
+- assert:
+ that:
+ - http_302_post is successful
+ - http_302_post.json.data == ''
+ - http_302_post.json.method == 'GET'
+ - http_302_post.json.url == 'https://{{ httpbin_host }}/anything'
+ - http_302_post.redirected == true
+ - http_302_post.status == 200
+ - http_302_post.url == 'https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 303 using HEAD
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=303&url=https://{{ httpbin_host }}/anything
+ follow_redirects: all
+ return_content: yes
+ method: HEAD
+ register: http_303_head
+
+- assert:
+ that:
+ - http_303_head is successful
+ - http_303_head.json is not defined
+ - http_303_head.redirected == true
+ - http_303_head.status == 200
+ - http_303_head.url == 'https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 303 using GET
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=303&url=https://{{ httpbin_host }}/anything
+ follow_redirects: all
+ return_content: yes
+ method: GET
+ register: http_303_get
+
+- assert:
+ that:
+ - http_303_get is successful
+ - http_303_get.json.data == ''
+ - http_303_get.json.method == 'GET'
+ - http_303_get.json.url == 'https://{{ httpbin_host }}/anything'
+ - http_303_get.redirected == true
+ - http_303_get.status == 200
+ - http_303_get.url == 'https://{{ httpbin_host }}/anything'
+
+# NOTE: The HTTP POST turns into an HTTP GET
+- name: Test HTTP 303 using POST
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=303&url=https://{{ httpbin_host }}/anything
+ follow_redirects: all
+ return_content: yes
+ method: POST
+ body: '{ "foo": "bar" }'
+ body_format: json
+ register: http_303_post
+
+- assert:
+ that:
+ - http_303_post is successful
+ - http_303_post.json.data == ''
+ - http_303_post.json.method == 'GET'
+ - http_303_post.json.url == 'https://{{ httpbin_host }}/anything'
+ - http_303_post.redirected == true
+ - http_303_post.status == 200
+ - http_303_post.url == 'https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 307 using HEAD
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=307&url=https://{{ httpbin_host }}/anything
+ follow_redirects: all
+ return_content: yes
+ method: HEAD
+ register: http_307_head
+
+- assert:
+ that:
+ - http_307_head is successful
+ - http_307_head.json is not defined
+ - http_307_head.redirected == true
+ - http_307_head.status == 200
+ - http_307_head.url == 'https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 307 using GET
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=307&url=https://{{ httpbin_host }}/anything
+ follow_redirects: all
+ return_content: yes
+ method: GET
+ register: http_307_get
+
+- assert:
+ that:
+ - http_307_get is successful
+ - http_307_get.json.data == ''
+ - http_307_get.json.method == 'GET'
+ - http_307_get.json.url == 'https://{{ httpbin_host }}/anything'
+ - http_307_get.redirected == true
+ - http_307_get.status == 200
+ - http_307_get.url == 'https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 307 using POST
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=307&url=https://{{ httpbin_host }}/anything
+ follow_redirects: all
+ return_content: yes
+ method: POST
+ body: '{ "foo": "bar" }'
+ body_format: json
+ register: http_307_post
+
+- assert:
+ that:
+ - http_307_post is successful
+ - http_307_post.json.json.foo == 'bar'
+ - http_307_post.json.method == 'POST'
+ - http_307_post.json.url == 'https://{{ httpbin_host }}/anything'
+ - http_307_post.redirected == true
+ - http_307_post.status == 200
+ - http_307_post.url == 'https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 308 using HEAD
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=308&url=https://{{ httpbin_host }}/anything
+ follow_redirects: all
+ return_content: yes
+ method: HEAD
+ register: http_308_head
+
+- assert:
+ that:
+ - http_308_head is successful
+ - http_308_head.json is undefined
+ - http_308_head.redirected == true
+ - http_308_head.status == 200
+ - http_308_head.url == 'https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 308 using GET
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=308&url=https://{{ httpbin_host }}/anything
+ follow_redirects: all
+ return_content: yes
+ method: GET
+ register: http_308_get
+
+- assert:
+ that:
+ - http_308_get is successful
+ - http_308_get.json.data == ''
+ - http_308_get.json.method == 'GET'
+ - http_308_get.json.url == 'https://{{ httpbin_host }}/anything'
+ - http_308_get.redirected == true
+ - http_308_get.status == 200
+ - http_308_get.url == 'https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 308 using POST
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=308&url=https://{{ httpbin_host }}/anything
+ follow_redirects: all
+ return_content: yes
+ method: POST
+ body: '{ "foo": "bar" }'
+ body_format: json
+ register: http_308_post
+
+- assert:
+ that:
+ - http_308_post is successful
+ - http_308_post.json.json.foo == 'bar'
+ - http_308_post.json.method == 'POST'
+ - http_308_post.json.url == 'https://{{ httpbin_host }}/anything'
+ - http_308_post.redirected == true
+ - http_308_post.status == 200
+ - http_308_post.url == 'https://{{ httpbin_host }}/anything'
diff --git a/test/integration/targets/uri/tasks/redirect-none.yml b/test/integration/targets/uri/tasks/redirect-none.yml
new file mode 100644
index 0000000..0d1b2b3
--- /dev/null
+++ b/test/integration/targets/uri/tasks/redirect-none.yml
@@ -0,0 +1,296 @@
+- name: Test HTTP 301 using HEAD
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=301&url=https://{{ httpbin_host }}/anything
+ follow_redirects: none
+ return_content: yes
+ method: HEAD
+ ignore_errors: yes
+ register: http_301_head
+
+- assert:
+ that:
+ - http_301_head is failure
+ - http_301_head.json is not defined
+ - http_301_head.location == 'https://{{ httpbin_host }}/anything'
+ - "http_301_head.msg == 'Status code was 301 and not [200]: HTTP Error 301: MOVED PERMANENTLY'"
+ - http_301_head.redirected == false
+ - http_301_head.status == 301
+ - http_301_head.url == 'https://{{ httpbin_host }}/redirect-to?status_code=301&url=https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 301 using GET
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=301&url=https://{{ httpbin_host }}/anything
+ follow_redirects: none
+ return_content: yes
+ method: GET
+ ignore_errors: yes
+ register: http_301_get
+
+- assert:
+ that:
+ - http_301_get is failure
+ - http_301_get.json is not defined
+ - http_301_get.location == 'https://{{ httpbin_host }}/anything'
+ - "http_301_get.msg == 'Status code was 301 and not [200]: HTTP Error 301: MOVED PERMANENTLY'"
+ - http_301_get.redirected == false
+ - http_301_get.status == 301
+ - http_301_get.url == 'https://{{ httpbin_host }}/redirect-to?status_code=301&url=https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 301 using POST
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=301&url=https://{{ httpbin_host }}/anything
+ follow_redirects: none
+ return_content: yes
+ method: POST
+ body: '{ "foo": "bar" }'
+ body_format: json
+ ignore_errors: yes
+ register: http_301_post
+
+- assert:
+ that:
+ - http_301_post is failure
+ - http_301_post.json is not defined
+ - http_301_post.location == 'https://{{ httpbin_host }}/anything'
+ - "http_301_post.msg == 'Status code was 301 and not [200]: HTTP Error 301: MOVED PERMANENTLY'"
+ - http_301_post.redirected == false
+ - http_301_post.status == 301
+ - http_301_post.url == 'https://{{ httpbin_host }}/redirect-to?status_code=301&url=https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 302 using HEAD
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=302&url=https://{{ httpbin_host }}/anything
+ follow_redirects: none
+ return_content: yes
+ method: HEAD
+ ignore_errors: yes
+ register: http_302_head
+
+- assert:
+ that:
+ - http_302_head is failure
+ - http_302_head.json is not defined
+ - http_302_head.location == 'https://{{ httpbin_host }}/anything'
+ - "http_302_head.msg == 'Status code was 302 and not [200]: HTTP Error 302: FOUND'"
+ - http_302_head.redirected == false
+ - http_302_head.status == 302
+ - http_302_head.url == 'https://{{ httpbin_host }}/redirect-to?status_code=302&url=https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 302 using GET
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=302&url=https://{{ httpbin_host }}/anything
+ follow_redirects: none
+ return_content: yes
+ method: GET
+ ignore_errors: yes
+ register: http_302_get
+
+- assert:
+ that:
+ - http_302_get is failure
+ - http_302_get.json is not defined
+ - http_302_get.location == 'https://{{ httpbin_host }}/anything'
+ - "http_302_get.msg == 'Status code was 302 and not [200]: HTTP Error 302: FOUND'"
+ - http_302_get.redirected == false
+ - http_302_get.status == 302
+ - http_302_get.url == 'https://{{ httpbin_host }}/redirect-to?status_code=302&url=https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 302 using POST
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=302&url=https://{{ httpbin_host }}/anything
+ follow_redirects: none
+ return_content: yes
+ method: POST
+ body: '{ "foo": "bar" }'
+ body_format: json
+ ignore_errors: yes
+ register: http_302_post
+
+- assert:
+ that:
+ - http_302_post is failure
+ - http_302_post.json is not defined
+ - http_302_post.location == 'https://{{ httpbin_host }}/anything'
+ - "http_302_post.msg == 'Status code was 302 and not [200]: HTTP Error 302: FOUND'"
+ - http_302_post.redirected == false
+ - http_302_post.status == 302
+ - http_302_post.url == 'https://{{ httpbin_host }}/redirect-to?status_code=302&url=https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 303 using HEAD
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=303&url=https://{{ httpbin_host }}/anything
+ follow_redirects: none
+ return_content: yes
+ method: HEAD
+ ignore_errors: yes
+ register: http_303_head
+
+- assert:
+ that:
+ - http_303_head is failure
+ - http_303_head.json is not defined
+ - http_303_head.location == 'https://{{ httpbin_host }}/anything'
+ - "http_303_head.msg == 'Status code was 303 and not [200]: HTTP Error 303: SEE OTHER'"
+ - http_303_head.redirected == false
+ - http_303_head.status == 303
+ - http_303_head.url == 'https://{{ httpbin_host }}/redirect-to?status_code=303&url=https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 303 using GET
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=303&url=https://{{ httpbin_host }}/anything
+ follow_redirects: none
+ return_content: yes
+ method: GET
+ ignore_errors: yes
+ register: http_303_get
+
+- assert:
+ that:
+ - http_303_get is failure
+ - http_303_get.json is not defined
+ - http_303_get.location == 'https://{{ httpbin_host }}/anything'
+ - "http_303_get.msg == 'Status code was 303 and not [200]: HTTP Error 303: SEE OTHER'"
+ - http_303_get.redirected == false
+ - http_303_get.status == 303
+ - http_303_get.url == 'https://{{ httpbin_host }}/redirect-to?status_code=303&url=https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 303 using POST
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=303&url=https://{{ httpbin_host }}/anything
+ follow_redirects: none
+ return_content: yes
+ method: POST
+ body: '{ "foo": "bar" }'
+ body_format: json
+ ignore_errors: yes
+ register: http_303_post
+
+- assert:
+ that:
+ - http_303_post is failure
+ - http_303_post.json is not defined
+ - http_303_post.location == 'https://{{ httpbin_host }}/anything'
+ - "http_303_post.msg == 'Status code was 303 and not [200]: HTTP Error 303: SEE OTHER'"
+ - http_303_post.redirected == false
+ - http_303_post.status == 303
+ - http_303_post.url == 'https://{{ httpbin_host }}/redirect-to?status_code=303&url=https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 307 using HEAD
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=307&url=https://{{ httpbin_host }}/anything
+ follow_redirects: none
+ return_content: yes
+ method: HEAD
+ ignore_errors: yes
+ register: http_307_head
+
+- assert:
+ that:
+ - http_307_head is failure
+ - http_307_head.json is not defined
+ - http_307_head.location == 'https://{{ httpbin_host }}/anything'
+ - "http_307_head.msg == 'Status code was 307 and not [200]: HTTP Error 307: TEMPORARY REDIRECT'"
+ - http_307_head.redirected == false
+ - http_307_head.status == 307
+ - http_307_head.url == 'https://{{ httpbin_host }}/redirect-to?status_code=307&url=https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 307 using GET
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=307&url=https://{{ httpbin_host }}/anything
+ follow_redirects: none
+ return_content: yes
+ method: GET
+ ignore_errors: yes
+ register: http_307_get
+
+- assert:
+ that:
+ - http_307_get is failure
+ - http_307_get.json is not defined
+ - http_307_get.location == 'https://{{ httpbin_host }}/anything'
+ - "http_307_get.msg == 'Status code was 307 and not [200]: HTTP Error 307: TEMPORARY REDIRECT'"
+ - http_307_get.redirected == false
+ - http_307_get.status == 307
+ - http_307_get.url == 'https://{{ httpbin_host }}/redirect-to?status_code=307&url=https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 307 using POST
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=307&url=https://{{ httpbin_host }}/anything
+ follow_redirects: none
+ return_content: yes
+ method: POST
+ body: '{ "foo": "bar" }'
+ body_format: json
+ ignore_errors: yes
+ register: http_307_post
+
+- assert:
+ that:
+ - http_307_post is failure
+ - http_307_post.json is not defined
+ - http_307_post.location == 'https://{{ httpbin_host }}/anything'
+ - "http_307_post.msg == 'Status code was 307 and not [200]: HTTP Error 307: TEMPORARY REDIRECT'"
+ - http_307_post.redirected == false
+ - http_307_post.status == 307
+ - http_307_post.url == 'https://{{ httpbin_host }}/redirect-to?status_code=307&url=https://{{ httpbin_host }}/anything'
+
+# NOTE: This is a bug, fixed in https://github.com/ansible/ansible/pull/36809
+- name: Test HTTP 308 using HEAD
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=308&url=https://{{ httpbin_host }}/anything
+ follow_redirects: none
+ return_content: yes
+ method: GET
+ ignore_errors: yes
+ register: http_308_head
+
+- assert:
+ that:
+ - http_308_head is failure
+ - http_308_head.json is not defined
+ - http_308_head.location == 'https://{{ httpbin_host }}/anything'
+ - "'Status code was 308 and not [200]: HTTP Error 308: ' in http_308_head.msg"
+ - http_308_head.redirected == false
+ - http_308_head.status == 308
+ - http_308_head.url == 'https://{{ httpbin_host }}/redirect-to?status_code=308&url=https://{{ httpbin_host }}/anything'
+
+# NOTE: This is a bug, fixed in https://github.com/ansible/ansible/pull/36809
+- name: Test HTTP 308 using GET
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=308&url=https://{{ httpbin_host }}/anything
+ follow_redirects: none
+ return_content: yes
+ method: GET
+ ignore_errors: yes
+ register: http_308_get
+
+- assert:
+ that:
+ - http_308_get is failure
+ - http_308_get.json is not defined
+ - http_308_get.location == 'https://{{ httpbin_host }}/anything'
+ - "'Status code was 308 and not [200]: HTTP Error 308: ' in http_308_get.msg"
+ - http_308_get.redirected == false
+ - http_308_get.status == 308
+ - http_308_get.url == 'https://{{ httpbin_host }}/redirect-to?status_code=308&url=https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 308 using POST
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=308&url=https://{{ httpbin_host }}/anything
+ follow_redirects: none
+ return_content: yes
+ method: POST
+ body: '{ "foo": "bar" }'
+ body_format: json
+ ignore_errors: yes
+ register: http_308_post
+
+- assert:
+ that:
+ - http_308_post is failure
+ - http_308_post.json is not defined
+ - http_308_post.location == 'https://{{ httpbin_host }}/anything'
+ - "'Status code was 308 and not [200]: HTTP Error 308: ' in http_308_post.msg"
+ - http_308_post.redirected == false
+ - http_308_post.status == 308
+ - http_308_post.url == 'https://{{ httpbin_host }}/redirect-to?status_code=308&url=https://{{ httpbin_host }}/anything'
diff --git a/test/integration/targets/uri/tasks/redirect-safe.yml b/test/integration/targets/uri/tasks/redirect-safe.yml
new file mode 100644
index 0000000..bcc4169
--- /dev/null
+++ b/test/integration/targets/uri/tasks/redirect-safe.yml
@@ -0,0 +1,274 @@
+- name: Test HTTP 301 using HEAD
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=301&url=https://{{ httpbin_host }}/anything
+ follow_redirects: safe
+ return_content: yes
+ method: HEAD
+ register: http_301_head
+
+- assert:
+ that:
+ - http_301_head is successful
+ - http_301_head.json is not defined
+ - http_301_head.redirected == true
+ - http_301_head.status == 200
+ - http_301_head.url == 'https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 301 using GET
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=301&url=https://{{ httpbin_host }}/anything
+ follow_redirects: safe
+ return_content: yes
+ method: GET
+ register: http_301_get
+
+- assert:
+ that:
+ - http_301_get is successful
+ - http_301_get.json.data == ''
+ - http_301_get.json.method == 'GET'
+ - http_301_get.json.url == 'https://{{ httpbin_host }}/anything'
+ - http_301_get.redirected == true
+ - http_301_get.status == 200
+ - http_301_get.url == 'https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 301 using POST
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=301&url=https://{{ httpbin_host }}/anything
+ follow_redirects: safe
+ return_content: yes
+ method: POST
+ body: '{ "foo": "bar" }'
+ body_format: json
+ ignore_errors: yes
+ register: http_301_post
+
+- assert:
+ that:
+ - http_301_post is failure
+ - http_301_post.json is not defined
+ - http_301_post.location == 'https://{{ httpbin_host }}/anything'
+ - "http_301_post.msg == 'Status code was 301 and not [200]: HTTP Error 301: MOVED PERMANENTLY'"
+ - http_301_post.redirected == false
+ - http_301_post.status == 301
+ - http_301_post.url == 'https://{{ httpbin_host }}/redirect-to?status_code=301&url=https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 302 using HEAD
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=302&url=https://{{ httpbin_host }}/anything
+ follow_redirects: safe
+ return_content: yes
+ method: HEAD
+ register: http_302_head
+
+- assert:
+ that:
+ - http_302_head is successful
+ - http_302_head.json is not defined
+ - http_302_head.redirected == true
+ - http_302_head.status == 200
+ - http_302_head.url == 'https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 302 using GET
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=302&url=https://{{ httpbin_host }}/anything
+ follow_redirects: safe
+ return_content: yes
+ method: GET
+ register: http_302_get
+
+- assert:
+ that:
+ - http_302_get is successful
+ - http_302_get.json.data == ''
+ - http_302_get.json.method == 'GET'
+ - http_302_get.json.url == 'https://{{ httpbin_host }}/anything'
+ - http_302_get.redirected == true
+ - http_302_get.status == 200
+ - http_302_get.url == 'https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 302 using POST
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=302&url=https://{{ httpbin_host }}/anything
+ follow_redirects: safe
+ return_content: yes
+ method: POST
+ body: '{ "foo": "bar" }'
+ body_format: json
+ ignore_errors: yes
+ register: http_302_post
+
+- assert:
+ that:
+ - http_302_post is failure
+ - http_302_post.json is not defined
+ - http_302_post.location == 'https://{{ httpbin_host }}/anything'
+ - "http_302_post.msg == 'Status code was 302 and not [200]: HTTP Error 302: FOUND'"
+ - http_302_post.redirected == false
+ - http_302_post.status == 302
+ - http_302_post.url == 'https://{{ httpbin_host }}/redirect-to?status_code=302&url=https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 303 using HEAD
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=303&url=https://{{ httpbin_host }}/anything
+ follow_redirects: safe
+ return_content: yes
+ method: HEAD
+ register: http_303_head
+
+- assert:
+ that:
+ - http_303_head is successful
+ - http_303_head.json is not defined
+ - http_303_head.redirected == true
+ - http_303_head.status == 200
+ - http_303_head.url == 'https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 303 using GET
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=303&url=https://{{ httpbin_host }}/anything
+ follow_redirects: safe
+ return_content: yes
+ method: GET
+ register: http_303_get
+
+- assert:
+ that:
+ - http_303_get is successful
+ - http_303_get.json.data == ''
+ - http_303_get.json.method == 'GET'
+ - http_303_get.json.url == 'https://{{ httpbin_host }}/anything'
+ - http_303_get.redirected == true
+ - http_303_get.status == 200
+ - http_303_get.url == 'https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 303 using POST
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=303&url=https://{{ httpbin_host }}/anything
+ follow_redirects: safe
+ return_content: yes
+ method: POST
+ body: '{ "foo": "bar" }'
+ body_format: json
+ ignore_errors: yes
+ register: http_303_post
+
+- assert:
+ that:
+ - http_303_post is failure
+ - http_303_post.json is not defined
+ - http_303_post.location == 'https://{{ httpbin_host }}/anything'
+ - "http_303_post.msg == 'Status code was 303 and not [200]: HTTP Error 303: SEE OTHER'"
+ - http_303_post.redirected == false
+ - http_303_post.status == 303
+ - http_303_post.url == 'https://{{ httpbin_host }}/redirect-to?status_code=303&url=https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 307 using HEAD
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=307&url=https://{{ httpbin_host }}/anything
+ follow_redirects: safe
+ return_content: yes
+ method: HEAD
+ register: http_307_head
+
+- assert:
+ that:
+ - http_307_head is successful
+ - http_307_head.json is not defined
+ - http_307_head.redirected == true
+ - http_307_head.status == 200
+ - http_307_head.url == 'https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 307 using GET
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=307&url=https://{{ httpbin_host }}/anything
+ follow_redirects: safe
+ return_content: yes
+ method: GET
+ register: http_307_get
+
+- assert:
+ that:
+ - http_307_get is successful
+ - http_307_get.json.data == ''
+ - http_307_get.json.method == 'GET'
+ - http_307_get.json.url == 'https://{{ httpbin_host }}/anything'
+ - http_307_get.redirected == true
+ - http_307_get.status == 200
+ - http_307_get.url == 'https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 307 using POST
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=307&url=https://{{ httpbin_host }}/anything
+ follow_redirects: safe
+ return_content: yes
+ method: POST
+ body: '{ "foo": "bar" }'
+ body_format: json
+ ignore_errors: yes
+ register: http_307_post
+
+- assert:
+ that:
+ - http_307_post is failure
+ - http_307_post.json is not defined
+ - http_307_post.location == 'https://{{ httpbin_host }}/anything'
+ - "http_307_post.msg == 'Status code was 307 and not [200]: HTTP Error 307: TEMPORARY REDIRECT'"
+ - http_307_post.redirected == false
+ - http_307_post.status == 307
+ - http_307_post.url == 'https://{{ httpbin_host }}/redirect-to?status_code=307&url=https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 308 using HEAD
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=308&url=https://{{ httpbin_host }}/anything
+ follow_redirects: safe
+ return_content: yes
+ method: HEAD
+ register: http_308_head
+
+- assert:
+ that:
+ - http_308_head is successful
+ - http_308_head.json is not defined
+ - http_308_head.redirected == true
+ - http_308_head.status == 200
+ - http_308_head.url == 'https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 308 using GET
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=308&url=https://{{ httpbin_host }}/anything
+ follow_redirects: safe
+ return_content: yes
+ method: GET
+ register: http_308_get
+
+- assert:
+ that:
+ - http_308_get is successful
+ - http_308_get.json.data == ''
+ - http_308_get.json.method == 'GET'
+ - http_308_get.json.url == 'https://{{ httpbin_host }}/anything'
+ - http_308_get.redirected == true
+ - http_308_get.status == 200
+ - http_308_get.url == 'https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 308 using POST
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=308&url=https://{{ httpbin_host }}/anything
+ follow_redirects: safe
+ return_content: yes
+ method: POST
+ body: '{ "foo": "bar" }'
+ body_format: json
+ ignore_errors: yes
+ register: http_308_post
+
+- assert:
+ that:
+ - http_308_post is failure
+ - http_308_post.json is not defined
+ - http_308_post.location == 'https://{{ httpbin_host }}/anything'
+ - "'Status code was 308 and not [200]: HTTP Error 308: ' in http_308_post.msg"
+ - http_308_post.redirected == false
+ - http_308_post.status == 308
+ - http_308_post.url == 'https://{{ httpbin_host }}/redirect-to?status_code=308&url=https://{{ httpbin_host }}/anything'
diff --git a/test/integration/targets/uri/tasks/redirect-urllib2.yml b/test/integration/targets/uri/tasks/redirect-urllib2.yml
new file mode 100644
index 0000000..6cdafdb
--- /dev/null
+++ b/test/integration/targets/uri/tasks/redirect-urllib2.yml
@@ -0,0 +1,294 @@
+# NOTE: The HTTP HEAD turns into an HTTP GET
+- name: Test HTTP 301 using HEAD
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=301&url=https://{{ httpbin_host }}/anything
+ follow_redirects: urllib2
+ return_content: yes
+ method: HEAD
+ register: http_301_head
+
+- assert:
+ that:
+ - http_301_head is successful
+ - http_301_head.json.data == ''
+ - http_301_head.json.method == 'GET'
+ - http_301_head.json.url == 'https://{{ httpbin_host }}/anything'
+ - http_301_head.redirected == true
+ - http_301_head.status == 200
+ - http_301_head.url == 'https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 301 using GET
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=301&url=https://{{ httpbin_host }}/anything
+ follow_redirects: urllib2
+ return_content: yes
+ method: GET
+ register: http_301_get
+
+- assert:
+ that:
+ - http_301_get is successful
+ - http_301_get.json.data == ''
+ - http_301_get.json.method == 'GET'
+ - http_301_get.json.url == 'https://{{ httpbin_host }}/anything'
+ - http_301_get.redirected == true
+ - http_301_get.status == 200
+ - http_301_get.url == 'https://{{ httpbin_host }}/anything'
+
+# NOTE: The HTTP POST turns into an HTTP GET
+- name: Test HTTP 301 using POST
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=301&url=https://{{ httpbin_host }}/anything
+ follow_redirects: urllib2
+ return_content: yes
+ method: POST
+ body: '{ "foo": "bar" }'
+ body_format: json
+ register: http_301_post
+
+- assert:
+ that:
+ - http_301_post is successful
+ - http_301_post.json.data == ''
+ - http_301_post.json.method == 'GET'
+ - http_301_post.json.url == 'https://{{ httpbin_host }}/anything'
+ - http_301_post.redirected == true
+ - http_301_post.status == 200
+ - http_301_post.url == 'https://{{ httpbin_host }}/anything'
+
+# NOTE: The HTTP HEAD turns into an HTTP GET
+- name: Test HTTP 302 using HEAD
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=302&url=https://{{ httpbin_host }}/anything
+ follow_redirects: urllib2
+ return_content: yes
+ method: HEAD
+ register: http_302_head
+
+- assert:
+ that:
+ - http_302_head is successful
+ - http_302_head.json.data == ''
+ - http_302_head.json.method == 'GET'
+ - http_302_head.json.url == 'https://{{ httpbin_host }}/anything'
+ - http_302_head.redirected == true
+ - http_302_head.status == 200
+ - http_302_head.url == 'https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 302 using GET
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=302&url=https://{{ httpbin_host }}/anything
+ follow_redirects: urllib2
+ return_content: yes
+ method: GET
+ register: http_302_get
+
+- assert:
+ that:
+ - http_302_get is successful
+ - http_302_get.json.data == ''
+ - http_302_get.json.method == 'GET'
+ - http_302_get.json.url == 'https://{{ httpbin_host }}/anything'
+ - http_302_get.redirected == true
+ - http_302_get.status == 200
+ - http_302_get.url == 'https://{{ httpbin_host }}/anything'
+
+# NOTE: The HTTP POST turns into an HTTP GET
+- name: Test HTTP 302 using POST
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=302&url=https://{{ httpbin_host }}/anything
+ follow_redirects: urllib2
+ return_content: yes
+ method: POST
+ body: '{ "foo": "bar" }'
+ body_format: json
+ register: http_302_post
+
+- assert:
+ that:
+ - http_302_post is successful
+ - http_302_post.json.data == ''
+ - http_302_post.json.method == 'GET'
+ - http_302_post.json.url == 'https://{{ httpbin_host }}/anything'
+ - http_302_post.redirected == true
+ - http_302_post.status == 200
+ - http_302_post.url == 'https://{{ httpbin_host }}/anything'
+
+# NOTE: The HTTP HEAD turns into an HTTP GET
+- name: Test HTTP 303 using HEAD
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=303&url=https://{{ httpbin_host }}/anything
+ follow_redirects: urllib2
+ return_content: yes
+ method: HEAD
+ register: http_303_head
+
+- assert:
+ that:
+ - http_303_head is successful
+ - http_303_head.json.data == ''
+ - http_303_head.json.method == 'GET'
+ - http_303_head.json.url == 'https://{{ httpbin_host }}/anything'
+ - http_303_head.redirected == true
+ - http_303_head.status == 200
+ - http_303_head.url == 'https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 303 using GET
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=303&url=https://{{ httpbin_host }}/anything
+ follow_redirects: urllib2
+ return_content: yes
+ method: GET
+ register: http_303_get
+
+- assert:
+ that:
+ - http_303_get is successful
+ - http_303_get.json.data == ''
+ - http_303_get.json.method == 'GET'
+ - http_303_get.json.url == 'https://{{ httpbin_host }}/anything'
+ - http_303_get.redirected == true
+ - http_303_get.status == 200
+ - http_303_get.url == 'https://{{ httpbin_host }}/anything'
+
+# NOTE: The HTTP POST turns into an HTTP GET
+- name: Test HTTP 303 using POST
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=303&url=https://{{ httpbin_host }}/anything
+ follow_redirects: urllib2
+ return_content: yes
+ method: POST
+ body: '{ "foo": "bar" }'
+ body_format: json
+ register: http_303_post
+
+- assert:
+ that:
+ - http_303_post is successful
+ - http_303_post.json.data == ''
+ - http_303_post.json.method == 'GET'
+ - http_303_post.json.url == 'https://{{ httpbin_host }}/anything'
+ - http_303_post.redirected == true
+ - http_303_post.status == 200
+ - http_303_post.url == 'https://{{ httpbin_host }}/anything'
+
+# NOTE: The HTTP HEAD turns into an HTTP GET
+- name: Test HTTP 307 using HEAD
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=307&url=https://{{ httpbin_host }}/anything
+ follow_redirects: urllib2
+ return_content: yes
+ method: HEAD
+ register: http_307_head
+
+- assert:
+ that:
+ - http_307_head is successful
+ - http_307_head.json.data == ''
+ - http_307_head.json.method == 'GET'
+ - http_307_head.json.url == 'https://{{ httpbin_host }}/anything'
+ - http_307_head.redirected == true
+ - http_307_head.status == 200
+ - http_307_head.url == 'https://{{ httpbin_host }}/anything'
+
+- name: Test HTTP 307 using GET
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=307&url=https://{{ httpbin_host }}/anything
+ follow_redirects: urllib2
+ return_content: yes
+ method: GET
+ register: http_307_get
+
+- assert:
+ that:
+ - http_307_get is successful
+ - http_307_get.json.data == ''
+ - http_307_get.json.method == 'GET'
+ - http_307_get.json.url == 'https://{{ httpbin_host }}/anything'
+ - http_307_get.redirected == true
+ - http_307_get.status == 200
+ - http_307_get.url == 'https://{{ httpbin_host }}/anything'
+
+# FIXME: This is fixed in https://github.com/ansible/ansible/pull/36809
+- name: Test HTTP 307 using POST
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=307&url=https://{{ httpbin_host }}/anything
+ follow_redirects: urllib2
+ return_content: yes
+ method: POST
+ body: '{ "foo": "bar" }'
+ body_format: json
+ ignore_errors: yes
+ register: http_307_post
+
+- assert:
+ that:
+ - http_307_post is failure
+ - http_307_post.json is not defined
+ - http_307_post.location == 'https://{{ httpbin_host }}/anything'
+ - "http_307_post.msg == 'Status code was 307 and not [200]: HTTP Error 307: TEMPORARY REDIRECT'"
+ - http_307_post.redirected == false
+ - http_307_post.status == 307
+ - http_307_post.url == 'https://{{ httpbin_host }}/redirect-to?status_code=307&url=https://{{ httpbin_host }}/anything'
+
+# FIXME: This is fixed in https://github.com/ansible/ansible/pull/36809
+- name: Test HTTP 308 using HEAD
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=308&url=https://{{ httpbin_host }}/anything
+ follow_redirects: urllib2
+ return_content: yes
+ method: GET
+ ignore_errors: yes
+ register: http_308_head
+
+- assert:
+ that:
+ - http_308_head is failure
+ - http_308_head.json is not defined
+ - http_308_head.location == 'https://{{ httpbin_host }}/anything'
+ - "'Status code was 308 and not [200]: HTTP Error 308: ' in http_308_head.msg"
+ - http_308_head.redirected == false
+ - http_308_head.status == 308
+ - http_308_head.url == 'https://{{ httpbin_host }}/redirect-to?status_code=308&url=https://{{ httpbin_host }}/anything'
+
+# FIXME: This is fixed in https://github.com/ansible/ansible/pull/36809
+- name: Test HTTP 308 using GET
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=308&url=https://{{ httpbin_host }}/anything
+ follow_redirects: urllib2
+ return_content: yes
+ method: GET
+ ignore_errors: yes
+ register: http_308_get
+
+- assert:
+ that:
+ - http_308_get is failure
+ - http_308_get.json is not defined
+ - http_308_get.location == 'https://{{ httpbin_host }}/anything'
+ - "'Status code was 308 and not [200]: HTTP Error 308: ' in http_308_get.msg"
+ - http_308_get.redirected == false
+ - http_308_get.status == 308
+ - http_308_get.url == 'https://{{ httpbin_host }}/redirect-to?status_code=308&url=https://{{ httpbin_host }}/anything'
+
+# FIXME: This is fixed in https://github.com/ansible/ansible/pull/36809
+- name: Test HTTP 308 using POST
+ uri:
+ url: https://{{ httpbin_host }}/redirect-to?status_code=308&url=https://{{ httpbin_host }}/anything
+ follow_redirects: urllib2
+ return_content: yes
+ method: POST
+ body: '{ "foo": "bar" }'
+ body_format: json
+ ignore_errors: yes
+ register: http_308_post
+
+- assert:
+ that:
+ - http_308_post is failure
+ - http_308_post.json is not defined
+ - http_308_post.location == 'https://{{ httpbin_host }}/anything'
+ - "'Status code was 308 and not [200]: HTTP Error 308: ' in http_308_post.msg"
+ - http_308_post.redirected == false
+ - http_308_post.status == 308
+ - http_308_post.url == 'https://{{ httpbin_host }}/redirect-to?status_code=308&url=https://{{ httpbin_host }}/anything'
diff --git a/test/integration/targets/uri/tasks/return-content.yml b/test/integration/targets/uri/tasks/return-content.yml
new file mode 100644
index 0000000..5a9b97e
--- /dev/null
+++ b/test/integration/targets/uri/tasks/return-content.yml
@@ -0,0 +1,49 @@
+- name: Test when return_content is yes
+ uri:
+ url: https://{{ httpbin_host }}/get
+ return_content: yes
+ register: result
+
+- name: Assert content exists when return_content is yes and request succeeds
+ assert:
+ that:
+ - result is successful
+ - "'content' in result"
+
+- name: Test when return_content is yes
+ uri:
+ url: http://does/not/exist
+ return_content: yes
+ register: result
+ ignore_errors: true
+
+- name: Assert content exists when return_content is yes and request fails
+ assert:
+ that:
+ - result is failed
+ - "'content' in result"
+
+- name: Test when return_content is no
+ uri:
+ url: https://{{ httpbin_host }}/get
+ return_content: no
+ register: result
+
+- name: Assert content does not exist when return_content is no and request succeeds
+ assert:
+ that:
+ - result is successful
+ - "'content' not in result"
+
+- name: Test when return_content is no
+ uri:
+ url: http://does/not/exist
+ return_content: no
+ register: result
+ ignore_errors: true
+
+- name: Assert content does not exist when return_content is no and request fails
+ assert:
+ that:
+ - result is failed
+ - "'content' not in result" \ No newline at end of file
diff --git a/test/integration/targets/uri/tasks/unexpected-failures.yml b/test/integration/targets/uri/tasks/unexpected-failures.yml
new file mode 100644
index 0000000..341b66e
--- /dev/null
+++ b/test/integration/targets/uri/tasks/unexpected-failures.yml
@@ -0,0 +1,26 @@
+---
+# same as expanduser & expandvars called on managed host
+- command: 'echo {{ remote_tmp_dir }}'
+ register: echo
+
+- set_fact:
+ remote_dir_expanded: '{{ echo.stdout }}'
+
+- name: ensure test directory doesn't exist
+ file:
+ path: '{{ remote_tmp_dir }}/non/existent/path'
+ state: absent
+
+- name: destination doesn't exist
+ uri:
+ url: 'https://{{ httpbin_host }}/get'
+ dest: '{{ remote_tmp_dir }}/non/existent/path'
+ ignore_errors: true
+ register: ret
+
+- name: check that unexpected failure didn't happen
+ assert:
+ that:
+ - ret is failed
+ - "not ret.msg.startswith('MODULE FAILURE')"
+ - '"Could not replace file" in ret.msg'
diff --git a/test/integration/targets/uri/tasks/use_gssapi.yml b/test/integration/targets/uri/tasks/use_gssapi.yml
new file mode 100644
index 0000000..6629cee
--- /dev/null
+++ b/test/integration/targets/uri/tasks/use_gssapi.yml
@@ -0,0 +1,62 @@
+- name: test that endpoint offers Negotiate auth
+ uri:
+ url: http://{{ httpbin_host }}/gssapi
+ status_code: 401
+ register: no_auth_failure
+ failed_when: no_auth_failure.www_authenticate != 'Negotiate'
+
+- name: test Negotiate auth over HTTP with explicit credentials
+ uri:
+ url: http://{{ httpbin_host }}/gssapi
+ use_gssapi: yes
+ url_username: '{{ krb5_username }}'
+ url_password: '{{ krb5_password }}'
+ return_content: yes
+ register: http_explicit
+
+- name: test Negotiate auth over HTTPS with explicit credentials
+ uri:
+ url: https://{{ httpbin_host }}/gssapi
+ use_gssapi: yes
+ url_username: '{{ krb5_username }}'
+ url_password: '{{ krb5_password }}'
+ return_content: yes
+ register: https_explicit
+
+- name: assert test Negotiate auth with implicit credentials
+ assert:
+ that:
+ - http_explicit.status == 200
+ - http_explicit.content | trim == 'Microsoft Rulz'
+ - https_explicit.status == 200
+ - https_explicit.content | trim == 'Microsoft Rulz'
+
+- name: skip tests on macOS, I cannot seem to get it to read a credential from a custom ccache
+ when: ansible_facts.distribution != 'MacOSX'
+ block:
+ - name: get Kerberos ticket for implicit auth tests
+ httptester_kinit:
+ username: '{{ krb5_username }}'
+ password: '{{ krb5_password }}'
+
+ - name: test Negotiate auth over HTTP with implicit credentials
+ uri:
+ url: http://{{ httpbin_host }}/gssapi
+ use_gssapi: yes
+ return_content: yes
+ register: http_implicit
+
+ - name: test Negotiate auth over HTTPS with implicit credentials
+ uri:
+ url: https://{{ httpbin_host }}/gssapi
+ use_gssapi: yes
+ return_content: yes
+ register: https_implicit
+
+ - name: assert test Negotiate auth with implicit credentials
+ assert:
+ that:
+ - http_implicit.status == 200
+ - http_implicit.content | trim == 'Microsoft Rulz'
+ - https_implicit.status == 200
+ - https_implicit.content | trim == 'Microsoft Rulz'
diff --git a/test/integration/targets/uri/tasks/use_netrc.yml b/test/integration/targets/uri/tasks/use_netrc.yml
new file mode 100644
index 0000000..da745b8
--- /dev/null
+++ b/test/integration/targets/uri/tasks/use_netrc.yml
@@ -0,0 +1,51 @@
+- name: Write out netrc
+ copy:
+ dest: "{{ remote_tmp_dir }}/netrc"
+ content: |
+ machine {{ httpbin_host }}
+ login foo
+ password bar
+
+- name: Test Bearer authorization is failed with netrc
+ uri:
+ url: https://{{ httpbin_host }}/bearer
+ return_content: yes
+ headers:
+ Authorization: Bearer foobar
+ ignore_errors: yes
+ environment:
+ NETRC: "{{ remote_tmp_dir }}/netrc"
+ register: response_failed
+
+- name: assert Test Bearer authorization is failed with netrc
+ assert:
+ that:
+ - response_failed.json.token != 'foobar'
+ - "'Zm9vOmJhcg==' in response_failed.json.token"
+ fail_msg: "Was expecting 'foo:bar' in base64, but received: {{ response_failed }}"
+ success_msg: "Expected to fail because netrc is using Basic authentication by default"
+
+- name: Test Bearer authorization is successfull with use_netrc=False
+ uri:
+ url: https://{{ httpbin_host }}/bearer
+ use_netrc: false
+ return_content: yes
+ headers:
+ Authorization: Bearer foobar
+ environment:
+ NETRC: "{{ remote_tmp_dir }}/netrc"
+ register: response
+
+- name: assert Test Bearer authorization is successfull with use_netrc=False
+ assert:
+ that:
+ - response.status == 200
+ - response.json.token == 'foobar'
+ - response.url == 'https://{{ httpbin_host }}/bearer'
+ fail_msg: "Was expecting successful Bearer authentication, but received: {{ response }}"
+ success_msg: "Bearer authentication successfull when netrc is ignored."
+
+- name: Clean up
+ file:
+ dest: "{{ remote_tmp_dir }}/netrc"
+ state: absent \ No newline at end of file
diff --git a/test/integration/targets/uri/templates/netrc.j2 b/test/integration/targets/uri/templates/netrc.j2
new file mode 100644
index 0000000..3a100d5
--- /dev/null
+++ b/test/integration/targets/uri/templates/netrc.j2
@@ -0,0 +1,3 @@
+machine {{ httpbin_host }}
+login user
+password passwd
diff --git a/test/integration/targets/uri/vars/main.yml b/test/integration/targets/uri/vars/main.yml
new file mode 100644
index 0000000..83a740b
--- /dev/null
+++ b/test/integration/targets/uri/vars/main.yml
@@ -0,0 +1,20 @@
+uri_os_packages:
+ RedHat:
+ urllib3: python-urllib3
+ step1:
+ - python-pyasn1
+ - pyOpenSSL
+ - python-urllib3
+ step2:
+ - libffi-devel
+ - openssl-devel
+ - python-devel
+ Debian:
+ step1:
+ - python-pyasn1
+ - python-openssl
+ - python-urllib3
+ step2:
+ - libffi-dev
+ - libssl-dev
+ - python-dev