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>
pull/84554/head
Abhijeet Kasurde 11 months ago committed by GitHub
parent f727d74fc2
commit 5b0d170496
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,3 @@
---
bugfixes:
- get_url - add support for BSD-style checksum digest file (https://github.com/ansible/ansible/issues/84476).

@ -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):

@ -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

@ -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
Loading…
Cancel
Save