From caa64b3f6a70f9401b07802fc130956064742024 Mon Sep 17 00:00:00 2001 From: Aanand Prasad Date: Thu, 10 Dec 2015 12:38:56 +0000 Subject: [PATCH 1/3] Allow overriding of positional args to py.test in tox.ini Signed-off-by: Aanand Prasad --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 96b91773bb..0970a6aaf2 100644 --- a/tox.ini +++ b/tox.ini @@ -5,7 +5,7 @@ skipsdist=True [testenv] usedevelop=True commands = - py.test --cov=docker tests/unit/ + py.test --cov=docker {posargs:tests/unit} deps = -r{toxinidir}/test-requirements.txt -r{toxinidir}/requirements.txt From 9b890c4540dd82cff67ac69568df9bbcc155d07e Mon Sep 17 00:00:00 2001 From: Aanand Prasad Date: Thu, 10 Dec 2015 12:36:51 +0000 Subject: [PATCH 2/3] Refactor resolve_authconfig tests The structure of the fake config dictionary was not reflective of what actual parsed config looks like. Signed-off-by: Aanand Prasad --- docker/auth/auth.py | 7 +--- tests/unit/auth_test.py | 83 +++++++++++++++++++++++++---------------- 2 files changed, 52 insertions(+), 38 deletions(-) diff --git a/docker/auth/auth.py b/docker/auth/auth.py index f771dedd97..1a44ce2232 100644 --- a/docker/auth/auth.py +++ b/docker/auth/auth.py @@ -82,11 +82,6 @@ def convert_to_hostname(url): return url.replace('http://', '').replace('https://', '').split('/', 1)[0] -def encode_auth(auth_info): - return base64.b64encode(auth_info.get('username', '') + b':' + - auth_info.get('password', '')) - - def decode_auth(auth): if isinstance(auth, six.string_types): auth = auth.encode('ascii') @@ -121,7 +116,7 @@ def parse_auth(entries): conf[registry] = { 'username': username, 'password': password, - 'email': entry['email'], + 'email': entry.get('email'), 'serveraddress': registry, } return conf diff --git a/tests/unit/auth_test.py b/tests/unit/auth_test.py index 8e0b1d4372..6a0f510f67 100644 --- a/tests/unit/auth_test.py +++ b/tests/unit/auth_test.py @@ -9,6 +9,7 @@ import tempfile from docker import auth +from docker.auth.auth import parse_auth from docker import errors from .. import base @@ -104,88 +105,105 @@ def test_invalid_index_name(self): ) +def encode_auth(auth_info): + return base64.b64encode( + auth_info.get('username', '').encode('utf-8') + b':' + + auth_info.get('password', '').encode('utf-8')) + + class ResolveAuthTest(base.BaseTestCase): - auth_config = { - 'https://index.docker.io/v1/': {'auth': 'indexuser'}, - 'my.registry.net': {'auth': 'privateuser'}, - 'http://legacy.registry.url/v1/': {'auth': 'legacyauth'} - } + index_config = {'auth': encode_auth({'username': 'indexuser'})} + private_config = {'auth': encode_auth({'username': 'privateuser'})} + legacy_config = {'auth': encode_auth({'username': 'legacyauth'})} + + auth_config = parse_auth({ + 'https://index.docker.io/v1/': index_config, + 'my.registry.net': private_config, + 'http://legacy.registry.url/v1/': legacy_config, + }) def test_resolve_authconfig_hostname_only(self): self.assertEqual( - auth.resolve_authconfig(self.auth_config, 'my.registry.net'), - {'auth': 'privateuser'} + auth.resolve_authconfig( + self.auth_config, 'my.registry.net' + )['username'], + 'privateuser' ) def test_resolve_authconfig_no_protocol(self): self.assertEqual( - auth.resolve_authconfig(self.auth_config, 'my.registry.net/v1/'), - {'auth': 'privateuser'} + auth.resolve_authconfig( + self.auth_config, 'my.registry.net/v1/' + )['username'], + 'privateuser' ) def test_resolve_authconfig_no_path(self): self.assertEqual( auth.resolve_authconfig( self.auth_config, 'http://my.registry.net' - ), - {'auth': 'privateuser'} + )['username'], + 'privateuser' ) def test_resolve_authconfig_no_path_trailing_slash(self): self.assertEqual( auth.resolve_authconfig( self.auth_config, 'http://my.registry.net/' - ), - {'auth': 'privateuser'} + )['username'], + 'privateuser' ) def test_resolve_authconfig_no_path_wrong_secure_proto(self): self.assertEqual( auth.resolve_authconfig( self.auth_config, 'https://my.registry.net' - ), - {'auth': 'privateuser'} + )['username'], + 'privateuser' ) def test_resolve_authconfig_no_path_wrong_insecure_proto(self): self.assertEqual( auth.resolve_authconfig( self.auth_config, 'http://index.docker.io' - ), - {'auth': 'indexuser'} + )['username'], + 'indexuser' ) def test_resolve_authconfig_path_wrong_proto(self): self.assertEqual( auth.resolve_authconfig( self.auth_config, 'https://my.registry.net/v1/' - ), - {'auth': 'privateuser'} + )['username'], + 'privateuser' ) def test_resolve_authconfig_default_registry(self): self.assertEqual( - auth.resolve_authconfig(self.auth_config), {'auth': 'indexuser'} + auth.resolve_authconfig(self.auth_config)['username'], + 'indexuser' ) def test_resolve_authconfig_default_explicit_none(self): self.assertEqual( - auth.resolve_authconfig(self.auth_config, None), - {'auth': 'indexuser'} + auth.resolve_authconfig(self.auth_config, None)['username'], + 'indexuser' ) def test_resolve_authconfig_fully_explicit(self): self.assertEqual( auth.resolve_authconfig( self.auth_config, 'http://my.registry.net/v1/' - ), - {'auth': 'privateuser'} + )['username'], + 'privateuser' ) def test_resolve_authconfig_legacy_config(self): self.assertEqual( - auth.resolve_authconfig(self.auth_config, 'legacy.registry.url'), - {'auth': 'legacyauth'} + auth.resolve_authconfig( + self.auth_config, 'legacy.registry.url' + )['username'], + 'legacyauth' ) def test_resolve_authconfig_no_match(self): @@ -198,8 +216,8 @@ def test_resolve_registry_and_auth_library_image(self): self.assertEqual( auth.resolve_authconfig( self.auth_config, auth.resolve_repository_name(image)[0] - ), - {'auth': 'indexuser'}, + )['username'], + 'indexuser', ) def test_resolve_registry_and_auth_hub_image(self): @@ -207,8 +225,9 @@ def test_resolve_registry_and_auth_hub_image(self): self.assertEqual( auth.resolve_authconfig( self.auth_config, auth.resolve_repository_name(image)[0] - ), - {'auth': 'indexuser'}, + )['username'], + 'indexuser', + ) ) def test_resolve_registry_and_auth_private_registry(self): @@ -216,8 +235,8 @@ def test_resolve_registry_and_auth_private_registry(self): self.assertEqual( auth.resolve_authconfig( self.auth_config, auth.resolve_repository_name(image)[0] - ), - {'auth': 'privateuser'}, + )['username'], + 'privateuser', ) def test_resolve_registry_and_auth_unauthenticated_registry(self): From 25b188440aecdb5482e815708d824c753d210edb Mon Sep 17 00:00:00 2001 From: Aanand Prasad Date: Thu, 10 Dec 2015 12:37:59 +0000 Subject: [PATCH 3/3] Treat 'index.docker.io' repo names as 'docker.io' Signed-off-by: Aanand Prasad --- docker/auth/auth.py | 15 +++++++++++---- tests/unit/auth_test.py | 31 +++++++++++++++++++++++++++---- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/docker/auth/auth.py b/docker/auth/auth.py index 1a44ce2232..5607520ede 100644 --- a/docker/auth/auth.py +++ b/docker/auth/auth.py @@ -21,7 +21,7 @@ from .. import errors -INDEX_NAME = 'index.docker.io' +INDEX_NAME = 'docker.io' INDEX_URL = 'https://{0}/v1/'.format(INDEX_NAME) DOCKER_CONFIG_FILENAME = os.path.join('.docker', 'config.json') LEGACY_DOCKER_CONFIG_FILENAME = '.dockercfg' @@ -41,7 +41,14 @@ def resolve_repository_name(repo_name): 'Invalid index name ({0}). Cannot begin or end with a' ' hyphen.'.format(index_name) ) - return index_name, remote_name + return resolve_index_name(index_name), remote_name + + +def resolve_index_name(index_name): + index_name = convert_to_hostname(index_name) + if index_name == 'index.'+INDEX_NAME: + index_name = INDEX_NAME + return index_name def split_repo_name(repo_name): @@ -62,7 +69,7 @@ def resolve_authconfig(authconfig, registry=None): Returns None if no match was found. """ # Default to the public index server - registry = convert_to_hostname(registry) if registry else INDEX_NAME + registry = resolve_index_name(registry) if registry else INDEX_NAME log.debug("Looking for auth entry for {0}".format(repr(registry))) if registry in authconfig: @@ -70,7 +77,7 @@ def resolve_authconfig(authconfig, registry=None): return authconfig[registry] for key, config in six.iteritems(authconfig): - if convert_to_hostname(key) == registry: + if resolve_index_name(key) == registry: log.debug("Found {0}".format(repr(key))) return config diff --git a/tests/unit/auth_test.py b/tests/unit/auth_test.py index 6a0f510f67..a88984f642 100644 --- a/tests/unit/auth_test.py +++ b/tests/unit/auth_test.py @@ -35,25 +35,31 @@ class ResolveRepositoryNameTest(base.BaseTestCase): def test_resolve_repository_name_hub_library_image(self): self.assertEqual( auth.resolve_repository_name('image'), - ('index.docker.io', 'image'), + ('docker.io', 'image'), ) def test_resolve_repository_name_dotted_hub_library_image(self): self.assertEqual( auth.resolve_repository_name('image.valid'), - ('index.docker.io', 'image.valid') + ('docker.io', 'image.valid') ) def test_resolve_repository_name_hub_image(self): self.assertEqual( auth.resolve_repository_name('username/image'), - ('index.docker.io', 'username/image'), + ('docker.io', 'username/image'), ) def test_explicit_hub_index_library_image(self): + self.assertEqual( + auth.resolve_repository_name('docker.io/image'), + ('docker.io', 'image') + ) + + def test_explicit_legacy_hub_index_library_image(self): self.assertEqual( auth.resolve_repository_name('index.docker.io/image'), - ('index.docker.io', 'image') + ('docker.io', 'image') ) def test_resolve_repository_name_private_registry(self): @@ -228,6 +234,23 @@ def test_resolve_registry_and_auth_hub_image(self): )['username'], 'indexuser', ) + + def test_resolve_registry_and_auth_explicit_hub(self): + image = 'docker.io/username/image' + self.assertEqual( + auth.resolve_authconfig( + self.auth_config, auth.resolve_repository_name(image)[0] + )['username'], + 'indexuser', + ) + + def test_resolve_registry_and_auth_explicit_legacy_hub(self): + image = 'index.docker.io/username/image' + self.assertEqual( + auth.resolve_authconfig( + self.auth_config, auth.resolve_repository_name(image)[0] + )['username'], + 'indexuser', ) def test_resolve_registry_and_auth_private_registry(self):