summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAbhijeet Kasurde <akasurde@redhat.com>2025-01-14 16:44:29 +0100
committerGitHub <noreply@github.com>2025-01-14 16:44:29 +0100
commit5b0d1704962b4634380c20f8ab5d23f80cbc5f52 (patch)
treeb11d9e81535931f61fac8d2944d7d0e6c895e878
parentAllows iptables chain creation with wait parameter (#84491) (diff)
downloadansible-5b0d1704962b4634380c20f8ab5d23f80cbc5f52.tar.xz
ansible-5b0d1704962b4634380c20f8ab5d23f80cbc5f52.zip
get_url: add support for BSD-style digest (#84485)
* Added support for BSD-style digest file to test checksum of downloaded file. Fixes: #84476 Signed-off-by: Abhijeet Kasurde <akasurde@redhat.com>
-rw-r--r--changelogs/fragments/get_url_bsd_style_digest.yml3
-rw-r--r--lib/ansible/modules/get_url.py55
-rw-r--r--test/integration/targets/get_url/tasks/main.yml22
-rw-r--r--test/units/modules/test_get_url.py45
4 files changed, 104 insertions, 21 deletions
diff --git a/changelogs/fragments/get_url_bsd_style_digest.yml b/changelogs/fragments/get_url_bsd_style_digest.yml
new file mode 100644
index 0000000000..fe4a6f288c
--- /dev/null
+++ b/changelogs/fragments/get_url_bsd_style_digest.yml
@@ -0,0 +1,3 @@
+---
+bugfixes:
+ - get_url - add support for BSD-style checksum digest file (https://github.com/ansible/ansible/issues/84476).
diff --git a/lib/ansible/modules/get_url.py b/lib/ansible/modules/get_url.py
index 52c812c0c6..563ae5a61e 100644
--- a/lib/ansible/modules/get_url.py
+++ b/lib/ansible/modules/get_url.py
@@ -460,6 +460,37 @@ def is_url(checksum):
return urlsplit(checksum).scheme in supported_schemes
+def parse_digest_lines(filename, lines):
+ """Returns a list of tuple containing the filename and digest depending upon
+ the lines provided
+
+ Args:
+ filename (str): Name of the filename, used only when the digest is one-liner
+ lines (list): A list of lines containing filenames and checksums
+ """
+ checksum_map = []
+ BSD_DIGEST_LINE = re.compile(r'^(\w+) ?\((?P<path>.+)\) ?= (?P<digest>[\w.]+)$')
+ GNU_DIGEST_LINE = re.compile(r'^(?P<digest>[\w.]+) ([ *])(?P<path>.+)$')
+
+ if len(lines) == 1 and len(lines[0].split()) == 1:
+ # Only a single line with a single string
+ # treat it as a checksum only file
+ checksum_map.append((lines[0], filename))
+ return checksum_map
+ # The assumption here is the file is in the format of
+ # checksum filename
+ for line in lines:
+ match = BSD_DIGEST_LINE.match(line)
+ if match:
+ checksum_map.append((match.group('digest'), match.group('path')))
+ else:
+ match = GNU_DIGEST_LINE.match(line)
+ if match:
+ checksum_map.append((match.group('digest'), match.group('path').lstrip("./")))
+
+ return checksum_map
+
+
# ==============================================================
# main
@@ -527,31 +558,13 @@ def main():
if is_url(checksum):
checksum_url = checksum
# download checksum file to checksum_tmpsrc
- checksum_tmpsrc, checksum_info = url_get(module, checksum_url, dest, use_proxy, last_mod_time, force, timeout, headers, tmp_dest,
- unredirected_headers=unredirected_headers, ciphers=ciphers, use_netrc=use_netrc)
+ checksum_tmpsrc, _dummy = url_get(module, checksum_url, dest, use_proxy, last_mod_time, force, timeout, headers, tmp_dest,
+ unredirected_headers=unredirected_headers, ciphers=ciphers, use_netrc=use_netrc)
with open(checksum_tmpsrc) as f:
lines = [line.rstrip('\n') for line in f]
os.remove(checksum_tmpsrc)
- checksum_map = []
filename = url_filename(url)
- if len(lines) == 1 and len(lines[0].split()) == 1:
- # Only a single line with a single string
- # treat it as a checksum only file
- checksum_map.append((lines[0], filename))
- else:
- # The assumption here is the file is in the format of
- # checksum filename
- for line in lines:
- # Split by one whitespace to keep the leading type char ' ' (whitespace) for text and '*' for binary
- parts = line.split(" ", 1)
- if len(parts) == 2:
- # Remove the leading type char, we expect
- if parts[1].startswith((" ", "*",)):
- parts[1] = parts[1][1:]
-
- # Append checksum and path without potential leading './'
- checksum_map.append((parts[0], parts[1].lstrip("./")))
-
+ checksum_map = parse_digest_lines(filename=filename, lines=lines)
# Look through each line in the checksum file for a hash corresponding to
# the filename in the url, returning the first hash that is found.
for cksum in (s for (s, f) in checksum_map if f == filename):
diff --git a/test/integration/targets/get_url/tasks/main.yml b/test/integration/targets/get_url/tasks/main.yml
index 66bd129368..0ec6afd202 100644
--- a/test/integration/targets/get_url/tasks/main.yml
+++ b/test/integration/targets/get_url/tasks/main.yml
@@ -376,6 +376,15 @@
30949cc401e30ac494d695ab8764a9f76aae17c5d73c67f65e9b558f47eff892 *not_target1.txt
d0dbfc1945bc83bf6606b770e442035f2c4e15c886ee0c22fb3901ba19900b5b *not_target2.txt
+- name: create sha256 checksum file of src in BSD-style checksum (--tag)
+ copy:
+ dest: '{{ files_dir }}/sha256sum_bsd_style.txt'
+ content: |
+ SHA256 (27617.txt) = b1b6ce5073c8fac263a8fc5edfffdbd5dec1980c784e09c5bc69f8fb6056f006.
+ SHA256 (71420.txt) = b1b6ce5073c8fac263a8fc5edfffdbd5dec1980c784e09c5bc69f8fb6056f006.
+ SHA256 (not_target1.txt) = 30949cc401e30ac494d695ab8764a9f76aae17c5d73c67f65e9b558f47eff892
+ SHA256 (not_target2.txt) = d0dbfc1945bc83bf6606b770e442035f2c4e15c886ee0c22fb3901ba19900b5b
+
# completing 27617 with bug 54390
- name: create sha256 checksum only with no filename inside
copy:
@@ -463,6 +472,17 @@
path: "{{ remote_tmp_dir }}/27617sha256_with_dot.txt"
register: stat_result_sha256_with_file_scheme
+- name: download src with sha256 checksum url with BSD style checksum
+ get_url:
+ url: 'http://localhost:{{ http_port }}/27617.txt'
+ dest: '{{ remote_tmp_dir }}/27617sha256_with_bsd_style.txt'
+ checksum: 'sha256:file://{{ files_dir }}/sha256sum_bsd_style.txt'
+ register: result_sha256_with_bsd_style
+
+- stat:
+ path: "{{ remote_tmp_dir }}/27617sha256_with_bsd_style.txt"
+ register: stat_result_sha256_with_bsd_style
+
- name: download 71420.txt with sha1 checksum url
get_url:
url: 'http://localhost:{{ http_port }}/71420.txt'
@@ -538,11 +558,13 @@
- result_sha256_with_dot is changed
- result_sha256_with_asterisk is changed
- result_sha256_with_file_scheme is changed
+ - result_sha256_with_bsd_style is changed
- "stat_result_sha1.stat.exists == true"
- "stat_result_sha256.stat.exists == true"
- "stat_result_sha256_with_dot.stat.exists == true"
- "stat_result_sha256_with_asterisk.stat.exists == true"
- "stat_result_sha256_with_file_scheme.stat.exists == true"
+ - stat_result_sha256_with_bsd_style.stat.exists
- result_sha1_71420 is changed
- result_sha256_71420 is changed
- result_sha256_with_dot_71420 is changed
diff --git a/test/units/modules/test_get_url.py b/test/units/modules/test_get_url.py
new file mode 100644
index 0000000000..9e09634193
--- /dev/null
+++ b/test/units/modules/test_get_url.py
@@ -0,0 +1,45 @@
+# -*- coding: utf-8 -*-
+
+# Copyright: Contributors to the Ansible project
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+from __future__ import annotations
+
+import pytest
+
+from ansible.modules.get_url import parse_digest_lines
+
+
+@pytest.mark.parametrize(
+ ("lines", "expected"),
+ [
+ pytest.param(
+ [
+ "a97e6837f60cec6da4491bab387296bbcd72bdba",
+ ],
+ [("a97e6837f60cec6da4491bab387296bbcd72bdba", "sample.txt")],
+ id="single-line-digest",
+ ),
+ pytest.param(
+ [
+ "a97e6837f60cec6da4491bab387296bbcd72bdba sample.txt",
+ ],
+ [("a97e6837f60cec6da4491bab387296bbcd72bdba", "sample.txt")],
+ id="GNU-style-digest",
+ ),
+ pytest.param(
+ [
+ "SHA256 (sample.txt) = b1b6ce5073c8fac263a8fc5edfffdbd5dec1980c784e09c5bc69f8fb6056f006.",
+ ],
+ [
+ (
+ "b1b6ce5073c8fac263a8fc5edfffdbd5dec1980c784e09c5bc69f8fb6056f006.",
+ "sample.txt",
+ )
+ ],
+ id="BSD-style-digest",
+ ),
+ ],
+)
+def test_parse_digest_lines(lines, expected):
+ filename = "sample.txt"
+ assert parse_digest_lines(filename, lines) == expected