From 67c0bf626336e49a5c77b8c606fc8f477347b860 Mon Sep 17 00:00:00 2001 From: Joseph Schorr Date: Wed, 22 Feb 2017 15:56:14 -0500 Subject: [PATCH] Fix docker versioning library to support new versioning scheme Fixes: https://sentry.io/coreos/backend-production/issues/222349174/ Reference: https://github.com/docker/docker/pull/31075 --- util/registry/dockerver.py | 9 ++++++++- util/registry/test/test_dockerver.py | 12 +++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/util/registry/dockerver.py b/util/registry/dockerver.py index 2156d6377..f73cd0e1f 100644 --- a/util/registry/dockerver.py +++ b/util/registry/dockerver.py @@ -16,7 +16,14 @@ def docker_version(user_agent_string): # First search for a well defined semver portion in the UA header. found_semver = _USER_AGENT_SEARCH_REGEX.search(user_agent_string) if found_semver: - return Version(found_semver.group(1), partial=True) + # Docker changed their versioning scheme on Feb 17, 2017 to use date-based versioning: + # https://github.com/docker/docker/pull/31075 + + # This scheme allows for 0s to appear as prefixes in the major or minor portions of the version, + # which violates semver. Strip them out. + portions = found_semver.group(1).split('.') + updated_portions = [(p[:-1].lstrip('0') + p[-1]) for p in portions] + return Version('.'.join(updated_portions), partial=True) # Check if we received the very specific header which represents a 1.5 request # to the auth endpoints. diff --git a/util/registry/test/test_dockerver.py b/util/registry/test/test_dockerver.py index f0b2c59a7..99b728138 100644 --- a/util/registry/test/test_dockerver.py +++ b/util/registry/test/test_dockerver.py @@ -4,6 +4,7 @@ from util.registry.dockerver import docker_version from semantic_version import Version, Spec @pytest.mark.parametrize('ua_string, ver_info', [ + # Old "semantic" versioning. ('docker/1.6.0 go/go1.4.2 git-commit/1234567 kernel/4.2.0-18-generic os/linux arch/amd64', Version('1.6.0')), ('docker/1.7.1 go/go1.4.2 kernel/4.1.7-15.23.amzn1.x86_64 os/linux arch/amd64', @@ -19,15 +20,24 @@ from semantic_version import Version, Spec ('Go 1.1 package http', Version('1.5.0')), ('curl', None), ('docker/1.8 stuff', Version('1.8.0')), + + # Newer date-based versioning: YY.MM.revnum + ('docker/17.03.0 my_version_sucks', Version('17.3.0')), + ('docker/17.03.0-foobar my_version_sucks', Version('17.3.0')), + ('docker/17.10.2 go/go1.4.2 git-commit/a34a1d5 kernel/3.10.0-229.20.1.el7.x86_64 os/linux arch/amd64', + Version('17.10.2')), + ('docker/17.00.4 my_version_sucks', Version('17.0.4')), + ('docker/17.12.00 my_version_sucks', Version('17.12.0')), ]) def test_parsing(ua_string, ver_info): parsed_ver = docker_version(ua_string) - assert parsed_ver == ver_info + assert parsed_ver == ver_info, 'Expected %s, Found %s' % (ver_info, parsed_ver) @pytest.mark.parametrize('spec, no_match_cases, match_cases', [ (Spec('<1.6.0'), ['1.6.0', '1.6.1', '1.9.0', '100.5.2'], ['0.0.0', '1.5.99']), (Spec('<1.9.0'), ['1.9.0', '100.5.2'], ['0.0.0', '1.5.99', '1.6.0', '1.6.1']), (Spec('<1.6.0,>0.0.1'), ['1.6.0', '1.6.1', '1.9.0', '0.0.0'], ['1.5.99']), + (Spec('>17.3.0'), ['17.3.0', '1.13.0'], ['17.4.0', '17.12.1']), ]) def test_specs(spec, no_match_cases, match_cases): for no_match_case in no_match_cases: