cloud-init uses GNU date(1) for parsing timestamps.
GNU date(1) is not available on all platforms cloud-init runs on.
self = <test_dump.TestParseTimestamp object at 0x14f2505885b0>
@skipIf(not which("date"), "'date' command not available.")
@pytest.mark.allow_subp_for("date")
def test_parse_unexpected_timestamp_format_with_date_command(self):
"""Dump sends unexpected timestamp formats to date for processing."""
new_fmt = "%H:%M %m/%d %Y"
new_stamp = "17:15 08/08"
# convert stamp ourselves by adding the missing year value
year = datetime.now().year
dt = datetime.strptime(new_stamp + " " + str(year), new_fmt)
> assert float(dt.strftime("%s.%f")) == parse_timestamp(new_stamp)
dt = datetime.datetime(2023, 8, 8, 17, 15)
new_fmt = '%H:%M %m/%d %Y'
new_stamp = '17:15 08/08'
self = <test_dump.TestParseTimestamp object at 0x14f2505885b0>
year = 2023
tests/unittests/analyze/test_dump.py:56:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
cloudinit/analyze/dump.py:48: in parse_timestamp
timestamp = parse_timestamp_from_date(timestampstr)
months = ['Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec']
timestampstr = '17:15 08/08'
cloudinit/analyze/dump.py:54: in parse_timestamp_from_date
out, _ = subp.subp(["date", "+%s.%3N", "-d", timestampstr])
timestampstr = '17:15 08/08'
<string>:3: in subp
???
args = (['date', '+%s.%3N', '-d', '17:15 08/08'],)
kwargs = {}
/usr/local/lib/python3.9/unittest/mock.py:1092: in __call__
return self._mock_call(*args, **kwargs)
args = (['date', '+%s.%3N', '-d', '17:15 08/08'],)
kwargs = {}
self = <MagicMock name='subp' spec='function' id='23031021882336'>
/usr/local/lib/python3.9/unittest/mock.py:1096: in _mock_call
return self._execute_mock_call(*args, **kwargs)
args = (['date', '+%s.%3N', '-d', '17:15 08/08'],)
kwargs = {}
self = <MagicMock name='subp' spec='function' id='23031021882336'>
/usr/local/lib/python3.9/unittest/mock.py:1157: in _execute_mock_call
result = effect(*args, **kwargs)
args = (['date', '+%s.%3N', '-d', '17:15 08/08'],)
effect = <function disable_subp_usage.<locals>.side_effect at 0x14f255a52e50>
kwargs = {}
self = <MagicMock name='subp' spec='function' id='23031021882336'>
conftest.py:168: in side_effect [998/1841]
return real_subp(args, *other_args, **kwargs)
allow_subp_for = ('date',)
args = ['date', '+%s.%3N', '-d', '17:15 08/08']
cmd = 'date'
kwargs = {}
other_args = ()
real_subp = <function subp at 0x14f24df1c160>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
args = ['date', '+%s.%3N', '-d', '17:15 08/08'], data = None, rcs = [0], env = None, capture = True, combine_capture = False
shell = False, logstring = False, decode = 'replace', target = None, update_env = None, status_cb = None, cwd = None
if rc not in rcs: [812/1841]
if status_cb:
status_cb("ERROR: End run command: exit({code})\n".format(code=rc))
> raise ProcessExecutionError(
stdout=out, stderr=err, exit_code=rc, cmd=args
)
E cloudinit.subp.ProcessExecutionError: Unexpected error while running command.
E Command: ['date', '+%s.%3N', '-d', '17:15 08/08']
E Exit code: 1
E Reason: -
E Stdout:
E Stderr: date: illegal time format
E usage: date [-jnRu] [-I[date|hours|minutes|seconds]] [-f input_fmt]
E [ -z output_zone ] [-r filename|seconds] [-v[+|-]val[y|m|w|d|H|M|S]]
E [[[[[[cc]yy]mm]dd]HH]MM[.SS] | new_date] [+output_fmt]
args = ['date', '+%s.%3N', '-d', '17:15 08/08']
bytes_args = [b'date', b'+%s.%3N', b'-d', b'17:15 08/08']
capture = True
combine_capture = False
cwd = None
data = None
decode = 'replace'
devnull_fp = <_io.TextIOWrapper name='/dev/null' mode='r' encoding='UTF-8'>
env = None
err = ('date: illegal time format\n'
'usage: date [-jnRu] [-I[date|hours|minutes|seconds]] [-f input_fmt]\n'
' [ -z output_zone ] [-r filename|seconds] '
'[-v[+|-]val[y|m|w|d|H|M|S]]\n'
' [[[[[[cc]yy]mm]dd]HH]MM[.SS] | new_date] [+output_fmt]\n')
ldecode = <function subp.<locals>.ldecode at 0x14f255a571f0>
logstring = False
out = ''
rc = 1
rcs = [0]
shell = False
sp = <Popen: returncode: 1 args: [b'date', b'+%s.%3N', b'-d', b'17:15 08/08']>
status_cb = None
stderr = -1
stdin = <_io.TextIOWrapper name='/dev/null' mode='r' encoding='UTF-8'>
stdout = -1
target = None
update_env = None
cloudinit/subp.py:335: ProcessExecutionError
-------------------------------------------------------- Captured stdout call ---------------------------------------------------------
2023-08-10 20:45:34,288 - subp.py[DEBUG]: Running command ['date', '+%s.%3N', '-d', '17:15 08/08'] with allowed return codes [0] (shell
=False, capture=True)
---------------------------------------------------------- Captured log call ----------------------------------------------------------
2023-08-10 20:45:34 DEBUG cloudinit.subp:subp.py:245 Running command ['date', '+%s.%3N', '-d', '17:15 08/08'] with allowed return c
odes [0] (shell=False, capture=True)
use python for parsing of dates.
Bug report
cloud-init uses GNU date(1) for parsing timestamps.
GNU date(1) is not available on all platforms cloud-init runs on.
Steps to reproduce the problem
run unit tests on FreeBSD and see:
Environment details
how to fix it
use python for parsing of dates.